<|start_filename|>lib/cpp/src/thrift/transport/TSocketPool.cpp<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 <thrift/thrift-config.h>

#include <algorithm>
#include <iostream>
#if __cplusplus >= 201703L
#include <random>
#endif

#include <thrift/transport/TSocketPool.h>

using std::pair;
using std::string;
using std::vector;

namespace apache {
namespace thrift {
namespace transport {

using stdcxx::shared_ptr;

/**
 * TSocketPoolServer implementation
 *
 */
TSocketPoolServer::TSocketPoolServer()
  : host_(""), port_(0), socket_(THRIFT_INVALID_SOCKET), lastFailTime_(0), consecutiveFailures_(0) {
}

/**
 * Constructor for TSocketPool server
 */
TSocketPoolServer::TSocketPoolServer(const string& host, int port)
  : host_(host),
    port_(port),
    socket_(THRIFT_INVALID_SOCKET),
    lastFailTime_(0),
    consecutiveFailures_(0) {
}

/**
 * TSocketPool implementation.
 *
 */

TSocketPool::TSocketPool()
  : TSocket(),
    numRetries_(1),
    retryInterval_(60),
    maxConsecutiveFailures_(1),
    randomize_(true),
    alwaysTryLast_(true) {
}

TSocketPool::TSocketPool(const vector<string>& hosts, const vector<int>& ports)
  : TSocket(),
    numRetries_(1),
    retryInterval_(60),
    maxConsecutiveFailures_(1),
    randomize_(true),
    alwaysTryLast_(true) {
  if (hosts.size() != ports.size()) {
    GlobalOutput("TSocketPool::TSocketPool: hosts.size != ports.size");
    throw TTransportException(TTransportException::BAD_ARGS);
  }

  for (unsigned int i = 0; i < hosts.size(); ++i) {
    addServer(hosts[i], ports[i]);
  }
}

TSocketPool::TSocketPool(const vector<pair<string, int> >& servers)
  : TSocket(),
    numRetries_(1),
    retryInterval_(60),
    maxConsecutiveFailures_(1),
    randomize_(true),
    alwaysTryLast_(true) {
  for (unsigned i = 0; i < servers.size(); ++i) {
    addServer(servers[i].first, servers[i].second);
  }
}

TSocketPool::TSocketPool(const vector<shared_ptr<TSocketPoolServer> >& servers)
  : TSocket(),
    servers_(servers),
    numRetries_(1),
    retryInterval_(60),
    maxConsecutiveFailures_(1),
    randomize_(true),
    alwaysTryLast_(true) {
}

TSocketPool::TSocketPool(const string& host, int port)
  : TSocket(),
    numRetries_(1),
    retryInterval_(60),
    maxConsecutiveFailures_(1),
    randomize_(true),
    alwaysTryLast_(true) {
  addServer(host, port);
}

TSocketPool::~TSocketPool() {
  vector<shared_ptr<TSocketPoolServer> >::const_iterator iter = servers_.begin();
  vector<shared_ptr<TSocketPoolServer> >::const_iterator iterEnd = servers_.end();
  for (; iter != iterEnd; ++iter) {
    setCurrentServer(*iter);
    TSocketPool::close();
  }
}

void TSocketPool::addServer(const string& host, int port) {
  servers_.push_back(shared_ptr<TSocketPoolServer>(new TSocketPoolServer(host, port)));
}

void TSocketPool::addServer(shared_ptr<TSocketPoolServer>& server) {
  if (server) {
    servers_.push_back(server);
  }
}

void TSocketPool::setServers(const vector<shared_ptr<TSocketPoolServer> >& servers) {
  servers_ = servers;
}

void TSocketPool::getServers(vector<shared_ptr<TSocketPoolServer> >& servers) {
  servers = servers_;
}

void TSocketPool::setNumRetries(int numRetries) {
  numRetries_ = numRetries;
}

void TSocketPool::setRetryInterval(int retryInterval) {
  retryInterval_ = retryInterval;
}

void TSocketPool::setMaxConsecutiveFailures(int maxConsecutiveFailures) {
  maxConsecutiveFailures_ = maxConsecutiveFailures;
}

void TSocketPool::setRandomize(bool randomize) {
  randomize_ = randomize;
}

void TSocketPool::setAlwaysTryLast(bool alwaysTryLast) {
  alwaysTryLast_ = alwaysTryLast;
}

void TSocketPool::setCurrentServer(const shared_ptr<TSocketPoolServer>& server) {
  currentServer_ = server;
  host_ = server->host_;
  port_ = server->port_;
  socket_ = server->socket_;
}

/**
 * This function throws an exception if socket open fails. When socket
 * opens fails, the socket in the current server is reset.
 */
/* TODO: without apc we ignore a lot of functionality from the php version */
void TSocketPool::open() {

  size_t numServers = servers_.size();
  if (numServers == 0) {
    socket_ = THRIFT_INVALID_SOCKET;
    throw TTransportException(TTransportException::NOT_OPEN);
  }

  if (isOpen()) {
    return;
  }

  if (randomize_ && numServers > 1) {
#if __cplusplus >= 201703L
    std::random_device rng;
    std::mt19937 urng(rng());
    std::shuffle(servers_.begin(), servers_.end(), urng);
#else
    std::random_shuffle(servers_.begin(), servers_.end());
#endif
  }

  for (size_t i = 0; i < numServers; ++i) {

    shared_ptr<TSocketPoolServer>& server = servers_[i];
    // Impersonate the server socket
    setCurrentServer(server);

    if (isOpen()) {
      // already open means we're done
      return;
    }

    bool retryIntervalPassed = (server->lastFailTime_ == 0);
    bool isLastServer = alwaysTryLast_ ? (i == (numServers - 1)) : false;

    if (server->lastFailTime_ > 0) {
      // The server was marked as down, so check if enough time has elapsed to retry
      time_t elapsedTime = time(NULL) - server->lastFailTime_;
      if (elapsedTime > retryInterval_) {
        retryIntervalPassed = true;
      }
    }

    if (retryIntervalPassed || isLastServer) {
      for (int j = 0; j < numRetries_; ++j) {
        try {
          TSocket::open();
        } catch (const TException &e) {
          string errStr = "TSocketPool::open failed " + getSocketInfo() + ": " + e.what();
          GlobalOutput(errStr.c_str());
          socket_ = THRIFT_INVALID_SOCKET;
          continue;
        }

        // Copy over the opened socket so that we can keep it persistent
        server->socket_ = socket_;
        // reset lastFailTime_ is required
        server->lastFailTime_ = 0;
        // success
        return;
      }

      ++server->consecutiveFailures_;
      if (server->consecutiveFailures_ > maxConsecutiveFailures_) {
        // Mark server as down
        server->consecutiveFailures_ = 0;
        server->lastFailTime_ = time(NULL);
      }
    }
  }

  GlobalOutput("TSocketPool::open: all connections failed");
  throw TTransportException(TTransportException::NOT_OPEN);
}

void TSocketPool::close() {
  TSocket::close();
  if (currentServer_) {
    currentServer_->socket_ = THRIFT_INVALID_SOCKET;
  }
}
}
}
} // apache::thrift::transport


<|start_filename|>lib/nodejs/test/server.js<|end_filename|>
#!/usr/bin/env node

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

const fs = require("fs");
const path = require("path");
const thrift = require("../lib/thrift");
const program = require("commander");
const helpers = require("./helpers");

program
  .option(
    "-p, --protocol <protocol>",
    "Set thrift protocol (binary|compact|json)",
    "binary"
  )
  .option(
    "-t, --transport <transport>",
    "Set thrift transport (buffered|framed|http)",
    "buffered"
  )
  .option("--ssl", "use ssl transport")
  .option("--port <port>", "Set thrift server port", 9090)
  .option("--domain-socket <path>", "Set thift server unix domain socket")
  .option(
    "-t, --type <type>",
    "Select server type (http|multiplex|tcp|websocket)",
    "tcp"
  )
  .option("--callback", "test with callback style functions")
  .option("--es6", "Use es6 code")
  .option("--es5", "Use es5 code")
  .parse(process.argv);

const ThriftTest = require(`./${helpers.genPath}/ThriftTest`);
const SecondService = require(`./${helpers.genPath}/SecondService`);
const { ThriftTestHandler } = require("./test_handler");

const port = program.port;
const domainSocket = program.domainSocket;
const ssl = program.ssl;

let type = program.type;
if (program.transport === "http") {
  program.transport = "buffered";
  type = "http";
}

let options = {
  transport: helpers.transports[program.transport],
  protocol: helpers.protocols[program.protocol]
};

if (type === "http" || type === "websocket") {
  options.handler = ThriftTestHandler;
  options.processor = ThriftTest;

  options = {
    services: { "/test": options },
    cors: {
      "*": true
    }
  };
}

let processor;
if (type === "multiplex") {
  const SecondServiceHandler = {
    secondtestString: function(thing, result) {
      console.log('testString("' + thing + '")');
      result(null, 'testString("' + thing + '")');
    }
  };

  processor = new thrift.MultiplexedProcessor();

  processor.registerProcessor(
    "ThriftTest",
    new ThriftTest.Processor(ThriftTestHandler)
  );

  processor.registerProcessor(
    "SecondService",
    new SecondService.Processor(SecondServiceHandler)
  );
}

if (ssl) {
  if (
    type === "tcp" ||
    type === "multiplex" ||
    type === "http" ||
    type === "websocket"
  ) {
    options.tls = {
      key: fs.readFileSync(path.resolve(__dirname, "server.key")),
      cert: fs.readFileSync(path.resolve(__dirname, "server.crt"))
    };
  }
}

let server;
if (type === "tcp") {
  server = thrift.createServer(ThriftTest, ThriftTestHandler, options);
} else if (type === "multiplex") {
  server = thrift.createMultiplexServer(processor, options);
} else if (type === "http" || type === "websocket") {
  server = thrift.createWebServer(options);
}

if (domainSocket) {
  server.listen(domainSocket);
} else if (
  type === "tcp" ||
  type === "multiplex" ||
  type === "http" ||
  type === "websocket"
) {
  server.listen(port);
}


<|start_filename|>lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 <thrift/c_glib/thrift.h>
#include <thrift/c_glib/protocol/thrift_protocol.h>
#include <thrift/c_glib/transport/thrift_transport.h>

/* define the GError domain string */
#define THRIFT_PROTOCOL_ERROR_DOMAIN "thrift-protocol-error-quark"

/* object properties */
enum _ThriftProtocolProperties
{
  PROP_0,
  PROP_THRIFT_PROTOCOL_TRANSPORT
};

G_DEFINE_ABSTRACT_TYPE(ThriftProtocol, thrift_protocol, G_TYPE_OBJECT)

void
thrift_protocol_get_property (GObject *object, guint property_id,
                              GValue *value, GParamSpec *pspec)
{
  ThriftProtocol *protocol = THRIFT_PROTOCOL (object);

  THRIFT_UNUSED_VAR (pspec);

  switch (property_id)
  {
    case PROP_THRIFT_PROTOCOL_TRANSPORT:
      g_value_set_object (value, protocol->transport);
      break;
  }
}

void
thrift_protocol_set_property (GObject *object, guint property_id,
                              const GValue *value, GParamSpec *pspec)
{

  ThriftProtocol *protocol = THRIFT_PROTOCOL (object);

  THRIFT_UNUSED_VAR (pspec);

  switch (property_id)
  {
    case PROP_THRIFT_PROTOCOL_TRANSPORT:
      protocol->transport = g_value_dup_object (value);
      break;
  }
}


gint32
thrift_protocol_write_message_begin (ThriftProtocol *protocol,
                                     const gchar *name,
                                     const ThriftMessageType message_type,
                                     const gint32 seqid, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_message_begin
                                                   (protocol, name,
                                                    message_type, seqid,
                                                    error);
}

gint32
thrift_protocol_write_message_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_message_end (protocol,
                                                                  error);
}

gint32
thrift_protocol_write_struct_begin (ThriftProtocol *protocol, const gchar *name,
                                    GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_struct_begin (protocol,
                                                   name, error);
}

gint32
thrift_protocol_write_struct_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_struct_end (protocol,
                                                                 error);
}

gint32
thrift_protocol_write_field_begin (ThriftProtocol *protocol,
                                   const gchar *name,
                                   const ThriftType field_type,
                                   const gint16 field_id,
                                   GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_begin (protocol,
                                                   name, field_type,
                                                   field_id, error);
}

gint32
thrift_protocol_write_field_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_end (protocol,
                                                                error);
}

gint32
thrift_protocol_write_field_stop (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_stop (protocol,
                                                                 error);
}

gint32
thrift_protocol_write_map_begin (ThriftProtocol *protocol,
                                 const ThriftType key_type,
                                 const ThriftType value_type,
                                 const guint32 size, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_map_begin (protocol,
                                                   key_type, value_type,
                                                   size, error);
}

gint32
thrift_protocol_write_map_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_map_end (protocol,
                                                              error);
}

gint32
thrift_protocol_write_list_begin (ThriftProtocol *protocol,
                                  const ThriftType element_type,
                                  const guint32 size, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_list_begin (protocol,
                                                   element_type, size,
                                                   error);
}

gint32
thrift_protocol_write_list_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_list_end (protocol,
                                                               error);
}

gint32
thrift_protocol_write_set_begin (ThriftProtocol *protocol,
                                 const ThriftType element_type,
                                 const guint32 size, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_set_begin (protocol,
                                                   element_type, size,
                                                   error);
}

gint32
thrift_protocol_write_set_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_set_end (protocol,
                                                              error);
}

gint32
thrift_protocol_write_bool (ThriftProtocol *protocol,
                            const gboolean value, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_bool (protocol, value,
                                                           error);
}

gint32
thrift_protocol_write_byte (ThriftProtocol *protocol, const gint8 value,
                            GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_byte (protocol, value,
                                                           error);
}

gint32
thrift_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value,
                           GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i16 (protocol, value,
                                                          error);
}

gint32
thrift_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value,
                           GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i32 (protocol, value,
                                                          error);
}

gint32
thrift_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value,
                           GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i64 (protocol, value,
                                                          error);
}

gint32
thrift_protocol_write_double (ThriftProtocol *protocol,
                              const gdouble value, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_double (protocol,
                                                             value, error);
}

gint32
thrift_protocol_write_string (ThriftProtocol *protocol,
                              const gchar *str, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_string (protocol, str,
                                                             error);
}

gint32
thrift_protocol_write_binary (ThriftProtocol *protocol, const gpointer buf,
                              const guint32 len, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_binary (protocol, buf,
                                                             len, error);
}

gint32
thrift_protocol_read_message_begin (ThriftProtocol *protocol,
                                    gchar **name,
                                    ThriftMessageType *message_type,
                                    gint32 *seqid, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_message_begin (protocol,
                                                   name, message_type,
                                                   seqid, error);
}

gint32
thrift_protocol_read_message_end (ThriftProtocol *protocol,
                                  GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_message_end (protocol,
                                                                 error);
}

gint32
thrift_protocol_read_struct_begin (ThriftProtocol *protocol,
                                   gchar **name,
                                   GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_struct_begin (protocol,
                                                                  name,
                                                                  error);
}

gint32
thrift_protocol_read_struct_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_struct_end (protocol,
                                                                error);
}

gint32
thrift_protocol_read_field_begin (ThriftProtocol *protocol,
                                  gchar **name,
                                  ThriftType *field_type,
                                  gint16 *field_id,
                                  GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_field_begin (protocol,
                                                                 name,
                                                                 field_type,
                                                                 field_id,
                                                                 error);
}

gint32
thrift_protocol_read_field_end (ThriftProtocol *protocol,
                                GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_field_end (protocol,
                                                               error);
}

gint32
thrift_protocol_read_map_begin (ThriftProtocol *protocol,
                                ThriftType *key_type,
                                ThriftType *value_type, guint32 *size,
                                GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_map_begin (protocol,
                                                               key_type,
                                                               value_type,
                                                               size,
                                                               error);
}

gint32
thrift_protocol_read_map_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_map_end (protocol,
                                                             error);
}

gint32
thrift_protocol_read_list_begin (ThriftProtocol *protocol,
                                 ThriftType *element_type,
                                 guint32 *size, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_list_begin (protocol,
                                                                element_type,
                                                                size, error);
}

gint32
thrift_protocol_read_list_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_list_end (protocol,
                                                              error);
}

gint32
thrift_protocol_read_set_begin (ThriftProtocol *protocol,
                                ThriftType *element_type,
                                guint32 *size, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_set_begin (protocol,
                                                               element_type,
                                                               size, error);
}

gint32
thrift_protocol_read_set_end (ThriftProtocol *protocol, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_set_end (protocol,
                                                             error);
}

gint32
thrift_protocol_read_bool (ThriftProtocol *protocol, gboolean *value,
                           GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_bool (protocol, value,
                                                          error);
}

gint32
thrift_protocol_read_byte (ThriftProtocol *protocol, gint8 *value,
                           GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_byte (protocol, value,
                                                          error);
}

gint32
thrift_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value,
                          GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i16 (protocol, value,
                                                         error);
}

gint32
thrift_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value,
                          GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i32 (protocol, value,
                                                         error);
}

gint32
thrift_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value,
                          GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i64 (protocol, value,
                                                         error);
}

gint32
thrift_protocol_read_double (ThriftProtocol *protocol,
                             gdouble *value, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_double (protocol, value,
                                                            error);
}

gint32
thrift_protocol_read_string (ThriftProtocol *protocol,
                             gchar **str, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_string (protocol, str,
                                                            error);
}

gint32
thrift_protocol_read_binary (ThriftProtocol *protocol, gpointer *buf,
                             guint32 *len, GError **error)
{
  return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_binary (protocol, buf,
                                                            len, error);
}

gint32
thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error)
{
  switch (type)
  {
    case T_BOOL:
      {
        gboolean boolv;
        return thrift_protocol_read_bool (protocol, &boolv, error);
      }
    case T_BYTE:
      {
        gint8 bytev;
        return thrift_protocol_read_byte (protocol, &bytev, error);
      }

    case T_I16:
      {
        gint16 i16;
        return thrift_protocol_read_i16 (protocol, &i16, error);
      }
    case T_I32:
      {
        gint32 i32;
        return thrift_protocol_read_i32 (protocol, &i32, error);
      }
    case T_I64:
      {
        gint64 i64;
        return thrift_protocol_read_i64 (protocol, &i64, error);
      }
    case T_DOUBLE:
      {
        gdouble dub;
        return thrift_protocol_read_double (protocol, &dub, error);
      }
    case T_STRING:
      {
        gpointer data;
        guint32 len;
        gint32 ret = thrift_protocol_read_binary (protocol, &data, &len, error);
        g_free (data);
        return ret;
      }
    case T_STRUCT:
      {
        gint32 result = 0;
        gchar *name;
        gint16 fid;
        ThriftType ftype;
        result += thrift_protocol_read_struct_begin (protocol, &name, error);

        while (1)
        {
          result += thrift_protocol_read_field_begin (protocol, &name, &ftype,
                                                      &fid, error);
          if (result < 0)
          {
            return result;  
          }
          if (ftype == T_STOP)
          {
            break;
          }
          result += thrift_protocol_skip (protocol, ftype, error);
          result += thrift_protocol_read_field_end (protocol, error);
        }
        result += thrift_protocol_read_struct_end (protocol, error);
        return result;
      }
    case T_SET:
      {
        gint32 result = 0;
        ThriftType elem_type;
        guint32 i, size;
        result += thrift_protocol_read_set_begin (protocol, &elem_type, &size,
                                                  error);
        for (i = 0; i < size; i++)
        {
          result += thrift_protocol_skip (protocol, elem_type, error);
        }
        result += thrift_protocol_read_set_end (protocol, error);
        return result;
      }
    case T_MAP:
      {
        gint32 result = 0;
        ThriftType elem_type;
        ThriftType key_type;
        guint32 i, size;
        result += thrift_protocol_read_map_begin (protocol, &key_type, &elem_type, &size,
                                                  error);
        for (i = 0; i < size; i++)
        {
          result += thrift_protocol_skip (protocol, key_type, error);
          result += thrift_protocol_skip (protocol, elem_type, error);
        }
        result += thrift_protocol_read_map_end (protocol, error);
        return result;
      }
    case T_LIST:
      {
        gint32 result = 0;
        ThriftType elem_type;
        guint32 i, size;
        result += thrift_protocol_read_list_begin (protocol, &elem_type, &size,
                                                   error);
        for (i = 0; i < size; i++)
        {
          result += thrift_protocol_skip (protocol, elem_type, error);
        }
        result += thrift_protocol_read_list_end (protocol, error);
        return result;
      }
    default:
      return 0;
  }
}

/* define the GError domain for Thrift protocols */
GQuark
thrift_protocol_error_quark (void)
{
  return g_quark_from_static_string (THRIFT_PROTOCOL_ERROR_DOMAIN);
}


static void
thrift_protocol_init (ThriftProtocol *protocol)
{
  protocol->transport = NULL;
}

static void
thrift_protocol_dispose (GObject *gobject)
{
  ThriftProtocol *self = THRIFT_PROTOCOL (gobject);

  g_clear_object(&self->transport);

  /* Always chain up to the parent class; there is no need to check if
   * the parent class implements the dispose() virtual function: it is
   * always guaranteed to do so
   */
  G_OBJECT_CLASS (thrift_protocol_parent_class)->dispose(gobject);
}

static void
thrift_protocol_class_init (ThriftProtocolClass *cls)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (cls);

  gobject_class->get_property = thrift_protocol_get_property;
  gobject_class->set_property = thrift_protocol_set_property;
  gobject_class->dispose = thrift_protocol_dispose;

  g_object_class_install_property (gobject_class,
      PROP_THRIFT_PROTOCOL_TRANSPORT,
      g_param_spec_object ("transport", "Transport", "Thrift Transport",
                           THRIFT_TYPE_TRANSPORT,
                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));

  cls->write_message_begin = thrift_protocol_write_message_begin;
  cls->write_message_end = thrift_protocol_write_message_end;
  cls->write_struct_begin = thrift_protocol_write_struct_begin;
  cls->write_struct_end = thrift_protocol_write_struct_end;
  cls->write_field_begin = thrift_protocol_write_field_begin;
  cls->write_field_end = thrift_protocol_write_field_end;
  cls->write_field_stop = thrift_protocol_write_field_stop;
  cls->write_map_begin = thrift_protocol_write_map_begin;
  cls->write_map_end = thrift_protocol_write_map_end;
  cls->write_list_begin = thrift_protocol_write_list_begin;
  cls->write_list_end = thrift_protocol_write_list_end;
  cls->write_set_begin = thrift_protocol_write_set_begin;
  cls->write_set_end = thrift_protocol_write_set_end;
  cls->write_bool = thrift_protocol_write_bool;
  cls->write_byte = thrift_protocol_write_byte;
  cls->write_i16 = thrift_protocol_write_i16;
  cls->write_i32 = thrift_protocol_write_i32;
  cls->write_i64 = thrift_protocol_write_i64;
  cls->write_double = thrift_protocol_write_double;
  cls->write_string = thrift_protocol_write_string;
  cls->write_binary = thrift_protocol_write_binary;
  cls->read_message_begin = thrift_protocol_read_message_begin;
  cls->read_message_end = thrift_protocol_read_message_end;
  cls->read_struct_begin = thrift_protocol_read_struct_begin;
  cls->read_struct_end = thrift_protocol_read_struct_end;
  cls->read_field_begin = thrift_protocol_read_field_begin;
  cls->read_field_end = thrift_protocol_read_field_end;
  cls->read_map_begin = thrift_protocol_read_map_begin;
  cls->read_map_end = thrift_protocol_read_map_end;
  cls->read_list_begin = thrift_protocol_read_list_begin;
  cls->read_set_begin = thrift_protocol_read_set_begin;
  cls->read_set_end = thrift_protocol_read_set_end;
  cls->read_bool = thrift_protocol_read_bool;
  cls->read_byte = thrift_protocol_read_byte;
  cls->read_i16 = thrift_protocol_read_i16;
  cls->read_i32 = thrift_protocol_read_i32;
  cls->read_i64 = thrift_protocol_read_i64;
  cls->read_double = thrift_protocol_read_double;
  cls->read_string = thrift_protocol_read_string;
  cls->read_binary = thrift_protocol_read_binary;
}


<|start_filename|>test/go/src/bin/testserver/main.go<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

package main

import (
	"common"
	"flag"
	"fmt"
	"log"
	"net/http"
	"thrift"
)

var host = flag.String("host", "localhost", "Host to connect")
var port = flag.Int64("port", 9090, "Port number to connect")
var domain_socket = flag.String("domain-socket", "", "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port")
var transport = flag.String("transport", "buffered", "Transport: buffered, framed, http, zlib")
var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json")
var ssl = flag.Bool("ssl", false, "Encrypted Transport using SSL")
var zlib = flag.Bool("zlib", false, "Wrapped Transport using Zlib")
var certPath = flag.String("certPath", "keys", "Directory that contains SSL certificates")

func main() {
	flag.Parse()

	processor, serverTransport, transportFactory, protocolFactory, err := common.GetServerParams(*host, *port, *domain_socket, *transport, *protocol, *ssl, *certPath, common.PrintingHandler)

	if err != nil {
		log.Fatalf("Unable to process server params: ", err)
	}

	if *transport == "http" {
		http.HandleFunc("/", thrift.NewThriftHandlerFunc(processor, protocolFactory, protocolFactory))

		if *ssl {
			err := http.ListenAndServeTLS(fmt.Sprintf(":%d", *port),
				*certPath+"/server.pem", *certPath+"/server.key", nil)

			if err != nil {
				fmt.Println(err)
				return
			}
		} else {
			http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)
		}
	} else {
		server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
		if err = server.Listen(); err != nil {
			return
		}
		go server.AcceptLoop()
		server.Serve()
	}
}
