<commit_before>/*
 * RemoteSyslogAppender.cpp
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Walter Stroebel. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "log4cpp/Portability.hh"

#ifdef LOG4CPP_HAVE_UNISTD_H
#    include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "log4cpp/RemoteSyslogAppender.hh"
#ifdef WIN32
#include <winsock2.h>
#else
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

namespace log4cpp {

    int RemoteSyslogAppender::toSyslogPriority(Priority::Value priority) {
        static int priorities[8] = { LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
                                     LOG_WARNING, LOG_NOTICE, LOG_INFO,
                                     LOG_DEBUG };
        int result;

        priority++;
        priority /= 100;

        if (priority < 0) {
            result = LOG_EMERG;
        } else if (priority > 7) {
            result = LOG_DEBUG;
        } else {
            result = priorities[priority];
        }

        return result;
    }

    RemoteSyslogAppender::RemoteSyslogAppender(const std::string& name,
                                   const std::string& syslogName,
				   const std::string& relayer,
                                   int facility,
				   int portNumber) :
        AppenderSkeleton(name),
        _syslogName(syslogName),
	_relayer(relayer),
        _facility(facility),
	_portNumber (portNumber),
	_socket (0),
	_ipAddr (0),
	_cludge (0)
    {
        open();
    }

    RemoteSyslogAppender::~RemoteSyslogAppender() {
        close();
#ifdef WIN32
	if (_cludge) {
	    // we started it, we end it.
	    WSACleanup ();
	}
#endif
    }

    void RemoteSyslogAppender::open() {
	if (!_ipAddr) {
	    struct hostent *pent = gethostbyname (_relayer.c_str ());
	    if (pent == NULL) {
#ifdef WIN32
		if (WSAGetLastError () == WSANOTINITIALISED) {
		    WSADATA wsaData;
		    int err;

		    err = WSAStartup (0x101, &wsaData );
		    if (err) abort ();
		    pent = gethostbyname (_relayer.c_str ());
		    _cludge = 1;
		} else {
		    abort ();
		}
#endif
	    }
	    if (pent == NULL) {
		unsigned long ip = (unsigned long) inet_addr (_relayer.c_str ());
		pent = gethostbyaddr ((const char *) &ip, 4, AF_INET);
	    }
	    if (pent == NULL) {
		abort ();
	    }
	    _ipAddr = *((unsigned long *) pent->h_addr);
	}
	// Get a datagram socket.

	if ((_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	    abort ();
	} else {
	    sockaddr_in sain;
	    sain.sin_family = AF_INET;
	    sain.sin_port   = htons (_portNumber);
	    sain.sin_addr.s_addr = htonl (_ipAddr);
	    if (connect (_socket, (struct sockaddr *) &sain, sizeof (sain)) < 0) {
		abort ();
	    }
	}
    }

    void RemoteSyslogAppender::close() {
	if (_socket) {
#if WIN32
	    closesocket (_socket);
#else
	    close (_socket);
#endif
	    _socket = 0;
	}
    }

    void RemoteSyslogAppender::_append(const LoggingEvent& event) {
        if (!_layout) {
            // XXX help! help!
            return;
        }

	std::string msgStr = _layout->format(event);
        const char* message = msgStr.c_str();
	int len = strlen (message) + 16;
	char *buf = new char [len];
        int priority = toSyslogPriority(event.priority);
	sprintf (buf, "<%d>", priority);
	memcpy (buf + strlen (buf), message, len - 16);
	sockaddr_in sain;
	sain.sin_family = AF_INET;
	sain.sin_port   = htons (_portNumber);
        sain.sin_addr.s_addr = htonl (_ipAddr);
	int r = sendto (_socket, buf, (int) len, 0, (struct sockaddr *) &sain, sizeof (sain));
	printf ("sendto: %d\n", r);
	delete buf;
    }

    bool RemoteSyslogAppender::reopen() {
        close();
        open();
        return true;
    }

    bool RemoteSyslogAppender::requiresLayout() const {
        return true;
    }

    void RemoteSyslogAppender::setLayout(Layout* layout) {
        _layout = layout;
    }

}
<commit_msg>Debugging<commit_after>/*
 * RemoteSyslogAppender.cpp
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Walter Stroebel. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "log4cpp/Portability.hh"

#ifdef LOG4CPP_HAVE_UNISTD_H
#    include <unistd.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "log4cpp/RemoteSyslogAppender.hh"
#ifdef WIN32
#include <winsock2.h>
#else
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

namespace log4cpp {

    int RemoteSyslogAppender::toSyslogPriority(Priority::Value priority) {
        static int priorities[8] = { LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
                                     LOG_WARNING, LOG_NOTICE, LOG_INFO,
                                     LOG_DEBUG };
        int result;

        priority++;
        priority /= 100;

        if (priority < 0) {
            result = LOG_EMERG;
        } else if (priority > 7) {
            result = LOG_DEBUG;
        } else {
            result = priorities[priority];
        }

        return result;
    }

    RemoteSyslogAppender::RemoteSyslogAppender(const std::string& name,
                                   const std::string& syslogName,
				   const std::string& relayer,
                                   int facility,
				   int portNumber) :
        AppenderSkeleton(name),
        _syslogName(syslogName),
	_relayer(relayer),
        _facility(facility),
	_portNumber (portNumber),
	_socket (0),
	_ipAddr (0),
	_cludge (0)
    {
        open();
    }

    RemoteSyslogAppender::~RemoteSyslogAppender() {
        close();
#ifdef WIN32
	if (_cludge) {
	    // we started it, we end it.
	    WSACleanup ();
	}
#endif
    }

    void RemoteSyslogAppender::open() {
	if (!_ipAddr) {
	    struct hostent *pent = gethostbyname (_relayer.c_str ());
	    if (pent == NULL) {
#ifdef WIN32
		if (WSAGetLastError () == WSANOTINITIALISED) {
		    WSADATA wsaData;
		    int err;

		    err = WSAStartup (0x101, &wsaData );
		    if (err) abort ();
		    pent = gethostbyname (_relayer.c_str ());
		    _cludge = 1;
		} else {
		    abort ();
		}
#endif
	    }
	    if (pent == NULL) {
		unsigned long ip = (unsigned long) inet_addr (_relayer.c_str ());
		pent = gethostbyaddr ((const char *) &ip, 4, AF_INET);
	    }
	    if (pent == NULL) {
		abort ();
	    }
	    _ipAddr = *((unsigned long *) pent->h_addr);
	}
	// Get a datagram socket.

	if ((_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	    abort ();
	} else {
	    sockaddr_in sain;
	    sain.sin_family = AF_INET;
	    sain.sin_port   = htons (_portNumber);
	    sain.sin_addr.s_addr = htonl (_ipAddr);
	    if (connect (_socket, (struct sockaddr *) &sain, sizeof (sain)) < 0) {
		abort ();
	    }
	}
    }

    void RemoteSyslogAppender::close() {
	if (_socket) {
#if WIN32
	    closesocket (_socket);
#else
	    ::close (_socket);
#endif
	    _socket = 0;
	}
    }

    void RemoteSyslogAppender::_append(const LoggingEvent& event) {
        if (!_layout) {
            // XXX help! help!
            return;
        }

	std::string msgStr = _layout->format(event);
        const char* message = msgStr.c_str();
	int len = strlen (message) + 16;
	char *buf = new char [len];
        int priority = toSyslogPriority(event.priority);
	sprintf (buf, "<%d>", priority);
	memcpy (buf + strlen (buf), message, len - 16);
	sockaddr_in sain;
	sain.sin_family = AF_INET;
	sain.sin_port   = htons (_portNumber);
        sain.sin_addr.s_addr = htonl (_ipAddr);
	int r = sendto (_socket, buf, (int) len, 0, (struct sockaddr *) &sain, sizeof (sain));
	printf ("sendto: %d\n", r);
	delete buf;
    }

    bool RemoteSyslogAppender::reopen() {
        close();
        open();
        return true;
    }

    bool RemoteSyslogAppender::requiresLayout() const {
        return true;
    }

    void RemoteSyslogAppender::setLayout(Layout* layout) {
        _layout = layout;
    }

}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include <wangle/acceptor/Acceptor.h>

#include <wangle/acceptor/ManagedConnection.h>
#include <wangle/ssl/SSLContextManager.h>
#include <wangle/acceptor/AcceptorHandshakeManager.h>
#include <wangle/acceptor/SecurityProtocolContextManager.h>
#include <fcntl.h>
#include <folly/ScopeGuard.h>
#include <folly/io/async/EventBase.h>
#include <fstream>
#include <sys/types.h>
#include <folly/io/async/AsyncSSLSocket.h>
#include <folly/io/async/AsyncSocket.h>
#include <folly/portability/Sockets.h>
#include <folly/portability/Unistd.h>
#include <gflags/gflags.h>

using folly::AsyncSocket;
using folly::AsyncSSLSocket;
using folly::AsyncSocketException;
using folly::AsyncServerSocket;
using folly::AsyncTransportWrapper;
using folly::EventBase;
using folly::SocketAddress;
using std::chrono::microseconds;
using std::chrono::milliseconds;
using std::filebuf;
using std::ifstream;
using std::ios;
using std::shared_ptr;
using std::string;

namespace wangle {

static const std::string empty_string;
std::atomic<uint64_t> Acceptor::totalNumPendingSSLConns_{0};

Acceptor::Acceptor(const ServerSocketConfig& accConfig) :
  accConfig_(accConfig),
  socketOptions_(accConfig.getSocketOptions()) {
}

void
Acceptor::init(AsyncServerSocket* serverSocket,
               EventBase* eventBase,
               SSLStats* stats) {
  CHECK(nullptr == this->base_ || eventBase == this->base_);

  if (accConfig_.isSSL()) {
    if (accConfig_.allowInsecureConnectionsOnSecureServer) {
      securityProtocolCtxManager_.addPeeker(&tlsPlaintextPeekingCallback_);
    }
    securityProtocolCtxManager_.addPeeker(&defaultPeekingCallback_);

    if (!sslCtxManager_) {
      sslCtxManager_ = folly::make_unique<SSLContextManager>(
        eventBase,
        "vip_" + getName(),
        accConfig_.strictSSL, stats);
    }
    try {
      for (const auto& sslCtxConfig : accConfig_.sslContextConfigs) {
        sslCtxManager_->addSSLContextConfig(
          sslCtxConfig,
          accConfig_.sslCacheOptions,
          &accConfig_.initialTicketSeeds,
          accConfig_.bindAddress,
          cacheProvider_);
        parseClientHello_ |= sslCtxConfig.clientHelloParsingEnabled;
      }

      CHECK(sslCtxManager_->getDefaultSSLCtx());
    } catch (const std::runtime_error& ex) {
      sslCtxManager_->clear();
      LOG(ERROR) << "Failed to configure TLS: " << ex.what();
    }
  }
  base_ = eventBase;
  state_ = State::kRunning;
  downstreamConnectionManager_ = ConnectionManager::makeUnique(
    eventBase, accConfig_.connectionIdleTimeout, this);

  if (serverSocket) {
    serverSocket->addAcceptCallback(this, eventBase);

    for (auto& fd : serverSocket->getSockets()) {
      if (fd < 0) {
        continue;
      }
      for (const auto& opt: socketOptions_) {
        opt.first.apply(fd, opt.second);
      }
    }
  }
}

void Acceptor::resetSSLContextConfigs() {
  try {
    sslCtxManager_->resetSSLContextConfigs(accConfig_.sslContextConfigs,
                                           accConfig_.sslCacheOptions,
                                           &accConfig_.initialTicketSeeds,
                                           accConfig_.bindAddress,
                                           cacheProvider_);
  } catch (const std::runtime_error& ex) {
    LOG(ERROR) << "Failed to re-configure TLS: "
               << ex.what()
               << "will keep old config";
  }

}

Acceptor::~Acceptor(void) {
}

void Acceptor::addSSLContextConfig(const SSLContextConfig& sslCtxConfig) {
  sslCtxManager_->addSSLContextConfig(sslCtxConfig,
                                      accConfig_.sslCacheOptions,
                                      &accConfig_.initialTicketSeeds,
                                      accConfig_.bindAddress,
                                      cacheProvider_);
}

void
Acceptor::drainAllConnections() {
  if (downstreamConnectionManager_) {
    downstreamConnectionManager_->initiateGracefulShutdown(
      gracefulShutdownTimeout_);
  }
}

void Acceptor::setLoadShedConfig(const LoadShedConfiguration& from,
                       IConnectionCounter* counter) {
  loadShedConfig_ = from;
  connectionCounter_ = counter;
}

bool Acceptor::canAccept(const SocketAddress& address) {
  if (!connectionCounter_) {
    return true;
  }

  uint64_t maxConnections = connectionCounter_->getMaxConnections();
  if (maxConnections == 0) {
    return true;
  }

  uint64_t currentConnections = connectionCounter_->getNumConnections();
  if (currentConnections < maxConnections) {
    return true;
  }

  if (loadShedConfig_.isWhitelisted(address)) {
    return true;
  }

  // Take care of the connection counts across all acceptors.
  // Expensive since a lock must be taken to get the counter.
  const auto activeConnLimit = loadShedConfig_.getMaxActiveConnections();
  const auto totalConnLimit = loadShedConfig_.getMaxConnections();
  const auto activeConnCount = getActiveConnectionCountForLoadShedding();
  const auto totalConnCount = getConnectionCountForLoadShedding();

  bool activeConnExceeded =
      (activeConnLimit > 0) && (activeConnCount >= activeConnLimit);
  bool totalConnExceeded =
      (totalConnLimit > 0) && (totalConnCount >= totalConnLimit);
  if (!activeConnExceeded && !totalConnExceeded) {
    return true;
  }

  VLOG(4) << address.describe() << " not whitelisted";
  return false;
}

void
Acceptor::connectionAccepted(
    int fd, const SocketAddress& clientAddr) noexcept {
  if (!canAccept(clientAddr)) {
    // Send a RST to free kernel memory faster
    struct linger optLinger = {1, 0};
    ::setsockopt(fd, SOL_SOCKET, SO_LINGER, &optLinger, sizeof(optLinger));
    close(fd);
    return;
  }
  auto acceptTime = std::chrono::steady_clock::now();
  for (const auto& opt: socketOptions_) {
    opt.first.apply(fd, opt.second);
  }

  onDoneAcceptingConnection(fd, clientAddr, acceptTime);
}

void Acceptor::onDoneAcceptingConnection(
    int fd,
    const SocketAddress& clientAddr,
    std::chrono::steady_clock::time_point acceptTime) noexcept {
  TransportInfo tinfo;
  processEstablishedConnection(fd, clientAddr, acceptTime, tinfo);
}

void
Acceptor::processEstablishedConnection(
    int fd,
    const SocketAddress& clientAddr,
    std::chrono::steady_clock::time_point acceptTime,
    TransportInfo& tinfo) noexcept {
  bool shouldDoSSL = false;
  if (accConfig_.isSSL()) {
    CHECK(sslCtxManager_);
    shouldDoSSL = sslCtxManager_->getDefaultSSLCtx() != nullptr;
  }
  if (shouldDoSSL) {
    AsyncSSLSocket::UniquePtr sslSock(
      makeNewAsyncSSLSocket(
        sslCtxManager_->getDefaultSSLCtx(), base_, fd));
    ++numPendingSSLConns_;
    ++totalNumPendingSSLConns_;
    if (numPendingSSLConns_ > accConfig_.maxConcurrentSSLHandshakes) {
      VLOG(2) << "dropped SSL handshake on " << accConfig_.name <<
        " too many handshakes in progress";
      auto error = SSLErrorEnum::DROPPED;
      auto latency = std::chrono::milliseconds(0);
      updateSSLStats(sslSock.get(), latency, error);
      auto ex = folly::make_exception_wrapper<SSLException>(
          error, latency, sslSock->getRawBytesReceived());
      sslConnectionError(ex);
      return;
    }
    startHandshakeManager(
        std::move(sslSock),
        this,
        clientAddr,
        acceptTime,
        tinfo);
  } else {
    tinfo.secure = false;
    tinfo.acceptTime = acceptTime;
    AsyncSocket::UniquePtr sock(makeNewAsyncSocket(base_, fd));
    plaintextConnectionReady(
        std::move(sock),
        clientAddr,
        empty_string,
        SecureTransportType::NONE,
        tinfo);
  }
}

void Acceptor::startHandshakeManager(
    AsyncSSLSocket::UniquePtr sslSock,
    Acceptor* acceptor,
    const SocketAddress& clientAddr,
    std::chrono::steady_clock::time_point acceptTime,
    TransportInfo& tinfo) noexcept {
  auto manager = securityProtocolCtxManager_.getHandshakeManager(
      this, clientAddr, acceptTime, tinfo);
  manager->start(std::move(sslSock));
}

void
Acceptor::connectionReady(
    AsyncTransportWrapper::UniquePtr sock,
    const SocketAddress& clientAddr,
    const string& nextProtocolName,
    SecureTransportType secureTransportType,
    TransportInfo& tinfo) {
  // Limit the number of reads from the socket per poll loop iteration,
  // both to keep memory usage under control and to prevent one fast-
  // writing client from starving other connections.
  auto asyncSocket = sock->getUnderlyingTransport<AsyncSocket>();
  asyncSocket->setMaxReadsPerEvent(16);
  tinfo.initWithSocket(asyncSocket);
  onNewConnection(
      std::move(sock),
      &clientAddr,
      nextProtocolName,
      secureTransportType,
      tinfo);
}

void Acceptor::plaintextConnectionReady(
    AsyncTransportWrapper::UniquePtr sock,
    const SocketAddress& clientAddr,
    const string& nextProtocolName,
    SecureTransportType secureTransportType,
    TransportInfo& tinfo) {
  connectionReady(
      std::move(sock),
      clientAddr,
      nextProtocolName,
      secureTransportType,
      tinfo);
}

void
Acceptor::sslConnectionReady(AsyncTransportWrapper::UniquePtr sock,
                             const SocketAddress& clientAddr,
                             const string& nextProtocol,
                             SecureTransportType secureTransportType,
                             TransportInfo& tinfo) {
  CHECK(numPendingSSLConns_ > 0);
  --numPendingSSLConns_;
  --totalNumPendingSSLConns_;
  connectionReady(
      std::move(sock),
      clientAddr,
      nextProtocol,
      secureTransportType,
      tinfo);
  if (state_ == State::kDraining) {
    checkDrained();
  }
}

void Acceptor::sslConnectionError(const folly::exception_wrapper& ex) {
  CHECK(numPendingSSLConns_ > 0);
  --numPendingSSLConns_;
  --totalNumPendingSSLConns_;
  if (state_ == State::kDraining) {
    checkDrained();
  }
}

void
Acceptor::acceptError(const std::exception& ex) noexcept {
  // An error occurred.
  // The most likely error is out of FDs.  AsyncServerSocket will back off
  // briefly if we are out of FDs, then continue accepting later.
  // Just log a message here.
  LOG(ERROR) << "error accepting on acceptor socket: " << ex.what();
}

void
Acceptor::acceptStopped() noexcept {
  VLOG(3) << "Acceptor " << this << " acceptStopped()";
  // Drain the open client connections
  drainAllConnections();

  // If we haven't yet finished draining, begin doing so by marking ourselves
  // as in the draining state. We must be sure to hit checkDrained() here, as
  // if we're completely idle, we can should consider ourself drained
  // immediately (as there is no outstanding work to complete to cause us to
  // re-evaluate this).
  if (state_ != State::kDone) {
    state_ = State::kDraining;
    checkDrained();
  }
}

void
Acceptor::onEmpty(const ConnectionManager& cm) {
  VLOG(3) << "Acceptor=" << this << " onEmpty()";
  if (state_ == State::kDraining) {
    checkDrained();
  }
}

void
Acceptor::checkDrained() {
  CHECK(state_ == State::kDraining);
  if (forceShutdownInProgress_ ||
      (downstreamConnectionManager_->getNumConnections() != 0) ||
      (numPendingSSLConns_ != 0)) {
    return;
  }

  VLOG(2) << "All connections drained from Acceptor=" << this << " in thread "
          << base_;

  downstreamConnectionManager_.reset();

  state_ = State::kDone;

  onConnectionsDrained();
}

void
Acceptor::drainConnections(double pctToDrain) {
  if (downstreamConnectionManager_) {
    VLOG(3) << "Dropping " << pctToDrain * 100 << "% of "
            << getNumConnections() << " connections from Acceptor=" << this
            << " in thread " << base_;
    assert(base_->isInEventBaseThread());
    downstreamConnectionManager_->
      drainConnections(pctToDrain, gracefulShutdownTimeout_);
  }
}

milliseconds
Acceptor::getConnTimeout() const {
  return accConfig_.connectionIdleTimeout;
}

void Acceptor::addConnection(ManagedConnection* conn) {
  // Add the socket to the timeout manager so that it can be cleaned
  // up after being left idle for a long time.
  downstreamConnectionManager_->addConnection(conn, true);
}

void
Acceptor::forceStop() {
  base_->runInEventBaseThread([&] { dropAllConnections(); });
}

void
Acceptor::dropAllConnections() {
  if (downstreamConnectionManager_) {
    VLOG(3) << "Dropping all connections from Acceptor=" << this <<
      " in thread " << base_;
    assert(base_->isInEventBaseThread());
    forceShutdownInProgress_ = true;
    downstreamConnectionManager_->dropAllConnections();
    CHECK(downstreamConnectionManager_->getNumConnections() == 0);
    downstreamConnectionManager_.reset();
  }
  CHECK(numPendingSSLConns_ == 0);

  state_ = State::kDone;
  onConnectionsDrained();
}

} // namespace wangle
<commit_msg>Change config validation<commit_after>/*
 *  Copyright (c) 2016, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include <wangle/acceptor/Acceptor.h>

#include <wangle/acceptor/ManagedConnection.h>
#include <wangle/ssl/SSLContextManager.h>
#include <wangle/acceptor/AcceptorHandshakeManager.h>
#include <wangle/acceptor/SecurityProtocolContextManager.h>
#include <fcntl.h>
#include <folly/ScopeGuard.h>
#include <folly/io/async/EventBase.h>
#include <fstream>
#include <sys/types.h>
#include <folly/io/async/AsyncSSLSocket.h>
#include <folly/io/async/AsyncSocket.h>
#include <folly/portability/Sockets.h>
#include <folly/portability/Unistd.h>
#include <gflags/gflags.h>

using folly::AsyncSocket;
using folly::AsyncSSLSocket;
using folly::AsyncSocketException;
using folly::AsyncServerSocket;
using folly::AsyncTransportWrapper;
using folly::EventBase;
using folly::SocketAddress;
using std::chrono::microseconds;
using std::chrono::milliseconds;
using std::filebuf;
using std::ifstream;
using std::ios;
using std::shared_ptr;
using std::string;

namespace wangle {

static const std::string empty_string;
std::atomic<uint64_t> Acceptor::totalNumPendingSSLConns_{0};

Acceptor::Acceptor(const ServerSocketConfig& accConfig) :
  accConfig_(accConfig),
  socketOptions_(accConfig.getSocketOptions()) {
}

void
Acceptor::init(AsyncServerSocket* serverSocket,
               EventBase* eventBase,
               SSLStats* stats) {
  CHECK(nullptr == this->base_ || eventBase == this->base_);

  if (accConfig_.isSSL()) {
    if (accConfig_.allowInsecureConnectionsOnSecureServer) {
      securityProtocolCtxManager_.addPeeker(&tlsPlaintextPeekingCallback_);
    }
    securityProtocolCtxManager_.addPeeker(&defaultPeekingCallback_);

    if (!sslCtxManager_) {
      sslCtxManager_ = folly::make_unique<SSLContextManager>(
        eventBase,
        "vip_" + getName(),
        accConfig_.strictSSL, stats);
    }
    try {
      for (const auto& sslCtxConfig : accConfig_.sslContextConfigs) {
        sslCtxManager_->addSSLContextConfig(
          sslCtxConfig,
          accConfig_.sslCacheOptions,
          &accConfig_.initialTicketSeeds,
          accConfig_.bindAddress,
          cacheProvider_);
        parseClientHello_ |= sslCtxConfig.clientHelloParsingEnabled;
      }

      CHECK(sslCtxManager_->getDefaultSSLCtx());
    } catch (const std::runtime_error& ex) {
      sslCtxManager_->clear();
      // This is not a Not a fatal error, but useful to know.
      LOG(INFO) << "Failed to configure TLS. This is not a fatal error. "
                << ex.what();
    }
  }
  base_ = eventBase;
  state_ = State::kRunning;
  downstreamConnectionManager_ = ConnectionManager::makeUnique(
    eventBase, accConfig_.connectionIdleTimeout, this);

  if (serverSocket) {
    serverSocket->addAcceptCallback(this, eventBase);

    for (auto& fd : serverSocket->getSockets()) {
      if (fd < 0) {
        continue;
      }
      for (const auto& opt: socketOptions_) {
        opt.first.apply(fd, opt.second);
      }
    }
  }
}

void Acceptor::resetSSLContextConfigs() {
  try {
    sslCtxManager_->resetSSLContextConfigs(accConfig_.sslContextConfigs,
                                           accConfig_.sslCacheOptions,
                                           &accConfig_.initialTicketSeeds,
                                           accConfig_.bindAddress,
                                           cacheProvider_);
  } catch (const std::runtime_error& ex) {
    LOG(ERROR) << "Failed to re-configure TLS: "
               << ex.what()
               << "will keep old config";
  }

}

Acceptor::~Acceptor(void) {
}

void Acceptor::addSSLContextConfig(const SSLContextConfig& sslCtxConfig) {
  sslCtxManager_->addSSLContextConfig(sslCtxConfig,
                                      accConfig_.sslCacheOptions,
                                      &accConfig_.initialTicketSeeds,
                                      accConfig_.bindAddress,
                                      cacheProvider_);
}

void
Acceptor::drainAllConnections() {
  if (downstreamConnectionManager_) {
    downstreamConnectionManager_->initiateGracefulShutdown(
      gracefulShutdownTimeout_);
  }
}

void Acceptor::setLoadShedConfig(const LoadShedConfiguration& from,
                       IConnectionCounter* counter) {
  loadShedConfig_ = from;
  connectionCounter_ = counter;
}

bool Acceptor::canAccept(const SocketAddress& address) {
  if (!connectionCounter_) {
    return true;
  }

  uint64_t maxConnections = connectionCounter_->getMaxConnections();
  if (maxConnections == 0) {
    return true;
  }

  uint64_t currentConnections = connectionCounter_->getNumConnections();
  if (currentConnections < maxConnections) {
    return true;
  }

  if (loadShedConfig_.isWhitelisted(address)) {
    return true;
  }

  // Take care of the connection counts across all acceptors.
  // Expensive since a lock must be taken to get the counter.
  const auto activeConnLimit = loadShedConfig_.getMaxActiveConnections();
  const auto totalConnLimit = loadShedConfig_.getMaxConnections();
  const auto activeConnCount = getActiveConnectionCountForLoadShedding();
  const auto totalConnCount = getConnectionCountForLoadShedding();

  bool activeConnExceeded =
      (activeConnLimit > 0) && (activeConnCount >= activeConnLimit);
  bool totalConnExceeded =
      (totalConnLimit > 0) && (totalConnCount >= totalConnLimit);
  if (!activeConnExceeded && !totalConnExceeded) {
    return true;
  }

  VLOG(4) << address.describe() << " not whitelisted";
  return false;
}

void
Acceptor::connectionAccepted(
    int fd, const SocketAddress& clientAddr) noexcept {
  if (!canAccept(clientAddr)) {
    // Send a RST to free kernel memory faster
    struct linger optLinger = {1, 0};
    ::setsockopt(fd, SOL_SOCKET, SO_LINGER, &optLinger, sizeof(optLinger));
    close(fd);
    return;
  }
  auto acceptTime = std::chrono::steady_clock::now();
  for (const auto& opt: socketOptions_) {
    opt.first.apply(fd, opt.second);
  }

  onDoneAcceptingConnection(fd, clientAddr, acceptTime);
}

void Acceptor::onDoneAcceptingConnection(
    int fd,
    const SocketAddress& clientAddr,
    std::chrono::steady_clock::time_point acceptTime) noexcept {
  TransportInfo tinfo;
  processEstablishedConnection(fd, clientAddr, acceptTime, tinfo);
}

void
Acceptor::processEstablishedConnection(
    int fd,
    const SocketAddress& clientAddr,
    std::chrono::steady_clock::time_point acceptTime,
    TransportInfo& tinfo) noexcept {
  bool shouldDoSSL = false;
  if (accConfig_.isSSL()) {
    CHECK(sslCtxManager_);
    shouldDoSSL = sslCtxManager_->getDefaultSSLCtx() != nullptr;
  }
  if (shouldDoSSL) {
    AsyncSSLSocket::UniquePtr sslSock(
      makeNewAsyncSSLSocket(
        sslCtxManager_->getDefaultSSLCtx(), base_, fd));
    ++numPendingSSLConns_;
    ++totalNumPendingSSLConns_;
    if (numPendingSSLConns_ > accConfig_.maxConcurrentSSLHandshakes) {
      VLOG(2) << "dropped SSL handshake on " << accConfig_.name <<
        " too many handshakes in progress";
      auto error = SSLErrorEnum::DROPPED;
      auto latency = std::chrono::milliseconds(0);
      updateSSLStats(sslSock.get(), latency, error);
      auto ex = folly::make_exception_wrapper<SSLException>(
          error, latency, sslSock->getRawBytesReceived());
      sslConnectionError(ex);
      return;
    }
    startHandshakeManager(
        std::move(sslSock),
        this,
        clientAddr,
        acceptTime,
        tinfo);
  } else {
    tinfo.secure = false;
    tinfo.acceptTime = acceptTime;
    AsyncSocket::UniquePtr sock(makeNewAsyncSocket(base_, fd));
    plaintextConnectionReady(
        std::move(sock),
        clientAddr,
        empty_string,
        SecureTransportType::NONE,
        tinfo);
  }
}

void Acceptor::startHandshakeManager(
    AsyncSSLSocket::UniquePtr sslSock,
    Acceptor* acceptor,
    const SocketAddress& clientAddr,
    std::chrono::steady_clock::time_point acceptTime,
    TransportInfo& tinfo) noexcept {
  auto manager = securityProtocolCtxManager_.getHandshakeManager(
      this, clientAddr, acceptTime, tinfo);
  manager->start(std::move(sslSock));
}

void
Acceptor::connectionReady(
    AsyncTransportWrapper::UniquePtr sock,
    const SocketAddress& clientAddr,
    const string& nextProtocolName,
    SecureTransportType secureTransportType,
    TransportInfo& tinfo) {
  // Limit the number of reads from the socket per poll loop iteration,
  // both to keep memory usage under control and to prevent one fast-
  // writing client from starving other connections.
  auto asyncSocket = sock->getUnderlyingTransport<AsyncSocket>();
  asyncSocket->setMaxReadsPerEvent(16);
  tinfo.initWithSocket(asyncSocket);
  onNewConnection(
      std::move(sock),
      &clientAddr,
      nextProtocolName,
      secureTransportType,
      tinfo);
}

void Acceptor::plaintextConnectionReady(
    AsyncTransportWrapper::UniquePtr sock,
    const SocketAddress& clientAddr,
    const string& nextProtocolName,
    SecureTransportType secureTransportType,
    TransportInfo& tinfo) {
  connectionReady(
      std::move(sock),
      clientAddr,
      nextProtocolName,
      secureTransportType,
      tinfo);
}

void
Acceptor::sslConnectionReady(AsyncTransportWrapper::UniquePtr sock,
                             const SocketAddress& clientAddr,
                             const string& nextProtocol,
                             SecureTransportType secureTransportType,
                             TransportInfo& tinfo) {
  CHECK(numPendingSSLConns_ > 0);
  --numPendingSSLConns_;
  --totalNumPendingSSLConns_;
  connectionReady(
      std::move(sock),
      clientAddr,
      nextProtocol,
      secureTransportType,
      tinfo);
  if (state_ == State::kDraining) {
    checkDrained();
  }
}

void Acceptor::sslConnectionError(const folly::exception_wrapper& ex) {
  CHECK(numPendingSSLConns_ > 0);
  --numPendingSSLConns_;
  --totalNumPendingSSLConns_;
  if (state_ == State::kDraining) {
    checkDrained();
  }
}

void
Acceptor::acceptError(const std::exception& ex) noexcept {
  // An error occurred.
  // The most likely error is out of FDs.  AsyncServerSocket will back off
  // briefly if we are out of FDs, then continue accepting later.
  // Just log a message here.
  LOG(ERROR) << "error accepting on acceptor socket: " << ex.what();
}

void
Acceptor::acceptStopped() noexcept {
  VLOG(3) << "Acceptor " << this << " acceptStopped()";
  // Drain the open client connections
  drainAllConnections();

  // If we haven't yet finished draining, begin doing so by marking ourselves
  // as in the draining state. We must be sure to hit checkDrained() here, as
  // if we're completely idle, we can should consider ourself drained
  // immediately (as there is no outstanding work to complete to cause us to
  // re-evaluate this).
  if (state_ != State::kDone) {
    state_ = State::kDraining;
    checkDrained();
  }
}

void
Acceptor::onEmpty(const ConnectionManager& cm) {
  VLOG(3) << "Acceptor=" << this << " onEmpty()";
  if (state_ == State::kDraining) {
    checkDrained();
  }
}

void
Acceptor::checkDrained() {
  CHECK(state_ == State::kDraining);
  if (forceShutdownInProgress_ ||
      (downstreamConnectionManager_->getNumConnections() != 0) ||
      (numPendingSSLConns_ != 0)) {
    return;
  }

  VLOG(2) << "All connections drained from Acceptor=" << this << " in thread "
          << base_;

  downstreamConnectionManager_.reset();

  state_ = State::kDone;

  onConnectionsDrained();
}

void
Acceptor::drainConnections(double pctToDrain) {
  if (downstreamConnectionManager_) {
    VLOG(3) << "Dropping " << pctToDrain * 100 << "% of "
            << getNumConnections() << " connections from Acceptor=" << this
            << " in thread " << base_;
    assert(base_->isInEventBaseThread());
    downstreamConnectionManager_->
      drainConnections(pctToDrain, gracefulShutdownTimeout_);
  }
}

milliseconds
Acceptor::getConnTimeout() const {
  return accConfig_.connectionIdleTimeout;
}

void Acceptor::addConnection(ManagedConnection* conn) {
  // Add the socket to the timeout manager so that it can be cleaned
  // up after being left idle for a long time.
  downstreamConnectionManager_->addConnection(conn, true);
}

void
Acceptor::forceStop() {
  base_->runInEventBaseThread([&] { dropAllConnections(); });
}

void
Acceptor::dropAllConnections() {
  if (downstreamConnectionManager_) {
    VLOG(3) << "Dropping all connections from Acceptor=" << this <<
      " in thread " << base_;
    assert(base_->isInEventBaseThread());
    forceShutdownInProgress_ = true;
    downstreamConnectionManager_->dropAllConnections();
    CHECK(downstreamConnectionManager_->getNumConnections() == 0);
    downstreamConnectionManager_.reset();
  }
  CHECK(numPendingSSLConns_ == 0);

  state_ = State::kDone;
  onConnectionsDrained();
}

} // namespace wangle
<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "app/gfx/gl/gl_implementation.h"
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/string_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/test_launcher_utils.h"
#include "chrome/test/ui/ui_layout_test.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

class MediaTest : public UITest {
 protected:
  virtual void SetUp() {
    EXPECT_TRUE(test_launcher_utils::OverrideGLImplementation(
        &launch_arguments_,
        gfx::kGLImplementationOSMesaName));

#if defined(OS_MACOSX)
    // Accelerated compositing does not work with OSMesa. AcceleratedSurface
    // assumes GL contexts are native.
    launch_arguments_.AppendSwitch(switches::kDisableAcceleratedCompositing);
#endif

    UITest::SetUp();
  }

  void PlayMedia(const char* tag, const char* media_file) {
    FilePath test_file(test_data_directory_);
    test_file = test_file.AppendASCII("media/player.html");

    GURL player_gurl = net::FilePathToFileURL(test_file);
    std::string url = StringPrintf("%s?%s=%s",
                                   player_gurl.spec().c_str(),
                                   tag,
                                   media_file);

    NavigateToURL(GURL(url));

    // Allow the media file to be loaded.
    const std::wstring kPlaying = L"PLAYING";
    const std::wstring kFailed = L"FAILED";
    const std::wstring kError = L"ERROR";
    for (int i = 0; i < 10; ++i) {
      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
      const std::wstring& title = GetActiveTabTitle();
      if (title == kPlaying || title == kFailed ||
          StartsWith(title, kError, true))
        break;
    }

    EXPECT_EQ(kPlaying, GetActiveTabTitle());
  }

  void PlayAudio(const char* url) {
    PlayMedia("audio", url);
  }

  void PlayVideo(const char* url) {
    PlayMedia("video", url);
  }
};

TEST_F(MediaTest, VideoBearTheora) {
  PlayVideo("bear.ogv");
}

TEST_F(MediaTest, VideoBearSilentTheora) {
  PlayVideo("bear_silent.ogv");
}

TEST_F(MediaTest, VideoBearWebm) {
  PlayVideo("bear.webm");
}

TEST_F(MediaTest, VideoBearSilentWebm) {
  PlayVideo("bear_silent.webm");
}

#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
TEST_F(MediaTest, VideoBearMp4) {
  PlayVideo("bear.mp4");
}

TEST_F(MediaTest, VideoBearSilentMp4) {
  PlayVideo("bear_silent.mp4");
}
#endif

TEST_F(MediaTest, VideoBearWav) {
  PlayVideo("bear.wav");
}

// See crbug/73287.
TEST_F(UILayoutTest, FAILS_MediaUILayoutTest) {
  static const char* kResources[] = {
    "content",
    "media-file.js",
    "media-fullscreen.js",
    "video-paint-test.js",
    "video-played.js",
    "video-test.js",
  };

  static const char* kMediaTests[] = {
    "video-autoplay.html",
    // "video-loop.html", disabled due to 52887.
    "video-no-autoplay.html",
    // TODO(sergeyu): Add more tests here.
  };

  FilePath test_dir;
  FilePath media_test_dir;
  media_test_dir = media_test_dir.AppendASCII("media");
  InitializeForLayoutTest(test_dir, media_test_dir, kNoHttpPort);

  // Copy resources first.
  for (size_t i = 0; i < arraysize(kResources); ++i)
    AddResourceForLayoutTest(
        test_dir, media_test_dir.AppendASCII(kResources[i]));

  for (size_t i = 0; i < arraysize(kMediaTests); ++i)
    RunLayoutTest(kMediaTests[i], kNoHttpPort);
}
<commit_msg>Re-enable UILayoutTest.MediaUILayoutTest<commit_after>// Copyright (c) 2011 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 "app/gfx/gl/gl_implementation.h"
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/string_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/test_launcher_utils.h"
#include "chrome/test/ui/ui_layout_test.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

class MediaTest : public UITest {
 protected:
  virtual void SetUp() {
    EXPECT_TRUE(test_launcher_utils::OverrideGLImplementation(
        &launch_arguments_,
        gfx::kGLImplementationOSMesaName));

#if defined(OS_MACOSX)
    // Accelerated compositing does not work with OSMesa. AcceleratedSurface
    // assumes GL contexts are native.
    launch_arguments_.AppendSwitch(switches::kDisableAcceleratedCompositing);
#endif

    UITest::SetUp();
  }

  void PlayMedia(const char* tag, const char* media_file) {
    FilePath test_file(test_data_directory_);
    test_file = test_file.AppendASCII("media/player.html");

    GURL player_gurl = net::FilePathToFileURL(test_file);
    std::string url = StringPrintf("%s?%s=%s",
                                   player_gurl.spec().c_str(),
                                   tag,
                                   media_file);

    NavigateToURL(GURL(url));

    // Allow the media file to be loaded.
    const std::wstring kPlaying = L"PLAYING";
    const std::wstring kFailed = L"FAILED";
    const std::wstring kError = L"ERROR";
    for (int i = 0; i < 10; ++i) {
      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
      const std::wstring& title = GetActiveTabTitle();
      if (title == kPlaying || title == kFailed ||
          StartsWith(title, kError, true))
        break;
    }

    EXPECT_EQ(kPlaying, GetActiveTabTitle());
  }

  void PlayAudio(const char* url) {
    PlayMedia("audio", url);
  }

  void PlayVideo(const char* url) {
    PlayMedia("video", url);
  }
};

TEST_F(MediaTest, VideoBearTheora) {
  PlayVideo("bear.ogv");
}

TEST_F(MediaTest, VideoBearSilentTheora) {
  PlayVideo("bear_silent.ogv");
}

TEST_F(MediaTest, VideoBearWebm) {
  PlayVideo("bear.webm");
}

TEST_F(MediaTest, VideoBearSilentWebm) {
  PlayVideo("bear_silent.webm");
}

#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
TEST_F(MediaTest, VideoBearMp4) {
  PlayVideo("bear.mp4");
}

TEST_F(MediaTest, VideoBearSilentMp4) {
  PlayVideo("bear_silent.mp4");
}
#endif

TEST_F(MediaTest, VideoBearWav) {
  PlayVideo("bear.wav");
}

TEST_F(UILayoutTest, MediaUILayoutTest) {
  static const char* kResources[] = {
    "content",
    "media-file.js",
    "media-fullscreen.js",
    "video-paint-test.js",
    "video-played.js",
    "video-test.js",
  };

  static const char* kMediaTests[] = {
    "video-autoplay.html",
    // "video-loop.html", disabled due to 52887.
    "video-no-autoplay.html",
    // TODO(sergeyu): Add more tests here.
  };

  FilePath test_dir;
  FilePath media_test_dir;
  media_test_dir = media_test_dir.AppendASCII("media");
  InitializeForLayoutTest(test_dir, media_test_dir, kNoHttpPort);

  // Copy resources first.
  for (size_t i = 0; i < arraysize(kResources); ++i)
    AddResourceForLayoutTest(
        test_dir, media_test_dir.AppendASCII(kResources[i]));

  for (size_t i = 0; i < arraysize(kMediaTests); ++i)
    RunLayoutTest(kMediaTests[i], kNoHttpPort);
}
<|endoftext|>


<commit_before>

#include "base64.h"
#include <iostream>

#include <stdint.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdlib.h>

static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                                'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
                                'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
                                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
                                'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                                'w', 'x', 'y', 'z', '0', '1', '2', '3',
                                '4', '5', '6', '7', '8', '9', '+', '/'};
static int mod_table[] = {0, 2, 1};

void b64::build_decoding_table() {

    this->decoding_table = (char *) malloc(256);

    for (int i = 0; i < 64; i++)
        this->decoding_table[(unsigned char) encoding_table[i]] = i;
}

void b64::base64_cleanup() {
    free(this->decoding_table);
}

b64::b64(){ //c'tor
    build_decoding_table();
}

b64::~b64(){ //d'tor
    base64_cleanup();
}

std::string b64::base64_encode(std::string src_str){
    //Public interface
    unsigned int dst_len = 0;
    char * dst_data = base64_encode((const unsigned char *)src_str.c_str(), src_str.size()+1, &dst_len);

    std::string ret(dst_data, dst_len);
    delete dst_data;

    return ret;
}

std::string b64::base64_decode(std::string src_str){
    //Public interface
    unsigned int dst_len = 0;
    unsigned char * dst_data = base64_decode(src_str.c_str(), src_str.size()+1, &dst_len);

    std::string ret((char*)dst_data, dst_len);
    delete dst_data;

    return ret;
}

std::string b64::base64_encode(unsigned char const* src_data, unsigned int src_len){
    //Public interface

    unsigned int dst_len = 0;
    char * dst_data = base64_encode(src_data, src_len, &dst_len);

    std::string ret(dst_data, dst_len);
    delete dst_data;

    return ret;
}

std::string b64::base64_decode(char const* src_data, unsigned int src_len){
    //Public interface

    unsigned int dst_len = 0;
    unsigned char * dst_data = base64_decode(src_data, src_len, &dst_len);

    std::string ret((char*)dst_data, dst_len);
    delete dst_data;

    return ret;
}

char *  b64::base64_encode(const unsigned char *data,
                    unsigned int input_length,
                    unsigned int *output_length) {

    *output_length = 4 * ((input_length + 2) / 3);

    char *encoded_data = (char *)malloc(*output_length);
    if (encoded_data == NULL) return NULL;

    for (int i = 0, j = 0; i < input_length;) {

        uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
        uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
        uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;

        uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;

        encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
        encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
        encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
        encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
    }

    for (int i = 0; i < mod_table[input_length % 3]; i++)
        encoded_data[*output_length - 1 - i] = '=';

    return encoded_data;
}

unsigned char * b64::base64_decode(const char *data,
                             unsigned int input_length,
                             unsigned int *output_length) {

    if (this->decoding_table == NULL) build_decoding_table();

    if (input_length % 4 != 0) return NULL;

    *output_length = input_length / 4 * 3;
    if (data[input_length - 1] == '=') (*output_length)--;
    if (data[input_length - 2] == '=') (*output_length)--;

    unsigned char *decoded_data = (unsigned char *) malloc(*output_length);
    if (decoded_data == NULL) return NULL;

    for (int i = 0, j = 0; i < input_length;) {

        uint32_t sextet_a = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
        uint32_t sextet_b = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
        uint32_t sextet_c = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
        uint32_t sextet_d = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];

        uint32_t triple = (sextet_a << 3 * 6)
        + (sextet_b << 2 * 6)
        + (sextet_c << 1 * 6)
        + (sextet_d << 0 * 6);

        if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
        if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
        if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
    }

    return decoded_data;
}

<commit_msg>Minor fixes<commit_after>

#include "base64.h"
#include <iostream>

#include <stdint.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdlib.h>

using namespace std;

static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                                'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
                                'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
                                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
                                'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                                'w', 'x', 'y', 'z', '0', '1', '2', '3',
                                '4', '5', '6', '7', '8', '9', '+', '/'};
static int mod_table[] = {0, 2, 1};

void b64::build_decoding_table() {

	this->decoding_table = (char *) malloc(256);

	for (int i = 0; i < 64; i++){
		this->decoding_table[(unsigned char) encoding_table[i]] = i;
	}
}

void b64::base64_cleanup() {
	free(this->decoding_table);
}

b64::b64(){ //c'tor
	build_decoding_table();
}

b64::~b64(){ //d'tor
	base64_cleanup();
}

std::string b64::base64_encode(std::string src_str){
	//Public interface
	unsigned int dst_len = 0;
	char * dst_data = base64_encode((const unsigned char *)src_str.c_str(), src_str.size(), &dst_len);

	std::string ret(dst_data, dst_len);
	delete dst_data;

	return ret;
}

std::string b64::base64_decode(std::string src_str){
	//Public interface
	unsigned int dst_len = 0;
	unsigned char * dst_data = base64_decode(src_str.c_str(), src_str.size(), &dst_len);

	std::string ret((char*)dst_data, dst_len);
	delete dst_data;

	return ret;
}

std::string b64::base64_encode(unsigned char const* src_data, unsigned int src_len){
	//Public interface

	unsigned int dst_len = 0;
	char * dst_data = base64_encode(src_data, src_len, &dst_len);

	std::string ret(dst_data, dst_len);
	delete dst_data;

	return ret;
}

std::string b64::base64_decode(char const* src_data, unsigned int src_len){
	//Public interface

	unsigned int dst_len = 0;
	unsigned char * dst_data = base64_decode(src_data, src_len, &dst_len);

	std::string ret((char*)dst_data, dst_len);
	delete dst_data;

	return ret;
}

char *  b64::base64_encode(const unsigned char *data,
                    unsigned int input_length,
                    unsigned int *output_length) {

	*output_length = 4 * ((input_length + 2) / 3);

	char *encoded_data = (char *)malloc(*output_length);
	if (encoded_data == NULL) return NULL;

	for (int i = 0, j = 0; i < input_length;) {
		uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
		uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
		uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;

		uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;

		encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
		encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
		encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
		encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
	}

	for (int i = 0; i < mod_table[input_length % 3]; i++){
		encoded_data[*output_length - 1 - i] = '=';
	}

	return encoded_data;
}

unsigned char * b64::base64_decode(const char *data,
                             unsigned int input_length,
                             unsigned int *output_length) {

	if (this->decoding_table == NULL) build_decoding_table();

	if (input_length % 4 != 0) return NULL;

	*output_length = input_length / 4 * 3;
	if (data[input_length - 1] == '=') (*output_length)--;
	if (data[input_length - 2] == '=') (*output_length)--;

	unsigned char *decoded_data = (unsigned char *) malloc(*output_length);
	if (decoded_data == NULL) return NULL;

	for (int i = 0, j = 0; i < input_length;) {
		uint32_t sextet_a = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
		uint32_t sextet_b = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
		uint32_t sextet_c = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
		uint32_t sextet_d = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];

		uint32_t triple = (sextet_a << 3 * 6)
		+ (sextet_b << 2 * 6)
		+ (sextet_c << 1 * 6)
		+ (sextet_d << 0 * 6);

		if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
		if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
		if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
	}

	return decoded_data;
}

<|endoftext|>


<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 "base/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/test/test_server.h"
#include "webkit/glue/plugins/plugin_switches.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));
    FilePath::StringType pepper_plugin = plugin_lib.value();
    pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
    launch_arguments_.AppendSwitchNative(switches::kRegisterPepperPlugins,
                                         pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);

    // Some stuff is hung off of the testing interface which is not enabled
    // by default.
    launch_arguments_.AppendSwitch(switches::kEnablePepperTesting);
  }

  void RunTest(const std::string& test_case) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("third_party"));
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL::Replacements replacements;
    replacements.SetQuery(test_case.c_str(),
                          url_parse::Component(0, test_case.size()));
    GURL test_url = net::FilePathToFileURL(test_path);
    RunTestURL(test_url.ReplaceComponents(replacements));
  }

  void RunTestViaHTTP(const std::string& test_case) {
    net::TestServer test_server(
        net::TestServer::TYPE_HTTP,
        FilePath(FILE_PATH_LITERAL("third_party/ppapi/tests")));
    ASSERT_TRUE(test_server.Start());
    RunTestURL(test_server.GetURL("files/test_case.html?" + test_case));
  }

 private:
  void RunTestURL(const GURL& test_url) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));
    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", action_max_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

TEST_F(PPAPITest, FAILS_Instance) {
  RunTest("Instance");
}

// http://crbug.com/54150
TEST_F(PPAPITest, FLAKY_Graphics2D) {
  RunTest("Graphics2D");
}

// TODO(brettw) bug 51344: this is flaky on bots. Seems to timeout navigating.
// Possibly all the image allocations slow things down on a loaded bot too much.
TEST_F(PPAPITest, FLAKY_ImageData) {
  RunTest("ImageData");
}

TEST_F(PPAPITest, Buffer) {
  RunTest("Buffer");
}

TEST_F(PPAPITest, URLLoader) {
  RunTestViaHTTP("URLLoader");
}

// Flaky, http://crbug.com/51012
TEST_F(PPAPITest, FLAKY_PaintAggregator) {
  RunTestViaHTTP("PaintAggregator");
}

// Flaky, http://crbug.com/48544.
TEST_F(PPAPITest, FLAKY_Scrollbar) {
  RunTest("Scrollbar");
}

TEST_F(PPAPITest, UrlUtil) {
  RunTest("UrlUtil");
}

TEST_F(PPAPITest, CharSet) {
  RunTest("CharSet");
}
<commit_msg>Mark PPAPITest.URLLoader as flaky.<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 "base/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/test/test_server.h"
#include "webkit/glue/plugins/plugin_switches.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));
    FilePath::StringType pepper_plugin = plugin_lib.value();
    pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
    launch_arguments_.AppendSwitchNative(switches::kRegisterPepperPlugins,
                                         pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);

    // Some stuff is hung off of the testing interface which is not enabled
    // by default.
    launch_arguments_.AppendSwitch(switches::kEnablePepperTesting);
  }

  void RunTest(const std::string& test_case) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("third_party"));
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL::Replacements replacements;
    replacements.SetQuery(test_case.c_str(),
                          url_parse::Component(0, test_case.size()));
    GURL test_url = net::FilePathToFileURL(test_path);
    RunTestURL(test_url.ReplaceComponents(replacements));
  }

  void RunTestViaHTTP(const std::string& test_case) {
    net::TestServer test_server(
        net::TestServer::TYPE_HTTP,
        FilePath(FILE_PATH_LITERAL("third_party/ppapi/tests")));
    ASSERT_TRUE(test_server.Start());
    RunTestURL(test_server.GetURL("files/test_case.html?" + test_case));
  }

 private:
  void RunTestURL(const GURL& test_url) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));
    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", action_max_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

TEST_F(PPAPITest, FAILS_Instance) {
  RunTest("Instance");
}

// http://crbug.com/54150
TEST_F(PPAPITest, FLAKY_Graphics2D) {
  RunTest("Graphics2D");
}

// TODO(brettw) bug 51344: this is flaky on bots. Seems to timeout navigating.
// Possibly all the image allocations slow things down on a loaded bot too much.
TEST_F(PPAPITest, FLAKY_ImageData) {
  RunTest("ImageData");
}

TEST_F(PPAPITest, Buffer) {
  RunTest("Buffer");
}

TEST_F(PPAPITest, FLAKY_URLLoader) {
  RunTestViaHTTP("URLLoader");
}

// Flaky, http://crbug.com/51012
TEST_F(PPAPITest, FLAKY_PaintAggregator) {
  RunTestViaHTTP("PaintAggregator");
}

// Flaky, http://crbug.com/48544.
TEST_F(PPAPITest, FLAKY_Scrollbar) {
  RunTest("Scrollbar");
}

TEST_F(PPAPITest, UrlUtil) {
  RunTest("UrlUtil");
}

TEST_F(PPAPITest, CharSet) {
  RunTest("CharSet");
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: tbxctl.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2004-07-06 13:07:25 $
 *
 *  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 _TBXCTL_HXX
#define _TBXCTL_HXX

#ifndef _SFXTBXCTRL_HXX //autogen
#include <sfx2/tbxctrl.hxx>
#endif

/*************************************************************************
|*
|* Klasse f"ur SwToolbox
|*
\************************************************************************/

class SvxTbxCtlDraw : public SfxToolBoxControl
{
private:
    USHORT  nLastAction;

public:
    virtual void                Select( BOOL bMod1 = FALSE );
    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();

            SFX_DECL_TOOLBOX_CONTROL();

            SvxTbxCtlDraw( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
            ~SvxTbxCtlDraw() {}

    void    SetLastAction( USHORT nAction ) { nLastAction = nAction; }
};

#endif

<commit_msg>INTEGRATION: CWS toolbars3 (1.2.250); FILE MERGED 2004/11/12 11:20:33 pb 1.2.250.1: fix: #i37018# toggleToolbox() added<commit_after>/*************************************************************************
 *
 *  $RCSfile: tbxctl.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2004-11-26 20:13:23 $
 *
 *  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 _TBXCTL_HXX
#define _TBXCTL_HXX

#ifndef _SFXTBXCTRL_HXX //autogen
#include <sfx2/tbxctrl.hxx>
#endif

/*************************************************************************
|*
|* Klasse f"ur SwToolbox
|*
\************************************************************************/

class SvxTbxCtlDraw : public SfxToolBoxControl
{
private:
    ::rtl::OUString     m_sToolboxName;

    void                toggleToolbox();

public:
    SvxTbxCtlDraw( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~SvxTbxCtlDraw() {}

    SFX_DECL_TOOLBOX_CONTROL();

    virtual void                Select( BOOL bMod1 = FALSE );
    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
};

#endif

<|endoftext|>


<commit_before>#include "core/argparse.h"

#include "core/image.h"
#include "core/imagefilters.h"
#include "core/palette_all.h"

#include "core/io.h"

#include <iostream>
#include <sstream>
#include <iomanip>

using namespace euphoria::core;

int
main(int argc, char* argv[])
{
    auto parser = argparse::Parser {"Apply filters to images"};

    std::string input;
    std::string output = "ret.png";

    Image image;

    auto load_image = [&]
    {
        auto ret = LoadImage(io::FileToChunk(input), input, AlphaLoad::Keep);
        if(!ret.error.empty())
        {
            std::cerr << ret.error << "\n";
            return false;
        }
        else
        {
            image = ret.image;
            return true;
        }
    };

    auto write_image = [&]
    {
        io::ChunkToFile(image.Write(ImageWriteFormat::PNG), output);
    };

    // todo(Gustav): change to generate/open - filter - save subparsing instead (with image targets)

    parser.Add("input", &input).Help("The image to apply filters to");
    parser.Add("-o, --output", &output)
            .Help("Where to write the resulting image");

    auto subs = parser.AddSubParsers();

    subs->Add
    (
        "nop", "Don't do anything",
        [&](argparse::SubParser* sub)
        {
            return sub->OnComplete
            (
                [&]
                {
                    if(!load_image())
                    {
                        return;
                    }
                    write_image();
                }
            );

        }
    );

    subs->Add
    (
        "grayscale", "Apply grayscale",
        [&](argparse::SubParser* sub)
        {
            Grayscale grayscale = Grayscale::Average;
            sub->Add("-g,--grayscale", &grayscale);
            return sub->OnComplete
            (
                [&]
                {
                    if(!load_image())
                    {
                        return;
                    }
                    MakeGrayscale(&image, grayscale);
                    write_image();
                }
            );

        }
    );

    subs->Add
    (
        "palswap", "Switch palette",
        [&](argparse::SubParser* sub)
        {
            palette::PaletteName palette = palette::PaletteName::OneBit;
            bool pal_dither = false;

            sub->Add("-p, --palette", &palette);
            sub->SetTrue("-d, --dither", &pal_dither);

            return sub->OnComplete
            (
                [&]
                {
                    if(!load_image())
                    {
                        return;
                    }
                    if(pal_dither)
                    {
                        MatchPaletteDither(&image, palette::GetPalette(palette));
                    }
                    else
                    {
                        MatchPalette(&image, palette::GetPalette(palette));
                    }
                    write_image();
                }
            );

        }
    );

    subs->Add
    (
        "edge", "Edge detection",
        [&](argparse::SubParser* sub)
        {
            float edge_r = 0.5f;
            sub->Add("-r, --range", &edge_r);
            return sub->OnComplete
            (
                [&]
                {
                    if(!load_image())
                    {
                        return;
                    }
                    EdgeDetection(&image, edge_r);
                    write_image();
                }
            );
        }
    );

    subs->Add
    (
        "color", "Detect colors",
        [&](argparse::SubParser* sub)
        {
            float edge_r = 0.5f;
            auto color_color = Color::Red;
            sub->Add("-r, --range", &edge_r);
            sub->Add("-c, --color", &color_color);
            return sub->OnComplete
            (
                [&]
                {
                    if(!load_image())
                    {
                        return;
                    }
                    ColorDetection(&image, color_color, edge_r);
                    write_image();
                }
            );
        }
    );

    subs->Add
    (
        "bright", "Change brightness",
        [&](argparse::SubParser* sub)
        {
            int bright_c = 10;
            sub->Add("-c, --change", &bright_c);
            return sub->OnComplete
            (
                [&]
                {
                    if(!load_image())
                    {
                        return;
                    }
                    ChangeBrightness(&image, bright_c);
                    write_image();
                }
            );
        }
    );

    subs->Add
    (
        "contrast", "Change contrast",
        [&](argparse::SubParser* sub)
        {
            float contrast = 10;
            sub->Add("-c, --change", &contrast);
            return sub->OnComplete
            (
                [&]
                {
                    if (!load_image())
                    {
                        return;
                    }
                    ChangeContrast(&image, contrast);
                    write_image();
                }
            );
        }
    );

    return argparse::ParseFromMain(&parser, argc, argv);
}
<commit_msg>refactored img tool so that it reflects how it is supposed to work (but currently doesn't)<commit_after>#include "core/argparse.h"

#include "core/image.h"
#include "core/imagefilters.h"
#include "core/palette_all.h"

#include "core/io.h"

#include <iostream>
#include <sstream>
#include <iomanip>

using namespace euphoria::core;

int
main(int argc, char* argv[])
{
    Image image;

    auto parser = argparse::Parser {"Apply filters to images"};

    auto io_subs = parser.AddSubParsers("transfer image to/from disk");

    io_subs->Add
    (
        "open", "Load image from disk",
        [&](argparse::SubParser* sub)
        {
            std::string input;
            parser.Add("input", &input).Help("The image to apply filters to");
            return sub->OnComplete
            (
                [&]
                {
                    auto ret = LoadImage(io::FileToChunk(input), input, AlphaLoad::Keep);
                    if(!ret.error.empty())
                    {
                        std::cerr << ret.error << "\n";
                        // return false;
                    }
                    else
                    {
                        image = ret.image;
                        // return true;
                    }
                }
            );
        }
    );

    io_subs->Add
    (
        "save", "Write image to disk",
        [&](argparse::SubParser* sub)
        {
            std::string output = "ret.png";
            parser.Add("-o, --output", &output).Help
            (
                "Where to write the resulting image"
            );
            return sub->OnComplete
            (
                [&]
                {
                    io::ChunkToFile(image.Write(ImageWriteFormat::PNG), output);
                }
            );

        }
    );

    auto filters_subs = parser.AddSubParsers("apply filter to current image");

    filters_subs->Add
    (
        "grayscale", "Apply grayscale",
        [&](argparse::SubParser* sub)
        {
            Grayscale grayscale = Grayscale::Average;
            sub->Add("-g,--grayscale", &grayscale);
            return sub->OnComplete
            (
                [&]
                {
                    MakeGrayscale(&image, grayscale);
                }
            );

        }
    );

    filters_subs->Add
    (
        "palswap", "Switch palette",
        [&](argparse::SubParser* sub)
        {
            palette::PaletteName palette = palette::PaletteName::OneBit;
            bool pal_dither = false;

            sub->Add("-p, --palette", &palette);
            sub->SetTrue("-d, --dither", &pal_dither);

            return sub->OnComplete
            (
                [&]
                {
                    if(pal_dither)
                    {
                        MatchPaletteDither(&image, palette::GetPalette(palette));
                    }
                    else
                    {
                        MatchPalette(&image, palette::GetPalette(palette));
                    }
                }
            );

        }
    );

    filters_subs->Add
    (
        "edge", "Edge detection",
        [&](argparse::SubParser* sub)
        {
            float edge_r = 0.5f;
            sub->Add("-r, --range", &edge_r);
            return sub->OnComplete
            (
                [&]
                {
                    EdgeDetection(&image, edge_r);
                }
            );
        }
    );

    filters_subs->Add
    (
        "color", "Detect colors",
        [&](argparse::SubParser* sub)
        {
            float edge_r = 0.5f;
            auto color_color = Color::Red;
            sub->Add("-r, --range", &edge_r);
            sub->Add("-c, --color", &color_color);
            return sub->OnComplete
            (
                [&]
                {
                    ColorDetection(&image, color_color, edge_r);
                }
            );
        }
    );

    filters_subs->Add
    (
        "bright", "Change brightness",
        [&](argparse::SubParser* sub)
        {
            int bright_c = 10;
            sub->Add("-c, --change", &bright_c);
            return sub->OnComplete
            (
                [&]
                {
                    ChangeBrightness(&image, bright_c);
                }
            );
        }
    );

    filters_subs->Add
    (
        "contrast", "Change contrast",
        [&](argparse::SubParser* sub)
        {
            float contrast = 10;
            sub->Add("-c, --change", &contrast);
            return sub->OnComplete
            (
                [&]
                {
                    ChangeContrast(&image, contrast);
                }
            );
        }
    );

    return argparse::ParseFromMain(&parser, argc, argv);
}
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 *
 * 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 "hal/LowPowerTickerWrapper.h"
#include "platform/Callback.h"

LowPowerTickerWrapper::LowPowerTickerWrapper(const ticker_data_t *data, const ticker_interface_t *interface, uint32_t min_cycles_between_writes, uint32_t min_cycles_until_match)
    : _intf(data->interface), _min_count_between_writes(min_cycles_between_writes + 1), _min_count_until_match(min_cycles_until_match + 1), _suspended(false)
{
    core_util_critical_section_enter();

    this->data.interface = interface;
    this->data.queue = data->queue;
    _reset();

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::irq_handler(ticker_irq_handler_type handler)
{
    core_util_critical_section_enter();

    if (_suspended) {
        if (handler) {
            handler(&data);
        }
        core_util_critical_section_exit();
        return;
    }

    if (_pending_fire_now || _match_check(_intf->read())) {
        _timeout.detach();
        _pending_timeout = false;
        _pending_match = false;
        _pending_fire_now = false;
        if (handler) {
            handler(&data);
        }
    } else {
        // Spurious interrupt
        _intf->clear_interrupt();
    }

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::suspend()
{
    core_util_critical_section_enter();

    // Wait until rescheduling is allowed
    while (!_set_interrupt_allowed) {
        timestamp_t current = _intf->read();
        if (((current - _last_actual_set_interrupt) & _mask) >= _min_count_between_writes) {
            _set_interrupt_allowed  = true;
        }
    }

    _reset();
    _suspended = true;

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::resume()
{
    core_util_critical_section_enter();

    _suspended = false;

    core_util_critical_section_exit();
}

bool LowPowerTickerWrapper::timeout_pending()
{
    core_util_critical_section_enter();

    bool pending = _pending_timeout;

    core_util_critical_section_exit();
    return pending;
}

void LowPowerTickerWrapper::init()
{
    core_util_critical_section_enter();

    _reset();
    _intf->init();

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::free()
{
    core_util_critical_section_enter();

    _reset();
    _intf->free();

    core_util_critical_section_exit();
}

uint32_t LowPowerTickerWrapper::read()
{
    core_util_critical_section_enter();

    timestamp_t current = _intf->read();
    if (_match_check(current)) {
        _intf->fire_interrupt();
    }

    core_util_critical_section_exit();
    return current;
}

void LowPowerTickerWrapper::set_interrupt(timestamp_t timestamp)
{
    core_util_critical_section_enter();

    _last_set_interrupt = _intf->read();
    _cur_match_time = timestamp;
    _pending_match = true;
    _schedule_match(_last_set_interrupt);

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::disable_interrupt()
{
    core_util_critical_section_enter();

    _intf->disable_interrupt();

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::clear_interrupt()
{
    core_util_critical_section_enter();

    _intf->clear_interrupt();

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::fire_interrupt()
{
    core_util_critical_section_enter();

    _pending_fire_now = 1;
    _intf->fire_interrupt();

    core_util_critical_section_exit();
}

const ticker_info_t *LowPowerTickerWrapper::get_info()
{

    core_util_critical_section_enter();

    const ticker_info_t *info = _intf->get_info();

    core_util_critical_section_exit();
    return info;
}

void LowPowerTickerWrapper::_reset()
{
    MBED_ASSERT(core_util_in_critical_section());

    _timeout.detach();
    _pending_timeout = false;
    _pending_match = false;
    _pending_fire_now = false;
    _set_interrupt_allowed = true;
    _cur_match_time = 0;
    _last_set_interrupt = 0;
    _last_actual_set_interrupt = 0;

    const ticker_info_t *info = _intf->get_info();
    if (info->bits >= 32) {
        _mask = 0xffffffff;
    } else {
        _mask = ((uint64_t)1 << info->bits) - 1;
    }

    // Round us_per_tick up
    _us_per_tick = (1000000 + info->frequency - 1) / info->frequency;
}

void LowPowerTickerWrapper::_timeout_handler()
{
    core_util_critical_section_enter();
    _pending_timeout = false;

    timestamp_t current = _intf->read();
    /* Add extra check for '_last_set_interrupt == _cur_match_time'
     *
     * When '_last_set_interrupt == _cur_match_time', _ticker_match_interval_passed sees it as
     * one-round interval rather than just-pass, so add extra check for it. In rare cases, we
     * may trap in _timeout_handler/_schedule_match loop. This check can break it.
     */
    if ((_last_set_interrupt == _cur_match_time) ||
        _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time)) {
        _intf->fire_interrupt();
    } else {
        _schedule_match(current);
    }

    core_util_critical_section_exit();
}

bool LowPowerTickerWrapper::_match_check(timestamp_t current)
{
    MBED_ASSERT(core_util_in_critical_section());

    if (!_pending_match) {
        return false;
    }
    /* Add extra check for '_last_set_interrupt == _cur_match_time' as above */
    return (_last_set_interrupt == _cur_match_time) ||
        _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time);
}

uint32_t LowPowerTickerWrapper::_lp_ticks_to_us(uint32_t ticks)
{
    MBED_ASSERT(core_util_in_critical_section());

    // Add 4 microseconds to round up the micro second ticker time (which has a frequency of at least 250KHz - 4us period)
    return _us_per_tick * ticks + 4;
}

void LowPowerTickerWrapper::_schedule_match(timestamp_t current)
{
    MBED_ASSERT(core_util_in_critical_section());

    // Check if _intf->set_interrupt is allowed
    if (!_set_interrupt_allowed) {
        if (((current - _last_actual_set_interrupt) & _mask) >= _min_count_between_writes) {
            _set_interrupt_allowed  = true;
        }
    }

    uint32_t cycles_until_match = (_cur_match_time - current) & _mask;
    bool too_close = cycles_until_match < _min_count_until_match;

    if (!_set_interrupt_allowed) {

        // Can't use _intf->set_interrupt so use microsecond Timeout instead

        // Speed optimization - if a timer has already been scheduled
        // then don't schedule it again.
        if (!_pending_timeout) {
            uint32_t ticks = cycles_until_match < _min_count_until_match ? cycles_until_match : _min_count_until_match;
            _timeout.attach_us(mbed::callback(this, &LowPowerTickerWrapper::_timeout_handler), _lp_ticks_to_us(ticks));
            _pending_timeout = true;
        }
        return;
    }

    if (!too_close) {

        // Schedule LP ticker
        _intf->set_interrupt(_cur_match_time);
        current = _intf->read();
        _last_actual_set_interrupt = current;
        _set_interrupt_allowed  = false;

        // Check for overflow
        uint32_t new_cycles_until_match = (_cur_match_time - current) & _mask;
        if (new_cycles_until_match > cycles_until_match) {
            // Overflow so fire now
            _intf->fire_interrupt();
            return;
        }

        // Update variables with new time
        cycles_until_match = new_cycles_until_match;
        too_close = cycles_until_match < _min_count_until_match;
    }

    if (too_close) {

        // Low power ticker incremented to less than _min_count_until_match
        // so low power ticker may not fire. Use Timeout to ensure it does fire.
        uint32_t ticks = cycles_until_match < _min_count_until_match ? cycles_until_match : _min_count_until_match;
        _timeout.attach_us(mbed::callback(this, &LowPowerTickerWrapper::_timeout_handler), _lp_ticks_to_us(ticks));
        _pending_timeout = true;
        return;
    }
}
<commit_msg>low power ticker: fix astyle<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 *
 * 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 "hal/LowPowerTickerWrapper.h"
#include "platform/Callback.h"

LowPowerTickerWrapper::LowPowerTickerWrapper(const ticker_data_t *data, const ticker_interface_t *interface, uint32_t min_cycles_between_writes, uint32_t min_cycles_until_match)
    : _intf(data->interface), _min_count_between_writes(min_cycles_between_writes + 1), _min_count_until_match(min_cycles_until_match + 1), _suspended(false)
{
    core_util_critical_section_enter();

    this->data.interface = interface;
    this->data.queue = data->queue;
    _reset();

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::irq_handler(ticker_irq_handler_type handler)
{
    core_util_critical_section_enter();

    if (_suspended) {
        if (handler) {
            handler(&data);
        }
        core_util_critical_section_exit();
        return;
    }

    if (_pending_fire_now || _match_check(_intf->read())) {
        _timeout.detach();
        _pending_timeout = false;
        _pending_match = false;
        _pending_fire_now = false;
        if (handler) {
            handler(&data);
        }
    } else {
        // Spurious interrupt
        _intf->clear_interrupt();
    }

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::suspend()
{
    core_util_critical_section_enter();

    // Wait until rescheduling is allowed
    while (!_set_interrupt_allowed) {
        timestamp_t current = _intf->read();
        if (((current - _last_actual_set_interrupt) & _mask) >= _min_count_between_writes) {
            _set_interrupt_allowed  = true;
        }
    }

    _reset();
    _suspended = true;

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::resume()
{
    core_util_critical_section_enter();

    _suspended = false;

    core_util_critical_section_exit();
}

bool LowPowerTickerWrapper::timeout_pending()
{
    core_util_critical_section_enter();

    bool pending = _pending_timeout;

    core_util_critical_section_exit();
    return pending;
}

void LowPowerTickerWrapper::init()
{
    core_util_critical_section_enter();

    _reset();
    _intf->init();

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::free()
{
    core_util_critical_section_enter();

    _reset();
    _intf->free();

    core_util_critical_section_exit();
}

uint32_t LowPowerTickerWrapper::read()
{
    core_util_critical_section_enter();

    timestamp_t current = _intf->read();
    if (_match_check(current)) {
        _intf->fire_interrupt();
    }

    core_util_critical_section_exit();
    return current;
}

void LowPowerTickerWrapper::set_interrupt(timestamp_t timestamp)
{
    core_util_critical_section_enter();

    _last_set_interrupt = _intf->read();
    _cur_match_time = timestamp;
    _pending_match = true;
    _schedule_match(_last_set_interrupt);

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::disable_interrupt()
{
    core_util_critical_section_enter();

    _intf->disable_interrupt();

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::clear_interrupt()
{
    core_util_critical_section_enter();

    _intf->clear_interrupt();

    core_util_critical_section_exit();
}

void LowPowerTickerWrapper::fire_interrupt()
{
    core_util_critical_section_enter();

    _pending_fire_now = 1;
    _intf->fire_interrupt();

    core_util_critical_section_exit();
}

const ticker_info_t *LowPowerTickerWrapper::get_info()
{

    core_util_critical_section_enter();

    const ticker_info_t *info = _intf->get_info();

    core_util_critical_section_exit();
    return info;
}

void LowPowerTickerWrapper::_reset()
{
    MBED_ASSERT(core_util_in_critical_section());

    _timeout.detach();
    _pending_timeout = false;
    _pending_match = false;
    _pending_fire_now = false;
    _set_interrupt_allowed = true;
    _cur_match_time = 0;
    _last_set_interrupt = 0;
    _last_actual_set_interrupt = 0;

    const ticker_info_t *info = _intf->get_info();
    if (info->bits >= 32) {
        _mask = 0xffffffff;
    } else {
        _mask = ((uint64_t)1 << info->bits) - 1;
    }

    // Round us_per_tick up
    _us_per_tick = (1000000 + info->frequency - 1) / info->frequency;
}

void LowPowerTickerWrapper::_timeout_handler()
{
    core_util_critical_section_enter();
    _pending_timeout = false;

    timestamp_t current = _intf->read();
    /* Add extra check for '_last_set_interrupt == _cur_match_time'
     *
     * When '_last_set_interrupt == _cur_match_time', _ticker_match_interval_passed sees it as
     * one-round interval rather than just-pass, so add extra check for it. In rare cases, we
     * may trap in _timeout_handler/_schedule_match loop. This check can break it.
     */
    if ((_last_set_interrupt == _cur_match_time) ||
            _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time)) {
        _intf->fire_interrupt();
    } else {
        _schedule_match(current);
    }

    core_util_critical_section_exit();
}

bool LowPowerTickerWrapper::_match_check(timestamp_t current)
{
    MBED_ASSERT(core_util_in_critical_section());

    if (!_pending_match) {
        return false;
    }
    /* Add extra check for '_last_set_interrupt == _cur_match_time' as above */
    return (_last_set_interrupt == _cur_match_time) ||
           _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time);
}

uint32_t LowPowerTickerWrapper::_lp_ticks_to_us(uint32_t ticks)
{
    MBED_ASSERT(core_util_in_critical_section());

    // Add 4 microseconds to round up the micro second ticker time (which has a frequency of at least 250KHz - 4us period)
    return _us_per_tick * ticks + 4;
}

void LowPowerTickerWrapper::_schedule_match(timestamp_t current)
{
    MBED_ASSERT(core_util_in_critical_section());

    // Check if _intf->set_interrupt is allowed
    if (!_set_interrupt_allowed) {
        if (((current - _last_actual_set_interrupt) & _mask) >= _min_count_between_writes) {
            _set_interrupt_allowed  = true;
        }
    }

    uint32_t cycles_until_match = (_cur_match_time - current) & _mask;
    bool too_close = cycles_until_match < _min_count_until_match;

    if (!_set_interrupt_allowed) {

        // Can't use _intf->set_interrupt so use microsecond Timeout instead

        // Speed optimization - if a timer has already been scheduled
        // then don't schedule it again.
        if (!_pending_timeout) {
            uint32_t ticks = cycles_until_match < _min_count_until_match ? cycles_until_match : _min_count_until_match;
            _timeout.attach_us(mbed::callback(this, &LowPowerTickerWrapper::_timeout_handler), _lp_ticks_to_us(ticks));
            _pending_timeout = true;
        }
        return;
    }

    if (!too_close) {

        // Schedule LP ticker
        _intf->set_interrupt(_cur_match_time);
        current = _intf->read();
        _last_actual_set_interrupt = current;
        _set_interrupt_allowed  = false;

        // Check for overflow
        uint32_t new_cycles_until_match = (_cur_match_time - current) & _mask;
        if (new_cycles_until_match > cycles_until_match) {
            // Overflow so fire now
            _intf->fire_interrupt();
            return;
        }

        // Update variables with new time
        cycles_until_match = new_cycles_until_match;
        too_close = cycles_until_match < _min_count_until_match;
    }

    if (too_close) {

        // Low power ticker incremented to less than _min_count_until_match
        // so low power ticker may not fire. Use Timeout to ensure it does fire.
        uint32_t ticks = cycles_until_match < _min_count_until_match ? cycles_until_match : _min_count_until_match;
        _timeout.attach_us(mbed::callback(this, &LowPowerTickerWrapper::_timeout_handler), _lp_ticks_to_us(ticks));
        _pending_timeout = true;
        return;
    }
}
<|endoftext|>