<commit_before>// Copyright 2015 CoreOS, Inc.
//
// 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.

package tpmclient

import (
	"bytes"
	"crypto/rand"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/coreos/go-tspi/verification"
	"github.com/coreos/go-tspi/tspiconst"
)

// TPMClient represents a connection to a system running a daemon providing
// access to TPM functionality
type TPMClient struct {
	host    string
	timeout time.Duration
}

const GetEKCertURL = "/v1/getEkcert"
const ExtendURL = "/v1/extend"
const QuoteURL = "/v1/quote"
const GenerateAikURL = "/v1/generateAik"
const GenerateKeyURL = "/v1/generateKey"
const AikChallengeURL = "/v1/aikChallenge"

func (client *TPMClient) get(endpoint string) (*http.Response, error) {
	url := fmt.Sprintf("http://%s/%s", client.host, endpoint)
	httpClient := &http.Client{
		Timeout: client.timeout,
	}
	resp, err := httpClient.Get(url)
	return resp, err
}

func (client *TPMClient) post(endpoint string, data io.Reader) (*http.Response, error) {
	url := fmt.Sprintf("http://%s/%s", client.host, endpoint)
	httpClient := &http.Client{
		Timeout: client.timeout,
	}
	resp, err := httpClient.Post(url, "application/json", data)
	return resp, err
}

type EkcertResponse struct {
	EKCert []byte
}

// GetEKCert obtains the Endorsement Key certificate from the client TPM. This
// is an X509 certificate containing the public half of the Endorsement Key
// and a signature chain chaining back to a vendor-issued signing certificate.
func (client *TPMClient) GetEKCert() (ekcert []byte, err error) {
	var ekcertData EkcertResponse

	ekresp, err := client.get(GetEKCertURL)
	if err != nil {
		return nil, fmt.Errorf("Can't obtain ekcert: %s", err)
	}
	defer ekresp.Body.Close()
	body, err := ioutil.ReadAll(ekresp.Body)
	if err != nil {
		return nil, fmt.Errorf("Can't read ekcert response: %s", err)
	}

	err = json.Unmarshal(body, &ekcertData)
	if err != nil {
		return nil, fmt.Errorf("Can't parse ekcert response: %s", err)
	}

	return ekcertData.EKCert, nil
}

type AikResponse struct {
	AIKBlob []byte
	AIKPub  []byte
}

// GenerateAIK requests that the TPM generate a new Attestation Identity Key.
// It returns an unencrypted copy of the public half of the AIK, along with
// a TSPI key blob encrypted by the TPM.
func (client *TPMClient) GenerateAIK() (aikpub []byte, aikblob []byte, err error) {
	var aikData AikResponse

	aikresp, err := client.post(GenerateAikURL, nil)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't generate AIK: %s", err)
	}
	defer aikresp.Body.Close()
	body, err := ioutil.ReadAll(aikresp.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't read AIK response: %s", err)
	}

	err = json.Unmarshal(body, &aikData)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't parse AIK response: %s (%s)", err, body)
	}

	aikpub = aikData.AIKPub
	aikblob = aikData.AIKBlob

	return aikpub, aikblob, nil
}

type KeyData struct {
	KeyFlags int
}

type KeyResponse struct {
	KeyBlob	[]byte
	KeyPub	[]byte
}

// GenerateKey requests that the TPM generate a new keypair
func (client *TPMClient) GenerateKey(flags int) (keypub []byte, keyblob []byte, err error) {
	var keyData KeyData
	var keyResponse KeyResponse

	keyData.KeyFlags = flags
	request, err := json.Marshal(keyData)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't construct request JSON: %s", err)
	}

	keyresp, err := client.post(GenerateKeyURL, bytes.NewBuffer(request))
	if err != nil {
		return nil, nil, fmt.Errorf("Can't generate key: %s", err)
	}
	defer keyresp.Body.Close()
	body, err := ioutil.ReadAll(keyresp.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't read key response: %s", err)
	}

	err = json.Unmarshal(body, &keyResponse)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't parse key response: %s (%s)", err, body)
	}

	keypub = keyResponse.KeyPub
	keyblob = keyResponse.KeyBlob

	return keypub, keyblob, nil
}

type ChallengeData struct {
	AIK     []byte
	Asymenc []byte
	Symenc  []byte
}

type ChallengeResponse struct {
	Response []byte
}

// ValidateAIK challenges the TPM to validate an AIK by using the provided
// key blob to decrypt a secret encrypted with the public half of the
// AIK. This will only be possible if the TPM is able to decrypt the
// encrypted key blob.  The AIK is used to decrypt asymenc, which then
// provides the AES key used to encrypt symenc. Decrypting symenc provides
// the original secret, which is then returned.
func (client *TPMClient) ValidateAIK(aikblob []byte, asymenc []byte, symenc []byte) (secret []byte, err error) {
	var challenge ChallengeData
	var response ChallengeResponse

	challenge.AIK = aikblob
	challenge.Asymenc = asymenc
	challenge.Symenc = symenc

	request, err := json.Marshal(challenge)
	if err != nil {
		return nil, fmt.Errorf("Can't construct challenge JSON: %s", err)
	}
	chalresp, err := client.post(AikChallengeURL, bytes.NewBuffer(request))
	if err != nil {
		return nil, fmt.Errorf("Can't perform AIK challenge: %s", err)
	}
	defer chalresp.Body.Close()
	body, err := ioutil.ReadAll(chalresp.Body)
	if err != nil {
		return nil, fmt.Errorf("Can't read AIK challenge response: %s", err)
	}

	err = json.Unmarshal(body, &response)
	if err != nil {
		return nil, fmt.Errorf("Can't parse AIK challenge response: %s", err)
	}
	return response.Response, nil
}

type ExtendInput struct {
	Pcr       int
	Eventtype int
	Data      []byte
	Event     string
}

// Extend extends a TPM PCR with the provided data. If event is nil, data must
// be pre-hashed with SHA1 and will be used to extend the PCR directly. If
// event is not nil, data and event will be hashed to generate the extension
// value. Event will then be stored in the TPM event log.
func (client *TPMClient) Extend(pcr int, eventtype int, data []byte, event string) error {
	var extendData ExtendInput

	extendData.Pcr = pcr
	extendData.Eventtype = eventtype
	extendData.Data = data
	extendData.Event = event

	request, err := json.Marshal(extendData)
	if err != nil {
		return fmt.Errorf("Can't construct extension JSON: %s", err)
	}
	chalresp, err := client.post(ExtendURL, bytes.NewBuffer(request))
	if err != nil {
		return fmt.Errorf("Can't perform PCR extension: %s", err)
	}
	defer chalresp.Body.Close()

	return nil
}

type QuoteData struct {
	AIK   []byte
	PCRs  []int
	Nonce []byte
}

type QuoteResponse struct {
	Data       []byte
	Validation []byte
	PCRValues  [][]byte
	Events     []tspiconst.Log
}

// GetQuote obtains a PCR quote from the TPM. It takes the aikpub Tspi Key, the
// encrypted AIK blob and a list of PCRs as arguments. The response will
// contain an array of PCR values, an array of log entries and any error.
func (client *TPMClient) GetQuote(aikpub []byte, aikblob []byte, pcrs []int) (pcrvals [][]byte, log []tspiconst.Log, err error) {
	var quoteRequest QuoteData
	var response QuoteResponse

	nonce := make([]byte, 20)
	_, err = rand.Read(nonce)
	if err != nil {
		return nil, nil, fmt.Errorf("Unable to generate nonce: %s", err)
	}

	quoteRequest.AIK = aikblob
	quoteRequest.PCRs = pcrs
	quoteRequest.Nonce = nonce

	request, err := json.Marshal(quoteRequest)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't construct quote request JSON: %s", err)
	}
	chalresp, err := client.post(QuoteURL, bytes.NewBuffer(request))
	if err != nil {
		return nil, nil, fmt.Errorf("Can't perform obtain quote: %s", err)
	}
	defer chalresp.Body.Close()
	body, err := ioutil.ReadAll(chalresp.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't read quote response: %s", err)
	}

	err = json.Unmarshal(body, &response)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't parse quote response: %s", err)
	}

	aikmod := aikpub[28:]

	err = verification.QuoteVerify(response.Data, response.Validation, aikmod, response.PCRValues, nonce)

	if err != nil {
		return nil, nil, fmt.Errorf("Can't verify quote: %s", err)
	}

	return response.PCRValues, response.Events, nil
}

// New returns a TPMClient structure configured to connect to the provided
// host with the provided timeout.
func New(host string, timeout time.Duration) *TPMClient {
	return &TPMClient{
		host:    host,
		timeout: timeout,
	}
}
<commit_msg>Avoid duplicate / in URLs<commit_after>// Copyright 2015 CoreOS, Inc.
//
// 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.

package tpmclient

import (
	"bytes"
	"crypto/rand"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/coreos/go-tspi/verification"
	"github.com/coreos/go-tspi/tspiconst"
)

// TPMClient represents a connection to a system running a daemon providing
// access to TPM functionality
type TPMClient struct {
	host    string
	timeout time.Duration
}

const GetEKCertURL = "/v1/getEkcert"
const ExtendURL = "/v1/extend"
const QuoteURL = "/v1/quote"
const GenerateAikURL = "/v1/generateAik"
const GenerateKeyURL = "/v1/generateKey"
const AikChallengeURL = "/v1/aikChallenge"

func (client *TPMClient) get(endpoint string) (*http.Response, error) {
	url := fmt.Sprintf("http://%s%s", client.host, endpoint)
	httpClient := &http.Client{
		Timeout: client.timeout,
	}
	resp, err := httpClient.Get(url)
	return resp, err
}

func (client *TPMClient) post(endpoint string, data io.Reader) (*http.Response, error) {
	url := fmt.Sprintf("http://%s%s", client.host, endpoint)
	httpClient := &http.Client{
		Timeout: client.timeout,
	}
	resp, err := httpClient.Post(url, "application/json", data)
	return resp, err
}

type EkcertResponse struct {
	EKCert []byte
}

// GetEKCert obtains the Endorsement Key certificate from the client TPM. This
// is an X509 certificate containing the public half of the Endorsement Key
// and a signature chain chaining back to a vendor-issued signing certificate.
func (client *TPMClient) GetEKCert() (ekcert []byte, err error) {
	var ekcertData EkcertResponse

	ekresp, err := client.get(GetEKCertURL)
	if err != nil {
		return nil, fmt.Errorf("Can't obtain ekcert: %s", err)
	}
	defer ekresp.Body.Close()
	body, err := ioutil.ReadAll(ekresp.Body)
	if err != nil {
		return nil, fmt.Errorf("Can't read ekcert response: %s", err)
	}

	err = json.Unmarshal(body, &ekcertData)
	if err != nil {
		return nil, fmt.Errorf("Can't parse ekcert response: %s", err)
	}

	return ekcertData.EKCert, nil
}

type AikResponse struct {
	AIKBlob []byte
	AIKPub  []byte
}

// GenerateAIK requests that the TPM generate a new Attestation Identity Key.
// It returns an unencrypted copy of the public half of the AIK, along with
// a TSPI key blob encrypted by the TPM.
func (client *TPMClient) GenerateAIK() (aikpub []byte, aikblob []byte, err error) {
	var aikData AikResponse

	aikresp, err := client.post(GenerateAikURL, nil)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't generate AIK: %s", err)
	}
	defer aikresp.Body.Close()
	body, err := ioutil.ReadAll(aikresp.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't read AIK response: %s", err)
	}

	err = json.Unmarshal(body, &aikData)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't parse AIK response: %s (%s)", err, body)
	}

	aikpub = aikData.AIKPub
	aikblob = aikData.AIKBlob

	return aikpub, aikblob, nil
}

type KeyData struct {
	KeyFlags int
}

type KeyResponse struct {
	KeyBlob	[]byte
	KeyPub	[]byte
}

// GenerateKey requests that the TPM generate a new keypair
func (client *TPMClient) GenerateKey(flags int) (keypub []byte, keyblob []byte, err error) {
	var keyData KeyData
	var keyResponse KeyResponse

	keyData.KeyFlags = flags
	request, err := json.Marshal(keyData)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't construct request JSON: %s", err)
	}

	keyresp, err := client.post(GenerateKeyURL, bytes.NewBuffer(request))
	if err != nil {
		return nil, nil, fmt.Errorf("Can't generate key: %s", err)
	}
	defer keyresp.Body.Close()
	body, err := ioutil.ReadAll(keyresp.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't read key response: %s", err)
	}

	err = json.Unmarshal(body, &keyResponse)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't parse key response: %s (%s)", err, body)
	}

	keypub = keyResponse.KeyPub
	keyblob = keyResponse.KeyBlob

	return keypub, keyblob, nil
}

type ChallengeData struct {
	AIK     []byte
	Asymenc []byte
	Symenc  []byte
}

type ChallengeResponse struct {
	Response []byte
}

// ValidateAIK challenges the TPM to validate an AIK by using the provided
// key blob to decrypt a secret encrypted with the public half of the
// AIK. This will only be possible if the TPM is able to decrypt the
// encrypted key blob.  The AIK is used to decrypt asymenc, which then
// provides the AES key used to encrypt symenc. Decrypting symenc provides
// the original secret, which is then returned.
func (client *TPMClient) ValidateAIK(aikblob []byte, asymenc []byte, symenc []byte) (secret []byte, err error) {
	var challenge ChallengeData
	var response ChallengeResponse

	challenge.AIK = aikblob
	challenge.Asymenc = asymenc
	challenge.Symenc = symenc

	request, err := json.Marshal(challenge)
	if err != nil {
		return nil, fmt.Errorf("Can't construct challenge JSON: %s", err)
	}
	chalresp, err := client.post(AikChallengeURL, bytes.NewBuffer(request))
	if err != nil {
		return nil, fmt.Errorf("Can't perform AIK challenge: %s", err)
	}
	defer chalresp.Body.Close()
	body, err := ioutil.ReadAll(chalresp.Body)
	if err != nil {
		return nil, fmt.Errorf("Can't read AIK challenge response: %s", err)
	}

	err = json.Unmarshal(body, &response)
	if err != nil {
		return nil, fmt.Errorf("Can't parse AIK challenge response: %s", err)
	}
	return response.Response, nil
}

type ExtendInput struct {
	Pcr       int
	Eventtype int
	Data      []byte
	Event     string
}

// Extend extends a TPM PCR with the provided data. If event is nil, data must
// be pre-hashed with SHA1 and will be used to extend the PCR directly. If
// event is not nil, data and event will be hashed to generate the extension
// value. Event will then be stored in the TPM event log.
func (client *TPMClient) Extend(pcr int, eventtype int, data []byte, event string) error {
	var extendData ExtendInput

	extendData.Pcr = pcr
	extendData.Eventtype = eventtype
	extendData.Data = data
	extendData.Event = event

	request, err := json.Marshal(extendData)
	if err != nil {
		return fmt.Errorf("Can't construct extension JSON: %s", err)
	}
	chalresp, err := client.post(ExtendURL, bytes.NewBuffer(request))
	if err != nil {
		return fmt.Errorf("Can't perform PCR extension: %s", err)
	}
	defer chalresp.Body.Close()

	return nil
}

type QuoteData struct {
	AIK   []byte
	PCRs  []int
	Nonce []byte
}

type QuoteResponse struct {
	Data       []byte
	Validation []byte
	PCRValues  [][]byte
	Events     []tspiconst.Log
}

// GetQuote obtains a PCR quote from the TPM. It takes the aikpub Tspi Key, the
// encrypted AIK blob and a list of PCRs as arguments. The response will
// contain an array of PCR values, an array of log entries and any error.
func (client *TPMClient) GetQuote(aikpub []byte, aikblob []byte, pcrs []int) (pcrvals [][]byte, log []tspiconst.Log, err error) {
	var quoteRequest QuoteData
	var response QuoteResponse

	nonce := make([]byte, 20)
	_, err = rand.Read(nonce)
	if err != nil {
		return nil, nil, fmt.Errorf("Unable to generate nonce: %s", err)
	}

	quoteRequest.AIK = aikblob
	quoteRequest.PCRs = pcrs
	quoteRequest.Nonce = nonce

	request, err := json.Marshal(quoteRequest)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't construct quote request JSON: %s", err)
	}
	chalresp, err := client.post(QuoteURL, bytes.NewBuffer(request))
	if err != nil {
		return nil, nil, fmt.Errorf("Can't perform obtain quote: %s", err)
	}
	defer chalresp.Body.Close()
	body, err := ioutil.ReadAll(chalresp.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't read quote response: %s", err)
	}

	err = json.Unmarshal(body, &response)
	if err != nil {
		return nil, nil, fmt.Errorf("Can't parse quote response: %s", err)
	}

	aikmod := aikpub[28:]

	err = verification.QuoteVerify(response.Data, response.Validation, aikmod, response.PCRValues, nonce)

	if err != nil {
		return nil, nil, fmt.Errorf("Can't verify quote: %s", err)
	}

	return response.PCRValues, response.Events, nil
}

// New returns a TPMClient structure configured to connect to the provided
// host with the provided timeout.
func New(host string, timeout time.Duration) *TPMClient {
	return &TPMClient{
		host:    host,
		timeout: timeout,
	}
}
<|endoftext|>


<commit_before>package bitso

import (
  "errors"
  "net/http"
  "net/url"
  "io/ioutil"
  "encoding/json"
)

const (
  URL = "https://api.bitso.com/v2/"
  btcmxn = "btc_mxn"
  ethmxn = "eth_mxn"
  tickerPath = "ticker"
  transactionsPath = "transactions"
  orderBookPath = "order_book"
)

type Ticker struct {
  High string
  Last string
  Timestamp string
  Volume string
  Vwap string
  Low string
  Ask string
  Bid string
}

type OrderBook struct {
  Asks [][]string
  Bids [][]string
}

type Transaction struct {
  Amount string
  Date string
  Price string
  Tid int
  Side string
}

// Client allows you to access to the Bitso API
type Client struct {
  configuration *Configuration
}

// Configuration stores the information needed to access
// to the private endpoints and the sanbox mode trigger.
type Configuration struct {
  Key       string
  Secret    string
  ClientId  string
  Sandbox   bool
}

// NewClient returns a new Bitso API client. It receives
// an optional Configuration, which is used to
// authenticate and enter in sandbox mode.
func NewClient(configuration *Configuration) *Client {
  return &Client{configuration}
}

// IsSandbox returns true if the sandbox mode is
// turned on.
func (c *Client) IsSandbox() bool {
  if c.configuration == nil {
    return false
  }
  return c.configuration.Sandbox
}

func (c *Client) Ticker(book string) (*Ticker, error) {
  if book != btcmxn && book != ethmxn {
    err := errors.New("Invalid book value")
    return nil, err
  }
  ticker := &Ticker{}
  v := &url.Values{}
  v.Set("book", book)
  err := c.get(tickerPath, v, ticker)
  if err != nil {
    return nil, err
  }
  return ticker, nil
}

func (c *Client) OrderBook(book string, group bool) (*OrderBook, error) {
  if validateBook(book) == false {
    err := errors.New("Invalid book value")
    return nil, err
  }
  orderBook := &OrderBook{}
  v := &url.Values{}
  v.Set("book", book)
  err := c.get(orderBookPath, v, orderBook)
  if err != nil {
    return nil, err
  }
  return orderBook, nil
}

func validateBook(book string) bool {
  return book == btcmxn || book == ethmxn
}

func (c *Client) get(path string, query *url.Values, schema interface{}) (error) {
  if config := c.configuration; config != nil && config.Sandbox == true {
    //Mock response
  }
  u, err := url.Parse(URL + path)
  if err != nil {
    return err
  }
  if query != nil {
    u.RawQuery = query.Encode()
  }
  resp, err := http.Get(u.String())
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    return err
  }
  err = json.Unmarshal(body, schema)
	if err != nil {
		return err
	}
  return nil
}
<commit_msg>Using validateBook in Ticker.<commit_after>package bitso

import (
  "errors"
  "net/http"
  "net/url"
  "io/ioutil"
  "encoding/json"
)

const (
  URL = "https://api.bitso.com/v2/"
  btcmxn = "btc_mxn"
  ethmxn = "eth_mxn"
  tickerPath = "ticker"
  transactionsPath = "transactions"
  orderBookPath = "order_book"
)

type Ticker struct {
  High string
  Last string
  Timestamp string
  Volume string
  Vwap string
  Low string
  Ask string
  Bid string
}

type OrderBook struct {
  Asks [][]string
  Bids [][]string
}

type Transaction struct {
  Amount string
  Date string
  Price string
  Tid int
  Side string
}

// Client allows you to access to the Bitso API
type Client struct {
  configuration *Configuration
}

// Configuration stores the information needed to access
// to the private endpoints and the sanbox mode trigger.
type Configuration struct {
  Key       string
  Secret    string
  ClientId  string
  Sandbox   bool
}

// NewClient returns a new Bitso API client. It receives
// an optional Configuration, which is used to
// authenticate and enter in sandbox mode.
func NewClient(configuration *Configuration) *Client {
  return &Client{configuration}
}

// IsSandbox returns true if the sandbox mode is
// turned on.
func (c *Client) IsSandbox() bool {
  if c.configuration == nil {
    return false
  }
  return c.configuration.Sandbox
}

func (c *Client) Ticker(book string) (*Ticker, error) {
  if validateBook(book) == false {
    err := errors.New("Invalid book value")
    return nil, err
  }
  ticker := &Ticker{}
  v := &url.Values{}
  v.Set("book", book)
  err := c.get(tickerPath, v, ticker)
  if err != nil {
    return nil, err
  }
  return ticker, nil
}

func (c *Client) OrderBook(book string, group bool) (*OrderBook, error) {
  if validateBook(book) == false {
    err := errors.New("Invalid book value")
    return nil, err
  }
  orderBook := &OrderBook{}
  v := &url.Values{}
  v.Set("book", book)
  err := c.get(orderBookPath, v, orderBook)
  if err != nil {
    return nil, err
  }
  return orderBook, nil
}

func validateBook(book string) bool {
  return book == btcmxn || book == ethmxn
}

func (c *Client) get(path string, query *url.Values, schema interface{}) (error) {
  if config := c.configuration; config != nil && config.Sandbox == true {
    //Mock response
  }
  u, err := url.Parse(URL + path)
  if err != nil {
    return err
  }
  if query != nil {
    u.RawQuery = query.Encode()
  }
  resp, err := http.Get(u.String())
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    return err
  }
  err = json.Unmarshal(body, schema)
	if err != nil {
		return err
	}
  return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"net/http"
	"regexp"
	"strconv"
	"testing"
	"time"
)

// Should redirect from HTTP to HTTPS without hitting origin.
func TestProtocolRedirect(t *testing.T) {
	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		t.Error("Request should not have made it to origin")
	})

	sourceUrl := fmt.Sprintf("http://%s/foo/bar", *edgeHost)
	destUrl := fmt.Sprintf("https://%s/foo/bar", *edgeHost)

	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)

	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != 301 {
		t.Errorf("Status code expected 301, got %d", resp.StatusCode)
	}
	if d := resp.Header.Get("Location"); d != destUrl {
		t.Errorf("Location header expected %s, got %s", destUrl, d)
	}
}

// Should return 403 for PURGE requests from IPs not in the whitelist. We
// assume that this is not running from a whitelisted address.
func TestRestrictPurgeRequests(t *testing.T) {
	const expectedStatusCode = 403

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		t.Error("Request should not have made it to origin")
	})

	url := fmt.Sprintf("https://%s/", *edgeHost)
	req, _ := http.NewRequest("PURGE", url, nil)

	resp, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != expectedStatusCode {
		t.Errorf("Incorrect status code. Expected %d, got %d", expectedStatusCode, resp.StatusCode)
	}
}

// Should set an `X-Forwarded-For` header for requests that don't already
// have one and append to requests that already have the header. This test
// will not work if run from behind a proxy that also sets XFF.
func TestHeaderXFFCreateAndAppend(t *testing.T) {
	const headerName = "X-Forwarded-For"
	const sentHeaderVal = "203.0.113.99"
	var ourReportedIP net.IP
	var receivedHeaderVal string

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Header.Get(headerName)
	})

	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)

	// First request with no existing XFF.
	_, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}
	if receivedHeaderVal == "" {
		t.Fatalf("Origin didn't receive request with %q header", headerName)
	}

	ourReportedIP = net.ParseIP(receivedHeaderVal)
	if ourReportedIP == nil {
		t.Fatalf(
			"Expected origin to receive %q header with single IP. Got %q",
			headerName,
			receivedHeaderVal,
		)
	}

	// Use the IP returned by the first response to predict the second.
	expectedHeaderVal := fmt.Sprintf("%s, %s", sentHeaderVal, ourReportedIP.String())

	// Second request with existing XFF.
	url = fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ = http.NewRequest("GET", url, nil)
	req.Header.Set(headerName, sentHeaderVal)

	_, err = client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	if receivedHeaderVal != expectedHeaderVal {
		t.Errorf(
			"Origin received %q header with wrong value. Expected %q, got %q",
			headerName,
			expectedHeaderVal,
			receivedHeaderVal,
		)
	}
}

// Should create a True-Client-IP header containing the client's IP
// address, discarding the value provided in the original request.
func TestHeaderUnspoofableClientIP(t *testing.T) {
	const headerName = "True-Client-IP"
	const sentHeaderVal = "203.0.113.99"
	var sentHeaderIP = net.ParseIP(sentHeaderVal)
	var receivedHeaderVal string

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Header.Get(headerName)
	})

	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set(headerName, sentHeaderVal)

	_, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	receivedHeaderIP := net.ParseIP(receivedHeaderVal)
	if receivedHeaderIP == nil {
		t.Fatalf("Origin received %q header with non-IP value %q", headerName, receivedHeaderVal)
	}
	if receivedHeaderIP.Equal(sentHeaderIP) {
		t.Errorf("Origin received %q header with unmodified value %q", headerName, receivedHeaderIP)
	}
}

// Should not modify Host header from original request.
func TestHeaderHostUnmodified(t *testing.T) {
	t.Error("Not implemented")
}

// Should serve a known static error page if cannot serve a page
// from origin, stale or any mirror.
// NB: ideally this should be a page that we control that has a mechanism
//     to alert us that it has been served.
func TestErrorPageIsServedWhenNoBackendAvailable(t *testing.T) {
	t.Error("Not implemented")
}

// ---------------------------------------------------------
// Test that useful common cache-related parameters are sent to the
// client by this CDN provider.

// Should set an Age header itself rather than passing the Age header from origin.
func TestAgeHeaderIsSetByProviderNotOrigin(t *testing.T) {
	const originAgeInSeconds = 100000
	const secondsToWaitBetweenRequests = 5
	requestReceivedCount := 0
	uuid := NewUUID()

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		if requestReceivedCount == 0 {
			w.Header().Set("Age", fmt.Sprintf("%d", originAgeInSeconds))
			w.Write([]byte("cacheable request"))
		} else {
			t.Error("Unexpected subsequent request received at Origin")
		}
		requestReceivedCount++
	})

	url := fmt.Sprintf("https://%s/?cache-lock=%s", *edgeHost, uuid)
	req, _ := http.NewRequest("GET", url, nil)

	resp, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	if resp.StatusCode != 200 {
		t.Fatalf("Edge returned an unexpected status: %q", resp.Status)
	}

	// wait a little bit. Edge should update the Age header, we know Origin will not
	time.Sleep(time.Duration(secondsToWaitBetweenRequests) * time.Second)

	resp, err = client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	if resp.StatusCode != 200 {
		t.Fatal("Edge returned an unexpected status: %q", resp.Status)
	}

	edgeAgeHeader := resp.Header.Get("Age")
	if edgeAgeHeader == "" {
		t.Fatal("Age Header is not set")
	}

	edgeAgeInSeconds, convErr := strconv.Atoi(edgeAgeHeader)
	if convErr != nil {
		t.Fatal(convErr)
	}
	if edgeAgeInSeconds == secondsToWaitBetweenRequests {
		// Edge has rewritten Age based on how long it has been since it
		// cached the page.
		return
	} else if edgeAgeInSeconds == originAgeInSeconds+secondsToWaitBetweenRequests {
		t.Error("Edge is adding to Age header from Origin. This is not as expected.")
	} else if edgeAgeInSeconds == 0 {
		t.Error("Edge is reporting Age to be '0'. This implies Egde is not preserving Age between cache nodes")
	}

	t.Errorf(
		"Age header from Edge is not as expected. Got %q, expected '%d'",
		edgeAgeHeader,
		secondsToWaitBetweenRequests,
	)

}

// Should set an X-Cache header containing HIT/MISS from 'origin, itself'
func TestXCacheHeaderContainsHitMissFromBothProviderAndOrigin(t *testing.T) {
	t.Error("Not implemented")
}

// Should set an X-Served-By header giving information on the (Fastly) node and location served from.
func TestXServedByHeaderContainsFastlyNodeIdAndLocation(t *testing.T) {

	expectedFastlyXServedByRegexp := regexp.MustCompile("^cache-[a-z0-9]+-[A-Z]{3}$")

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {})

	sourceUrl := fmt.Sprintf("https://%s/", *edgeHost)

	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	actualHeader := resp.Header.Get("X-Served-By")
	if actualHeader == "" {
		t.Error("X-Served-By header has not been set by Edge")
	}

	if expectedFastlyXServedByRegexp.FindString(actualHeader) != actualHeader {
		t.Errorf("X-Served-By is not as expected: got %q", actualHeader)
	}

}

// Should set an X-Cache-Hits header containing hit count for this object,
// from the Edge AND the Origin, assuming Origin sets one.
// This is in the format "{origin-hit-count}, {edge-hit-count}"
func TestXCacheHitsContainsProviderHitCountForThisObject(t *testing.T) {

	const originXCacheHits = "53"

	var (
		xCacheHits         string
		expectedXCacheHits string
	)

	uuid := NewUUID()
	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "GET" && r.URL.Path == fmt.Sprintf("/%s", uuid) {
			w.Header().Set("X-Cache-Hits", originXCacheHits)
		}
	})

	sourceUrl := fmt.Sprintf("https://%s/%s", *edgeHost, uuid)

	// Get first request, will come from origin. Edge Hit Count 0
	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	xCacheHits = resp.Header.Get("X-Cache-Hits")
	expectedXCacheHits = fmt.Sprintf("%s, 0", originXCacheHits)
	if xCacheHits != expectedXCacheHits {
		t.Errorf(
			"X-Cache-Hits on initial hit is wrong: expected %q, got %q",
			expectedXCacheHits,
			xCacheHits,
		)
	}

	// Get request again. Should come from Edge now, hit count 1
	resp, err = client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	xCacheHits = resp.Header.Get("X-Cache-Hits")
	expectedXCacheHits = fmt.Sprintf("%s, 1", originXCacheHits)
	if xCacheHits != expectedXCacheHits {
		t.Errorf(
			"X-Cache-Hits on second hit is wrong: expected %q, got %q",
			expectedXCacheHits,
			xCacheHits,
		)
	}

}
<commit_msg>Fix Age header test to reflect Varnish behaviour<commit_after>package main

import (
	"fmt"
	"net"
	"net/http"
	"regexp"
	"strconv"
	"testing"
	"time"
)

// Should redirect from HTTP to HTTPS without hitting origin.
func TestProtocolRedirect(t *testing.T) {
	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		t.Error("Request should not have made it to origin")
	})

	sourceUrl := fmt.Sprintf("http://%s/foo/bar", *edgeHost)
	destUrl := fmt.Sprintf("https://%s/foo/bar", *edgeHost)

	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)

	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != 301 {
		t.Errorf("Status code expected 301, got %d", resp.StatusCode)
	}
	if d := resp.Header.Get("Location"); d != destUrl {
		t.Errorf("Location header expected %s, got %s", destUrl, d)
	}
}

// Should return 403 for PURGE requests from IPs not in the whitelist. We
// assume that this is not running from a whitelisted address.
func TestRestrictPurgeRequests(t *testing.T) {
	const expectedStatusCode = 403

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		t.Error("Request should not have made it to origin")
	})

	url := fmt.Sprintf("https://%s/", *edgeHost)
	req, _ := http.NewRequest("PURGE", url, nil)

	resp, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}
	if resp.StatusCode != expectedStatusCode {
		t.Errorf("Incorrect status code. Expected %d, got %d", expectedStatusCode, resp.StatusCode)
	}
}

// Should set an `X-Forwarded-For` header for requests that don't already
// have one and append to requests that already have the header. This test
// will not work if run from behind a proxy that also sets XFF.
func TestHeaderXFFCreateAndAppend(t *testing.T) {
	const headerName = "X-Forwarded-For"
	const sentHeaderVal = "203.0.113.99"
	var ourReportedIP net.IP
	var receivedHeaderVal string

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Header.Get(headerName)
	})

	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)

	// First request with no existing XFF.
	_, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}
	if receivedHeaderVal == "" {
		t.Fatalf("Origin didn't receive request with %q header", headerName)
	}

	ourReportedIP = net.ParseIP(receivedHeaderVal)
	if ourReportedIP == nil {
		t.Fatalf(
			"Expected origin to receive %q header with single IP. Got %q",
			headerName,
			receivedHeaderVal,
		)
	}

	// Use the IP returned by the first response to predict the second.
	expectedHeaderVal := fmt.Sprintf("%s, %s", sentHeaderVal, ourReportedIP.String())

	// Second request with existing XFF.
	url = fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ = http.NewRequest("GET", url, nil)
	req.Header.Set(headerName, sentHeaderVal)

	_, err = client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	if receivedHeaderVal != expectedHeaderVal {
		t.Errorf(
			"Origin received %q header with wrong value. Expected %q, got %q",
			headerName,
			expectedHeaderVal,
			receivedHeaderVal,
		)
	}
}

// Should create a True-Client-IP header containing the client's IP
// address, discarding the value provided in the original request.
func TestHeaderUnspoofableClientIP(t *testing.T) {
	const headerName = "True-Client-IP"
	const sentHeaderVal = "203.0.113.99"
	var sentHeaderIP = net.ParseIP(sentHeaderVal)
	var receivedHeaderVal string

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Header.Get(headerName)
	})

	url := fmt.Sprintf("https://%s/%s", *edgeHost, NewUUID())
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set(headerName, sentHeaderVal)

	_, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	receivedHeaderIP := net.ParseIP(receivedHeaderVal)
	if receivedHeaderIP == nil {
		t.Fatalf("Origin received %q header with non-IP value %q", headerName, receivedHeaderVal)
	}
	if receivedHeaderIP.Equal(sentHeaderIP) {
		t.Errorf("Origin received %q header with unmodified value %q", headerName, receivedHeaderIP)
	}
}

// Should not modify Host header from original request.
func TestHeaderHostUnmodified(t *testing.T) {
	t.Error("Not implemented")
}

// Should serve a known static error page if cannot serve a page
// from origin, stale or any mirror.
// NB: ideally this should be a page that we control that has a mechanism
//     to alert us that it has been served.
func TestErrorPageIsServedWhenNoBackendAvailable(t *testing.T) {
	t.Error("Not implemented")
}

// ---------------------------------------------------------
// Test that useful common cache-related parameters are sent to the
// client by this CDN provider.

// Should set an Age header itself rather than passing the Age header from origin.
func TestAgeHeaderIsSetByProviderNotOrigin(t *testing.T) {
	const originAgeInSeconds = 100
	const secondsToWaitBetweenRequests = 5
	requestReceivedCount := 0
	uuid := NewUUID()

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		if requestReceivedCount == 0 {
			w.Header().Set("Cache-Control", "max-age=1800, public")
			w.Header().Set("Age", fmt.Sprintf("%d", originAgeInSeconds))
			w.Write([]byte("cacheable request"))
		} else {
			t.Error("Unexpected subsequent request received at Origin")
		}
		requestReceivedCount++
	})

	url := fmt.Sprintf("https://%s/?cache-lock=%s", *edgeHost, uuid)
	req, _ := http.NewRequest("GET", url, nil)

	resp, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	if resp.StatusCode != 200 {
		t.Fatalf("Edge returned an unexpected status: %q", resp.Status)
	}

	// wait a little bit. Edge should update the Age header, we know Origin will not
	time.Sleep(time.Duration(secondsToWaitBetweenRequests) * time.Second)

	resp, err = client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	if resp.StatusCode != 200 {
		t.Fatal("Edge returned an unexpected status: %q", resp.Status)
	}

	edgeAgeHeader := resp.Header.Get("Age")
	if edgeAgeHeader == "" {
		t.Fatal("Age Header is not set")
	}

	edgeAgeInSeconds, convErr := strconv.Atoi(edgeAgeHeader)
	if convErr != nil {
		t.Fatal(convErr)
	}

	expectedAgeInSeconds := originAgeInSeconds + secondsToWaitBetweenRequests
	if edgeAgeInSeconds != expectedAgeInSeconds {
		t.Errorf(
			"Age header from Edge is not as expected. Got %q, expected '%d'",
			edgeAgeHeader,
			expectedAgeInSeconds,
		)
	}

}

// Should set an X-Cache header containing HIT/MISS from 'origin, itself'
func TestXCacheHeaderContainsHitMissFromBothProviderAndOrigin(t *testing.T) {
	t.Error("Not implemented")
}

// Should set an X-Served-By header giving information on the (Fastly) node and location served from.
func TestXServedByHeaderContainsFastlyNodeIdAndLocation(t *testing.T) {

	expectedFastlyXServedByRegexp := regexp.MustCompile("^cache-[a-z0-9]+-[A-Z]{3}$")

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {})

	sourceUrl := fmt.Sprintf("https://%s/", *edgeHost)

	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	actualHeader := resp.Header.Get("X-Served-By")
	if actualHeader == "" {
		t.Error("X-Served-By header has not been set by Edge")
	}

	if expectedFastlyXServedByRegexp.FindString(actualHeader) != actualHeader {
		t.Errorf("X-Served-By is not as expected: got %q", actualHeader)
	}

}

// Should set an X-Cache-Hits header containing hit count for this object,
// from the Edge AND the Origin, assuming Origin sets one.
// This is in the format "{origin-hit-count}, {edge-hit-count}"
func TestXCacheHitsContainsProviderHitCountForThisObject(t *testing.T) {

	const originXCacheHits = "53"

	var (
		xCacheHits         string
		expectedXCacheHits string
	)

	uuid := NewUUID()
	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "GET" && r.URL.Path == fmt.Sprintf("/%s", uuid) {
			w.Header().Set("X-Cache-Hits", originXCacheHits)
		}
	})

	sourceUrl := fmt.Sprintf("https://%s/%s", *edgeHost, uuid)

	// Get first request, will come from origin. Edge Hit Count 0
	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	xCacheHits = resp.Header.Get("X-Cache-Hits")
	expectedXCacheHits = fmt.Sprintf("%s, 0", originXCacheHits)
	if xCacheHits != expectedXCacheHits {
		t.Errorf(
			"X-Cache-Hits on initial hit is wrong: expected %q, got %q",
			expectedXCacheHits,
			xCacheHits,
		)
	}

	// Get request again. Should come from Edge now, hit count 1
	resp, err = client.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	xCacheHits = resp.Header.Get("X-Cache-Hits")
	expectedXCacheHits = fmt.Sprintf("%s, 1", originXCacheHits)
	if xCacheHits != expectedXCacheHits {
		t.Errorf(
			"X-Cache-Hits on second hit is wrong: expected %q, got %q",
			expectedXCacheHits,
			xCacheHits,
		)
	}

}
<|endoftext|>


<commit_before>package node

import (
	"github.com/AutoRoute/l2"
)

// The layer two protocol takes a layer two device and returns the hash of the
// Public Key of all neighbors it can find.
type NeighborFinder interface {
	Find(l2.FrameReadWriter) <-chan string
}

// A map of a fixed size representing an interfaces potential
type ReachabilityMap interface{}

// A receipt listing packets which have been succesfully deliver.
type PacketReceipt interface{}

// Layer three interfaces for network control traffic
type MapConnection interface {
	SendMap(ReachabilityMap)
	ReadabilityMaps() <-chan ReachabilityMap
}
type ReceiptConnection interface {
	SendReceipt(PacketReceipt)
	PacketReceipts() <-chan PacketReceipt
}

// While the two connections use different messages, a working ControlConnection has both interfaces
type ControlConnection interface {
	MapConnection
	ReceiptConnection
}

// The actual data connection. Should be done at the layer two level in order to be able to send congestion signals
type DataConnection interface {
	SendPacket([]byte)
	Packets() <-chan []byte
}
<commit_msg>More fleshing out of interfaces<commit_after>package node

import (
	"github.com/AutoRoute/l2"
)

// The layer two protocol takes a layer two device and returns the hash of the
// Public Key of all neighbors it can find.
type NeighborFinder interface {
	Find(l2.FrameReadWriter) <-chan string
}

// Dummy interface to represent public keys
type PublicKey interface{}

// A map of a fixed size representing an interfaces potential
type ReachabilityMap interface {
	IsReachable(p PublicKey)
}

// A receipt listing packets which have been succesfully delivered
type PacketReceipt interface {
	ListPackets() []string
	Verify(p PublicKey) error
}

// Layer three interfaces for network control traffic
type MapConnection interface {
	SendMap(ReachabilityMap) error
	ReadabilityMaps() <-chan ReachabilityMap
}
type ReceiptConnection interface {
	SendReceipt(PacketReceipt) error
	PacketReceipts() <-chan PacketReceipt
}

// While the two connections use different messages, a working ControlConnection has both interfaces
type ControlConnection interface {
	MapConnection
	ReceiptConnection
}

// The actual data connection. Should be done at the layer two level in order to be able to send congestion signals
type DataConnection interface {
	SendPacket([]byte) error
	Packets() <-chan []byte
}
<|endoftext|>


<commit_before>package transport

import (
	"fmt"

	"sync"

	"gitlab.fg/go/disco/node"
	"gitlab.fg/go/stela"
	"gitlab.fg/go/stela/store"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

// Server implements the stela.proto service
type Server struct {
	mu    sync.Mutex
	Store store.Store
	peers []*node.Node
}

// AddClient adds a client to the store and returns it's id
func (s *Server) AddClient(ctx context.Context, req *stela.AddClientRequest) (*stela.AddClientResponse, error) {
	// Add client to the store
	c := &stela.Client{}
	c.Address = req.ClientAddress
	if err := s.Store.AddClient(c); err != nil {
		return nil, err
	}

	return &stela.AddClientResponse{
		ClientId: c.ID,
	}, nil
}

// Connect a stela client to a stream of possible subscriptions. Uses the client id in to keep track
// of services and subscriptions it registers
func (s *Server) Connect(req *stela.ConnectRequest, stream stela.Stela_ConnectServer) error {
	ctx := stream.Context()

	// Look up client
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return err
	}

	fmt.Println("connect!", c)

	// Send service to clients on interval for simiulation
	for {
		select {
		case rs := <-c.SubscribeCh():
			response := &stela.ServiceResponse{
				Name:     rs.Name,
				Hostname: rs.Target,
				Address:  rs.Address,
				Port:     rs.Port,
				Priority: rs.Priority,
			}

			fmt.Println("send", rs)

			if err := stream.Send(response); err != nil {
				return err
			}
		case <-ctx.Done():
			// Remove client from store to cleanup
			s.Store.RemoveClient(c)
			return nil
		}
	}
}

// Subscribe a client to a service name.
func (s *Server) Subscribe(ctx context.Context, req *stela.SubscribeRequest) (*stela.SubscribeResponse, error) {
	// Look up client that sent the request
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return nil, err
	}

	// Subscribe the client to the serviceName
	s.Store.Subscribe(req.ServiceName, c)

	return &stela.SubscribeResponse{}, nil
}

// Unsubscribe a client to a service name.
func (s *Server) Unsubscribe(ctx context.Context, req *stela.SubscribeRequest) (*stela.SubscribeResponse, error) {
	// Look up client that sent the request
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return nil, err
	}

	// Subscribe the client to the serviceName
	s.Store.Unsubscribe(req.ServiceName, c)

	return &stela.SubscribeResponse{}, nil
}

// Register a service to a client
func (s *Server) Register(ctx context.Context, req *stela.RegisterRequest) (*stela.RegisterResponse, error) {
	// Look up client that sent the request
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return nil, err
	}

	// Convert req to service
	service := &stela.Service{
		Name:     req.Name,
		Target:   req.Hostname,
		Address:  req.Address,
		Port:     req.Port,
		Priority: req.Priority,
		Action:   stela.RegisterAction,
		Client:   c,
	}

	// Register service to store
	if err := s.Store.Register(service); err != nil {
		return nil, err
	}

	return &stela.RegisterResponse{}, nil
}

// Deregister a service
func (s *Server) Deregister(ctx context.Context, req *stela.RegisterRequest) (*stela.RegisterResponse, error) {
	// Look up client that sent the request
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return nil, err
	}

	// Convert req to service
	service := &stela.Service{
		Name:     req.Name,
		Target:   req.Hostname,
		Address:  req.Address,
		Port:     req.Port,
		Priority: req.Priority,
		Action:   stela.RegisterAction,
		Client:   c,
	}

	// Register service to store
	s.Store.Deregister(service)

	return &stela.RegisterResponse{}, nil
}

// Discover all services registered under a service name. Ex. "test.services.fg"
func (s *Server) Discover(ctx context.Context, req *stela.DiscoverRequest) (*stela.DiscoverResponse, error) {
	services, err := s.Store.Discover(req.ServiceName)
	if err != nil {
		return nil, err
	}

	// Convert stela.Service struct to stela.ServiceResponse
	var srs []*stela.ServiceResponse
	for _, ds := range services {
		sr := &stela.ServiceResponse{
			Name:     ds.Name,
			Hostname: ds.Target,
			Address:  ds.Address,
			Port:     ds.Port,
			Priority: ds.Priority,
		}
		srs = append(srs, sr)
	}

	return &stela.DiscoverResponse{Services: srs}, nil
}

// DiscoverOne service registered under a service name.
func (s *Server) DiscoverOne(ctx context.Context, req *stela.DiscoverRequest) (*stela.ServiceResponse, error) {
	service, err := s.Store.DiscoverOne(req.ServiceName)
	if err != nil {
		return nil, err
	}

	// Convert stela.Service struct to stela.ServiceResponse
	return &stela.ServiceResponse{
		Name:     service.Name,
		Hostname: service.Target,
		Address:  service.Address,
		Port:     service.Port,
		Priority: service.Priority,
	}, nil
}

// DiscoverAll returns all services registered with stela even other clients TODO
func (s *Server) DiscoverAll(ctx context.Context, req *stela.DiscoverAllRequest) (*stela.DiscoverResponse, error) {
	services := s.Store.DiscoverAll()

	// Convert stela.Service struct to stela.ServiceResponse
	var srs []*stela.ServiceResponse
	for _, ds := range services {
		sr := &stela.ServiceResponse{
			Name:     ds.Name,
			Hostname: ds.Target,
			Address:  ds.Address,
			Port:     ds.Port,
			Priority: ds.Priority,
		}
		srs = append(srs, sr)
	}

	return &stela.DiscoverResponse{Services: srs}, nil
}

// PeerDiscover all services registered under a service name. Ex. "test.services.fg"
func (s *Server) PeerDiscover(ctx context.Context, req *stela.DiscoverRequest) (*stela.DiscoverResponse, error) {
	return nil, grpc.Errorf(codes.Unimplemented, "Currently Unimplemented")
}

// PeerDiscoverOne service registered under a service name.
func (s *Server) PeerDiscoverOne(ctx context.Context, req *stela.DiscoverRequest) (*stela.ServiceResponse, error) {
	return nil, grpc.Errorf(codes.Unimplemented, "Currently Unimplemented")
}

// PeerDiscoverAll returns all services registered with any stela member peer
func (s *Server) PeerDiscoverAll(ctx context.Context, req *stela.DiscoverAllRequest) (*stela.DiscoverResponse, error) {
	return nil, grpc.Errorf(codes.Unimplemented, "Currently Unimplemented")
}

// SetPeers sets the peers slice
func (s *Server) SetPeers(peers []*node.Node) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.peers = peers
}
<commit_msg>Starting logic for peer discoverer<commit_after>package transport

import (
	"fmt"

	"sync"

	"gitlab.fg/go/disco/node"
	"gitlab.fg/go/stela"
	"gitlab.fg/go/stela/store"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

// Server implements the stela.proto service
type Server struct {
	mu    sync.Mutex
	Store store.Store
	peers []*node.Node
}

// AddClient adds a client to the store and returns it's id
func (s *Server) AddClient(ctx context.Context, req *stela.AddClientRequest) (*stela.AddClientResponse, error) {
	// Add client to the store
	c := &stela.Client{}
	c.Address = req.ClientAddress
	if err := s.Store.AddClient(c); err != nil {
		return nil, err
	}

	return &stela.AddClientResponse{
		ClientId: c.ID,
	}, nil
}

// Connect a stela client to a stream of possible subscriptions. Uses the client id in to keep track
// of services and subscriptions it registers
func (s *Server) Connect(req *stela.ConnectRequest, stream stela.Stela_ConnectServer) error {
	ctx := stream.Context()

	// Look up client
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return err
	}

	fmt.Println("connect!", c)

	// Send service to clients on interval for simiulation
	for {
		select {
		case rs := <-c.SubscribeCh():
			response := &stela.ServiceResponse{
				Name:     rs.Name,
				Hostname: rs.Target,
				Address:  rs.Address,
				Port:     rs.Port,
				Priority: rs.Priority,
			}

			fmt.Println("send", rs)

			if err := stream.Send(response); err != nil {
				return err
			}
		case <-ctx.Done():
			// Remove client from store to cleanup
			s.Store.RemoveClient(c)
			return nil
		}
	}
}

// Subscribe a client to a service name.
func (s *Server) Subscribe(ctx context.Context, req *stela.SubscribeRequest) (*stela.SubscribeResponse, error) {
	// Look up client that sent the request
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return nil, err
	}

	// Subscribe the client to the serviceName
	s.Store.Subscribe(req.ServiceName, c)

	return &stela.SubscribeResponse{}, nil
}

// Unsubscribe a client to a service name.
func (s *Server) Unsubscribe(ctx context.Context, req *stela.SubscribeRequest) (*stela.SubscribeResponse, error) {
	// Look up client that sent the request
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return nil, err
	}

	// Subscribe the client to the serviceName
	s.Store.Unsubscribe(req.ServiceName, c)

	return &stela.SubscribeResponse{}, nil
}

// Register a service to a client
func (s *Server) Register(ctx context.Context, req *stela.RegisterRequest) (*stela.RegisterResponse, error) {
	// Look up client that sent the request
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return nil, err
	}

	// Convert req to service
	service := &stela.Service{
		Name:     req.Name,
		Target:   req.Hostname,
		Address:  req.Address,
		Port:     req.Port,
		Priority: req.Priority,
		Action:   stela.RegisterAction,
		Client:   c,
	}

	// Register service to store
	if err := s.Store.Register(service); err != nil {
		return nil, err
	}

	return &stela.RegisterResponse{}, nil
}

// Deregister a service
func (s *Server) Deregister(ctx context.Context, req *stela.RegisterRequest) (*stela.RegisterResponse, error) {
	// Look up client that sent the request
	c, err := s.Store.Client(req.ClientId)
	if err != nil {
		return nil, err
	}

	// Convert req to service
	service := &stela.Service{
		Name:     req.Name,
		Target:   req.Hostname,
		Address:  req.Address,
		Port:     req.Port,
		Priority: req.Priority,
		Action:   stela.RegisterAction,
		Client:   c,
	}

	// Register service to store
	s.Store.Deregister(service)

	return &stela.RegisterResponse{}, nil
}

// Discover all services registered under a service name. Ex. "test.services.fg"
func (s *Server) Discover(ctx context.Context, req *stela.DiscoverRequest) (*stela.DiscoverResponse, error) {
	services, err := s.Store.Discover(req.ServiceName)
	if err != nil {
		return nil, err
	}

	// Convert stela.Service struct to stela.ServiceResponse
	var srs []*stela.ServiceResponse
	for _, ds := range services {
		sr := &stela.ServiceResponse{
			Name:     ds.Name,
			Hostname: ds.Target,
			Address:  ds.Address,
			Port:     ds.Port,
			Priority: ds.Priority,
		}
		srs = append(srs, sr)
	}

	return &stela.DiscoverResponse{Services: srs}, nil
}

// DiscoverOne service registered under a service name.
func (s *Server) DiscoverOne(ctx context.Context, req *stela.DiscoverRequest) (*stela.ServiceResponse, error) {
	service, err := s.Store.DiscoverOne(req.ServiceName)
	if err != nil {
		return nil, err
	}

	// Convert stela.Service struct to stela.ServiceResponse
	return &stela.ServiceResponse{
		Name:     service.Name,
		Hostname: service.Target,
		Address:  service.Address,
		Port:     service.Port,
		Priority: service.Priority,
	}, nil
}

// DiscoverAll returns all services registered with stela even other clients TODO
func (s *Server) DiscoverAll(ctx context.Context, req *stela.DiscoverAllRequest) (*stela.DiscoverResponse, error) {
	services := s.Store.DiscoverAll()

	// Convert stela.Service struct to stela.ServiceResponse
	var srs []*stela.ServiceResponse
	for _, ds := range services {
		sr := &stela.ServiceResponse{
			Name:     ds.Name,
			Hostname: ds.Target,
			Address:  ds.Address,
			Port:     ds.Port,
			Priority: ds.Priority,
		}
		srs = append(srs, sr)
	}

	return &stela.DiscoverResponse{Services: srs}, nil
}

// PeerDiscover all services registered under a service name. Ex. "test.services.fg"
// TODO look into errgroup
func (s *Server) PeerDiscover(ctx context.Context, req *stela.DiscoverRequest) (*stela.DiscoverResponse, error) {
	wg := &sync.WaitGroup{}
	wg.Add(len(s.peers))

	var results []*stela.ServiceResponse
	var mu sync.Mutex
	for _, p := range s.peers {
		go func(p *node.Node) {
			defer wg.Done()
			conn, err := grpc.Dial(p.Values["Address"], grpcOptions()...)
			if err != nil {
				return
			}
			c := stela.NewStelaClient(conn)
			resp, err := c.Discover(ctx, req)
			if err != nil {
				return
			}

			mu.Lock()
			defer mu.Unlock()
			results = append(results, resp.Services...)
		}(p)
	}
	wg.Wait()

	return &stela.DiscoverResponse{Services: results}, nil
}

// PeerDiscoverOne service registered under a service name.
func (s *Server) PeerDiscoverOne(ctx context.Context, req *stela.DiscoverRequest) (*stela.ServiceResponse, error) {
	return nil, grpc.Errorf(codes.Unimplemented, "Currently Unimplemented")
}

// PeerDiscoverAll returns all services registered with any stela member peer
func (s *Server) PeerDiscoverAll(ctx context.Context, req *stela.DiscoverAllRequest) (*stela.DiscoverResponse, error) {
	return nil, grpc.Errorf(codes.Unimplemented, "Currently Unimplemented")
}

// SetPeers sets the peers slice
func (s *Server) SetPeers(peers []*node.Node) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.peers = peers
}

func grpcOptions() []grpc.DialOption {
	var opts []grpc.DialOption
	// creds, err := credentials.NewClientTLSFromFile(caFile, "")
	// if err != nil {
	// 	return nil, err
	// }

	// opts = append(opts, grpc.WithTransportCredentials(creds))
	opts = append(opts, grpc.WithInsecure())

	return opts
}
<|endoftext|>


<commit_before>package tuikit

type SplitLayout struct {
	*BaseView

	split1, split2 Painter
}

func NewSplitLayout(split1, split2 Painter) *SplitLayout {
	l := &SplitLayout{
		BaseView: NewBaseView(),
		split1:   split1,
		split2:   split2,
	}
	l.SetUpdateChildrenRect(l.updateChildrenRect)
	return l
}

func (l *SplitLayout) updateChildrenRect(rect Rect) error {
	r1 := rect
	r1.Height = rect.Height / 2
	l.AttachChild(l.split1, r1)

	r2 := rect
	r2.Height = rect.Height - r1.Height
	r2.Y = r1.Y + r1.Height
	l.AttachChild(l.split2, r2)

	return nil
}
<commit_msg>SplitLayout now supports splitting with a ratio<commit_after>package tuikit

type SplitLayout struct {
	*BaseView

	split1, split2 Painter
	ratio          float32
}

func NewSplitLayout(split1, split2 Painter) *SplitLayout {
	l := &SplitLayout{
		BaseView: NewBaseView(),
		split1:   split1,
		split2:   split2,
	}
	l.SetRatio(0.5)
	l.SetUpdateChildrenRect(l.updateChildrenRect)
	return l
}

func (l *SplitLayout) SetRatio(ratio float32) {
	switch {
	case ratio > 1:
		ratio = 1
	case ratio < 0:
		ratio = 0
	}
	l.ratio = ratio
}

func (l *SplitLayout) updateChildrenRect(rect Rect) error {
	r1 := rect
	r1.Height = int(float32(rect.Height) * l.ratio)
	l.AttachChild(l.split1, r1)

	r2 := rect
	r2.Height = rect.Height - r1.Height
	r2.Y = r1.Y + r1.Height
	l.AttachChild(l.split2, r2)

	return nil
}
<|endoftext|>


<commit_before>package irc

import (
	"fmt"
	"net"
	"time"
)

const (
	LOGIN_TIMEOUT = time.Minute / 2 // how long the client has to login
	IDLE_TIMEOUT  = time.Minute     // how long before a client is considered idle
	QUIT_TIMEOUT  = time.Minute     // how long after idle before a client is kicked
)

type Client struct {
	atime        time.Time
	authorized   bool
	awayMessage  Text
	capabilities CapabilitySet
	capState     CapState
	channels     ChannelSet
	commands     chan Command
	ctime        time.Time
	flags        map[UserMode]bool
	hasQuit      bool
	hops         uint
	hostname     Name
	idleTimer    *time.Timer
	loginTimer   *time.Timer
	nick         Name
	quitTimer    *time.Timer
	realname     Text
	registered   bool
	server       *Server
	socket       *Socket
	username     Name
}

func NewClient(server *Server, conn net.Conn) *Client {
	now := time.Now()
	client := &Client{
		atime:        now,
		authorized:   server.password == nil,
		capState:     CapNone,
		capabilities: make(CapabilitySet),
		channels:     make(ChannelSet),
		commands:     make(chan Command),
		ctime:        now,
		flags:        make(map[UserMode]bool),
		server:       server,
	}
	client.socket = NewSocket(conn, client.commands)
	client.loginTimer = time.AfterFunc(LOGIN_TIMEOUT, client.connectionTimeout)
	go client.run()

	return client
}

//
// command goroutine
//

func (client *Client) run() {
	for command := range client.commands {
		command.SetClient(client)

		checkPass, ok := command.(checkPasswordCommand)
		if ok {
			checkPass.LoadPassword(client.server)
			checkPass.CheckPassword()
		}

		client.server.commands <- command
	}
}

func (client *Client) connectionTimeout() {
	client.commands <- &QuitCommand{
		message: "connection timeout",
	}
}

//
// idle timer goroutine
//

func (client *Client) connectionIdle() {
	client.server.idle <- client
}

//
// server goroutine
//

func (client *Client) Active() {
	client.atime = time.Now()
}

func (client *Client) Touch() {
	if client.quitTimer != nil {
		client.quitTimer.Stop()
	}

	if client.idleTimer == nil {
		client.idleTimer = time.AfterFunc(IDLE_TIMEOUT, client.connectionIdle)
	} else {
		client.idleTimer.Reset(IDLE_TIMEOUT)
	}
}

func (client *Client) Idle() {
	client.Reply(RplPing(client))

	if client.quitTimer == nil {
		client.quitTimer = time.AfterFunc(QUIT_TIMEOUT, client.connectionTimeout)
	} else {
		client.quitTimer.Reset(QUIT_TIMEOUT)
	}
}

func (client *Client) Register() {
	if client.registered {
		return
	}
	client.registered = true
	client.loginTimer.Stop()
	client.Touch()
}

func (client *Client) destroy() {
	// clean up channels

	for channel := range client.channels {
		channel.Quit(client)
	}

	// clean up server

	client.server.clients.Remove(client)

	// clean up self

	if client.loginTimer != nil {
		client.loginTimer.Stop()
	}
	if client.idleTimer != nil {
		client.idleTimer.Stop()
	}
	if client.quitTimer != nil {
		client.quitTimer.Stop()
	}

	client.socket.Close()

	Log.debug.Printf("%s: destroyed", client)
}

func (client *Client) IdleTime() time.Duration {
	return time.Since(client.atime)
}

func (client *Client) SignonTime() int64 {
	return client.ctime.Unix()
}

func (client *Client) IdleSeconds() uint64 {
	return uint64(client.IdleTime().Seconds())
}

func (client *Client) HasNick() bool {
	return client.nick != ""
}

func (client *Client) HasUsername() bool {
	return client.username != ""
}

// <mode>
func (c *Client) ModeString() (str string) {
	for flag := range c.flags {
		str += flag.String()
	}

	if len(str) > 0 {
		str = "+" + str
	}
	return
}

func (c *Client) UserHost() Name {
	username := "*"
	if c.HasUsername() {
		username = c.username.String()
	}
	return Name(fmt.Sprintf("%s!%s@%s", c.Nick(), username, c.hostname))
}

func (c *Client) Nick() Name {
	if c.HasNick() {
		return c.nick
	}
	return Name("*")
}

func (c *Client) Id() Name {
	return c.UserHost()
}

func (c *Client) String() string {
	return c.Id().String()
}

func (client *Client) Friends() ClientSet {
	friends := make(ClientSet)
	friends.Add(client)
	for channel := range client.channels {
		for member := range channel.members {
			friends.Add(member)
		}
	}
	return friends
}

func (client *Client) SetNickname(nickname Name) {
	client.nick = nickname
	client.server.clients.Add(client)
}

func (client *Client) ChangeNickname(nickname Name) {
	// Make reply before changing nick to capture original source id.
	reply := RplNick(client, nickname)
	client.server.clients.Remove(client)
	client.server.whoWas.Append(client)
	client.nick = nickname
	client.server.clients.Add(client)
	for friend := range client.Friends() {
		friend.Reply(reply)
	}
}

func (client *Client) Reply(reply string, args ...interface{}) {
	if len(args) > 0 {
		reply = fmt.Sprintf(reply, args...)
	}
	client.socket.Write(reply)
}

func (client *Client) Quit(message Text) {
	if client.hasQuit {
		return
	}

	client.Reply(RplError("connection closed"))
	client.hasQuit = true
	client.server.whoWas.Append(client)
	friends := client.Friends()
	friends.Remove(client)
	client.destroy()

	if len(friends) > 0 {
		reply := RplQuit(client, message)
		for friend := range friends {
			friend.Reply(reply)
		}
	}
}
<commit_msg>explain why CheckPassword happens in client thread<commit_after>package irc

import (
	"fmt"
	"net"
	"time"
)

const (
	LOGIN_TIMEOUT = time.Minute / 2 // how long the client has to login
	IDLE_TIMEOUT  = time.Minute     // how long before a client is considered idle
	QUIT_TIMEOUT  = time.Minute     // how long after idle before a client is kicked
)

type Client struct {
	atime        time.Time
	authorized   bool
	awayMessage  Text
	capabilities CapabilitySet
	capState     CapState
	channels     ChannelSet
	commands     chan Command
	ctime        time.Time
	flags        map[UserMode]bool
	hasQuit      bool
	hops         uint
	hostname     Name
	idleTimer    *time.Timer
	loginTimer   *time.Timer
	nick         Name
	quitTimer    *time.Timer
	realname     Text
	registered   bool
	server       *Server
	socket       *Socket
	username     Name
}

func NewClient(server *Server, conn net.Conn) *Client {
	now := time.Now()
	client := &Client{
		atime:        now,
		authorized:   server.password == nil,
		capState:     CapNone,
		capabilities: make(CapabilitySet),
		channels:     make(ChannelSet),
		commands:     make(chan Command),
		ctime:        now,
		flags:        make(map[UserMode]bool),
		server:       server,
	}
	client.socket = NewSocket(conn, client.commands)
	client.loginTimer = time.AfterFunc(LOGIN_TIMEOUT, client.connectionTimeout)
	go client.run()

	return client
}

//
// command goroutine
//

func (client *Client) run() {
	for command := range client.commands {
		command.SetClient(client)

		checkPass, ok := command.(checkPasswordCommand)
		if ok {
			checkPass.LoadPassword(client.server)
			// Block the client thread while handling a potentially expensive
			// password bcrypt operation. Since the server is single-threaded
			// for commands, we don't want the server to perform the bcrypt,
			// blocking anyone else from sending commands until it
			// completes. This could be a form of DoS if handled naively.
			checkPass.CheckPassword()
		}

		client.server.commands <- command
	}
}

func (client *Client) connectionTimeout() {
	client.commands <- &QuitCommand{
		message: "connection timeout",
	}
}

//
// idle timer goroutine
//

func (client *Client) connectionIdle() {
	client.server.idle <- client
}

//
// server goroutine
//

func (client *Client) Active() {
	client.atime = time.Now()
}

func (client *Client) Touch() {
	if client.quitTimer != nil {
		client.quitTimer.Stop()
	}

	if client.idleTimer == nil {
		client.idleTimer = time.AfterFunc(IDLE_TIMEOUT, client.connectionIdle)
	} else {
		client.idleTimer.Reset(IDLE_TIMEOUT)
	}
}

func (client *Client) Idle() {
	client.Reply(RplPing(client))

	if client.quitTimer == nil {
		client.quitTimer = time.AfterFunc(QUIT_TIMEOUT, client.connectionTimeout)
	} else {
		client.quitTimer.Reset(QUIT_TIMEOUT)
	}
}

func (client *Client) Register() {
	if client.registered {
		return
	}
	client.registered = true
	client.loginTimer.Stop()
	client.Touch()
}

func (client *Client) destroy() {
	// clean up channels

	for channel := range client.channels {
		channel.Quit(client)
	}

	// clean up server

	client.server.clients.Remove(client)

	// clean up self

	if client.loginTimer != nil {
		client.loginTimer.Stop()
	}
	if client.idleTimer != nil {
		client.idleTimer.Stop()
	}
	if client.quitTimer != nil {
		client.quitTimer.Stop()
	}

	client.socket.Close()

	Log.debug.Printf("%s: destroyed", client)
}

func (client *Client) IdleTime() time.Duration {
	return time.Since(client.atime)
}

func (client *Client) SignonTime() int64 {
	return client.ctime.Unix()
}

func (client *Client) IdleSeconds() uint64 {
	return uint64(client.IdleTime().Seconds())
}

func (client *Client) HasNick() bool {
	return client.nick != ""
}

func (client *Client) HasUsername() bool {
	return client.username != ""
}

// <mode>
func (c *Client) ModeString() (str string) {
	for flag := range c.flags {
		str += flag.String()
	}

	if len(str) > 0 {
		str = "+" + str
	}
	return
}

func (c *Client) UserHost() Name {
	username := "*"
	if c.HasUsername() {
		username = c.username.String()
	}
	return Name(fmt.Sprintf("%s!%s@%s", c.Nick(), username, c.hostname))
}

func (c *Client) Nick() Name {
	if c.HasNick() {
		return c.nick
	}
	return Name("*")
}

func (c *Client) Id() Name {
	return c.UserHost()
}

func (c *Client) String() string {
	return c.Id().String()
}

func (client *Client) Friends() ClientSet {
	friends := make(ClientSet)
	friends.Add(client)
	for channel := range client.channels {
		for member := range channel.members {
			friends.Add(member)
		}
	}
	return friends
}

func (client *Client) SetNickname(nickname Name) {
	client.nick = nickname
	client.server.clients.Add(client)
}

func (client *Client) ChangeNickname(nickname Name) {
	// Make reply before changing nick to capture original source id.
	reply := RplNick(client, nickname)
	client.server.clients.Remove(client)
	client.server.whoWas.Append(client)
	client.nick = nickname
	client.server.clients.Add(client)
	for friend := range client.Friends() {
		friend.Reply(reply)
	}
}

func (client *Client) Reply(reply string, args ...interface{}) {
	if len(args) > 0 {
		reply = fmt.Sprintf(reply, args...)
	}
	client.socket.Write(reply)
}

func (client *Client) Quit(message Text) {
	if client.hasQuit {
		return
	}

	client.Reply(RplError("connection closed"))
	client.hasQuit = true
	client.server.whoWas.Append(client)
	friends := client.Friends()
	friends.Remove(client)
	client.destroy()

	if len(friends) > 0 {
		reply := RplQuit(client, message)
		for friend := range friends {
			friend.Reply(reply)
		}
	}
}
<|endoftext|>


<commit_before>package checkers

import "github.com/cl0ne/go-checkers/point"

/*
Checker board class
For example:

  abcdefgh
 ..........
8| # # # #|8
7|# # # # |7
6| # # # #|6
5|# # # # |5
4| # # # #|4
3|# # # # |3
2| # # # #|2
1|# # # # |1
 ''''''''''
  abcdefgh

Here a1 has position (0,0) and h8 is on (7,7)
*/
type Board struct {
	cells [][]*Checker
}

func NewBoard(size int) (*Board, bool) {
	if size < 0 {
		return nil, false
	}
	cells := make([][]*Checker, size)
	for i := range cells {
		cells[i] = make([]*Checker, size)
	}
	return &Board{cells: cells}, true
}

func (b Board) Size() int {
	return len(b.cells)
}

func (b *Board) placeChecker(x, y int, c *Checker) {
	b.cells[y][x] = c
	if c != nil {
		c.setPosition(x, y)
	}
}

func (b *Board) takeChecker(x, y int) *Checker {
	c := b.cells[y][x]
	b.cells[y][x] = nil
	return c
}

func (b *Board) moveChecker(from, to point.Point) {
	c1 := b.cells[from.Y][from.X]
	c2 := b.cells[to.Y][to.X]
	b.placeChecker(from.X, from.Y, c2)
	b.placeChecker(to.X, to.Y, c1)
}

func (b Board) GetChecker(x, y int) *Checker {
	return b.cells[y][x]
}

func (b Board) IsEmpty(x, y int) bool {
	return b.cells[y][x] == nil
}

func (b Board) IsBlackSquare(pos point.Point) bool {
	return pos.Manhattan()%2 == 0
}

func (b Board) IsWhiteSquare(pos point.Point) bool {
	return pos.Manhattan()%2 == 1
}

func (b Board) ContainsPos(x, y int) bool {
	fieldSize := b.Size()
	return x >= 0 && y >= 0 && x < fieldSize && y < fieldSize
}
<commit_msg>Remove unneeded 'success' result for NewBoard<commit_after>package checkers

import "github.com/cl0ne/go-checkers/point"

/*
Checker board class
For example:

  abcdefgh
 ..........
8| # # # #|8
7|# # # # |7
6| # # # #|6
5|# # # # |5
4| # # # #|4
3|# # # # |3
2| # # # #|2
1|# # # # |1
 ''''''''''
  abcdefgh

Here a1 has position (0,0) and h8 is on (7,7)
*/
type Board struct {
	cells [][]*Checker
}

func NewBoard(size int) *Board {
	if size < 0 {
		return nil
	}
	cells := make([][]*Checker, size)
	for i := range cells {
		cells[i] = make([]*Checker, size)
	}
	return &Board{cells: cells}
}

func (b Board) Size() int {
	return len(b.cells)
}

func (b *Board) placeChecker(x, y int, c *Checker) {
	b.cells[y][x] = c
	if c != nil {
		c.setPosition(x, y)
	}
}

func (b *Board) takeChecker(x, y int) *Checker {
	c := b.cells[y][x]
	b.cells[y][x] = nil
	return c
}

func (b *Board) moveChecker(from, to point.Point) {
	c1 := b.cells[from.Y][from.X]
	c2 := b.cells[to.Y][to.X]
	b.placeChecker(from.X, from.Y, c2)
	b.placeChecker(to.X, to.Y, c1)
}

func (b Board) GetChecker(x, y int) *Checker {
	return b.cells[y][x]
}

func (b Board) IsEmpty(x, y int) bool {
	return b.cells[y][x] == nil
}

func (b Board) IsBlackSquare(pos point.Point) bool {
	return pos.Manhattan()%2 == 0
}

func (b Board) IsWhiteSquare(pos point.Point) bool {
	return pos.Manhattan()%2 == 1
}

func (b Board) ContainsPos(x, y int) bool {
	fieldSize := b.Size()
	return x >= 0 && y >= 0 && x < fieldSize && y < fieldSize
}
<|endoftext|>


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

// Pipe adapter to connect code expecting an io.Reader
// with code expecting an io.Writer.

package io

import (
	"os"
	"runtime"
	"sync"
)

type pipeResult struct {
	n   int
	err os.Error
}

// Shared pipe structure.
type pipe struct {
	// Reader sends on cr1, receives on cr2.
	// Writer does the same on cw1, cw2.
	r1, w1 chan []byte
	r2, w2 chan pipeResult

	rclose chan os.Error // read close; error to return to writers
	wclose chan os.Error // write close; error to return to readers

	done chan int // read or write half is done
}

func (p *pipe) run() {
	var (
		rb    []byte      // pending Read
		wb    []byte      // pending Write
		wn    int         // amount written so far from wb
		rerr  os.Error    // if read end is closed, error to send to writers
		werr  os.Error    // if write end is closed, error to send to readers
		r1    chan []byte // p.cr1 or nil depending on whether Read is ok
		w1    chan []byte // p.cw1 or nil depending on whether Write is ok
		ndone int
	)

	// Read and Write are enabled at the start.
	r1 = p.r1
	w1 = p.w1

	for {
		select {
		case <-p.done:
			if ndone++; ndone == 2 {
				// both reader and writer are gone
				// close out any existing i/o
				if r1 == nil {
					p.r2 <- pipeResult{0, os.EINVAL}
				}
				if w1 == nil {
					p.w2 <- pipeResult{0, os.EINVAL}
				}
				return
			}
			continue
		case rerr = <-p.rclose:
			if w1 == nil {
				// finish pending Write
				p.w2 <- pipeResult{wn, rerr}
				wn = 0
				w1 = p.w1 // allow another Write
			}
			if r1 == nil {
				// Close of read side during Read.
				// finish pending Read with os.EINVAL.
				p.r2 <- pipeResult{0, os.EINVAL}
				r1 = p.r1 // allow another Read
			}
			continue
		case werr = <-p.wclose:
			if r1 == nil {
				// finish pending Read
				p.r2 <- pipeResult{0, werr}
				r1 = p.r1 // allow another Read
			}
			if w1 == nil {
				// Close of write side during Write.
				// finish pending Write with os.EINVAL.
				p.w2 <- pipeResult{wn, os.EINVAL}
				wn = 0
				w1 = p.w1 // allow another Write
			}
			continue
		case rb = <-r1:
			if werr != nil {
				// write end is closed
				p.r2 <- pipeResult{0, werr}
				continue
			}
			if rerr != nil {
				// read end is closed
				p.r2 <- pipeResult{0, os.EINVAL}
				continue
			}
			r1 = nil // disable Read until this one is done
		case wb = <-w1:
			if rerr != nil {
				// read end is closed
				p.w2 <- pipeResult{0, rerr}
				continue
			}
			if werr != nil {
				// write end is closed
				p.w2 <- pipeResult{0, os.EINVAL}
				continue
			}
			w1 = nil // disable Write until this one is done
		}

		if r1 == nil && w1 == nil {
			// Have rb and wb.  Execute.
			n := copy(rb, wb)
			wn += n
			wb = wb[n:]

			// Finish Read.
			p.r2 <- pipeResult{n, nil}
			r1 = p.r1 // allow another Read

			// Maybe finish Write.
			if len(wb) == 0 {
				p.w2 <- pipeResult{wn, nil}
				wn = 0
				w1 = p.w1 // allow another Write
			}
		}
	}
}

// Read/write halves of the pipe.
// They are separate structures for two reasons:
//  1.  If one end becomes garbage without being Closed,
//      its finalizer can Close so that the other end
//      does not hang indefinitely.
//  2.  Clients cannot use interface conversions on the
//      read end to find the Write method, and vice versa.

type pipeHalf struct {
	c1     chan []byte
	c2     chan pipeResult
	cclose chan os.Error
	done   chan int

	lock   sync.Mutex
	closed bool

	io       sync.Mutex
	ioclosed bool
}

func (p *pipeHalf) rw(data []byte) (n int, err os.Error) {
	// Run i/o operation.
	// Check ioclosed flag under lock to make sure we're still allowed to do i/o.
	p.io.Lock()
	if p.ioclosed {
		p.io.Unlock()
		return 0, os.EINVAL
	}
	p.io.Unlock()
	p.c1 <- data
	res := <-p.c2
	return res.n, res.err
}

func (p *pipeHalf) close(err os.Error) os.Error {
	// Close pipe half.
	// Only first call to close does anything.
	p.lock.Lock()
	if p.closed {
		p.lock.Unlock()
		return os.EINVAL
	}
	p.closed = true
	p.lock.Unlock()

	// First, send the close notification.
	p.cclose <- err

	// Runner is now responding to rw operations
	// with os.EINVAL.  Cut off future rw operations
	// by setting ioclosed flag.
	p.io.Lock()
	p.ioclosed = true
	p.io.Unlock()

	// With ioclosed set, there will be no more rw operations
	// working on the channels.
	// Tell the runner we won't be bothering it anymore.
	p.done <- 1

	// Successfully torn down; can disable finalizer.
	runtime.SetFinalizer(p, nil)

	return nil
}

func (p *pipeHalf) finalizer() {
	p.close(os.EINVAL)
}

// A PipeReader is the read half of a pipe.
type PipeReader struct {
	pipeHalf
}

// Read implements the standard Read interface:
// it reads data from the pipe, blocking until a writer
// arrives or the write end is closed.
// If the write end is closed with an error, that error is
// returned as err; otherwise err is nil.
func (r *PipeReader) Read(data []byte) (n int, err os.Error) {
	return r.rw(data)
}

// Close closes the reader; subsequent writes to the
// write half of the pipe will return the error os.EPIPE.
func (r *PipeReader) Close() os.Error {
	return r.CloseWithError(nil)
}

// CloseWithError closes the reader; subsequent writes
// to the write half of the pipe will return the error err.
func (r *PipeReader) CloseWithError(err os.Error) os.Error {
	if err == nil {
		err = os.EPIPE
	}
	return r.close(err)
}

// A PipeWriter is the write half of a pipe.
type PipeWriter struct {
	pipeHalf
}

// Write implements the standard Write interface:
// it writes data to the pipe, blocking until readers
// have consumed all the data or the read end is closed.
// If the read end is closed with an error, that err is
// returned as err; otherwise err is os.EPIPE.
func (w *PipeWriter) Write(data []byte) (n int, err os.Error) {
	return w.rw(data)
}

// Close closes the writer; subsequent reads from the
// read half of the pipe will return no bytes and os.EOF.
func (w *PipeWriter) Close() os.Error {
	return w.CloseWithError(nil)
}

// CloseWithError closes the writer; subsequent reads from the
// read half of the pipe will return no bytes and the error err.
func (w *PipeWriter) CloseWithError(err os.Error) os.Error {
	if err == nil {
		err = os.EOF
	}
	return w.close(err)
}

// Pipe creates a synchronous in-memory pipe.
// It can be used to connect code expecting an io.Reader
// with code expecting an io.Writer.
// Reads on one end are matched with writes on the other,
// copying data directly between the two; there is no internal buffering.
func Pipe() (*PipeReader, *PipeWriter) {
	p := &pipe{
		r1:     make(chan []byte),
		r2:     make(chan pipeResult),
		w1:     make(chan []byte),
		w2:     make(chan pipeResult),
		rclose: make(chan os.Error),
		wclose: make(chan os.Error),
		done:   make(chan int),
	}
	go p.run()

	// NOTE: Cannot use composite literal here:
	//	pipeHalf{c1: p.cr1, c2: p.cr2, cclose: p.crclose, cdone: p.cdone}
	// because this implicitly copies the pipeHalf, which copies the inner mutex.

	r := new(PipeReader)
	r.c1 = p.r1
	r.c2 = p.r2
	r.cclose = p.rclose
	r.done = p.done
	// TODO(rsc): Should be able to write
	//	runtime.SetFinalizer(r, (*PipeReader).finalizer)
	// but 6g doesn't see the finalizer method.
	runtime.SetFinalizer(&r.pipeHalf, (*pipeHalf).finalizer)

	w := new(PipeWriter)
	w.c1 = p.w1
	w.c2 = p.w2
	w.cclose = p.wclose
	w.done = p.done
	// TODO(rsc): Should be able to write
	//	runtime.SetFinalizer(w, (*PipeWriter).finalizer)
	// but 6g doesn't see the finalizer method.
	runtime.SetFinalizer(&w.pipeHalf, (*pipeHalf).finalizer)

	return r, w
}
<commit_msg>io: use SetFinalizer more elegantly in Pipe<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Pipe adapter to connect code expecting an io.Reader
// with code expecting an io.Writer.

package io

import (
	"os"
	"runtime"
	"sync"
)

type pipeResult struct {
	n   int
	err os.Error
}

// Shared pipe structure.
type pipe struct {
	// Reader sends on cr1, receives on cr2.
	// Writer does the same on cw1, cw2.
	r1, w1 chan []byte
	r2, w2 chan pipeResult

	rclose chan os.Error // read close; error to return to writers
	wclose chan os.Error // write close; error to return to readers

	done chan int // read or write half is done
}

func (p *pipe) run() {
	var (
		rb    []byte      // pending Read
		wb    []byte      // pending Write
		wn    int         // amount written so far from wb
		rerr  os.Error    // if read end is closed, error to send to writers
		werr  os.Error    // if write end is closed, error to send to readers
		r1    chan []byte // p.cr1 or nil depending on whether Read is ok
		w1    chan []byte // p.cw1 or nil depending on whether Write is ok
		ndone int
	)

	// Read and Write are enabled at the start.
	r1 = p.r1
	w1 = p.w1

	for {
		select {
		case <-p.done:
			if ndone++; ndone == 2 {
				// both reader and writer are gone
				// close out any existing i/o
				if r1 == nil {
					p.r2 <- pipeResult{0, os.EINVAL}
				}
				if w1 == nil {
					p.w2 <- pipeResult{0, os.EINVAL}
				}
				return
			}
			continue
		case rerr = <-p.rclose:
			if w1 == nil {
				// finish pending Write
				p.w2 <- pipeResult{wn, rerr}
				wn = 0
				w1 = p.w1 // allow another Write
			}
			if r1 == nil {
				// Close of read side during Read.
				// finish pending Read with os.EINVAL.
				p.r2 <- pipeResult{0, os.EINVAL}
				r1 = p.r1 // allow another Read
			}
			continue
		case werr = <-p.wclose:
			if r1 == nil {
				// finish pending Read
				p.r2 <- pipeResult{0, werr}
				r1 = p.r1 // allow another Read
			}
			if w1 == nil {
				// Close of write side during Write.
				// finish pending Write with os.EINVAL.
				p.w2 <- pipeResult{wn, os.EINVAL}
				wn = 0
				w1 = p.w1 // allow another Write
			}
			continue
		case rb = <-r1:
			if werr != nil {
				// write end is closed
				p.r2 <- pipeResult{0, werr}
				continue
			}
			if rerr != nil {
				// read end is closed
				p.r2 <- pipeResult{0, os.EINVAL}
				continue
			}
			r1 = nil // disable Read until this one is done
		case wb = <-w1:
			if rerr != nil {
				// read end is closed
				p.w2 <- pipeResult{0, rerr}
				continue
			}
			if werr != nil {
				// write end is closed
				p.w2 <- pipeResult{0, os.EINVAL}
				continue
			}
			w1 = nil // disable Write until this one is done
		}

		if r1 == nil && w1 == nil {
			// Have rb and wb.  Execute.
			n := copy(rb, wb)
			wn += n
			wb = wb[n:]

			// Finish Read.
			p.r2 <- pipeResult{n, nil}
			r1 = p.r1 // allow another Read

			// Maybe finish Write.
			if len(wb) == 0 {
				p.w2 <- pipeResult{wn, nil}
				wn = 0
				w1 = p.w1 // allow another Write
			}
		}
	}
}

// Read/write halves of the pipe.
// They are separate structures for two reasons:
//  1.  If one end becomes garbage without being Closed,
//      its finalizer can Close so that the other end
//      does not hang indefinitely.
//  2.  Clients cannot use interface conversions on the
//      read end to find the Write method, and vice versa.

type pipeHalf struct {
	c1     chan []byte
	c2     chan pipeResult
	cclose chan os.Error
	done   chan int

	lock   sync.Mutex
	closed bool

	io       sync.Mutex
	ioclosed bool
}

func (p *pipeHalf) rw(data []byte) (n int, err os.Error) {
	// Run i/o operation.
	// Check ioclosed flag under lock to make sure we're still allowed to do i/o.
	p.io.Lock()
	if p.ioclosed {
		p.io.Unlock()
		return 0, os.EINVAL
	}
	p.io.Unlock()
	p.c1 <- data
	res := <-p.c2
	return res.n, res.err
}

func (p *pipeHalf) close(err os.Error) os.Error {
	// Close pipe half.
	// Only first call to close does anything.
	p.lock.Lock()
	if p.closed {
		p.lock.Unlock()
		return os.EINVAL
	}
	p.closed = true
	p.lock.Unlock()

	// First, send the close notification.
	p.cclose <- err

	// Runner is now responding to rw operations
	// with os.EINVAL.  Cut off future rw operations
	// by setting ioclosed flag.
	p.io.Lock()
	p.ioclosed = true
	p.io.Unlock()

	// With ioclosed set, there will be no more rw operations
	// working on the channels.
	// Tell the runner we won't be bothering it anymore.
	p.done <- 1

	// Successfully torn down; can disable finalizer.
	runtime.SetFinalizer(p, nil)

	return nil
}

func (p *pipeHalf) finalizer() {
	p.close(os.EINVAL)
}

// A PipeReader is the read half of a pipe.
type PipeReader struct {
	pipeHalf
}

// Read implements the standard Read interface:
// it reads data from the pipe, blocking until a writer
// arrives or the write end is closed.
// If the write end is closed with an error, that error is
// returned as err; otherwise err is nil.
func (r *PipeReader) Read(data []byte) (n int, err os.Error) {
	return r.rw(data)
}

// Close closes the reader; subsequent writes to the
// write half of the pipe will return the error os.EPIPE.
func (r *PipeReader) Close() os.Error {
	return r.CloseWithError(nil)
}

// CloseWithError closes the reader; subsequent writes
// to the write half of the pipe will return the error err.
func (r *PipeReader) CloseWithError(err os.Error) os.Error {
	if err == nil {
		err = os.EPIPE
	}
	return r.close(err)
}

// A PipeWriter is the write half of a pipe.
type PipeWriter struct {
	pipeHalf
}

// Write implements the standard Write interface:
// it writes data to the pipe, blocking until readers
// have consumed all the data or the read end is closed.
// If the read end is closed with an error, that err is
// returned as err; otherwise err is os.EPIPE.
func (w *PipeWriter) Write(data []byte) (n int, err os.Error) {
	return w.rw(data)
}

// Close closes the writer; subsequent reads from the
// read half of the pipe will return no bytes and os.EOF.
func (w *PipeWriter) Close() os.Error {
	return w.CloseWithError(nil)
}

// CloseWithError closes the writer; subsequent reads from the
// read half of the pipe will return no bytes and the error err.
func (w *PipeWriter) CloseWithError(err os.Error) os.Error {
	if err == nil {
		err = os.EOF
	}
	return w.close(err)
}

// Pipe creates a synchronous in-memory pipe.
// It can be used to connect code expecting an io.Reader
// with code expecting an io.Writer.
// Reads on one end are matched with writes on the other,
// copying data directly between the two; there is no internal buffering.
func Pipe() (*PipeReader, *PipeWriter) {
	p := &pipe{
		r1:     make(chan []byte),
		r2:     make(chan pipeResult),
		w1:     make(chan []byte),
		w2:     make(chan pipeResult),
		rclose: make(chan os.Error),
		wclose: make(chan os.Error),
		done:   make(chan int),
	}
	go p.run()

	// NOTE: Cannot use composite literal here:
	//	pipeHalf{c1: p.cr1, c2: p.cr2, cclose: p.crclose, cdone: p.cdone}
	// because this implicitly copies the pipeHalf, which copies the inner mutex.

	r := new(PipeReader)
	r.c1 = p.r1
	r.c2 = p.r2
	r.cclose = p.rclose
	r.done = p.done
	runtime.SetFinalizer(r, (*PipeReader).finalizer)

	w := new(PipeWriter)
	w.c1 = p.w1
	w.c2 = p.w2
	w.cclose = p.wclose
	w.done = p.done
	runtime.SetFinalizer(w, (*PipeWriter).finalizer)

	return r, w
}
<|endoftext|>


<commit_before>package qshell

import (
	"qiniu/api.v6/conf"
)

type ZoneConfig struct {
	UpHost    string
	RsHost    string
	RsfHost   string
	IovipHost string
	ApiHost   string
}

var (
	DEFAULT_API_HOST = ZoneNBConfig.ApiHost
)

const (
	ZoneNB  = "nb"
	ZoneBC  = "bc"
	ZoneAWS = "aws"
)

//zone all defaults to the service source site

var ZoneNBConfig = ZoneConfig{
	UpHost:    "http://up.qiniu.com",
	RsHost:    "http://rs.qiniu.com",
	RsfHost:   "http://rsf.qbox.me",
	IovipHost: "http://iovip.qbox.me",
	ApiHost:   "http://api.qiniu.com",
}

var ZoneBCConfig = ZoneConfig{
	UpHost:    "http://up-z1.qiniu.com",
	RsHost:    "http://rs.qiniu.com",
	RsfHost:   "http://rsf-z1.qbox.me",
	IovipHost: "http://iovip-z1.qbox.me",
	ApiHost:   "http://api-z1.qiniu.com",
}

var ZoneAWSConfig = ZoneConfig{
	UpHost:    "http://up.gdipper.com",
	RsHost:    "http://rs.gdipper.com",
	RsfHost:   "http://rsf.gdipper.com",
	IovipHost: "http://iovip.gdipper.me",
	ApiHost:   "http://api.gdipper.com",
}

func SetZone(zoneConfig ZoneConfig) {
	conf.UP_HOST = zoneConfig.UpHost
	conf.RS_HOST = zoneConfig.RsHost
	conf.RSF_HOST = zoneConfig.RsfHost
	conf.IO_HOST = zoneConfig.IovipHost
	DEFAULT_API_HOST = zoneConfig.ApiHost
}

func IsValidZone(zone string) (valid bool) {
	switch zone {
	case ZoneNB, ZoneBC, ZoneAWS:
		valid = true
	default:
		valid = false
	}
	return
}
<commit_msg>fix bug of aws io domain<commit_after>package qshell

import (
	"qiniu/api.v6/conf"
)

type ZoneConfig struct {
	UpHost    string
	RsHost    string
	RsfHost   string
	IovipHost string
	ApiHost   string
}

var (
	DEFAULT_API_HOST = ZoneNBConfig.ApiHost
)

const (
	ZoneNB  = "nb"
	ZoneBC  = "bc"
	ZoneAWS = "aws"
)

//zone all defaults to the service source site

var ZoneNBConfig = ZoneConfig{
	UpHost:    "http://up.qiniu.com",
	RsHost:    "http://rs.qiniu.com",
	RsfHost:   "http://rsf.qbox.me",
	IovipHost: "http://iovip.qbox.me",
	ApiHost:   "http://api.qiniu.com",
}

var ZoneBCConfig = ZoneConfig{
	UpHost:    "http://up-z1.qiniu.com",
	RsHost:    "http://rs.qiniu.com",
	RsfHost:   "http://rsf-z1.qbox.me",
	IovipHost: "http://iovip-z1.qbox.me",
	ApiHost:   "http://api-z1.qiniu.com",
}

var ZoneAWSConfig = ZoneConfig{
	UpHost:    "http://up.gdipper.com",
	RsHost:    "http://rs.gdipper.com",
	RsfHost:   "http://rsf.gdipper.com",
	IovipHost: "http://iovip.gdipper.com",
	ApiHost:   "http://api.gdipper.com",
}

func SetZone(zoneConfig ZoneConfig) {
	conf.UP_HOST = zoneConfig.UpHost
	conf.RS_HOST = zoneConfig.RsHost
	conf.RSF_HOST = zoneConfig.RsfHost
	conf.IO_HOST = zoneConfig.IovipHost
	DEFAULT_API_HOST = zoneConfig.ApiHost
}

func IsValidZone(zone string) (valid bool) {
	switch zone {
	case ZoneNB, ZoneBC, ZoneAWS:
		valid = true
	default:
		valid = false
	}
	return
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package newton

import (
	"github.com/szabba/md/src/vect"
)

type Body struct {
	Xs, Vs []vect.Vector
	mass   float64
	currAt int
}

// Constructs a body of specified mass suitable for working with the integrator
func NewBody(algo Integrator, mass float64) *Body {

	b := new(Body)

	b.Xs = make([]vect.Vector, algo.StateLen())
	b.Vs = make([]vect.Vector, algo.StateLen())

	b.mass = mass
	b.currAt = algo.CurrentAt()

	return b
}

// Give a body's mass
func (b *Body) Mass() float64 {

	return b.mass
}

// Put new values of x and v a the beginning of the remembered values
//
// The oldest values get discarded
func (b *Body) Shift(x, v vect.Vector) {

	Shift(b.Xs, x)
	Shift(b.Vs, v)
}

// Shifts all the values in xs by one and puts x at the beginning.
func Shift(xs []vect.Vector, x vect.Vector) {

	for i := len(xs) - 1; i > 0; i-- {

		xs[i] = xs[i-1]
	}

	xs[0] = x
}
<commit_msg>Add newton.Body{,X,V}Now<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package newton

import (
	"github.com/szabba/md/src/vect"
)

type Body struct {
	Xs, Vs []vect.Vector
	mass   float64
	currAt int
}

// Constructs a body of specified mass suitable for working with the integrator
func NewBody(algo Integrator, mass float64) *Body {

	b := new(Body)

	b.Xs = make([]vect.Vector, algo.StateLen())
	b.Vs = make([]vect.Vector, algo.StateLen())

	b.mass = mass
	b.currAt = algo.CurrentAt()

	return b
}

// Give a body's mass
func (b *Body) Mass() float64 {

	return b.mass
}

// Put new values of x and v a the beginning of the remembered values
//
// The oldest values get discarded
func (b *Body) Shift(x, v vect.Vector) {

	Shift(b.Xs, x)
	Shift(b.Vs, v)
}

// Current positon and velocity
func (b *Body) Now() (x, v vect.Vector) {

	return b.XNow(), b.VNow()
}

// Current position
func (b *Body) XNow() vect.Vector {

	return b.Xs[b.currAt]
}

// Current velocity
func (b *Body) VNow() vect.Vector {

	return b.Vs[b.currAt]
}

// Shifts all the values in xs by one and puts x at the beginning.
func Shift(xs []vect.Vector, x vect.Vector) {

	for i := len(xs) - 1; i > 0; i-- {

		xs[i] = xs[i-1]
	}

	xs[0] = x
}
<|endoftext|>


<commit_before>package self_test

import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"sync"

	quic "github.com/lucas-clemente/quic-go"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type clientSessionCache struct {
	mutex sync.Mutex
	cache map[string]*tls.ClientSessionState

	gets chan<- string
	puts chan<- string
}

func newClientSessionCache(gets, puts chan<- string) *clientSessionCache {
	return &clientSessionCache{
		cache: make(map[string]*tls.ClientSessionState),
		gets:  gets,
		puts:  puts,
	}
}

var _ tls.ClientSessionCache = &clientSessionCache{}

func (c *clientSessionCache) Get(sessionKey string) (*tls.ClientSessionState, bool) {
	c.gets <- sessionKey
	c.mutex.Lock()
	session, ok := c.cache[sessionKey]
	c.mutex.Unlock()
	return session, ok
}

func (c *clientSessionCache) Put(sessionKey string, cs *tls.ClientSessionState) {
	c.puts <- sessionKey
	c.mutex.Lock()
	c.cache[sessionKey] = cs
	c.mutex.Unlock()
}

var _ = Describe("TLS session resumption", func() {
	It("uses session resumption", func() {
		server, err := quic.ListenAddr("localhost:0", getTLSConfig(), nil)
		Expect(err).ToNot(HaveOccurred())
		defer server.Close()

		done := make(chan struct{})
		go func() {
			defer close(done)
			defer GinkgoRecover()
			sess, err := server.Accept(context.Background())
			Expect(err).ToNot(HaveOccurred())
			Expect(sess.ConnectionState().DidResume).To(BeFalse())

			sess, err = server.Accept(context.Background())
			Expect(err).ToNot(HaveOccurred())
			Expect(sess.ConnectionState().DidResume).To(BeTrue())
		}()

		gets := make(chan string, 100)
		puts := make(chan string, 100)
		cache := newClientSessionCache(gets, puts)
		tlsConf := getTLSClientConfig()
		tlsConf.ClientSessionCache = cache
		sess, err := quic.DialAddr(
			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
			tlsConf,
			nil,
		)
		Expect(err).ToNot(HaveOccurred())
		var sessionKey string
		Eventually(puts).Should(Receive(&sessionKey))
		Expect(sess.ConnectionState().DidResume).To(BeFalse())

		sess, err = quic.DialAddr(
			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
			tlsConf,
			nil,
		)
		Expect(err).ToNot(HaveOccurred())
		Expect(gets).To(Receive(Equal(sessionKey)))
		Expect(sess.ConnectionState().DidResume).To(BeTrue())

		Eventually(done).Should(BeClosed())
	})
})
<commit_msg>fix flaky session resumption integration test<commit_after>package self_test

import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"sync"

	quic "github.com/lucas-clemente/quic-go"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type clientSessionCache struct {
	mutex sync.Mutex
	cache map[string]*tls.ClientSessionState

	gets chan<- string
	puts chan<- string
}

func newClientSessionCache(gets, puts chan<- string) *clientSessionCache {
	return &clientSessionCache{
		cache: make(map[string]*tls.ClientSessionState),
		gets:  gets,
		puts:  puts,
	}
}

var _ tls.ClientSessionCache = &clientSessionCache{}

func (c *clientSessionCache) Get(sessionKey string) (*tls.ClientSessionState, bool) {
	c.gets <- sessionKey
	c.mutex.Lock()
	session, ok := c.cache[sessionKey]
	c.mutex.Unlock()
	return session, ok
}

func (c *clientSessionCache) Put(sessionKey string, cs *tls.ClientSessionState) {
	c.puts <- sessionKey
	c.mutex.Lock()
	c.cache[sessionKey] = cs
	c.mutex.Unlock()
}

var _ = Describe("TLS session resumption", func() {
	It("uses session resumption", func() {
		server, err := quic.ListenAddr("localhost:0", getTLSConfig(), nil)
		Expect(err).ToNot(HaveOccurred())
		defer server.Close()

		gets := make(chan string, 100)
		puts := make(chan string, 100)
		cache := newClientSessionCache(gets, puts)
		tlsConf := getTLSClientConfig()
		tlsConf.ClientSessionCache = cache
		sess, err := quic.DialAddr(
			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
			tlsConf,
			nil,
		)
		Expect(err).ToNot(HaveOccurred())
		var sessionKey string
		Eventually(puts).Should(Receive(&sessionKey))
		Expect(sess.ConnectionState().DidResume).To(BeFalse())

		serverSess, err := server.Accept(context.Background())
		Expect(err).ToNot(HaveOccurred())
		Expect(serverSess.ConnectionState().DidResume).To(BeFalse())

		sess, err = quic.DialAddr(
			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
			tlsConf,
			nil,
		)
		Expect(err).ToNot(HaveOccurred())
		Expect(gets).To(Receive(Equal(sessionKey)))
		Expect(sess.ConnectionState().DidResume).To(BeTrue())

		serverSess, err = server.Accept(context.Background())
		Expect(err).ToNot(HaveOccurred())
		Expect(serverSess.ConnectionState().DidResume).To(BeTrue())
	})
})
<|endoftext|>