// Copyright 2016 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 "vpn_instance.h"

#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <openconnect.h>
#include <netdb.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#include <functional>
#include <queue>

#include "nacl_io/nacl_io.h"
#include "ppapi/c/ppb_console.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array.h"
#include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/cpp/var_dictionary.h"

namespace {

// keys
const char* const kCmd = "cmd";
const char* const kData = "data";

// js -> nacl
const char* const kConnect = "connect";
const char* const kDisconnect = "disconnect";
const char* const kPause = "pause";
const char* const kResume = "resume";
const char* const kReconnect = "reconnect";
const char* const kCmdDebug = "debug";
const char* const kCryptoGetCert = "crypto-getcert";
const char* const kCryptoGetPrivkey = "crypto-getprivkey";
const char* const kCryptoSign = "crypto-sign";

// nacl -> js
const char* const kStatus = "status";
const char* const kIp = "ip";
const char* const kAuthForm = "auth_form";
const char* const kPeerCert = "peer_cert";
const char* const kAbort = "abort";

// other parameters
const char* const kUrl = "url";

// ip_info fields
const char* const kGatewayIps = "gateway_ips";
const char* const kIpv4Addr = "ipv4_addr";
const char* const kIpv4Netmask = "ipv4_netmask";
const char* const kIpv6Addr = "ipv6_addr";
const char* const kIpv6Netmask = "ipv6_netmask";
const char* const kDns = "dns";
const char* const kNbns = "nbns";
const char* const kDomain = "domain";
const char* const kProxyPac = "proxy_pac";
const char* const kMtu = "mtu";
const char* const kSplitDns = "split_dns";
const char* const kSplitIncludes = "split_includes";
const char* const kSplitExcludes = "split_excludes";

// status values
const char* const kConnected = "connected";
const char* const kReconnected = "reconnected";
const char* const kDisconnected = "disconnected";

// oc_auth_form fields
const char* const kFormBanner = "banner";
const char* const kFormMessage = "message";
const char* const kFormError = "error";
const char* const kFormAuthId = "auth_id";
const char* const kFormMethod = "method";
const char* const kFormAction = "action";
const char* const kFormOpts = "opts";
const char* const kFormAuthgroupSelection = "authgroup_selection";

// oc_form_opt and oc_form_opt_select fields
const char* const kOptType = "type";
const char* const kOptName = "name";
const char* const kOptLabel = "label";
const char* const kOptFlags = "flags";
const char* const kOptChoices = "choices";

// OC_FORM_OPT_* enums
const char* const kOptTypeText = "text";
const char* const kOptTypePassword = "password";
const char* const kOptTypeSelect = "select";
const char* const kOptTypeHidden = "hidden";
const char* const kOptTypeToken = "token";
const char* const kOptTypeUnknown = "unknown";
const char* const kOptFlagIgnore = "ignore";
const char* const kOptFlagNumeric = "numeric";

// oc_choice fields
const char* const kChoiceName = "name";
const char* const kChoiceLabel = "label";
const char* const kChoiceAuthType = "auth_type";
const char* const kChoiceOverrideName = "override_name";
const char* const kChoiceOverrideLabel = "override_label";

// js -> nacl auth_form results
const char* const kResult = "result";
const char* const kSubmit = "submit";
const char* const kCancel = "cancel";
const char* const kNewgroup = "newgroup";

// peer cert validation
const char* const kReason = "reason";
const char* const kHostname = "hostname";
const char* const kCertChain = "cert_chain";
const char* const kCertHash = "cert_hash";
const char* const kAccept = "accept";

// crypto fields
const char* const kHash = "hash";
const char* const kClientCert = "client_cert";
const char* const kSuccess = "success";
const char* const kPrivkeyType = "privkey_type";

// misc constants
const int kReconnectTimeout = 180;
const int kReconnectInterval = 5;

}  // namespace

namespace vpn_nacl {

VpnInstance::VpnInstance(PP_Instance instance) :
    pp::Instance(instance) {
  nacl_io_init_ppapi(instance, pp::Module::Get()->get_browser_interface());
  core_ = pp::Module::Get()->core();
  debug_enabled_ = false;
  InitBackgroundThreads();

  pthread_mutex_init(&lib_mutex_, NULL);

  pthread_cond_init(&auth_result_ready_, NULL);
  pthread_mutex_init(&auth_result_mutex_, NULL);

  pthread_cond_init(&crypto_result_ready_, NULL);
  pthread_mutex_init(&crypto_result_mutex_, NULL);

  crypto_ = new Crypto(this);
}

void VpnInstance::HandleMessage(const pp::Var& var_message) {
  // data from kernel
  if (var_message.is_array_buffer()) {
    pp::VarArrayBuffer* pkt = new pp::VarArrayBuffer(var_message);

    pthread_mutex_lock(&rx_data_mutex_);
    rx_queue_.push(pkt);
    pthread_cond_signal(&rx_data_ready_);
    pthread_mutex_unlock(&rx_data_mutex_);

    return;
  }

  if (!var_message.is_dictionary()) {
    Log(kFatal, "malformed message: not a dictionary");
    return;
  }

  pp::VarDictionary* dict = new pp::VarDictionary(var_message);
  std::string cmd = dict->Get(kCmd).AsString();

  if (cmd == kConnect) {
    SetDesiredState(kStateRunning);
    // dict is passed to ConnectionThread as connect_options_
    Connect(dict);
    return;
  } else if (cmd == kAuthForm || cmd == kPeerCert) {
    // stored in auth_result_
    SendAuthResult(dict);
    return;
  } else if (cmd == kCryptoGetCert || cmd == kCryptoGetPrivkey ||
             cmd == kCryptoSign) {
    // stored in crypto_result_
    SendCryptoResult(dict);
    return;
  } else if (cmd == kDisconnect) {
    SetDesiredState(kStateDisconnected);
    SendCommand(OC_CMD_CANCEL);
  } else if (cmd == kPause) {
    SetDesiredState(kStatePaused);
    SendCommand(OC_CMD_PAUSE);
  } else if (cmd == kResume) {
    SetDesiredState(kStateRunning);
  } else if (cmd == kReconnect) {
    // i.e. drop connection, then immediate reinstate it
    SetDesiredState(kStateRunning);
    SendCommand(OC_CMD_PAUSE);
  } else if (cmd == kCmdDebug) {
    debug_enabled_ = dict->Get(kData).AsBool();
  } else {
    Log(kError, "unrecognized command '%s'", cmd.c_str());
  }

  delete dict;
}

int VpnInstance::CryptoGetCert(std::string& sha256,
                               void** cert_der,
                               size_t* cert_der_len) {
  pp::VarDictionary cmd_dict;

  cmd_dict.Set(kCmd, kCryptoGetCert);
  cmd_dict.Set(kHash, sha256);

  pthread_mutex_lock(&crypto_result_mutex_);
  PostMessage(cmd_dict);
  pthread_cond_wait(&crypto_result_ready_, &crypto_result_mutex_);

  *cert_der = nullptr;
  pp::Var cert_der_var = crypto_result_->Get(kData);
  if (cert_der_var.is_array_buffer()) {
    pp::VarArrayBuffer buf(cert_der_var);
    *cert_der_len = buf.ByteLength();
    *cert_der = malloc(*cert_der_len);
    if (*cert_der) {
      memcpy(*cert_der, buf.Map(), *cert_der_len);
    }
  }

  delete crypto_result_;
  crypto_result_ = nullptr;
  pthread_mutex_unlock(&crypto_result_mutex_);

  return *cert_der ? 0 : -1;
}

int VpnInstance::CryptoGetPrivkey(std::string& sha256,
                                  std::string* pk_algorithm,
                                  std::string* sign_algorithm) {
  pp::VarDictionary cmd_dict;

  cmd_dict.Set(kCmd, kCryptoGetPrivkey);
  cmd_dict.Set(kHash, sha256);

  pthread_mutex_lock(&crypto_result_mutex_);
  PostMessage(cmd_dict);
  pthread_cond_wait(&crypto_result_ready_, &crypto_result_mutex_);

  int ret = -1;
  if (crypto_result_->Get(kSuccess).AsBool()) {
    *pk_algorithm = crypto_result_->Get(kPrivkeyType).AsString();
    ret = 0;
  }

  delete crypto_result_;
  crypto_result_ = nullptr;
  pthread_mutex_unlock(&crypto_result_mutex_);

  return ret;
}

int VpnInstance::CryptoSign(std::string& sha256,
                            void* raw_data,
                            size_t raw_data_len,
                            void** signature,
                            size_t* signature_len) {
  pp::VarDictionary cmd_dict;

  cmd_dict.Set(kCmd, kCryptoSign);
  cmd_dict.Set(kHash, sha256);

  pp::VarArrayBuffer raw_data_var(raw_data_len);
  memcpy(raw_data_var.Map(), raw_data, raw_data_len);
  cmd_dict.Set(kData, raw_data_var);

  pthread_mutex_lock(&crypto_result_mutex_);
  PostMessage(cmd_dict);
  pthread_cond_wait(&crypto_result_ready_, &crypto_result_mutex_);

  *signature = nullptr;
  pp::Var sig_var = crypto_result_->Get(kData);
  if (sig_var.is_array_buffer()) {
    pp::VarArrayBuffer buf(sig_var);
    *signature_len = buf.ByteLength();
    *signature = malloc(*signature_len);
    if (*signature)
      memcpy(*signature, buf.Map(), *signature_len);
  }

  delete crypto_result_;
  crypto_result_ = nullptr;
  pthread_mutex_unlock(&crypto_result_mutex_);

  return *signature ? 0 : -1;
}

void VpnInstance::SendCryptoResult(pp::VarDictionary* dict) {
  pthread_mutex_lock(&crypto_result_mutex_);
  if (crypto_result_) {
    Log(kError, "crypto_result_ is already set");
    delete crypto_result_;
  }
  crypto_result_ = dict;
  pthread_cond_signal(&crypto_result_ready_);
  pthread_mutex_unlock(&crypto_result_mutex_);
}

void VpnInstance::SimpleMessage(const char* const cmd,
                                const char* const data) {
  pp::VarDictionary dict;

  dict.Set(kCmd, cmd);
  if (data)
    dict.Set(kData, data);

  PostMessage(dict);
}

void VpnInstance::VLog(VpnLogLevel level, const char* fmt, va_list ap) {
  PP_LogLevel pp_level;

  switch (level) {
    case kDebug:
      if (!debug_enabled_)
        return;
      // fall through
    case kVerbose:
      pp_level = PP_LOGLEVEL_TIP;
      break;
    case kInfo:
      pp_level = PP_LOGLEVEL_LOG;
      break;
    case kWarning:
      pp_level = PP_LOGLEVEL_WARNING;
      break;
    default:
      pp_level = PP_LOGLEVEL_ERROR;
  }

  char msg[kMaxMsg];
  vsnprintf(msg, sizeof(msg), fmt, ap);
  LogToConsole(pp_level, msg);

  // Asks JS to kill the NaCl process (eventually...)
  if (level == kFatal)
    SimpleMessage(kAbort, nullptr);
}

void VpnInstance::Log(VpnLogLevel level, const char* fmt, ...) {
  va_list ap;

  va_start(ap, fmt);
  VLog(level, fmt, ap);
  va_end(ap);
}

void VpnInstance::CryptoAbort(const char* fmt, va_list ap) {
  VLog(kFatal, fmt, ap);
}

void VpnInstance::InitBackgroundThreads() {
  int fd_pair[2];
  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd_pair) < 0)
    Log(kFatal, "socketpair() failed: %d", errno);

  tun_fd_ = fd_pair[0];
  tun_lib_fd_ = fd_pair[1];

  pthread_cond_init(&rx_data_ready_, NULL);
  pthread_mutex_init(&rx_data_mutex_, NULL);

  pthread_cond_init(&desired_state_ready_, NULL);
  pthread_mutex_init(&desired_state_mutex_, NULL);

  pthread_create(&rx_thread_, NULL, &RxThread, this);
  pthread_create(&tx_thread_, NULL, &TxThread, this);
}

void* VpnInstance::RxThread() {
  pthread_mutex_lock(&rx_data_mutex_);
  while (1) {
    pthread_cond_wait(&rx_data_ready_, &rx_data_mutex_);
    while (!rx_queue_.empty()) {
      pp::VarArrayBuffer* pkt = rx_queue_.front();
      rx_queue_.pop();
      pthread_mutex_unlock(&rx_data_mutex_);

      void* data = pkt->Map();
      int len = pkt->ByteLength();
      if (write(tun_fd_, data, len) != len)
        rx_dropped_++;
      pkt->Unmap();
      delete pkt;

      pthread_mutex_lock(&rx_data_mutex_);
    }
  }

  return NULL;
}

void* VpnInstance::RxThread(void* data) {
  VpnInstance* self = static_cast<VpnInstance*>(data);
  return self->RxThread();
}

void* VpnInstance::TxThread() {
  int ret;
  char pkt[kMaxPkt];

  while (1) {
    ret = read(tun_fd_, pkt, sizeof(pkt));
    if (ret <= 0)
      break;

    pp::VarArrayBuffer out(ret);
    char* data = static_cast<char*>(out.Map());
    memcpy(data, pkt, ret);
    PostMessage(out);
  }
  return NULL;
}

void* VpnInstance::TxThread(void* data) {
  VpnInstance* self = static_cast<VpnInstance*>(data);
  return self->TxThread();
}

void VpnInstance::SetupTunCb() {
  const struct oc_ip_info* ip_info;

  if (openconnect_get_ip_info(oc_, &ip_info, NULL, NULL) < 0) {
    Log(kFatal, "Error retrieving connection parameters");
    return;
  }
  SendIpInfo(ip_info);

  if (openconnect_setup_tun_fd(oc_, tun_lib_fd_) < 0) {
    Log(kFatal, "Error setting up tunnel");
    return;
  }
}

void VpnInstance::SetupTunCb(void* privdata) {
  VpnInstance* self = static_cast<VpnInstance*>(privdata);
  return self->SetupTunCb();
}

void VpnInstance::ReconnectedCb() {
  SimpleMessage(kStatus, kReconnected);
}

void VpnInstance::ReconnectedCb(void* privdata) {
  VpnInstance* self = static_cast<VpnInstance*>(privdata);
  return self->ReconnectedCb();
}

int VpnInstance::PeerCertCb(const char* reason) {
  pp::VarDictionary cmd_dict;

  cmd_dict.Set(kCmd, kPeerCert);
  cmd_dict.Set(kReason, reason);

  cmd_dict.Set(kHostname, openconnect_get_dnsname(oc_));

  pp::VarArray certs;
  struct oc_cert *chain;
  int ncerts = openconnect_get_peer_cert_chain(oc_, &chain);
  if (ncerts <= 0) {
    Log(kWarning, "error retrieving cert chain");
  } else {
    for (int i = 0; i < ncerts; i++) {
      pp::VarArrayBuffer jscert(chain[i].der_len);
      void* buf = jscert.Map();
      memcpy(buf, chain[i].der_data, chain[i].der_len);
      jscert.Unmap();
      certs.Set(i, jscert);
    }
    openconnect_free_peer_cert_chain(oc_, chain);
  }

  cmd_dict.Set(kCertChain, certs);
  cmd_dict.Set(kCertHash, openconnect_get_peer_cert_hash(oc_));

  pthread_mutex_lock(&auth_result_mutex_);
  PostMessage(cmd_dict);
  pthread_cond_wait(&auth_result_ready_, &auth_result_mutex_);

  std::string result = auth_result_->Get(kResult).AsString();
  int ret = -1;
  if (result == kAccept)
    ret = 0;

  delete auth_result_;
  auth_result_ = nullptr;
  pthread_mutex_unlock(&auth_result_mutex_);

  return ret;
}

int VpnInstance::PeerCertCb(void* privdata, const char* reason) {
  VpnInstance* self = static_cast<VpnInstance*>(privdata);
  return self->PeerCertCb(reason);
}

int VpnInstance::NewConfigCb(const char* buf, int buflen) {
  Log(kInfo, "%s", __FUNCTION__);
  return 0;
}

int VpnInstance::NewConfigCb(void* privdata, const char* buf, int buflen) {
  VpnInstance* self = static_cast<VpnInstance*>(privdata);
  return self->NewConfigCb(buf, buflen);
}

void VpnInstance::TranslateSelectOpt(struct oc_form_opt_select* opt,
                                     pp::VarDictionary& opt_dict) {
  pp::VarArray choices;

  for (int i = 0; i < opt->nr_choices; i++) {
    struct oc_choice* in = opt->choices[i];
    pp::VarDictionary out;

    out.Set(kChoiceName, in->name);
    if (in->label)
      out.Set(kChoiceLabel, in->label);
    if (in->auth_type)
      out.Set(kChoiceAuthType, in->auth_type);
    if (in->override_name)
      out.Set(kChoiceOverrideName, in->override_name);
    if (in->override_label)
      out.Set(kChoiceOverrideLabel, in->override_label);

    choices.Set(i, out);
  }
  opt_dict.Set(kOptChoices, choices);
}

void VpnInstance::TranslateOpt(struct oc_form_opt* opt,
                               pp::VarDictionary& opt_dict) {
  opt_dict.Set(kOptName, opt->name);
  if (opt->label)
    opt_dict.Set(kOptLabel, opt->label);

  pp::VarDictionary opt_flags;
  opt_flags.Set(kOptFlagIgnore, !!(opt->flags & OC_FORM_OPT_IGNORE));
  opt_flags.Set(kOptFlagNumeric, !!(opt->flags & OC_FORM_OPT_NUMERIC));
  opt_dict.Set(kOptFlags, opt_flags);

  switch (opt->type) {
    case OC_FORM_OPT_TEXT:
      opt_dict.Set(kOptType, kOptTypeText);
      break;
    case OC_FORM_OPT_PASSWORD:
      opt_dict.Set(kOptType, kOptTypePassword);
      break;
    case OC_FORM_OPT_SELECT:
      opt_dict.Set(kOptType, kOptTypeSelect);
      TranslateSelectOpt(reinterpret_cast<struct oc_form_opt_select*>(opt),
                         opt_dict);
      break;
    case OC_FORM_OPT_HIDDEN:
      opt_dict.Set(kOptType, kOptTypeHidden);
      break;
    case OC_FORM_OPT_TOKEN:
      opt_dict.Set(kOptType, kOptTypeToken);
      break;
    default:
      opt_dict.Set(kOptType, kOptTypeUnknown);
  }
}

int VpnInstance::TranslateAuthResult(pp::VarDictionary* dict,
                                     struct oc_auth_form* form) {
  pp::VarDictionary opts(dict->Get(kFormOpts));

  if (!opts.is_undefined()) {
    struct oc_form_opt* opt;
    for (opt = form->opts; opt; opt = opt->next) {
      pp::Var value = opts.Get(opt->name);
      if (!value.is_undefined()) {
        std::string str = value.AsString();
        openconnect_set_option_value(opt, strdup(str.c_str()));
      }
    }
  }

  std::string result = dict->Get(kResult).AsString();
  if (result == kSubmit)
    return OC_FORM_RESULT_OK;
  else if (result == kCancel)
    return OC_FORM_RESULT_CANCELLED;
  else if (result == kNewgroup)
    return OC_FORM_RESULT_NEWGROUP;
  else
    return OC_FORM_RESULT_ERR;
}

int VpnInstance::AuthFormCb(struct oc_auth_form* form) {
  pp::VarDictionary cmd_dict;

  cmd_dict.Set(kCmd, kAuthForm);

  // top-level fields
  if (form->banner)
    cmd_dict.Set(kFormBanner, form->banner);
  if (form->message)
    cmd_dict.Set(kFormMessage, form->message);
  if (form->error)
    cmd_dict.Set(kFormError, form->error);
  if (form->auth_id)
    cmd_dict.Set(kFormAuthId, form->auth_id);
  if (form->method)
    cmd_dict.Set(kFormMethod, form->method);
  if (form->action)
    cmd_dict.Set(kFormAction, form->action);

  // individual options
  int id;
  struct oc_form_opt* opt;
  pp::VarArray opt_array;

  for (opt = form->opts, id = 0; opt; opt = opt->next, id++) {
    pp::VarDictionary opt_dict;
    TranslateOpt(opt, opt_dict);
    if (opt == reinterpret_cast<struct oc_form_opt*>(form->authgroup_opt))
      opt_dict.Set(kFormAuthgroupSelection, form->authgroup_selection);
    opt_array.Set(id, opt_dict);
  }

  cmd_dict.Set(kFormOpts, opt_array);

  pthread_mutex_lock(&auth_result_mutex_);
  PostMessage(cmd_dict);
  pthread_cond_wait(&auth_result_ready_, &auth_result_mutex_);

  int ret = TranslateAuthResult(auth_result_, form);

  delete auth_result_;
  auth_result_ = nullptr;
  pthread_mutex_unlock(&auth_result_mutex_);

  return ret;
}

void VpnInstance::SendAuthResult(pp::VarDictionary* dict) {
  pthread_mutex_lock(&auth_result_mutex_);
  if (auth_result_) {
    Log(kError, "auth_result_ is already set");
    delete auth_result_;
  }
  auth_result_ = dict;
  pthread_cond_signal(&auth_result_ready_);
  pthread_mutex_unlock(&auth_result_mutex_);
}

int VpnInstance::AuthFormCb(void* privdata, struct oc_auth_form* form) {
  VpnInstance* self = static_cast<VpnInstance*>(privdata);
  return self->AuthFormCb(form);
}

void VpnInstance::ProgressCb(int level, const char* fmt, va_list ap) {
  VpnLogLevel mapping;

  switch (level) {
    case PRG_TRACE:
      mapping = kDebug;
      break;
    case PRG_DEBUG:
      mapping = kVerbose;
      break;
    case PRG_INFO:
      mapping = kInfo;
      break;
    default:
      mapping = kError;
  }
  VLog(mapping, fmt, ap);
}

void VpnInstance::ProgressCb(void* privdata, int level, const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VpnInstance* self = static_cast<VpnInstance*>(privdata);
  self->ProgressCb(level, fmt, ap);
  va_end(ap);
}

void VpnInstance::SendIpInfo(const struct oc_ip_info* ip_info)
{
  pp::VarDictionary dict;

  dict.Set(kCmd, kIp);

  if (ip_info->addr)
    dict.Set(kIpv4Addr, ip_info->addr);
  if (ip_info->netmask)
  dict.Set(kIpv4Netmask, ip_info->netmask);
  if (ip_info->addr6)
    dict.Set(kIpv6Addr, ip_info->addr6);
  if (ip_info->netmask6)
    dict.Set(kIpv6Netmask, ip_info->netmask6);
  if (ip_info->domain)
    dict.Set(kDomain, ip_info->domain);
  if (ip_info->proxy_pac)
    dict.Set(kProxyPac, ip_info->proxy_pac);
  dict.Set(kMtu, ip_info->mtu);

  int i;
  pp::VarArray dns;
  for (i = 0; i < 3; i++) {
    if (ip_info->dns[i])
      dns.Set(i, ip_info->dns[i]);
  }
  dict.Set(kDns, dns);

  pp::VarArray nbns;
  for (i = 0; i < 3; i++) {
    if (ip_info->nbns[i])
      dns.Set(i, ip_info->nbns[i]);
  }
  dict.Set(kNbns, nbns);

  struct oc_split_include* entry;
  pp::VarArray split_dns;
  for (entry = ip_info->split_dns, i = 0; entry; entry = entry->next)
    split_dns.Set(i++, entry->route);
  dict.Set(kSplitDns, split_dns);

  pp::VarArray split_includes;
  for (entry = ip_info->split_includes, i = 0; entry; entry = entry->next)
    split_includes.Set(i++, entry->route);
  dict.Set(kSplitIncludes, split_includes);

  pp::VarArray split_excludes;
  for (entry = ip_info->split_excludes, i = 0; entry; entry = entry->next)
    split_excludes.Set(i++, entry->route);
  dict.Set(kSplitExcludes, split_excludes);

  pp::VarArray gateway_ips;
  gateway_ips.Set(0, ip_info->gateway_addr);
  dict.Set(kGatewayIps, gateway_ips);

  PostMessage(dict);
  SimpleMessage(kStatus, kConnected);
}

void VpnInstance::ConnectionThread() {
  Log(kInfo, "starting connection thread...");

  std::string url = connect_options_->Get(kUrl).AsString();
  if (openconnect_parse_url(oc_, url.c_str()) < 0) {
    Log(kFatal, "Can't parse URL '%s'", url.c_str());
    return;
  }

  pp::Var cert_var = connect_options_->Get(kClientCert);
  if (cert_var.is_string()) {
    const char* cert_url = cert_var.AsString().c_str();
    if (openconnect_set_client_cert(oc_, cert_url, cert_url)) {
      Log(kFatal, "Error setting cert URL '%s'", cert_url);
    }
  }

  openconnect_set_system_trust(oc_, 0);
  if (openconnect_obtain_cookie(oc_) < 0) {
    Log(kFatal, "Error logging in to gateway");
    return;
  }
  if (openconnect_make_cstp_connection(oc_) < 0) {
    Log(kFatal, "Error connecting to gateway");
    return;
  }

  if (openconnect_setup_dtls(oc_, 60))
    Log(kWarning, "Could not configure DTLS");

  cmd_fd_ = openconnect_setup_cmd_pipe(oc_);
  if (cmd_fd_ < 0) {
    Log(kFatal, "Error setting up command interface");
    return;
  }
  if (fcntl(cmd_fd_, F_SETFL, O_NONBLOCK) < 0) {
    Log(kFatal, "Error setting nonblocking mode on cmd_fd: %d", errno);
    return;
  }

  openconnect_set_setup_tun_handler(oc_, SetupTunCb);
  openconnect_set_reconnected_handler(oc_, ReconnectedCb);

  while (1) {
    pthread_mutex_lock(&desired_state_mutex_);
    if (desired_state_ == kStateDisconnected) {
      pthread_mutex_unlock(&desired_state_mutex_);
      break;
    } else if (desired_state_ == kStatePaused) {
      pthread_cond_wait(&desired_state_ready_, &desired_state_mutex_);
      pthread_mutex_unlock(&desired_state_mutex_);
    } else if (desired_state_ == kStateRunning) {
      pthread_mutex_unlock(&desired_state_mutex_);
      if (openconnect_mainloop(oc_, kReconnectTimeout, kReconnectInterval))
        break;
    }
  }

  SimpleMessage(kStatus, kDisconnected);

  pthread_mutex_lock(&lib_mutex_);
  delete connect_options_;
  connect_options_ = nullptr;
  openconnect_vpninfo_free(oc_);
  cmd_fd_ = 0;
  oc_ = nullptr;
  pthread_mutex_unlock(&lib_mutex_);
}

void* VpnInstance::ConnectionThread(void* privdata) {
  VpnInstance* self = static_cast<VpnInstance*>(privdata);
  self->ConnectionThread();
  return NULL;
}

void VpnInstance::Connect(pp::VarDictionary* dict) {
  pthread_mutex_lock(&lib_mutex_);
  if (oc_) {
    Log(kError, "called Connect() with another session in progress");
    pthread_mutex_unlock(&lib_mutex_);
    return;
  }

  openconnect_init_ssl();
  oc_ = openconnect_vpninfo_new("CrOS", PeerCertCb, NewConfigCb,
      AuthFormCb, ProgressCb, this);
  if (!oc_) {
    Log(kFatal, "unable to create library instance");
    return;
  }

  connect_options_ = dict;
  gateway_ips_.clear();
  rx_dropped_ = 0;

  pthread_create(&connection_thread_, NULL, &ConnectionThread, this);
  pthread_mutex_unlock(&lib_mutex_);
}

void VpnInstance::SendCommand(char cmd) {
  if (!cmd_fd_ || write(cmd_fd_, &cmd, 1) != 1)
    Log(kWarning, "error writing cmd: %d", errno);
}

void VpnInstance::SetDesiredState(MainloopState new_state) {
  pthread_mutex_lock(&desired_state_mutex_);
  desired_state_ = new_state;
  pthread_cond_signal(&desired_state_ready_);
  pthread_mutex_unlock(&desired_state_mutex_);
}

}  // namespace vpn_nacl
