<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "zorbaerrors/error_manager.h"
#include "errors/user_error.h"
#include "zorbatypes/URI.h"

#include "api/serialization/serializer.h"

#include "system/globalenv.h"

#include "types/schema/revalidateUtils.h"

#include "compiler/api/compilercb.h"

#include "runtime/misc/MiscImpl.h"
#include "runtime/api/runtimecb.h"
#include "runtime/util/iterator_impl.h"
#include "runtime/visitors/planitervisitor.h"

#include "store/api/item_factory.h"
#include "store/api/store.h"
#include "store/api/pul.h"

#include "context/static_context.h"

#include <iostream>

namespace zorba {

SERIALIZABLE_CLASS_VERSIONS(FnErrorIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FnErrorIterator)

SERIALIZABLE_CLASS_VERSIONS(FnResolveUriIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FnResolveUriIterator)

SERIALIZABLE_CLASS_VERSIONS(SequentialIterator)
END_SERIALIZABLE_CLASS_VERSIONS(SequentialIterator)

SERIALIZABLE_CLASS_VERSIONS(FlowCtlIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FlowCtlIterator)

SERIALIZABLE_CLASS_VERSIONS(LoopIterator)
END_SERIALIZABLE_CLASS_VERSIONS(LoopIterator)

SERIALIZABLE_CLASS_VERSIONS(FnReadStringIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FnReadStringIterator)

SERIALIZABLE_CLASS_VERSIONS(FnPrintIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FnPrintIterator)

NARY_ACCEPT(FnErrorIterator);

NARY_ACCEPT(FnResolveUriIterator);

NARY_ACCEPT(SequentialIterator);

NARY_ACCEPT(FlowCtlIterator);

NARY_ACCEPT (LoopIterator);

NARY_ACCEPT (FnReadStringIterator);

NARY_ACCEPT(FnPrintIterator);

// 3 The Error Function
//---------------------
bool FnErrorIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  static const char *err_ns = "http://www.w3.org/2005/xqt-errors";
  store::Item_t err_qname;
  GENV_ITEMFACTORY->createQName (err_qname, err_ns, "err", "FOER0000");
  store::Item_t lTmpQName;
  store::Item_t lTmpErrorObject;
  store::Item_t lTmpDescr;
  xqp_string ns;
  xqp_string description;
  std::vector<store::Item_t> lErrorObject;

  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  if (theChildren.size () >= 1) {
    if (consumeNext(lTmpQName, theChildren[0].getp(), planState))
      err_qname = lTmpQName;
  }
  if (theChildren.size () >= 2) {
    consumeNext(lTmpDescr, theChildren[1].getp(), planState);
    description = lTmpDescr->getStringValue ().getp();
  }
  if (theChildren.size() == 3) {
    while (consumeNext(lTmpErrorObject, theChildren[2].getp(), planState)) {
      lErrorObject.push_back(lTmpErrorObject);
    }
  }

  {
    error::ZorbaUserError lError(err_qname, description, loc,
                                 __FILE__, __LINE__, lErrorObject);
    throw lError;
  }

  STACK_END (state);
}

// 8.1 fn:resolve-uri
//---------------------
bool FnResolveUriIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  store::Item_t item;
  xqpStringStore_t strRelative;
  xqpStringStore_t strBase;
  xqpStringStore_t strResult;
  URI              baseURI;
  URI              resolvedURI;

  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  if (consumeNext(item, theChildren[0], planState ))
  {
    strRelative = item->getStringValue();

    //If first param is an absolute URI reference, it is returned unchanged.
    try{
      resolvedURI = URI(&*strRelative);
    } catch (error::ZorbaError&) {}

    if (resolvedURI.is_absolute()) {
      strResult = strRelative;
    }
    else
    {
      try
      {
        if (theChildren.size() == 1)
        {
          // use base-uri from static context
          strBase = theSctx->baseuri().getStore();
          if (strBase->empty())
          {
            ZORBA_ERROR_LOC_DESC(FONS0005, loc,
                                 "base-uri is not initialized in the static context");
          }
        }
        else if (consumeNext(item, theChildren[1], planState ))
        {
          // two parameters => get baseuri from the second argument
          strBase = item->getStringValue();
        }
        else
        {
          ZORBA_ERROR_LOC_DESC(FORG0009, loc, "Can't treat empty-sequence as base-uri");
        }
        baseURI = URI(&*strBase, true);
      }
      catch (error::ZorbaError& e)
      {
        ZORBA_ERROR_LOC_DESC(FORG0002, loc,
                             "String {" + strBase->str() +  "} is not a valid URI: " + e.theDescription);
      }

      try
      {
        resolvedURI = URI(baseURI, &*strRelative, true); // resolve with baseURI or return strRelative if it's a valid absolute URI
        strResult = resolvedURI.toString().getStore();
      }
      catch (error::ZorbaError& e)
      {
        ZORBA_ERROR_LOC_DESC(FORG0002, loc, e.theDescription);
      }
    }
    STACK_PUSH(GENV_ITEMFACTORY->createString(result, strResult), state);
  } // else return empty sequence if the first argument is the empty sequence

  STACK_END (state);
}

bool SequentialIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  rchandle<store::PUL> lPul;

  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  for (unsigned i = 0; i < theChildren.size() - 1; i++)
  {
    while (CONSUME (result, i))
    {
      if (theChildren[i]->isUpdating())
      {
        std::set<zorba::store::Item*> validationNodes;

        static_cast<store::PUL *> (result.getp ())->applyUpdates(validationNodes);

        store::Item_t validationPul = GENV_ITEMFACTORY->createPendingUpdateList();

#ifndef ZORBA_NO_XMLSCHEMA
        QueryLoc& loc = theChildren[i]->loc;
        validateAfterUpdate(validationNodes,
                            validationPul,
                            getStaticContext(planState),
                            loc);
#endif
        validationPul->applyUpdates(validationNodes);
      }
    }
  }

  while (CONSUME (result, theChildren.size () - 1))
    STACK_PUSH (true, state);

  STACK_END (state);
}

bool FlowCtlIterator::nextImpl(store::Item_t& result, PlanState& planState) const {
  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
  switch (act) {
  case EXIT:
    throw ExitException (new PlanIteratorWrapper (theChildren [0], planState));
  default:
    throw FlowCtlException (act);
  }

  STACK_END (state);
}

bool FnReadStringIterator::nextImpl (store::Item_t& result, PlanState& planState) const {
  PlanIteratorState *state;
  xqpStringStore_t xstr;
  char str [512];
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
  std::cin.getline (str, sizeof (str));
  xstr = new xqpStringStore (str);
  GENV_ITEMFACTORY->createString (result, xstr);
  STACK_PUSH (true, state);
  STACK_END (state);
}

bool FnPrintIterator::nextImpl (store::Item_t& result, PlanState& planState) const
{
  std::ostringstream os;
  serializer* lSerializer = NULL;
  store::Item_t item;
  xqpStringStore_t resString;

  PlanIteratorState* state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  while (CONSUME (item, theChildren.size () - 1))
  {
    if (item->isNode())
    {
      if (lSerializer == NULL)
      {
        lSerializer = new serializer(planState.theCompilerCB->m_error_manager);
        lSerializer->set_parameter("omit-xml-declaration", "yes");
      }

      if (m_printToConsole) {
        lSerializer->serialize(item.getp(), std::cout);
      } else {
        lSerializer->serialize(item.getp(), os);
      }
    }
    else
    {
      if (m_printToConsole) {
          std::cout << item->getStringValue ();
      } else {
        os << item->getStringValue();
      }
    }
  }
  if (!m_printToConsole) {
    resString = new xqpStringStore(os.str());
    STACK_PUSH(GENV_ITEMFACTORY->createString(result, resString) , state);
  }
  STACK_END (state);
}

bool LoopIterator::nextImpl (store::Item_t& result, PlanState& planState) const {
  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
  for (;;) {
    try {
      while (! CONSUME (result, 0))
        theChildren [0]->reset (planState);
    } catch (FlowCtlIterator::FlowCtlException &e) {
      switch (e.act) {
      case FlowCtlIterator::BREAK:
        goto done;
      case FlowCtlIterator::CONTINUE:
        theChildren [0]->reset (planState);
        continue;
      default:
        throw;
      }
    }
    STACK_PUSH (true, state);
  }

done:
  STACK_END (state);
}

} /* namespace zorba */
<commit_msg>bug fix: handle case where the last child of a sequantial iterator in an updating one<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "zorbaerrors/error_manager.h"
#include "errors/user_error.h"
#include "zorbatypes/URI.h"

#include "api/serialization/serializer.h"

#include "system/globalenv.h"

#include "types/schema/revalidateUtils.h"

#include "compiler/api/compilercb.h"

#include "runtime/misc/MiscImpl.h"
#include "runtime/api/runtimecb.h"
#include "runtime/util/iterator_impl.h"
#include "runtime/visitors/planitervisitor.h"

#include "store/api/item_factory.h"
#include "store/api/store.h"
#include "store/api/pul.h"

#include "context/static_context.h"

#include <iostream>

namespace zorba {

SERIALIZABLE_CLASS_VERSIONS(FnErrorIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FnErrorIterator)

SERIALIZABLE_CLASS_VERSIONS(FnResolveUriIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FnResolveUriIterator)

SERIALIZABLE_CLASS_VERSIONS(SequentialIterator)
END_SERIALIZABLE_CLASS_VERSIONS(SequentialIterator)

SERIALIZABLE_CLASS_VERSIONS(FlowCtlIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FlowCtlIterator)

SERIALIZABLE_CLASS_VERSIONS(LoopIterator)
END_SERIALIZABLE_CLASS_VERSIONS(LoopIterator)

SERIALIZABLE_CLASS_VERSIONS(FnReadStringIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FnReadStringIterator)

SERIALIZABLE_CLASS_VERSIONS(FnPrintIterator)
END_SERIALIZABLE_CLASS_VERSIONS(FnPrintIterator)

NARY_ACCEPT(FnErrorIterator);

NARY_ACCEPT(FnResolveUriIterator);

NARY_ACCEPT(SequentialIterator);

NARY_ACCEPT(FlowCtlIterator);

NARY_ACCEPT (LoopIterator);

NARY_ACCEPT (FnReadStringIterator);

NARY_ACCEPT(FnPrintIterator);

// 3 The Error Function
//---------------------
bool FnErrorIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  static const char *err_ns = "http://www.w3.org/2005/xqt-errors";
  store::Item_t err_qname;
  GENV_ITEMFACTORY->createQName (err_qname, err_ns, "err", "FOER0000");
  store::Item_t lTmpQName;
  store::Item_t lTmpErrorObject;
  store::Item_t lTmpDescr;
  xqp_string ns;
  xqp_string description;
  std::vector<store::Item_t> lErrorObject;

  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  if (theChildren.size () >= 1) {
    if (consumeNext(lTmpQName, theChildren[0].getp(), planState))
      err_qname = lTmpQName;
  }
  if (theChildren.size () >= 2) {
    consumeNext(lTmpDescr, theChildren[1].getp(), planState);
    description = lTmpDescr->getStringValue ().getp();
  }
  if (theChildren.size() == 3) {
    while (consumeNext(lTmpErrorObject, theChildren[2].getp(), planState)) {
      lErrorObject.push_back(lTmpErrorObject);
    }
  }

  {
    error::ZorbaUserError lError(err_qname, description, loc,
                                 __FILE__, __LINE__, lErrorObject);
    throw lError;
  }

  STACK_END (state);
}

// 8.1 fn:resolve-uri
//---------------------
bool FnResolveUriIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  store::Item_t item;
  xqpStringStore_t strRelative;
  xqpStringStore_t strBase;
  xqpStringStore_t strResult;
  URI              baseURI;
  URI              resolvedURI;

  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  if (consumeNext(item, theChildren[0], planState ))
  {
    strRelative = item->getStringValue();

    //If first param is an absolute URI reference, it is returned unchanged.
    try{
      resolvedURI = URI(&*strRelative);
    } catch (error::ZorbaError&) {}

    if (resolvedURI.is_absolute()) {
      strResult = strRelative;
    }
    else
    {
      try
      {
        if (theChildren.size() == 1)
        {
          // use base-uri from static context
          strBase = theSctx->baseuri().getStore();
          if (strBase->empty())
          {
            ZORBA_ERROR_LOC_DESC(FONS0005, loc,
                                 "base-uri is not initialized in the static context");
          }
        }
        else if (consumeNext(item, theChildren[1], planState ))
        {
          // two parameters => get baseuri from the second argument
          strBase = item->getStringValue();
        }
        else
        {
          ZORBA_ERROR_LOC_DESC(FORG0009, loc, "Can't treat empty-sequence as base-uri");
        }
        baseURI = URI(&*strBase, true);
      }
      catch (error::ZorbaError& e)
      {
        ZORBA_ERROR_LOC_DESC(FORG0002, loc,
                             "String {" + strBase->str() +  "} is not a valid URI: " + e.theDescription);
      }

      try
      {
        resolvedURI = URI(baseURI, &*strRelative, true); // resolve with baseURI or return strRelative if it's a valid absolute URI
        strResult = resolvedURI.toString().getStore();
      }
      catch (error::ZorbaError& e)
      {
        ZORBA_ERROR_LOC_DESC(FORG0002, loc, e.theDescription);
      }
    }
    STACK_PUSH(GENV_ITEMFACTORY->createString(result, strResult), state);
  } // else return empty sequence if the first argument is the empty sequence

  STACK_END (state);
}

bool SequentialIterator::nextImpl(store::Item_t& result, PlanState& planState) const
{
  rchandle<store::PUL> lPul;
  ulong i = 0;

  PlanIteratorState* state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  for (; i < theChildren.size(); ++i)
  {
    while (CONSUME(result, i))
    {
      if (theChildren[i]->isUpdating())
      {
        std::set<zorba::store::Item*> validationNodes;

        static_cast<store::PUL*>(result.getp())->applyUpdates(validationNodes);

        store::Item_t validationPul = GENV_ITEMFACTORY->createPendingUpdateList();

#ifndef ZORBA_NO_XMLSCHEMA
        QueryLoc& loc = theChildren[i]->loc;
        validateAfterUpdate(validationNodes,
                            validationPul,
                            getStaticContext(planState),
                            loc);
#endif
        validationPul->applyUpdates(validationNodes);
      }
      else if (i == theChildren.size() - 1)
      {
        STACK_PUSH(true, state);
        i = theChildren.size() - 1;
      }
    }
  }

  STACK_END (state);
}

bool FlowCtlIterator::nextImpl(store::Item_t& result, PlanState& planState) const {
  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
  switch (act) {
  case EXIT:
    throw ExitException (new PlanIteratorWrapper (theChildren [0], planState));
  default:
    throw FlowCtlException (act);
  }

  STACK_END (state);
}

bool FnReadStringIterator::nextImpl (store::Item_t& result, PlanState& planState) const {
  PlanIteratorState *state;
  xqpStringStore_t xstr;
  char str [512];
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
  std::cin.getline (str, sizeof (str));
  xstr = new xqpStringStore (str);
  GENV_ITEMFACTORY->createString (result, xstr);
  STACK_PUSH (true, state);
  STACK_END (state);
}

bool FnPrintIterator::nextImpl (store::Item_t& result, PlanState& planState) const
{
  std::ostringstream os;
  serializer* lSerializer = NULL;
  store::Item_t item;
  xqpStringStore_t resString;

  PlanIteratorState* state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);

  while (CONSUME (item, theChildren.size () - 1))
  {
    if (item->isNode())
    {
      if (lSerializer == NULL)
      {
        lSerializer = new serializer(planState.theCompilerCB->m_error_manager);
        lSerializer->set_parameter("omit-xml-declaration", "yes");
      }

      if (m_printToConsole) {
        lSerializer->serialize(item.getp(), std::cout);
      } else {
        lSerializer->serialize(item.getp(), os);
      }
    }
    else
    {
      if (m_printToConsole) {
          std::cout << item->getStringValue ();
      } else {
        os << item->getStringValue();
      }
    }
  }
  if (!m_printToConsole) {
    resString = new xqpStringStore(os.str());
    STACK_PUSH(GENV_ITEMFACTORY->createString(result, resString) , state);
  }
  STACK_END (state);
}

bool LoopIterator::nextImpl (store::Item_t& result, PlanState& planState) const {
  PlanIteratorState *state;
  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
  for (;;) {
    try {
      while (! CONSUME (result, 0))
        theChildren [0]->reset (planState);
    } catch (FlowCtlIterator::FlowCtlException &e) {
      switch (e.act) {
      case FlowCtlIterator::BREAK:
        goto done;
      case FlowCtlIterator::CONTINUE:
        theChildren [0]->reset (planState);
        continue;
      default:
        throw;
      }
    }
    STACK_PUSH (true, state);
  }

done:
  STACK_END (state);
}

} /* namespace zorba */
<|endoftext|>


<commit_before>// Copyright (c) 2009 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 "chrome/browser/worker_host/worker_service.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_layout_test.h"

static const char kTestCompleteCookie[] = "status";
static const char kTestCompleteSuccess[] = "OK";

class WorkerTest : public UILayoutTest {
 protected:
  virtual ~WorkerTest() { }

  void RunTest(const std::wstring& test_case) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());

    GURL url = GetTestUrl(L"workers", test_case);
    ASSERT_TRUE(tab->NavigateToURL(url));

    std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
        kTestCompleteCookie, kTestIntervalMs, kTestWaitTimeoutMs);
    ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
  }
};

TEST_F(WorkerTest, SingleWorker) {
  RunTest(L"single_worker.html");
}

TEST_F(WorkerTest, MultipleWorkers) {
  RunTest(L"multi_worker.html");
}

// This fails on all platforms. Disable it for now. See http://crbug.com/22942
TEST_F(WorkerTest, DISABLED_WorkerFastLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "stress-js-execution.html",
#if defined(OS_WIN)
    // Workers don't properly initialize the V8 stack guard.
    // (http://code.google.com/p/chromium/issues/detail?id=21653).
    "use-machine-stack.html",
#endif
    "worker-call.html",
    // Disabled because cloning ports are too slow in Chromium to meet the
    // thresholds in this test.
    // http://code.google.com/p/chromium/issues/detail?id=22780
    // "worker-cloneport.html",

    "worker-close.html",
    "worker-constructor.html",
    "worker-context-gc.html",
    "worker-context-multi-port.html",
    "worker-event-listener.html",
    "worker-gc.html",
    // worker-lifecycle.html relies on layoutTestController.workerThreadCount
    // which is not currently implemented.
    // "worker-lifecycle.html",
    "worker-location.html",
    "worker-messageport.html",
    "worker-messageport-gc.html",
    "worker-multi-port.html",
    "worker-navigator.html",
    "worker-replace-global-constructor.html",
    "worker-replace-self.html",
    "worker-script-error.html",
    "worker-terminate.html",
    "worker-timeout.html"
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // Worker tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], false);
}

TEST_F(WorkerTest, WorkerHttpLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    // flakey? BUG 16934 "text-encoding.html",
#if defined(OS_WIN)
    // Fails on the mac (and linux?):
    // http://code.google.com/p/chromium/issues/detail?id=22599
    "worker-importScripts.html",
#endif
    "worker-redirect.html",
  };

  FilePath http_test_dir;
  http_test_dir = http_test_dir.AppendASCII("LayoutTests");
  http_test_dir = http_test_dir.AppendASCII("http");
  http_test_dir = http_test_dir.AppendASCII("tests");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(http_test_dir, worker_test_dir, true);

  StartHttpServer(new_http_root_dir_);
  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], true);
  StopHttpServer();
}

TEST_F(WorkerTest, WorkerXhrHttpLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "abort-exception-assert.html",
#if defined(OS_WIN)
    // Fails on the mac (and linux?):
    // http://code.google.com/p/chromium/issues/detail?id=22599
    "close.html",
#endif
    //"methods-async.html",
    //"methods.html",
    "xmlhttprequest-file-not-found.html"
  };

  FilePath http_test_dir;
  http_test_dir = http_test_dir.AppendASCII("LayoutTests");
  http_test_dir = http_test_dir.AppendASCII("http");
  http_test_dir = http_test_dir.AppendASCII("tests");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("xmlhttprequest");
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(http_test_dir, worker_test_dir, true);

  StartHttpServer(new_http_root_dir_);
  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], true);
  StopHttpServer();
}

TEST_F(WorkerTest, MessagePorts) {
  static const char* kLayoutTestFiles[] = {
    "message-channel-gc.html",
    "message-channel-gc-2.html",
    "message-channel-gc-3.html",
    "message-channel-gc-4.html",
    "message-port.html",
    "message-port-clone.html",
    "message-port-constructor-for-deleted-document.html",
    "message-port-deleted-document.html",
    "message-port-deleted-frame.html",
    "message-port-inactive-document.html",
    "message-port-multi.html",
    "message-port-no-wrapper.html",
    // Only works with run-webkit-tests --leaks.
    //"message-channel-listener-circular-ownership.html",
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("events");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // MessagePort tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], false);
}

// Disable LimitPerPage on Linux. Seems to work on Mac though:
// http://code.google.com/p/chromium/issues/detail?id=22608
#if !defined(OS_LINUX)
TEST_F(WorkerTest, LimitPerPage) {
  int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
  GURL url = GetTestUrl(L"workers", L"many_workers.html");
  url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab + 1));

  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURL(url));

  EXPECT_EQ(max_workers_per_tab + 1 + (UITest::in_process_renderer() ? 0 : 1),
            UITest::GetBrowserProcessCount());
}
#endif

// Disable LimitTotal on Linux and Mac.
// http://code.google.com/p/chromium/issues/detail?id=22608
#if defined(OS_WIN)
TEST_F(WorkerTest, LimitTotal) {
  int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
  int total_workers = WorkerService::kMaxWorkersWhenSeparate;

  int tab_count = (total_workers / max_workers_per_tab) + 1;
  GURL url = GetTestUrl(L"workers", L"many_workers.html");
  url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab));

  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURL(url));
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  for (int i = 1; i < tab_count; ++i)
    window->AppendTab(url);

  // Check that we didn't create more than the max number of workers.
  EXPECT_EQ(total_workers + 1 + (UITest::in_process_renderer() ? 0 : tab_count),
            UITest::GetBrowserProcessCount());

  // Now close the first tab and check that the queued workers were started.
  tab->Close(true);
  tab->NavigateToURL(GetTestUrl(L"google", L"google.html"));

  EXPECT_EQ(total_workers + 1 + (UITest::in_process_renderer() ? 0 : tab_count),
            UITest::GetBrowserProcessCount());
}
#endif
<commit_msg>Re-enable WorkerFastTests and disable only one that fails. BUG=22947 TEST=none Review URL: http://codereview.chromium.org/219033<commit_after>// Copyright (c) 2009 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 "chrome/browser/worker_host/worker_service.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_layout_test.h"

static const char kTestCompleteCookie[] = "status";
static const char kTestCompleteSuccess[] = "OK";

class WorkerTest : public UILayoutTest {
 protected:
  virtual ~WorkerTest() { }

  void RunTest(const std::wstring& test_case) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());

    GURL url = GetTestUrl(L"workers", test_case);
    ASSERT_TRUE(tab->NavigateToURL(url));

    std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
        kTestCompleteCookie, kTestIntervalMs, kTestWaitTimeoutMs);
    ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
  }
};

TEST_F(WorkerTest, SingleWorker) {
  RunTest(L"single_worker.html");
}

TEST_F(WorkerTest, MultipleWorkers) {
  RunTest(L"multi_worker.html");
}

TEST_F(WorkerTest, WorkerFastLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "stress-js-execution.html",
#if defined(OS_WIN)
    // Workers don't properly initialize the V8 stack guard.
    // (http://code.google.com/p/chromium/issues/detail?id=21653).
    "use-machine-stack.html",
#endif
    "worker-call.html",
    // Disabled because cloning ports are too slow in Chromium to meet the
    // thresholds in this test.
    // http://code.google.com/p/chromium/issues/detail?id=22780
    // "worker-cloneport.html",

    "worker-close.html",
    "worker-constructor.html",
    "worker-context-gc.html",
    "worker-context-multi-port.html",
    "worker-event-listener.html",
    "worker-gc.html",
    // worker-lifecycle.html relies on layoutTestController.workerThreadCount
    // which is not currently implemented.
    // "worker-lifecycle.html",
    "worker-location.html",
    "worker-messageport.html",
    // Disabled after r27089 (WebKit merge), http://crbug.com/22947
    // "worker-messageport-gc.html",
    "worker-multi-port.html",
    "worker-navigator.html",
    "worker-replace-global-constructor.html",
    "worker-replace-self.html",
    "worker-script-error.html",
    "worker-terminate.html",
    "worker-timeout.html"
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // Worker tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], false);
}

TEST_F(WorkerTest, WorkerHttpLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    // flakey? BUG 16934 "text-encoding.html",
#if defined(OS_WIN)
    // Fails on the mac (and linux?):
    // http://code.google.com/p/chromium/issues/detail?id=22599
    "worker-importScripts.html",
#endif
    "worker-redirect.html",
  };

  FilePath http_test_dir;
  http_test_dir = http_test_dir.AppendASCII("LayoutTests");
  http_test_dir = http_test_dir.AppendASCII("http");
  http_test_dir = http_test_dir.AppendASCII("tests");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(http_test_dir, worker_test_dir, true);

  StartHttpServer(new_http_root_dir_);
  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], true);
  StopHttpServer();
}

TEST_F(WorkerTest, WorkerXhrHttpLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "abort-exception-assert.html",
#if defined(OS_WIN)
    // Fails on the mac (and linux?):
    // http://code.google.com/p/chromium/issues/detail?id=22599
    "close.html",
#endif
    //"methods-async.html",
    //"methods.html",
    "xmlhttprequest-file-not-found.html"
  };

  FilePath http_test_dir;
  http_test_dir = http_test_dir.AppendASCII("LayoutTests");
  http_test_dir = http_test_dir.AppendASCII("http");
  http_test_dir = http_test_dir.AppendASCII("tests");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("xmlhttprequest");
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(http_test_dir, worker_test_dir, true);

  StartHttpServer(new_http_root_dir_);
  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], true);
  StopHttpServer();
}

TEST_F(WorkerTest, MessagePorts) {
  static const char* kLayoutTestFiles[] = {
    "message-channel-gc.html",
    "message-channel-gc-2.html",
    "message-channel-gc-3.html",
    "message-channel-gc-4.html",
    "message-port.html",
    "message-port-clone.html",
    "message-port-constructor-for-deleted-document.html",
    "message-port-deleted-document.html",
    "message-port-deleted-frame.html",
    "message-port-inactive-document.html",
    "message-port-multi.html",
    "message-port-no-wrapper.html",
    // Only works with run-webkit-tests --leaks.
    //"message-channel-listener-circular-ownership.html",
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("events");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // MessagePort tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], false);
}

// Disable LimitPerPage on Linux. Seems to work on Mac though:
// http://code.google.com/p/chromium/issues/detail?id=22608
#if !defined(OS_LINUX)
TEST_F(WorkerTest, LimitPerPage) {
  int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
  GURL url = GetTestUrl(L"workers", L"many_workers.html");
  url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab + 1));

  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURL(url));

  EXPECT_EQ(max_workers_per_tab + 1 + (UITest::in_process_renderer() ? 0 : 1),
            UITest::GetBrowserProcessCount());
}
#endif

// Disable LimitTotal on Linux and Mac.
// http://code.google.com/p/chromium/issues/detail?id=22608
#if defined(OS_WIN)
TEST_F(WorkerTest, LimitTotal) {
  int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
  int total_workers = WorkerService::kMaxWorkersWhenSeparate;

  int tab_count = (total_workers / max_workers_per_tab) + 1;
  GURL url = GetTestUrl(L"workers", L"many_workers.html");
  url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab));

  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURL(url));
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  for (int i = 1; i < tab_count; ++i)
    window->AppendTab(url);

  // Check that we didn't create more than the max number of workers.
  EXPECT_EQ(total_workers + 1 + (UITest::in_process_renderer() ? 0 : tab_count),
            UITest::GetBrowserProcessCount());

  // Now close the first tab and check that the queued workers were started.
  tab->Close(true);
  tab->NavigateToURL(GetTestUrl(L"google", L"google.html"));

  EXPECT_EQ(total_workers + 1 + (UITest::in_process_renderer() ? 0 : tab_count),
            UITest::GetBrowserProcessCount());
}
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>

#include <SDL_syswm.h>
#include "egl_helper.hpp"

#ifdef EGL_HELPER_DISABLED
egl_helper::
egl_helper(const fastuidraw::reference_counted_ptr<StreamHolder> &str,
           const params&, SDL_Window*)
{
  FASTUIDRAWassert(!"Platform does not support EGL");
  std::abort();
}

egl_helper::
~egl_helper()
{}

void
egl_helper::
make_current(void)
{}

void
egl_helper::
swap_buffers(void)
{}

void*
egl_helper::
egl_get_proc(fastuidraw::c_string)
{
  return nullptr;
}

void
egl_helper::
print_info(std::ostream&)
{}

#else

/* This is hideously delicate; We need the eglGetProc symbol from
 * EGL/egl.h. The header fastuidraw/ngl_egl might make that symbol
 * a macro, thus we first include <EGL/egl.h> and then include
 * the macro magic.
 */
#include <EGL/egl.h>
#include <fastuidraw/util/api_callback.hpp>

namespace
{
  void*
  get_proc(fastuidraw::c_string proc_name)
  {
    return (void*)eglGetProcAddress(proc_name);
  }
}

/* Shudders. FastUIDraws's ngl_egl.hpp is/was built with the system
 * defaults, which means the typedefs of EGL native types to X11
 * types. The Wayland types are different, but have the exact same
 * sizes. For C this is fine, but the header ngl_egl.hpp defines
 * the debug function C++ style in a namespace, which means the
 * symbols will be decorated with the argument types. We get around
 * this entire heartache by simply including the Wayland header
 * -AFTER- the EGL headers and we do C-style casts to do the deed.
 */
#include <fastuidraw/egl_binding.hpp>
#include <fastuidraw/ngl_egl.hpp>
#include <wayland-egl.h>

namespace
{
  class Logger:public fastuidraw::egl_binding::CallbackEGL
  {
  public:
    Logger(const fastuidraw::reference_counted_ptr<StreamHolder> &str):
      m_str(str)
    {}

    void
    pre_call(fastuidraw::c_string call_string_values,
             fastuidraw::c_string call_string_src,
             fastuidraw::c_string function_name,
             void *function_ptr,
             fastuidraw::c_string src_file, int src_line)
    {
      FASTUIDRAWunused(call_string_src);
      FASTUIDRAWunused(function_name);
      FASTUIDRAWunused(function_ptr);
      m_str->stream() << "Pre: [" << src_file << "," << src_line << "] "
                      << call_string_values << "\n";
    }

    void
    post_call(fastuidraw::c_string call_string_values,
              fastuidraw::c_string call_string_src,
              fastuidraw::c_string function_name,
              fastuidraw::c_string error_string,
              void *function_ptr,
              fastuidraw::c_string src_file, int src_line)
    {
      FASTUIDRAWunused(call_string_src);
      FASTUIDRAWunused(function_name);
      FASTUIDRAWunused(function_ptr);
      FASTUIDRAWunused(error_string);
      m_str->stream() << "Post: [" << src_file << "," << src_line << "] "
                      << call_string_values;

      if(error_string && *error_string)
        {
          m_str->stream() << "{" << error_string << "}";
        }
      m_str->stream() << "\n";
    }

  private:
    fastuidraw::reference_counted_ptr<StreamHolder> m_str;
  };

  EGLConfig
  choose_config(void *dpy, const egl_helper::params &P)
  {
    EGLint config_attribs[32];
    EGLint n(0), renderable_type(0), num_configs(0);
    EGLConfig ret;

    #ifdef FASTUIDRAW_GL_USE_GLES
      {
        renderable_type |= EGL_OPENGL_ES3_BIT;
      }
    #else
      {
        renderable_type |= EGL_OPENGL_BIT;
      }
    #endif

    config_attribs[n++] = EGL_RED_SIZE;
    config_attribs[n++] = P.m_red_bits;
    config_attribs[n++] = EGL_GREEN_SIZE;
    config_attribs[n++] = P.m_green_bits;
    config_attribs[n++] = EGL_BLUE_SIZE;
    config_attribs[n++] = P.m_blue_bits;
    config_attribs[n++] = EGL_ALPHA_SIZE;
    config_attribs[n++] = P.m_alpha_bits;
    config_attribs[n++] = EGL_DEPTH_SIZE;
    config_attribs[n++] = P.m_depth_bits;
    config_attribs[n++] = EGL_STENCIL_SIZE;
    config_attribs[n++] = P.m_stencil_bits;
    config_attribs[n++] = EGL_SURFACE_TYPE;
    config_attribs[n++] = EGL_WINDOW_BIT;
    config_attribs[n++] = EGL_RENDERABLE_TYPE;
    config_attribs[n++] = renderable_type;
    if (P.m_msaa > 0)
      {
        config_attribs[n++] = EGL_SAMPLE_BUFFERS;
        config_attribs[n++] = 1;
        config_attribs[n++] = EGL_SAMPLES;
        config_attribs[n++] = P.m_msaa;
      }

    config_attribs[n] = EGL_NONE;
    /* TODO: rather than just getting one config, examine
     * all the configs and choose one that matches tightest;
     * eglChooseConfig's ordering of choices places those
     * with deepest color-depths first, which means we actually
     * should walk the list to get closest match.
     */
    eglChooseConfig(dpy, config_attribs, &ret, 1, &num_configs);
    FASTUIDRAWassert(num_configs != 0);
    return ret;
  }
}

egl_helper::
egl_helper(const fastuidraw::reference_counted_ptr<StreamHolder> &str,
           const params &P, SDL_Window *sdl):
  m_ctx(EGL_NO_CONTEXT),
  m_surface(EGL_NO_SURFACE),
  m_dpy(EGL_NO_DISPLAY),
  m_wl_window(nullptr)
{
  FASTUIDRAWunused(P);
  FASTUIDRAWunused(sdl);

  SDL_SysWMinfo wm;
  int egl_major(0), egl_minor(0);
  EGLNativeWindowType egl_window;
  EGLNativeDisplayType egl_display;

  SDL_VERSION(&wm.version);
  SDL_GetWindowWMInfo(sdl, &wm);

  switch (wm.subsystem)
    {
    case SDL_SYSWM_X11:
      egl_window = (EGLNativeWindowType)wm.info.x11.window;
      egl_display = (EGLNativeDisplayType)wm.info.x11.display;
      break;

    case SDL_SYSWM_WAYLAND:
      int width, height;
      SDL_GetWindowSize(sdl, &width, &height);
      m_wl_window = wl_egl_window_create(wm.info.wl.surface, width, height);
      egl_window = (EGLNativeWindowType)m_wl_window;
      egl_display = (EGLNativeDisplayType)wm.info.wl.display;
      break;

    default:
      FASTUIDRAWassert(!"Unsupported Platform for EGL\n");
      std::abort();
    }

  if (str)
    {
      m_logger = FASTUIDRAWnew Logger(str);
    }
  fastuidraw::egl_binding::get_proc_function(get_proc);
  m_dpy = eglGetDisplay(egl_display);
  eglInitialize(m_dpy, &egl_major, &egl_minor);

  /* find a config.
   */
  EGLConfig config;
  config = choose_config(m_dpy, P);
  m_surface = eglCreateWindowSurface(m_dpy, config, egl_window, nullptr);

  EGLint context_attribs[32];
  int n(0);

  context_attribs[n++] = EGL_CONTEXT_MAJOR_VERSION;
  context_attribs[n++] = P.m_gles_major_version;
  if(P.m_gles_minor_version != 0)
    {
      context_attribs[n++] = EGL_CONTEXT_MINOR_VERSION;
      context_attribs[n++] = P.m_gles_minor_version;
    }
  context_attribs[n++] = EGL_NONE;

  #ifdef FASTUIDRAW_GL_USE_GLES
    {
      eglBindAPI(EGL_OPENGL_ES_API);
    }
  #else
    {
      eglBindAPI(EGL_OPENGL_API);
    }
  #endif

  std::cout << "\n\nUsing EGL!\n\n";

  m_ctx = eglCreateContext(m_dpy, config, EGL_NO_CONTEXT, context_attribs);
  eglMakeCurrent(m_dpy, m_surface, m_surface, m_ctx);
}

egl_helper::
~egl_helper()
{
  eglMakeCurrent(m_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  eglDestroyContext(m_dpy, m_ctx);
  eglDestroySurface(m_dpy, m_surface);
  eglTerminate(m_dpy);

  if (m_wl_window)
    {
      wl_egl_window_destroy(m_wl_window);
    }
}

void
egl_helper::
make_current(void)
{
  eglMakeCurrent(m_dpy, m_surface, m_surface, m_ctx);
}

void
egl_helper::
swap_buffers(void)
{
  eglSwapBuffers(m_dpy, m_surface);
}

void*
egl_helper::
egl_get_proc(fastuidraw::c_string name)
{
  return (void*)eglGetProcAddress(name);
}

void
egl_helper::
print_info(std::ostream &dst)
{
  dst << "\nEGL extensions: " << eglQueryString(m_dpy, EGL_EXTENSIONS);
}

#endif
<commit_msg>demos/common/egl_helper: remove trickery for setting eglGetProcAddress function<commit_after>#include <iostream>
#include <iomanip>

#include <SDL_syswm.h>
#include "egl_helper.hpp"

#ifdef EGL_HELPER_DISABLED
egl_helper::
egl_helper(const fastuidraw::reference_counted_ptr<StreamHolder> &str,
           const params&, SDL_Window*)
{
  FASTUIDRAWassert(!"Platform does not support EGL");
  std::abort();
}

egl_helper::
~egl_helper()
{}

void
egl_helper::
make_current(void)
{}

void
egl_helper::
swap_buffers(void)
{}

void*
egl_helper::
egl_get_proc(fastuidraw::c_string)
{
  return nullptr;
}

void
egl_helper::
print_info(std::ostream&)
{}

#else

/* Shudders. FastUIDraws's ngl_egl.hpp is/was built with the system
 * defaults, which means the typedefs of EGL native types to X11
 * types. The Wayland types are different, but have the exact same
 * sizes. For C this is fine, but the header ngl_egl.hpp defines
 * the debug function C++ style in a namespace, which means the
 * symbols will be decorated with the argument types. We get around
 * this entire heartache by simply including the Wayland header
 * -AFTER- the EGL headers and we do C-style casts to do the deed.
 */
#include <fastuidraw/egl_binding.hpp>
#include <fastuidraw/ngl_egl.hpp>
#include <wayland-egl.h>

namespace
{
  void*
  get_proc(fastuidraw::c_string proc_name)
  {
    return (void*)eglGetProcAddress(proc_name);
  }

  class Logger:public fastuidraw::egl_binding::CallbackEGL
  {
  public:
    Logger(const fastuidraw::reference_counted_ptr<StreamHolder> &str):
      m_str(str)
    {}

    void
    pre_call(fastuidraw::c_string call_string_values,
             fastuidraw::c_string call_string_src,
             fastuidraw::c_string function_name,
             void *function_ptr,
             fastuidraw::c_string src_file, int src_line)
    {
      FASTUIDRAWunused(call_string_src);
      FASTUIDRAWunused(function_name);
      FASTUIDRAWunused(function_ptr);
      m_str->stream() << "Pre: [" << src_file << "," << src_line << "] "
                      << call_string_values << "\n";
    }

    void
    post_call(fastuidraw::c_string call_string_values,
              fastuidraw::c_string call_string_src,
              fastuidraw::c_string function_name,
              fastuidraw::c_string error_string,
              void *function_ptr,
              fastuidraw::c_string src_file, int src_line)
    {
      FASTUIDRAWunused(call_string_src);
      FASTUIDRAWunused(function_name);
      FASTUIDRAWunused(function_ptr);
      FASTUIDRAWunused(error_string);
      m_str->stream() << "Post: [" << src_file << "," << src_line << "] "
                      << call_string_values;

      if(error_string && *error_string)
        {
          m_str->stream() << "{" << error_string << "}";
        }
      m_str->stream() << "\n";
    }

  private:
    fastuidraw::reference_counted_ptr<StreamHolder> m_str;
  };

  EGLConfig
  choose_config(void *dpy, const egl_helper::params &P)
  {
    EGLint config_attribs[32];
    EGLint n(0), renderable_type(0), num_configs(0);
    EGLConfig ret;

    #ifdef FASTUIDRAW_GL_USE_GLES
      {
        renderable_type |= EGL_OPENGL_ES3_BIT;
      }
    #else
      {
        renderable_type |= EGL_OPENGL_BIT;
      }
    #endif

    config_attribs[n++] = EGL_RED_SIZE;
    config_attribs[n++] = P.m_red_bits;
    config_attribs[n++] = EGL_GREEN_SIZE;
    config_attribs[n++] = P.m_green_bits;
    config_attribs[n++] = EGL_BLUE_SIZE;
    config_attribs[n++] = P.m_blue_bits;
    config_attribs[n++] = EGL_ALPHA_SIZE;
    config_attribs[n++] = P.m_alpha_bits;
    config_attribs[n++] = EGL_DEPTH_SIZE;
    config_attribs[n++] = P.m_depth_bits;
    config_attribs[n++] = EGL_STENCIL_SIZE;
    config_attribs[n++] = P.m_stencil_bits;
    config_attribs[n++] = EGL_SURFACE_TYPE;
    config_attribs[n++] = EGL_WINDOW_BIT;
    config_attribs[n++] = EGL_RENDERABLE_TYPE;
    config_attribs[n++] = renderable_type;
    if (P.m_msaa > 0)
      {
        config_attribs[n++] = EGL_SAMPLE_BUFFERS;
        config_attribs[n++] = 1;
        config_attribs[n++] = EGL_SAMPLES;
        config_attribs[n++] = P.m_msaa;
      }

    config_attribs[n] = EGL_NONE;
    /* TODO: rather than just getting one config, examine
     * all the configs and choose one that matches tightest;
     * eglChooseConfig's ordering of choices places those
     * with deepest color-depths first, which means we actually
     * should walk the list to get closest match.
     */
    eglChooseConfig(dpy, config_attribs, &ret, 1, &num_configs);
    FASTUIDRAWassert(num_configs != 0);
    return ret;
  }
}

egl_helper::
egl_helper(const fastuidraw::reference_counted_ptr<StreamHolder> &str,
           const params &P, SDL_Window *sdl):
  m_ctx(EGL_NO_CONTEXT),
  m_surface(EGL_NO_SURFACE),
  m_dpy(EGL_NO_DISPLAY),
  m_wl_window(nullptr)
{
  FASTUIDRAWunused(P);
  FASTUIDRAWunused(sdl);

  SDL_SysWMinfo wm;
  int egl_major(0), egl_minor(0);
  EGLNativeWindowType egl_window;
  EGLNativeDisplayType egl_display;

  SDL_VERSION(&wm.version);
  SDL_GetWindowWMInfo(sdl, &wm);

  switch (wm.subsystem)
    {
    case SDL_SYSWM_X11:
      egl_window = (EGLNativeWindowType)wm.info.x11.window;
      egl_display = (EGLNativeDisplayType)wm.info.x11.display;
      break;

    case SDL_SYSWM_WAYLAND:
      int width, height;
      SDL_GetWindowSize(sdl, &width, &height);
      m_wl_window = wl_egl_window_create(wm.info.wl.surface, width, height);
      egl_window = (EGLNativeWindowType)m_wl_window;
      egl_display = (EGLNativeDisplayType)wm.info.wl.display;
      break;

    default:
      FASTUIDRAWassert(!"Unsupported Platform for EGL\n");
      std::abort();
    }

  if (str)
    {
      m_logger = FASTUIDRAWnew Logger(str);
    }
  fastuidraw::egl_binding::get_proc_function(get_proc);
  m_dpy = eglGetDisplay(egl_display);
  eglInitialize(m_dpy, &egl_major, &egl_minor);

  /* find a config.
   */
  EGLConfig config;
  config = choose_config(m_dpy, P);
  m_surface = eglCreateWindowSurface(m_dpy, config, egl_window, nullptr);

  EGLint context_attribs[32];
  int n(0);

  context_attribs[n++] = EGL_CONTEXT_MAJOR_VERSION;
  context_attribs[n++] = P.m_gles_major_version;
  if(P.m_gles_minor_version != 0)
    {
      context_attribs[n++] = EGL_CONTEXT_MINOR_VERSION;
      context_attribs[n++] = P.m_gles_minor_version;
    }
  context_attribs[n++] = EGL_NONE;

  #ifdef FASTUIDRAW_GL_USE_GLES
    {
      eglBindAPI(EGL_OPENGL_ES_API);
    }
  #else
    {
      eglBindAPI(EGL_OPENGL_API);
    }
  #endif

  std::cout << "\n\nUsing EGL!\n\n";

  m_ctx = eglCreateContext(m_dpy, config, EGL_NO_CONTEXT, context_attribs);
  eglMakeCurrent(m_dpy, m_surface, m_surface, m_ctx);
}

egl_helper::
~egl_helper()
{
  eglMakeCurrent(m_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  eglDestroyContext(m_dpy, m_ctx);
  eglDestroySurface(m_dpy, m_surface);
  eglTerminate(m_dpy);

  if (m_wl_window)
    {
      wl_egl_window_destroy(m_wl_window);
    }
}

void
egl_helper::
make_current(void)
{
  eglMakeCurrent(m_dpy, m_surface, m_surface, m_ctx);
}

void
egl_helper::
swap_buffers(void)
{
  eglSwapBuffers(m_dpy, m_surface);
}

void*
egl_helper::
egl_get_proc(fastuidraw::c_string name)
{
  return (void*)eglGetProcAddress(name);
}

void
egl_helper::
print_info(std::ostream &dst)
{
  dst << "\nEGL extensions: " << eglQueryString(m_dpy, EGL_EXTENSIONS);
}

#endif
<|endoftext|>


<commit_before>

#include "bignum.h"
#include "sync.h"
#include "net.h"
#include "key.h"
#include "util.h"
#include "script.h"
#include "hashblock.h"
#include "base58.h"
#include "instantx.h"
#include "masternode.h"
#include "activemasternode.h"
#include "darksend.h"

using namespace std;
using namespace boost;

std::vector<CTransactionLock> vecTxLocks;

std::map<uint256, CTransaction> mapTxLockReq;
std::map<uint256, CTransaction> mapTxLockReqRejected;
std::map<uint256, CTransactionLock> mapTxLocks;

#define INSTANTX_SIGNATURES_REQUIRED           2

//txlock - Locks transaction
//
//step 1.) Broadcast intention to lock transaction inputs, "txlreg", CTransaction
//step 2.) Top 10 masternodes, open connect to top 1 masternode. Send "txvote", CTransaction, Signature, Approve
//step 3.) Top 1 masternode, waits for 10 messages. Upon success, sends "txlock'

void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
{
    return;

    if (strCommand == "txlreq")
    {
        //LogPrintf("ProcessMessageInstantX::txlreq\n");
        CDataStream vMsg(vRecv);
        CTransaction tx;
        vRecv >> tx;

        CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash());
        pfrom->AddInventoryKnown(inv);

        if(mapTxLockReq.count(inv.hash) || mapTxLockReqRejected.count(inv.hash)){
            return;
        }

        int nTxAge = GetInputAge(tx.vin[0]);
        if(nTxAge < 5){
            LogPrintf("ProcessMessageInstantX::txlreq - Transaction not found / too new: %s\n", tx.GetHash().ToString().c_str());
            return;
        }
        int nBlockHeight = pindexBest->nHeight - nTxAge; //calculate the height

        BOOST_FOREACH(const CTxOut o, txCollateral.vout){
            if(!o.scriptPubKey.IsNormalPaymentScript()){
                LogPrintf ("ProcessMessageInstantX::txlreq - Invalid Script %s\n", txCollateral.ToString().c_str());
                return false;
            }
        }

        bool fMissingInputs = false;
        CValidationState state;
        if (tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
        {
            RelayTransactionLockReq(tx, inv.hash);
            DoConsensusVote(tx, true, nBlockHeight);

            mapTxLockReq.insert(make_pair(inv.hash, tx));

            LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : accepted %s\n",
                pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                tx.GetHash().ToString().c_str()
            );

            return;

        } else {
            mapTxLockReqRejected.insert(make_pair(inv.hash, tx));

            // can we get the conflicting transaction as proof?

            RelayTransactionLockReq(tx, inv.hash);
            DoConsensusVote(tx, false, nBlockHeight);

            LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : rejected %s\n",
                pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                tx.GetHash().ToString().c_str()
            );

            //record prevout, increment the amount of times seen. Ban if over 100

            return;
        }
    }
    else if (strCommand == "txlvote") //InstantX Lock Consensus Votes
    {
        CConsensusVote ctx;
        vRecv >> ctx;

        ProcessConsensusVote(ctx);

        return;
    }
    else if (strCommand == "txlock") //InstantX Lock Transaction Inputs
    {
        LogPrintf("ProcessMessageInstantX::txlock\n");

        CDataStream vMsg(vRecv);
        CTransactionLock ctxl;
        vRecv >> ctxl;

        CInv inv(MSG_TXLOCK, ctxl.GetHash());
        pfrom->AddInventoryKnown(inv);

        LogPrintf(" -- ProcessMessageInstantX::txlock %d  %s\n", mapTxLocks.count(inv.hash), inv.hash.ToString().c_str());

        if(!mapTxLocks.count(inv.hash)){
            if(ctxl.CountSignatures() < INSTANTX_SIGNATURES_REQUIRED){
                LogPrintf("InstantX::txlock - not enough signatures\n");
                return;
            }
            if(!ctxl.SignaturesValid()){
                LogPrintf("InstantX::txlock - got invalid TransactionLock, rejected\n");
                return;
            }
            if(!ctxl.AllInFavor()){
                LogPrintf("InstantX::txlock - not all in favor of lock, rejected\n");
                return;
            }

            BOOST_FOREACH(const CTxOut o, ctxl.tx.vout){
                if(!o.scriptPubKey.IsNormalPaymentScript()){
                    LogPrintf ("ProcessMessageInstantX::cxlock - Invalid Script %s\n", txCollateral.ToString().c_str());
                    return false;
                }
            }
            mapTxLocks.insert(make_pair(inv.hash, ctxl));

            //we should have the lock request in place
            if(!mapTxLockReq.count(inv.hash)){
                //if we don't
                bool fMissingInputs = false;
                CValidationState state;
                if (ctxl.tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
                {
                    mapTxLockReq.insert(make_pair(inv.hash, ctxl.tx));

                    LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : accepted (no reversing) %s\n",
                        pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                        ctxl.tx.GetHash().ToString().c_str()
                    );

                } else {
                    // we have a conflicting transaction (an attack)
                    CValidationState state;
                    DisconnectBlockAndInputs(state, ctxl.tx);

                    if (ctxl.tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
                    {
                        mapTxLockReq.insert(make_pair(inv.hash, ctxl.tx));

                        LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : accepted (reversed) %s\n",
                            pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                            ctxl.tx.GetHash().ToString().c_str()
                        );
                    } else {
                        LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : rejected (reversed) %s\n",
                            pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                            ctxl.tx.GetHash().ToString().c_str()
                        );
                    }
                }
            }

            //broadcast the new lock
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodes)
            {
                if(!pnode->fRelayTxes)
                    continue;

                pnode->PushMessage("txlock", ctxl);
            }

            pwalletMain->UpdatedTransaction(ctxl.GetHash());

            LogPrintf("InstantX :: Got Transaction Lock: %s %s : accepted %s\n",
                pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                ctxl.GetHash().ToString().c_str()
            );
        }
    }
}

// check if we need to vote on this transaction
void DoConsensusVote(CTransaction& tx, bool approved, int64 nBlockHeight)
{
    if(!fMasterNode) {
        LogPrintf("InstantX::DoConsensusVote - Not masternode\n");
        return;
    }

    int winner = GetCurrentMasterNode(1, nBlockHeight);
    int n = GetMasternodeRank(activeMasternode.vinMasternode, nBlockHeight, MIN_INSTANTX_PROTO_VERSION);

    if(n == -1 || winner == -1)
    {
        LogPrintf("InstantX::DoConsensusVote - Unknown Masternode\n");
        return;
    }

    if(n == 1)
    { // winner, I'll be keeping track of this
        LogPrintf("InstantX::DoConsensusVote - Managing Masternode\n");
        CTransactionLock newLock;
        newLock.nBlockHeight = nBlockHeight;
        newLock.tx = tx;
        vecTxLocks.push_back(newLock);
    }

    CConsensusVote ctx;
    ctx.vinMasternode = activeMasternode.vinMasternode;
    ctx.approved = approved;
    ctx.txHash = tx.GetHash();
    ctx.nBlockHeight = nBlockHeight;
    if(!ctx.Sign()){
        LogPrintf("InstantX::DoConsensusVote - Failed to sign consensus vote\n");
        return;
    }
    if(!ctx.SignatureValid()) {
        LogPrintf("InstantX::DoConsensusVote - Signature invalid\n");
        return;
    }

    if(n == 1){ //I'm the winner
        ProcessConsensusVote(ctx);
    } else if(n <= 10){ // not winner, but in the top10
        if(ConnectNode((CAddress)darkSendMasterNodes[winner].addr, NULL, true)){
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodes)
            {
                if(darkSendMasterNodes[winner].addr != pnode->addr) continue;

                pnode->PushMessage("txlvote", ctx);
                LogPrintf("InstantX::DoConsensusVote --- connected, sending vote %s\n", pnode->addr.ToString().c_str());
                return;
            }
        } else {
            LogPrintf("InstantX::DoConsensusVote --- error connecting \n");
            return;
        }
    }
}

//received a consensus vote
void ProcessConsensusVote(CConsensusVote& ctx)
{
    if(!fMasterNode) {
        LogPrintf("InstantX::ProcessConsensusVote - Not masternode\n");
        return;
    }

    int winner = GetCurrentMasterNode(1, ctx.nBlockHeight);
    if(winner == -1) {
        LogPrintf("InstantX::ProcessConsensusVote - Can't detect winning masternode\n");
        return;
    }

    //We're not the winning masternode
    if(darkSendMasterNodes[winner].vin != activeMasternode.vinMasternode) {
        LogPrintf("InstantX::ProcessConsensusVote - I'm not the winning masternode\n");
        return;
    }

    int n = GetMasternodeRank(ctx.vinMasternode, ctx.nBlockHeight, MIN_INSTANTX_PROTO_VERSION);

    if(n == -1)
    {
        LogPrintf("InstantX::ProcessConsensusVote - Unknown Masternode\n");
        return;
    }

    if(n > 10)
    {
        LogPrintf("InstantX::ProcessConsensusVote - Masternode not in the top 10\n");
        return;
    }

    if(!ctx.SignatureValid()) {
        LogPrintf("InstantX::ProcessConsensusVote - Signature invalid\n");
        //don't ban, it could just be a non-synced masternode
        return;
    }

    //compile consessus vote
    BOOST_FOREACH(CTransactionLock& ctxl, vecTxLocks){
        if(ctxl.nBlockHeight == ctx.nBlockHeight){
            ctxl.AddSignature(ctx);
            if(ctxl.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){
                LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Is Complete, broadcasting!\n");

                CInv inv(MSG_TXLOCK, ctxl.GetHash());
                mapTxLocks.insert(make_pair(inv.hash, ctxl));

                //broadcast the new lock
                LOCK(cs_vNodes);
                BOOST_FOREACH(CNode* pnode, vNodes){
                    pnode->PushMessage("txlock", ctxl);
                }
            }
            return;
        }
    }

    return;
}

void CleanTransactionLocksList()
{
    if(pindexBest == NULL) return;

    std::map<uint256, CTransactionLock>::iterator it = mapTxLocks.begin();

    while(it != mapTxLocks.end()) {
        if(pindexBest->nHeight - it->second.nBlockHeight > 3){ //keep them for an hour
            LogPrintf("Removing old transaction lock %s\n", it->second.GetHash().ToString().c_str());
            mapTxLocks.erase(it++);
        } else {
            it++;
        }
    }

}

bool CConsensusVote::SignatureValid()
{
    std::string errorMessage;
    std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight) + boost::lexical_cast<std::string>(approved);
    LogPrintf("verify strMessage %s \n", strMessage.c_str());

    int n = GetMasternodeByVin(vinMasternode);

    if(n == -1)
    {
        LogPrintf("InstantX::CConsensusVote::SignatureValid() - Unknown Masternode\n");
        return false;
    }

    LogPrintf("verify addr %s \n", darkSendMasterNodes[0].addr.ToString().c_str());
    LogPrintf("verify addr %s \n", darkSendMasterNodes[1].addr.ToString().c_str());
    LogPrintf("verify addr %d %s \n", n, darkSendMasterNodes[n].addr.ToString().c_str());

    CScript pubkey;
    pubkey.SetDestination(darkSendMasterNodes[n].pubkey2.GetID());
    CTxDestination address1;
    ExtractDestination(pubkey, address1);
    CBitcoinAddress address2(address1);
    LogPrintf("verify pubkey2 %s \n", address2.ToString().c_str());

    if(!darkSendSigner.VerifyMessage(darkSendMasterNodes[n].pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
        LogPrintf("InstantX::CConsensusVote::SignatureValid() - Verify message failed\n");
        return false;
    }

    return true;
}

bool CConsensusVote::Sign()
{
    std::string errorMessage;

    CKey key2;
    CPubKey pubkey2;
    std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight) + boost::lexical_cast<std::string>(approved);
    LogPrintf("signing strMessage %s \n", strMessage.c_str());
    LogPrintf("signing privkey %s \n", strMasterNodePrivKey.c_str());

    if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2))
    {
        LogPrintf("Invalid masternodeprivkey: '%s'\n", errorMessage.c_str());
        exit(0);
    }

    CScript pubkey;
    pubkey.SetDestination(pubkey2.GetID());
    CTxDestination address1;
    ExtractDestination(pubkey, address1);
    CBitcoinAddress address2(address1);
    LogPrintf("signing pubkey2 %s \n", address2.ToString().c_str());

    if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, key2)) {
        LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed");
        return false;
    }

    if(!darkSendSigner.VerifyMessage(pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
        LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Verify message failed");
        return false;
    }

    return true;
}

bool CTransactionLock::SignaturesValid()
{

    BOOST_FOREACH(CConsensusVote vote, vecConsensusVotes)
    {
        int n = GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTX_PROTO_VERSION);

        if(n == -1)
        {
            LogPrintf("InstantX::DoConsensusVote - Unknown Masternode\n");
            return false;
        }

        if(n > 10)
        {
            LogPrintf("InstantX::DoConsensusVote - Masternode not in the top 10\n");
            return false;
        }

        if(!vote.SignatureValid()){
            LogPrintf("InstantX::CTransactionLock::SignaturesValid - Signature not valid\n");
            return false;
        }
    }

    return true;
}

bool CTransactionLock::AllInFavor()
{
    BOOST_FOREACH(CConsensusVote vote, vecConsensusVotes)
        if(vote.approved == false) return false;

    return true;
}

void CTransactionLock::AddSignature(CConsensusVote cv)
{
    vecConsensusVotes.push_back(cv);
}

int CTransactionLock::CountSignatures()
{
    return vecConsensusVotes.size();
}<commit_msg>fixed remote enabled masternode<commit_after>

#include "bignum.h"
#include "sync.h"
#include "net.h"
#include "key.h"
#include "util.h"
#include "script.h"
#include "hashblock.h"
#include "base58.h"
#include "instantx.h"
#include "masternode.h"
#include "activemasternode.h"
#include "darksend.h"

using namespace std;
using namespace boost;

std::vector<CTransactionLock> vecTxLocks;

std::map<uint256, CTransaction> mapTxLockReq;
std::map<uint256, CTransaction> mapTxLockReqRejected;
std::map<uint256, CTransactionLock> mapTxLocks;

#define INSTANTX_SIGNATURES_REQUIRED           2

//txlock - Locks transaction
//
//step 1.) Broadcast intention to lock transaction inputs, "txlreg", CTransaction
//step 2.) Top 10 masternodes, open connect to top 1 masternode. Send "txvote", CTransaction, Signature, Approve
//step 3.) Top 1 masternode, waits for 10 messages. Upon success, sends "txlock'

void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
{
    return;

    if (strCommand == "txlreq")
    {
        //LogPrintf("ProcessMessageInstantX::txlreq\n");
        CDataStream vMsg(vRecv);
        CTransaction tx;
        vRecv >> tx;

        CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash());
        pfrom->AddInventoryKnown(inv);

        if(mapTxLockReq.count(inv.hash) || mapTxLockReqRejected.count(inv.hash)){
            return;
        }

        int nTxAge = GetInputAge(tx.vin[0]);
        if(nTxAge < 5){
            LogPrintf("ProcessMessageInstantX::txlreq - Transaction not found / too new: %s\n", tx.GetHash().ToString().c_str());
            return;
        }
        int nBlockHeight = pindexBest->nHeight - nTxAge; //calculate the height

        BOOST_FOREACH(const CTxOut o, tx.vout){
            if(!o.scriptPubKey.IsNormalPaymentScript()){
                LogPrintf ("ProcessMessageInstantX::txlreq - Invalid Script %s\n", tx.ToString().c_str());
                return;
            }
        }

        bool fMissingInputs = false;
        CValidationState state;
        if (tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
        {
            RelayTransactionLockReq(tx, inv.hash);
            DoConsensusVote(tx, true, nBlockHeight);

            mapTxLockReq.insert(make_pair(inv.hash, tx));

            LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : accepted %s\n",
                pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                tx.GetHash().ToString().c_str()
            );

            return;

        } else {
            mapTxLockReqRejected.insert(make_pair(inv.hash, tx));

            // can we get the conflicting transaction as proof?

            RelayTransactionLockReq(tx, inv.hash);
            DoConsensusVote(tx, false, nBlockHeight);

            LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : rejected %s\n",
                pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                tx.GetHash().ToString().c_str()
            );

            //record prevout, increment the amount of times seen. Ban if over 100

            return;
        }
    }
    else if (strCommand == "txlvote") //InstantX Lock Consensus Votes
    {
        CConsensusVote ctx;
        vRecv >> ctx;

        ProcessConsensusVote(ctx);

        return;
    }
    else if (strCommand == "txlock") //InstantX Lock Transaction Inputs
    {
        LogPrintf("ProcessMessageInstantX::txlock\n");

        CDataStream vMsg(vRecv);
        CTransactionLock ctxl;
        vRecv >> ctxl;

        CInv inv(MSG_TXLOCK, ctxl.GetHash());
        pfrom->AddInventoryKnown(inv);

        LogPrintf(" -- ProcessMessageInstantX::txlock %d  %s\n", mapTxLocks.count(inv.hash), inv.hash.ToString().c_str());

        if(!mapTxLocks.count(inv.hash)){
            if(ctxl.CountSignatures() < INSTANTX_SIGNATURES_REQUIRED){
                LogPrintf("InstantX::txlock - not enough signatures\n");
                return;
            }
            if(!ctxl.SignaturesValid()){
                LogPrintf("InstantX::txlock - got invalid TransactionLock, rejected\n");
                return;
            }
            if(!ctxl.AllInFavor()){
                LogPrintf("InstantX::txlock - not all in favor of lock, rejected\n");
                return;
            }

            BOOST_FOREACH(const CTxOut o, ctxl.tx.vout){
                if(!o.scriptPubKey.IsNormalPaymentScript()){
                    LogPrintf ("ProcessMessageInstantX::cxlock - Invalid Script %s\n", ctxl.tx.ToString().c_str());
                    return;
                }
            }
            mapTxLocks.insert(make_pair(inv.hash, ctxl));

            //we should have the lock request in place
            if(!mapTxLockReq.count(inv.hash)){
                //if we don't
                bool fMissingInputs = false;
                CValidationState state;
                if (ctxl.tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
                {
                    mapTxLockReq.insert(make_pair(inv.hash, ctxl.tx));

                    LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : accepted (no reversing) %s\n",
                        pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                        ctxl.tx.GetHash().ToString().c_str()
                    );

                } else {
                    // we have a conflicting transaction (an attack)
                    CValidationState state;
                    DisconnectBlockAndInputs(state, ctxl.tx);

                    if (ctxl.tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
                    {
                        mapTxLockReq.insert(make_pair(inv.hash, ctxl.tx));

                        LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : accepted (reversed) %s\n",
                            pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                            ctxl.tx.GetHash().ToString().c_str()
                        );
                    } else {
                        LogPrintf("ProcessMessageInstantX::txlock - Transaction Lock Request: %s %s : rejected (reversed) %s\n",
                            pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                            ctxl.tx.GetHash().ToString().c_str()
                        );
                    }
                }
            }

            //broadcast the new lock
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodes)
            {
                if(!pnode->fRelayTxes)
                    continue;

                pnode->PushMessage("txlock", ctxl);
            }

            pwalletMain->UpdatedTransaction(ctxl.GetHash());

            LogPrintf("InstantX :: Got Transaction Lock: %s %s : accepted %s\n",
                pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
                ctxl.GetHash().ToString().c_str()
            );
        }
    }
}

// check if we need to vote on this transaction
void DoConsensusVote(CTransaction& tx, bool approved, int64 nBlockHeight)
{
    if(!fMasterNode) {
        LogPrintf("InstantX::DoConsensusVote - Not masternode\n");
        return;
    }

    int winner = GetCurrentMasterNode(1, nBlockHeight);
    int n = GetMasternodeRank(activeMasternode.vinMasternode, nBlockHeight, MIN_INSTANTX_PROTO_VERSION);

    if(n == -1 || winner == -1)
    {
        LogPrintf("InstantX::DoConsensusVote - Unknown Masternode\n");
        return;
    }

    if(n == 1)
    { // winner, I'll be keeping track of this
        LogPrintf("InstantX::DoConsensusVote - Managing Masternode\n");
        CTransactionLock newLock;
        newLock.nBlockHeight = nBlockHeight;
        newLock.tx = tx;
        vecTxLocks.push_back(newLock);
    }

    CConsensusVote ctx;
    ctx.vinMasternode = activeMasternode.vinMasternode;
    ctx.approved = approved;
    ctx.txHash = tx.GetHash();
    ctx.nBlockHeight = nBlockHeight;
    if(!ctx.Sign()){
        LogPrintf("InstantX::DoConsensusVote - Failed to sign consensus vote\n");
        return;
    }
    if(!ctx.SignatureValid()) {
        LogPrintf("InstantX::DoConsensusVote - Signature invalid\n");
        return;
    }

    if(n == 1){ //I'm the winner
        ProcessConsensusVote(ctx);
    } else if(n <= 10){ // not winner, but in the top10
        if(ConnectNode((CAddress)darkSendMasterNodes[winner].addr, NULL, true)){
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodes)
            {
                if(darkSendMasterNodes[winner].addr != pnode->addr) continue;

                pnode->PushMessage("txlvote", ctx);
                LogPrintf("InstantX::DoConsensusVote --- connected, sending vote %s\n", pnode->addr.ToString().c_str());
                return;
            }
        } else {
            LogPrintf("InstantX::DoConsensusVote --- error connecting \n");
            return;
        }
    }
}

//received a consensus vote
void ProcessConsensusVote(CConsensusVote& ctx)
{
    if(!fMasterNode) {
        LogPrintf("InstantX::ProcessConsensusVote - Not masternode\n");
        return;
    }

    int winner = GetCurrentMasterNode(1, ctx.nBlockHeight);
    if(winner == -1) {
        LogPrintf("InstantX::ProcessConsensusVote - Can't detect winning masternode\n");
        return;
    }

    //We're not the winning masternode
    if(darkSendMasterNodes[winner].vin != activeMasternode.vinMasternode) {
        LogPrintf("InstantX::ProcessConsensusVote - I'm not the winning masternode\n");
        return;
    }

    int n = GetMasternodeRank(ctx.vinMasternode, ctx.nBlockHeight, MIN_INSTANTX_PROTO_VERSION);

    if(n == -1)
    {
        LogPrintf("InstantX::ProcessConsensusVote - Unknown Masternode\n");
        return;
    }

    if(n > 10)
    {
        LogPrintf("InstantX::ProcessConsensusVote - Masternode not in the top 10\n");
        return;
    }

    if(!ctx.SignatureValid()) {
        LogPrintf("InstantX::ProcessConsensusVote - Signature invalid\n");
        //don't ban, it could just be a non-synced masternode
        return;
    }

    //compile consessus vote
    BOOST_FOREACH(CTransactionLock& ctxl, vecTxLocks){
        if(ctxl.nBlockHeight == ctx.nBlockHeight){
            ctxl.AddSignature(ctx);
            if(ctxl.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){
                LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Is Complete, broadcasting!\n");

                CInv inv(MSG_TXLOCK, ctxl.GetHash());
                mapTxLocks.insert(make_pair(inv.hash, ctxl));

                //broadcast the new lock
                LOCK(cs_vNodes);
                BOOST_FOREACH(CNode* pnode, vNodes){
                    pnode->PushMessage("txlock", ctxl);
                }
            }
            return;
        }
    }

    return;
}

void CleanTransactionLocksList()
{
    if(pindexBest == NULL) return;

    std::map<uint256, CTransactionLock>::iterator it = mapTxLocks.begin();

    while(it != mapTxLocks.end()) {
        if(pindexBest->nHeight - it->second.nBlockHeight > 3){ //keep them for an hour
            LogPrintf("Removing old transaction lock %s\n", it->second.GetHash().ToString().c_str());
            mapTxLocks.erase(it++);
        } else {
            it++;
        }
    }

}

bool CConsensusVote::SignatureValid()
{
    std::string errorMessage;
    std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight) + boost::lexical_cast<std::string>(approved);
    LogPrintf("verify strMessage %s \n", strMessage.c_str());

    int n = GetMasternodeByVin(vinMasternode);

    if(n == -1)
    {
        LogPrintf("InstantX::CConsensusVote::SignatureValid() - Unknown Masternode\n");
        return false;
    }

    LogPrintf("verify addr %s \n", darkSendMasterNodes[0].addr.ToString().c_str());
    LogPrintf("verify addr %s \n", darkSendMasterNodes[1].addr.ToString().c_str());
    LogPrintf("verify addr %d %s \n", n, darkSendMasterNodes[n].addr.ToString().c_str());

    CScript pubkey;
    pubkey.SetDestination(darkSendMasterNodes[n].pubkey2.GetID());
    CTxDestination address1;
    ExtractDestination(pubkey, address1);
    CBitcoinAddress address2(address1);
    LogPrintf("verify pubkey2 %s \n", address2.ToString().c_str());

    if(!darkSendSigner.VerifyMessage(darkSendMasterNodes[n].pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
        LogPrintf("InstantX::CConsensusVote::SignatureValid() - Verify message failed\n");
        return false;
    }

    return true;
}

bool CConsensusVote::Sign()
{
    std::string errorMessage;

    CKey key2;
    CPubKey pubkey2;
    std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight) + boost::lexical_cast<std::string>(approved);
    LogPrintf("signing strMessage %s \n", strMessage.c_str());
    LogPrintf("signing privkey %s \n", strMasterNodePrivKey.c_str());

    if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2))
    {
        LogPrintf("Invalid masternodeprivkey: '%s'\n", errorMessage.c_str());
        exit(0);
    }

    CScript pubkey;
    pubkey.SetDestination(pubkey2.GetID());
    CTxDestination address1;
    ExtractDestination(pubkey, address1);
    CBitcoinAddress address2(address1);
    LogPrintf("signing pubkey2 %s \n", address2.ToString().c_str());

    if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, key2)) {
        LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed");
        return false;
    }

    if(!darkSendSigner.VerifyMessage(pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
        LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Verify message failed");
        return false;
    }

    return true;
}

bool CTransactionLock::SignaturesValid()
{

    BOOST_FOREACH(CConsensusVote vote, vecConsensusVotes)
    {
        int n = GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTX_PROTO_VERSION);

        if(n == -1)
        {
            LogPrintf("InstantX::DoConsensusVote - Unknown Masternode\n");
            return false;
        }

        if(n > 10)
        {
            LogPrintf("InstantX::DoConsensusVote - Masternode not in the top 10\n");
            return false;
        }

        if(!vote.SignatureValid()){
            LogPrintf("InstantX::CTransactionLock::SignaturesValid - Signature not valid\n");
            return false;
        }
    }

    return true;
}

bool CTransactionLock::AllInFavor()
{
    BOOST_FOREACH(CConsensusVote vote, vecConsensusVotes)
        if(vote.approved == false) return false;

    return true;
}

void CTransactionLock::AddSignature(CConsensusVote cv)
{
    vecConsensusVotes.push_back(cv);
}

int CTransactionLock::CountSignatures()
{
    return vecConsensusVotes.size();
}<|endoftext|>


<commit_before>// Copyright (c) 2016, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int, char**) {
  write(STDOUT_FILENO, "hello, world\n", strlen("hello, world\n"));
  return 0;
}
<commit_msg>Save and restore screen<commit_after>// Copyright (c) 2016, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define ESC "\x1B"

namespace term {

template <size_t n>
void Put(const char (&message)[n]) {
  write(STDOUT_FILENO, message, n);
}

void SaveScreen() {
  Put(ESC "[?47h");
}

void RestoreScreen() {
  Put(ESC "[?47l");
}

void ClearScreen() {
  Put(ESC "[2J");
}

}  // namespace

void Run() {
  for (;;) {
    int c = getchar();
    if (c == 'q')
      return;
  }
}

int main(int, char**) {
  term::SaveScreen();
  term::ClearScreen();
  term::Put("hello, world\n");
  Run();
  term::RestoreScreen();
  return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include <memory>
#include <climits>
#include <systemd/sd-bus.h>
#include <sdbusplus/message.hpp>

namespace sdbusplus
{
namespace bus
{

using busp_t = sd_bus*;
class bus;

/** @brief Get an instance of the 'default' bus. */
bus new_default();
/** @brief Get an instance of the 'user' session bus. */
bus new_user();
/** @brief Get an instance of the 'system' bus. */
bus new_system();

namespace details
{

/** @brief unique_ptr functor to release a bus reference. */
struct BusDeleter
{
    void operator()(sd_bus* ptr) const
    {
        sd_bus_flush_close_unref(ptr);
    }
};

/* @brief Alias 'bus' to a unique_ptr type for auto-release. */
using bus = std::unique_ptr<sd_bus, BusDeleter>;

} // namespace details

/** @class bus
 *  @brief Provides C++ bindings to the sd_bus_* class functions.
 */
struct bus
{
        /* Define all of the basic class operations:
         *     Not allowed:
         *         - Default constructor to avoid nullptrs.
         *         - Copy operations due to internal unique_ptr.
         *     Allowed:
         *         - Move operations.
         *         - Destructor.
         */
    bus() = delete;
    bus(const bus&) = delete;
    bus& operator=(const bus&) = delete;
    bus(bus&&) = default;
    bus& operator=(bus&&) = default;
    ~bus() = default;

    /** @brief Conversion constructor from 'busp_t'.
     *
     *  Takes ownership of the bus-pointer and releases it when done.
     */
    explicit bus(busp_t b) : _bus(b) {}

    /** @brief Release ownership of the stored bus-pointer. */
    busp_t release() { return _bus.release(); }

    /** @brief Wait for new dbus messages or signals.
     *
     *  @param[in] timeout_us - Timeout in usec.
     */
    void wait(uint64_t timeout_us = ULLONG_MAX)
    {
        sd_bus_wait(_bus.get(), timeout_us);
    }

    /** @brief Process waiting dbus messages or signals. */
    auto process()
    {
        sd_bus_message* m = nullptr;
        sd_bus_process(_bus.get(), &m);

        return message::message(m);
    }

    /** @brief Claim a service name on the dbus.
     *
     *  @param[in] service - The service name to claim.
     */
    void request_name(const char* service)
    {
        sd_bus_request_name(_bus.get(), service, 0);
    }

    /** @brief Create a method_call message.
     *
     *  @param[in] service - The service to call.
     *  @param[in] objpath - The object's path for the call.
     *  @param[in] interf - The object's interface to call.
     *  @param[in] method - The object's method to call.
     *
     *  @return A newly constructed message.
     */
    auto new_method_call(const char* service, const char* objpath,
                         const char* interf, const char* method)
    {
        sd_bus_message* m = nullptr;
        sd_bus_message_new_method_call(_bus.get(), &m, service, objpath,
                                       interf, method);

        return message::message(m);
    }

    /** @brief Perform a message call.
     *
     *  @param[in] m - The method_call message.
     *  @param[in] timeout_us - The timeout for the method call.
     *
     *  @return The response message.
     */
    auto call(message::message& m, uint64_t timeout_us = 0)
    {
        sd_bus_message* reply = nullptr;
        sd_bus_call(_bus.get(), m.get(), timeout_us, nullptr, &reply);

        return reply;
    }

    /** @brief Perform a message call, ignoring the reply.
     *
     *  @param[in] m - The method_call message.
     *  @param[in] timeout_us - The timeout for the method call.
     */
    void call_noreply(message::message& m, uint64_t timeout_us = 0)
    {
        sd_bus_call(_bus.get(), m.get(), timeout_us, nullptr, nullptr);
    }

    private:
        details::bus _bus;
};

inline bus new_default()
{
    sd_bus* b = nullptr;
    sd_bus_open(&b);
    return bus(b);
}

inline bus new_user()
{
    sd_bus* b = nullptr;
    sd_bus_open_user(&b);
    return bus(b);
}

inline bus new_system()
{
    sd_bus* b = nullptr;
    sd_bus_open_system(&b);
    return bus(b);
}

} // namespace bus

} // namespace sdbusplus
<commit_msg>bus: 'method_return' for responding to method-calls<commit_after>#pragma once

#include <memory>
#include <climits>
#include <systemd/sd-bus.h>
#include <sdbusplus/message.hpp>

namespace sdbusplus
{
namespace bus
{

using busp_t = sd_bus*;
class bus;

/** @brief Get an instance of the 'default' bus. */
bus new_default();
/** @brief Get an instance of the 'user' session bus. */
bus new_user();
/** @brief Get an instance of the 'system' bus. */
bus new_system();

namespace details
{

/** @brief unique_ptr functor to release a bus reference. */
struct BusDeleter
{
    void operator()(sd_bus* ptr) const
    {
        sd_bus_flush_close_unref(ptr);
    }
};

/* @brief Alias 'bus' to a unique_ptr type for auto-release. */
using bus = std::unique_ptr<sd_bus, BusDeleter>;

} // namespace details

/** @class bus
 *  @brief Provides C++ bindings to the sd_bus_* class functions.
 */
struct bus
{
        /* Define all of the basic class operations:
         *     Not allowed:
         *         - Default constructor to avoid nullptrs.
         *         - Copy operations due to internal unique_ptr.
         *     Allowed:
         *         - Move operations.
         *         - Destructor.
         */
    bus() = delete;
    bus(const bus&) = delete;
    bus& operator=(const bus&) = delete;
    bus(bus&&) = default;
    bus& operator=(bus&&) = default;
    ~bus() = default;

    /** @brief Conversion constructor from 'busp_t'.
     *
     *  Takes ownership of the bus-pointer and releases it when done.
     */
    explicit bus(busp_t b) : _bus(b) {}

    /** @brief Release ownership of the stored bus-pointer. */
    busp_t release() { return _bus.release(); }

    /** @brief Wait for new dbus messages or signals.
     *
     *  @param[in] timeout_us - Timeout in usec.
     */
    void wait(uint64_t timeout_us = ULLONG_MAX)
    {
        sd_bus_wait(_bus.get(), timeout_us);
    }

    /** @brief Process waiting dbus messages or signals. */
    auto process()
    {
        sd_bus_message* m = nullptr;
        sd_bus_process(_bus.get(), &m);

        return message::message(m);
    }

    /** @brief Claim a service name on the dbus.
     *
     *  @param[in] service - The service name to claim.
     */
    void request_name(const char* service)
    {
        sd_bus_request_name(_bus.get(), service, 0);
    }

    /** @brief Create a method_call message.
     *
     *  @param[in] service - The service to call.
     *  @param[in] objpath - The object's path for the call.
     *  @param[in] interf - The object's interface to call.
     *  @param[in] method - The object's method to call.
     *
     *  @return A newly constructed message.
     */
    auto new_method_call(const char* service, const char* objpath,
                         const char* interf, const char* method)
    {
        sd_bus_message* m = nullptr;
        sd_bus_message_new_method_call(_bus.get(), &m, service, objpath,
                                       interf, method);

        return message::message(m);
    }

    /** @brief Perform a message call.
     *
     *  @param[in] m - The method_call message.
     *  @param[in] timeout_us - The timeout for the method call.
     *
     *  @return The response message.
     */
    auto call(message::message& m, uint64_t timeout_us = 0)
    {
        sd_bus_message* reply = nullptr;
        sd_bus_call(_bus.get(), m.get(), timeout_us, nullptr, &reply);

        return reply;
    }

    /** @brief Perform a message call, ignoring the reply.
     *
     *  @param[in] m - The method_call message.
     *  @param[in] timeout_us - The timeout for the method call.
     */
    void call_noreply(message::message& m, uint64_t timeout_us = 0)
    {
        sd_bus_call(_bus.get(), m.get(), timeout_us, nullptr, nullptr);
    }

    /** @brief Perform a 'method-return' response call.
     *
     *  @param[in] m - The method-return type message to send.
     *
     *  This is a static method on bus because:
     *      1. The typical caller of this is from within a method callback
     *         on an sd-bus managed object, which does not have access to
     *         its own bus.
     *      2. Due to header dependency, sdbusplus::message cannot create
     *         an sdbusplus::bus itself.
     *      3. We do not want sdbusplus::message to call sd_bus_call directly,
     *         in order to have common error handling code with bus::call.
     */
    static void method_return(message::message& m)
    {
        auto b = bus(sd_bus_message_get_bus(m.get()));

        // Need to increment the reference since 'b' will now decrement
        // on destruction.
        sd_bus_ref(b._bus.get());

        b.call_noreply(m);
    }

    private:
        details::bus _bus;
};

inline bus new_default()
{
    sd_bus* b = nullptr;
    sd_bus_open(&b);
    return bus(b);
}

inline bus new_user()
{
    sd_bus* b = nullptr;
    sd_bus_open_user(&b);
    return bus(b);
}

inline bus new_system()
{
    sd_bus* b = nullptr;
    sd_bus_open_system(&b);
    return bus(b);
}

/** Alias sdbusplus::bus::bus::method_return for convenience. */
inline void method_return(message::message& m) { return bus::method_return(m); }

} // namespace bus

} // namespace sdbusplus
<|endoftext|>