<commit_before>// +build windows

package ansicolor_test

import (
	"bytes"
	"fmt"
	"syscall"
	"testing"

	"github.com/shiena/ansicolor"
	. "github.com/shiena/ansicolor"
)

func TestWritePlanText(t *testing.T) {
	inner := bytes.NewBufferString("")
	w := ansicolor.NewAnsiColorWriter(inner)
	expected := "plain text"
	fmt.Fprintf(w, expected)
	actual := inner.String()
	if actual != expected {
		t.Errorf("Get %v, want %v", actual, expected)
	}
}

type screenNotFoundError struct {
	error
}

func writeAnsiColor(expectedText, colorCode string) (actualText string, actualAttributes uint16, err error) {
	inner := bytes.NewBufferString("")
	w := ansicolor.NewAnsiColorWriter(inner)
	fmt.Fprintf(w, "\x1b[%sm%s", colorCode, expectedText)

	actualText = inner.String()
	screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo != nil {
		actualAttributes = screenInfo.WAttributes
	} else {
		err = &screenNotFoundError{}
	}
	return
}

type testParam struct {
	text       string
	attributes uint16
	ansiColor  string
}

func TestWriteAnsiColorText(t *testing.T) {
	screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo == nil {
		t.Fatal("Could not get ConsoleScreenBufferInfo")
	}
	defer ChangeColor(screenInfo.WAttributes)

	fgParam := []testParam{
		{"foreground black", uint16(0x0000), "30"},
		{"foreground red", uint16(0x0004), "31"},
		{"foreground green", uint16(0x0002), "32"},
		{"foreground yellow", uint16(0x0006), "33"},
		{"foreground blue", uint16(0x0001), "34"},
		{"foreground magenta", uint16(0x0005), "35"},
		{"foreground cyan", uint16(0x0003), "36"},
		{"foreground white", uint16(0x0007), "37"},
		{"foreground default", uint16(0x0007), "39"},
	}

	bgParam := []testParam{
		{"background black", uint16(0x0007 | 0x0000), "40"},
		{"background red", uint16(0x0007 | 0x0040), "41"},
		{"background green", uint16(0x0007 | 0x0020), "42"},
		{"background yellow", uint16(0x0007 | 0x0060), "43"},
		{"background blue", uint16(0x0007 | 0x0010), "44"},
		{"background magenta", uint16(0x0007 | 0x0050), "45"},
		{"background cyan", uint16(0x0007 | 0x0030), "46"},
		{"background white", uint16(0x0007 | 0x0070), "47"},
		{"background default", uint16(0x0007 | 0x0000), "49"},
	}

	resetParam := []testParam{
		{"all reset", uint16(screenInfo.WAttributes), "0"},
	}

	boldParam := []testParam{
		{"bold on", uint16(0x0007 | 0x0008), "1"},
		{"bold off", uint16(0x0007), "21"},
	}

	underscoreParam := []testParam{
		{"underscore on", uint16(0x0007 | 0x8000), "4"},
		{"underscore off", uint16(0x0007), "24"},
	}

	blinkParam := []testParam{
		{"blink on", uint16(0x0007 | 0x0080), "5"},
		{"blink off", uint16(0x0007), "25"},
	}

	mixedParam := []testParam{
		{"both black and bold", uint16(0x0000 | 0x0000 | 0x0008), "30;40;1"},
		{"both red and bold", uint16(0x0004 | 0x0040 | 0x0008), "31;41;1"},
		{"both green and bold", uint16(0x0002 | 0x0020 | 0x0008), "32;42;1"},
		{"both yellow and bold", uint16(0x0006 | 0x0060 | 0x0008), "33;43;1"},
		{"both blue and bold", uint16(0x0001 | 0x0010 | 0x0008), "34;44;1"},
		{"both magenta and bold", uint16(0x0005 | 0x0050 | 0x0008), "35;45;1"},
		{"both cyan and bold", uint16(0x0003 | 0x0030 | 0x0008), "36;46;1"},
		{"both white and bold", uint16(0x0007 | 0x0070 | 0x0008), "37;47;1"},
		{"both default and bold", uint16(0x0007 | 0x0000 | 0x0008), "39;49;1"},
	}

	assertTextAttribute := func(expectedText string, expectedAttributes uint16, ansiColor string) {
		actualText, actualAttributes, err := writeAnsiColor(expectedText, ansiColor)
		if actualText != expectedText {
			t.Errorf("Get %s, want %s", actualText, expectedText)
		}
		if err != nil {
			t.Fatal("Could not get ConsoleScreenBufferInfo")
		}
		if actualAttributes != expectedAttributes {
			t.Errorf("Text: %s, Get %d, want %d", expectedText, actualAttributes, expectedAttributes)
		}
	}

	for _, v := range fgParam {
		ResetColor()
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range bgParam {
		ChangeColor(uint16(0x0070 | 0x0007))
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range resetParam {
		ChangeColor(uint16(0x0000 | 0x0070 | 0x0008))
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range boldParam {
		ResetColor()
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range underscoreParam {
		ResetColor()
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range blinkParam {
		ResetColor()
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range mixedParam {
		ResetColor()
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}
}
<commit_msg>Fixed test pattern for blink and underline<commit_after>// +build windows

package ansicolor_test

import (
	"bytes"
	"fmt"
	"syscall"
	"testing"

	"github.com/shiena/ansicolor"
	. "github.com/shiena/ansicolor"
)

func TestWritePlanText(t *testing.T) {
	inner := bytes.NewBufferString("")
	w := ansicolor.NewAnsiColorWriter(inner)
	expected := "plain text"
	fmt.Fprintf(w, expected)
	actual := inner.String()
	if actual != expected {
		t.Errorf("Get %v, want %v", actual, expected)
	}
}

type screenNotFoundError struct {
	error
}

func writeAnsiColor(expectedText, colorCode string) (actualText string, actualAttributes uint16, err error) {
	inner := bytes.NewBufferString("")
	w := ansicolor.NewAnsiColorWriter(inner)
	fmt.Fprintf(w, "\x1b[%sm%s", colorCode, expectedText)

	actualText = inner.String()
	screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo != nil {
		actualAttributes = screenInfo.WAttributes
	} else {
		err = &screenNotFoundError{}
	}
	return
}

type testParam struct {
	text       string
	attributes uint16
	ansiColor  string
}

func TestWriteAnsiColorText(t *testing.T) {
	screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo == nil {
		t.Fatal("Could not get ConsoleScreenBufferInfo")
	}
	defer ChangeColor(screenInfo.WAttributes)

	fgParam := []testParam{
		{"foreground black", uint16(0x0000), "30"},
		{"foreground red", uint16(0x0004), "31"},
		{"foreground green", uint16(0x0002), "32"},
		{"foreground yellow", uint16(0x0006), "33"},
		{"foreground blue", uint16(0x0001), "34"},
		{"foreground magenta", uint16(0x0005), "35"},
		{"foreground cyan", uint16(0x0003), "36"},
		{"foreground white", uint16(0x0007), "37"},
		{"foreground default", uint16(0x0007), "39"},
	}

	bgParam := []testParam{
		{"background black", uint16(0x0007 | 0x0000), "40"},
		{"background red", uint16(0x0007 | 0x0040), "41"},
		{"background green", uint16(0x0007 | 0x0020), "42"},
		{"background yellow", uint16(0x0007 | 0x0060), "43"},
		{"background blue", uint16(0x0007 | 0x0010), "44"},
		{"background magenta", uint16(0x0007 | 0x0050), "45"},
		{"background cyan", uint16(0x0007 | 0x0030), "46"},
		{"background white", uint16(0x0007 | 0x0070), "47"},
		{"background default", uint16(0x0007 | 0x0000), "49"},
	}

	resetParam := []testParam{
		{"all reset", uint16(screenInfo.WAttributes), "0"},
	}

	boldParam := []testParam{
		{"bold on", uint16(0x0007 | 0x0008), "1"},
		{"bold off", uint16(0x0007), "21"},
	}

	underscoreParam := []testParam{
		{"underscore on", uint16(0x0007 | 0x8000), "4"},
		{"underscore off", uint16(0x0007), "24"},
	}

	blinkParam := []testParam{
		{"blink on", uint16(0x0007 | 0x0080), "5"},
		{"blink off", uint16(0x0007), "25"},
	}

	mixedParam := []testParam{
		{"both black,   bold, underline, blink", uint16(0x0000 | 0x0000 | 0x0008 | 0x8000 | 0x0080), "30;40;1;4;5"},
		{"both red,     bold, underline, blink", uint16(0x0004 | 0x0040 | 0x0008 | 0x8000 | 0x0080), "31;41;1;4;5"},
		{"both green,   bold, underline, blink", uint16(0x0002 | 0x0020 | 0x0008 | 0x8000 | 0x0080), "32;42;1;4;5"},
		{"both yellow,  bold, underline, blink", uint16(0x0006 | 0x0060 | 0x0008 | 0x8000 | 0x0080), "33;43;1;4;5"},
		{"both blue,    bold, underline, blink", uint16(0x0001 | 0x0010 | 0x0008 | 0x8000 | 0x0080), "34;44;1;4;5"},
		{"both magenta, bold, underline, blink", uint16(0x0005 | 0x0050 | 0x0008 | 0x8000 | 0x0080), "35;45;1;4;5"},
		{"both cyan,    bold, underline, blink", uint16(0x0003 | 0x0030 | 0x0008 | 0x8000 | 0x0080), "36;46;1;4;5"},
		{"both white,   bold, underline, blink", uint16(0x0007 | 0x0070 | 0x0008 | 0x8000 | 0x0080), "37;47;1;4;5"},
		{"both default, bold, underline, blink", uint16(0x0007 | 0x0000 | 0x0008 | 0x8000 | 0x0080), "39;49;1;4;5"},
	}

	assertTextAttribute := func(expectedText string, expectedAttributes uint16, ansiColor string) {
		actualText, actualAttributes, err := writeAnsiColor(expectedText, ansiColor)
		if actualText != expectedText {
			t.Errorf("Get %s, want %s", actualText, expectedText)
		}
		if err != nil {
			t.Fatal("Could not get ConsoleScreenBufferInfo")
		}
		if actualAttributes != expectedAttributes {
			t.Errorf("Text: %s, Get %d, want %d", expectedText, actualAttributes, expectedAttributes)
		}
	}

	for _, v := range fgParam {
		ResetColor()
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range bgParam {
		ChangeColor(uint16(0x0070 | 0x0007))
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range resetParam {
		ChangeColor(uint16(0x0000 | 0x0070 | 0x0008))
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	ResetColor()
	for _, v := range boldParam {
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	ResetColor()
	for _, v := range underscoreParam {
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	ResetColor()
	for _, v := range blinkParam {
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}

	for _, v := range mixedParam {
		ResetColor()
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
	}
}
<|endoftext|>


<commit_before>package gobcy

import "time"

//TokenUsage represents information about
//the limits and usage against your token.
type TokenUsage struct {
	Limits Usage `json:"limits"`
	Hits   Usage `json:"hits"`
}

type Usage struct {
	PerSec       int `json:"api/second"`
	PerHour      int `json:"api/hour"`
	PerDay       int `json:"api/day"`
	HooksPerHour int `json:"hooks/hour"`
	ConfPerDay   int `json:"confidence/day"`
	Hooks        int `json:"hooks"`
	PayFwds      int `json:"payments"`
}

//Blockchain represents information about
//the state of a blockchain.
type Blockchain struct {
	Name             string    `json:"name"`
	Height           int       `json:"height"`
	Hash             string    `json:"hash"`
	Time             time.Time `json:"time"`
	PrevHash         string    `json:"previous_hash"`
	PeerCount        int       `json:"peer_count"`
	HighFee          int       `json:"high_fee_per_kb"`
	MediumFee        int       `json:"medium_fee_per_kb"`
	LowFee           int       `json:"low_fee_per_kb"`
	UnconfirmedCount int       `json:"unconfirmed_count"`
	LastForkHeight   int       `json:"last_fork_height"`
	LastForkHash     string    `json:"last_fork_hash"`
}

//Block represents information about the state
//of a given block in a blockchain.
type Block struct {
	Hash         string    `json:"hash"`
	Height       int       `json:"height"`
	Depth        int       `json:"depth"`
	Chain        string    `json:"chain"`
	Total        int       `json:"total"`
	Fees         int       `json:"fees"`
	Ver          int       `json:"ver"`
	Time         time.Time `json:"time"`
	ReceivedTime time.Time `json:"received_time"`
	RelayedBy    string    `json:"relayed_by,omitempty"`
	Bits         int       `json:"bits"`
	Nonce        int       `json:"nonce"`
	NumTX        int       `json:"n_tx"`
	PrevBlock    string    `json:"prev_block"`
	MerkleRoot   string    `json:"mrkl_root"`
	TXids        []string  `json:"txids"`
	NextTXs      string    `json:"next_txids"`
}

//TX represents information about the state
//of a given transaction in a blockchain.
type TX struct {
	BlockHash     string     `json:"block_hash,omitempty"`
	BlockHeight   int        `json:"block_height,omitempty"`
	Hash          string     `json:"hash,omitempty"`
	Addresses     []string   `json:"addresses,omitempty"`
	Total         int        `json:"total,omitempty"`
	Fees          int        `json:"fees,omitempty"`
	Size          int        `json:"size"`
	Preference    string     `json:"preference,omitempty"`
	RelayedBy     string     `json:"relayed_by,omitempty"`
	Received      time.Time  `json:"received,omitempty"`
	Confirmed     time.Time  `json:"confirmed,omitempty"`
	Confirmations int        `json:"confirmations,omitempty"`
	Confidence    float64    `json:"confidence,omitempty"`
	Ver           int        `json:"ver,omitempty"`
	LockTime      int        `json:"lock_time,omitempty"`
	DoubleSpend   bool       `json:"double_spend,omitempty"`
	DoubleOf      string     `json:"double_of,omitempty"`
	ReceiveCount  int        `json:"receive_count,omitempty"`
	VinSize       int        `json:"vin_sz,omitempty"`
	VoutSize      int        `json:"vout_sz,omitempty"`
	Hex           string     `json:"hex,omitempty"`
	DataProtocol  string     `json:"data_protocol,omitempty"`
	ChangeAddress string     `json:"change_address,omitempty"`
	NextInputs    string     `json:"next_inputs,omitempty"`
	NextOutputs   string     `json:"next_outputs,omitempty"`
	Inputs        []TXInput  `json:"inputs"`
	Outputs       []TXOutput `json:"outputs"`
}

//TXInput represents the state of a transaction input
type TXInput struct {
	PrevHash    string   `json:"prev_hash,omitempty"`
	OutputIndex int      `json:"output_index,omitempty"`
	OutputValue int      `json:"output_value,omitempty"`
	Addresses   []string `json:"addresses"`
	Sequence    int      `json:"sequence,omitempty"`
	ScriptType  string   `json:"script_type,omitempty"`
	Script      string   `json:"script,omitempty"`
	Age         int      `json:"age,omitempty"`
	WalletName  string   `json:"wallet_name,omitempty"`
}

//TXOutput represents the state of a transaction output
type TXOutput struct {
	SpentBy    string   `json:"spent_by,omitempty"`
	Value      int      `json:"value"`
	Addresses  []string `json:"addresses"`
	ScriptType string   `json:"script_type,omitempty"`
	Script     string   `json:"script,omitempty"`
	DataHex    string   `json:"data_hex,omitempty"`
	DataString string   `json:"data_string,omitempty"`
}

//TXConf represents information about the
//confidence of an unconfirmed transaction.
type TXConf struct {
	Age          int     `json:"age_millis"`
	ReceiveCount int     `json:"receive_count,omitempty"`
	Confidence   float64 `json:"confidence"`
	TXHash       string  `json:"txhash"`
}

//TXRef represents summarized data about a
//transaction input or output.
type TXRef struct {
	Address       string    `json:"address,omitempty"`
	BlockHeight   int       `json:"block_height"`
	TXHash        string    `json:"tx_hash"`
	TXInputN      int       `json:"tx_input_n"`
	TXOutputN     int       `json:"tx_output_n"`
	Value         int       `json:"value"`
	Pref          string    `json:"preference"`
	Spent         bool      `json:"spent"`
	DoubleSpend   bool      `json:"double_spend"`
	DoubleOf      string    `json:"double_of,omitempty"`
	Confirmations int       `json:"confirmations"`
	Script        string    `json:"script,omitempty"`
	RefBalance    int       `json:"ref_balance,omitempty"`
	Confidence    float64   `json:"confidence,omitempty"`
	Confirmed     time.Time `json:"confirmed,omitempty"`
	SpentBy       string    `json:"spent_by,omitempty"`
	Received      time.Time `json:"received,omitempty"`
	ReceivedCount int       `json:"received_count,omitempty"`
}

//TXSkel represents the return call to BlockCypher's
//txs/new endpoint, and includes error information,
//hex transactions that need to be signed, and space
//for the signed transactions and associated public keys.
type TXSkel struct {
	Trans      TX       `json:"tx"`
	ToSign     []string `json:"tosign"`
	Signatures []string `json:"signatures"`
	PubKeys    []string `json:"pubkeys,omitempty"`
	ToSignTX   []string `json:"tosign_tx,omitempty"`
	Errors     []struct {
		Error string `json:"error,omitempty"`
	} `json:"errors,omitempty"`
}

//NullData represents the call and return to BlockCypher's
//Data API, allowing you to embed up to 80 bytes into
//a blockchain via an OP_RETURN.
type NullData struct {
	Data     string `json:"data"`
	Encoding string `json:"encoding,omitempty"`
	Hash     string `json:"hash,omitempty"`
}

//MicroTX represents a microtransaction. For small-value
//transactions, BlockCypher will sign the transaction
//on your behalf, with your private key (if provided).
//Setting a separate change address is recommended.
//Where your application model allows it, consider
//only using public keys with microtransactions,
//and sign the microtransaction with your private key
//(without sending to BlockCypher's server).
type MicroTX struct {
	//Only one of Pubkey/Private/Wif is required
	Pubkey     string   `json:"from_pubkey,omitempty"`
	Priv       string   `json:"from_private,omitempty"`
	Wif        string   `json:"from_wif,omitempty"`
	ToAddr     string   `json:"to_address"`
	Value      int      `json:"value_satoshis"`
	ChangeAddr string   `json:"change_address,omitempty"`
	Wait       bool     `json:"wait_guarantee,omitempty"`
	ToSign     []string `json:"tosign,omitempty"`
	Signatures []string `json:"signatures,omitempty"`
	Hash       string   `json:"hash,omitempty"`
	Inputs     []struct {
		PrevHash    string `json:"prev_hash"`
		OutputIndex int    `json:"output_index"`
	} `json:"inputs,omitempty"`
	Outputs []struct {
		Value   int    `json:"value"`
		Address string `json:"address"`
	} `json:"outputs,omitempty"`
	Fees int `json:"fees,omitempty"`
}

//Addr represents information about the state
//of a public address.
type Addr struct {
	Address            string   `json:"address,omitempty"`
	Wallet             Wallet   `json:"wallet,omitempty"`
	HDWallet           HDWallet `json:"hd_wallet,omitempty"`
	TotalReceived      int      `json:"total_received"`
	TotalSent          int      `json:"total_sent"`
	Balance            int      `json:"balance"`
	UnconfirmedBalance int      `json:"unconfirmed_balance"`
	FinalBalance       int      `json:"final_balance"`
	NumTX              int      `json:"n_tx"`
	UnconfirmedNumTX   int      `json:"unconfirmed_n_tx"`
	FinalNumTX         int      `json:"final_n_tx"`
	TXs                []TX     `json:"txs,omitempty"`
	TXRefs             []TXRef  `json:"txrefs,omitempty"`
	UnconfirmedTXRefs  []TXRef  `json:"unconfirmed_txrefs,omitempty"`
	HasMore            bool     `json:"hasMore,omitempty"`
}

//AddrKeychain represents information about a generated
//public-private key pair from BlockCypher's address
//generation API. Large amounts are not recommended to be
//stored with these addresses.
type AddrKeychain struct {
	Address         string   `json:"address,omitempty"`
	Private         string   `json:"private,omitempty"`
	Public          string   `json:"public,omitempty"`
	Wif             string   `json:"wif,omitempty"`
	PubKeys         []string `json:"pubkeys,omitempty"`
	ScriptType      string   `json:"script_type,omitempty"`
	OriginalAddress string   `json:"original_address,omitempty"`
	OAPAddress      string   `json:"oap_address,omitempty"`
}

//Wallet represents information about a standard wallet.
//Typically, wallets can be used wherever an address can be
//used within the API.
type Wallet struct {
	Name      string   `json:"name,omitempty"`
	Addresses []string `json:"addresses,omitempty"`
}

//HDWallet represents information about a Hierarchical Deterministic
//(HD) wallet. Like regular Wallets, HDWallets can be used wherever an
//address can be used within the API.
type HDWallet struct {
	Name            string `json:"name,omitempty"`
	ExtPubKey       string `json:"extended_public_key,omitempty"`
	SubchainIndexes []int  `json:"subchain_indexes,omitempty"`
	Chains          []struct {
		ChainAddr []struct {
			Address string `json:"address,omitempty"`
			Path    string `json:"path,omitempty"`
			Public  string `json:"public,omitempty"`
		} `json:"chain_addresses,omitempty"`
		Index int `json:"index,omitempty"`
	} `json:"chains,omitempty"`
}

//Hook represents a WebHook/WebSockets event.
//BlockCypher supports the following events:
//	Event = "unconfirmed-tx"
//	Event = "new-block"
//	Event = "confirmed-tx"
//	Event = "tx-confirmation"
//	Event = "double-spend-tx"
//  Event = "tx-confidence"
//Hash, Address, and Script are all optional; creating
//a WebHook with any of them will filter the resulting
//notifications, if appropriate. ID is returned by
//BlockCyphers servers after Posting a new WebHook; you
//shouldn't manually generate this field.
type Hook struct {
	ID            string  `json:"id,omitempty"`
	Event         string  `json:"event"`
	Hash          string  `json:"hash,omitempty"`
	WalletName    string  `json:"wallet_name,omitempty"`
	Address       string  `json:"address,omitempty"`
	Confirmations int     `json:"confirmations,omitempty"`
	Confidence    float32 `json:"confidence,omitempty"`
	Script        string  `json:"script,omitempty"`
	URL           string  `json:"url,omitempty"`
	CallbackErrs  int     `json:"callback_errors,omitempty"`
}

//PayFwd represents a reference to
//a Payment Forwarding request.
type PayFwd struct {
	ID             string   `json:"id,omitempty"`
	Destination    string   `json:"destination"`
	InputAddr      string   `json:"input_address,omitempty"`
	ProcessAddr    string   `json:"process_fees_address,omitempty"`
	ProcessPercent float64  `json:"process_fees_percent,omitempty"`
	ProcessValue   int      `json:"process_fees_satoshis,omitempty"`
	CallbackURL    string   `json:"callback_url,omitempty"`
	EnableConfirm  bool     `json:"enable_confirmations,omitempty"`
	MiningFees     int      `json:"mining_fees_satoshis,omitempty"`
	TXHistory      []string `json:"transactions,omitempty"`
}

//Payback represents a Payment Forwarding Callback.
//It's more fun to call it a "payback."
type Payback struct {
	Value       int    `json:"value"`
	Destination string `json:"destination"`
	DestHash    string `json:"transaction_hash"`
	InputAddr   string `json:"input_address"`
	InputHash   string `json:"input_transaction_hash"`
}

//OAPIssue represents a request for issuance or transfer of
//an Open Asset on a blockchain.
type OAPIssue struct {
	Priv     string `json:"from_private"`
	ToAddr   string `json:"to_address"`
	Amount   int    `json:"amount"`
	Metadata string `json:"metadata,omitempty"`
}

//OAPTX represents an Open Asset protocol transaction, generated
//when issuing or transferring assets.
type OAPTX struct {
	Ver         int       `json:"ver"`
	AssetID     string    `json:"assetid"`
	Hash        string    `json:"hash"`
	Confirmed   time.Time `json:"confirmed,omitempty"`
	Received    time.Time `json:"received"`
	Metadata    string    `json:"oap_meta,omitempty"`
	DoubleSpend bool      `json:"double_spend"`
	Inputs      []struct {
		PrevHash    string `json:"prev_hash"`
		OutputIndex int    `json:"output_index"`
		OAPAddress  string `json:"address"`
		OutputValue int    `json:"output_value"`
	} `json:"inputs"`
	Outputs []struct {
		OAPAddress      string `json:"address"`
		Value           int    `json:"value"`
		OrigOutputIndex int    `json:"original_output_index"`
	} `json:"outputs"`
}
<commit_msg>add omitempties to usage struct<commit_after>package gobcy

import "time"

//TokenUsage represents information about
//the limits and usage against your token.
type TokenUsage struct {
	Limits Usage `json:"limits"`
	Hits   Usage `json:"hits"`
}

type Usage struct {
	PerSec       int `json:"api/second,omitempty"`
	PerHour      int `json:"api/hour,omitempty"`
	PerDay       int `json:"api/day,omitempty"`
	HooksPerHour int `json:"hooks/hour,omitempty"`
	ConfPerDay   int `json:"confidence/day,omitempty"`
	Hooks        int `json:"hooks,omitempty"`
	PayFwds      int `json:"payments,omitempty"`
}

//Blockchain represents information about
//the state of a blockchain.
type Blockchain struct {
	Name             string    `json:"name"`
	Height           int       `json:"height"`
	Hash             string    `json:"hash"`
	Time             time.Time `json:"time"`
	PrevHash         string    `json:"previous_hash"`
	PeerCount        int       `json:"peer_count"`
	HighFee          int       `json:"high_fee_per_kb"`
	MediumFee        int       `json:"medium_fee_per_kb"`
	LowFee           int       `json:"low_fee_per_kb"`
	UnconfirmedCount int       `json:"unconfirmed_count"`
	LastForkHeight   int       `json:"last_fork_height"`
	LastForkHash     string    `json:"last_fork_hash"`
}

//Block represents information about the state
//of a given block in a blockchain.
type Block struct {
	Hash         string    `json:"hash"`
	Height       int       `json:"height"`
	Depth        int       `json:"depth"`
	Chain        string    `json:"chain"`
	Total        int       `json:"total"`
	Fees         int       `json:"fees"`
	Ver          int       `json:"ver"`
	Time         time.Time `json:"time"`
	ReceivedTime time.Time `json:"received_time"`
	RelayedBy    string    `json:"relayed_by,omitempty"`
	Bits         int       `json:"bits"`
	Nonce        int       `json:"nonce"`
	NumTX        int       `json:"n_tx"`
	PrevBlock    string    `json:"prev_block"`
	MerkleRoot   string    `json:"mrkl_root"`
	TXids        []string  `json:"txids"`
	NextTXs      string    `json:"next_txids"`
}

//TX represents information about the state
//of a given transaction in a blockchain.
type TX struct {
	BlockHash     string     `json:"block_hash,omitempty"`
	BlockHeight   int        `json:"block_height,omitempty"`
	Hash          string     `json:"hash,omitempty"`
	Addresses     []string   `json:"addresses,omitempty"`
	Total         int        `json:"total,omitempty"`
	Fees          int        `json:"fees,omitempty"`
	Size          int        `json:"size"`
	Preference    string     `json:"preference,omitempty"`
	RelayedBy     string     `json:"relayed_by,omitempty"`
	Received      time.Time  `json:"received,omitempty"`
	Confirmed     time.Time  `json:"confirmed,omitempty"`
	Confirmations int        `json:"confirmations,omitempty"`
	Confidence    float64    `json:"confidence,omitempty"`
	Ver           int        `json:"ver,omitempty"`
	LockTime      int        `json:"lock_time,omitempty"`
	DoubleSpend   bool       `json:"double_spend,omitempty"`
	DoubleOf      string     `json:"double_of,omitempty"`
	ReceiveCount  int        `json:"receive_count,omitempty"`
	VinSize       int        `json:"vin_sz,omitempty"`
	VoutSize      int        `json:"vout_sz,omitempty"`
	Hex           string     `json:"hex,omitempty"`
	DataProtocol  string     `json:"data_protocol,omitempty"`
	ChangeAddress string     `json:"change_address,omitempty"`
	NextInputs    string     `json:"next_inputs,omitempty"`
	NextOutputs   string     `json:"next_outputs,omitempty"`
	Inputs        []TXInput  `json:"inputs"`
	Outputs       []TXOutput `json:"outputs"`
}

//TXInput represents the state of a transaction input
type TXInput struct {
	PrevHash    string   `json:"prev_hash,omitempty"`
	OutputIndex int      `json:"output_index,omitempty"`
	OutputValue int      `json:"output_value,omitempty"`
	Addresses   []string `json:"addresses"`
	Sequence    int      `json:"sequence,omitempty"`
	ScriptType  string   `json:"script_type,omitempty"`
	Script      string   `json:"script,omitempty"`
	Age         int      `json:"age,omitempty"`
	WalletName  string   `json:"wallet_name,omitempty"`
}

//TXOutput represents the state of a transaction output
type TXOutput struct {
	SpentBy    string   `json:"spent_by,omitempty"`
	Value      int      `json:"value"`
	Addresses  []string `json:"addresses"`
	ScriptType string   `json:"script_type,omitempty"`
	Script     string   `json:"script,omitempty"`
	DataHex    string   `json:"data_hex,omitempty"`
	DataString string   `json:"data_string,omitempty"`
}

//TXConf represents information about the
//confidence of an unconfirmed transaction.
type TXConf struct {
	Age          int     `json:"age_millis"`
	ReceiveCount int     `json:"receive_count,omitempty"`
	Confidence   float64 `json:"confidence"`
	TXHash       string  `json:"txhash"`
}

//TXRef represents summarized data about a
//transaction input or output.
type TXRef struct {
	Address       string    `json:"address,omitempty"`
	BlockHeight   int       `json:"block_height"`
	TXHash        string    `json:"tx_hash"`
	TXInputN      int       `json:"tx_input_n"`
	TXOutputN     int       `json:"tx_output_n"`
	Value         int       `json:"value"`
	Pref          string    `json:"preference"`
	Spent         bool      `json:"spent"`
	DoubleSpend   bool      `json:"double_spend"`
	DoubleOf      string    `json:"double_of,omitempty"`
	Confirmations int       `json:"confirmations"`
	Script        string    `json:"script,omitempty"`
	RefBalance    int       `json:"ref_balance,omitempty"`
	Confidence    float64   `json:"confidence,omitempty"`
	Confirmed     time.Time `json:"confirmed,omitempty"`
	SpentBy       string    `json:"spent_by,omitempty"`
	Received      time.Time `json:"received,omitempty"`
	ReceivedCount int       `json:"received_count,omitempty"`
}

//TXSkel represents the return call to BlockCypher's
//txs/new endpoint, and includes error information,
//hex transactions that need to be signed, and space
//for the signed transactions and associated public keys.
type TXSkel struct {
	Trans      TX       `json:"tx"`
	ToSign     []string `json:"tosign"`
	Signatures []string `json:"signatures"`
	PubKeys    []string `json:"pubkeys,omitempty"`
	ToSignTX   []string `json:"tosign_tx,omitempty"`
	Errors     []struct {
		Error string `json:"error,omitempty"`
	} `json:"errors,omitempty"`
}

//NullData represents the call and return to BlockCypher's
//Data API, allowing you to embed up to 80 bytes into
//a blockchain via an OP_RETURN.
type NullData struct {
	Data     string `json:"data"`
	Encoding string `json:"encoding,omitempty"`
	Hash     string `json:"hash,omitempty"`
}

//MicroTX represents a microtransaction. For small-value
//transactions, BlockCypher will sign the transaction
//on your behalf, with your private key (if provided).
//Setting a separate change address is recommended.
//Where your application model allows it, consider
//only using public keys with microtransactions,
//and sign the microtransaction with your private key
//(without sending to BlockCypher's server).
type MicroTX struct {
	//Only one of Pubkey/Private/Wif is required
	Pubkey     string   `json:"from_pubkey,omitempty"`
	Priv       string   `json:"from_private,omitempty"`
	Wif        string   `json:"from_wif,omitempty"`
	ToAddr     string   `json:"to_address"`
	Value      int      `json:"value_satoshis"`
	ChangeAddr string   `json:"change_address,omitempty"`
	Wait       bool     `json:"wait_guarantee,omitempty"`
	ToSign     []string `json:"tosign,omitempty"`
	Signatures []string `json:"signatures,omitempty"`
	Hash       string   `json:"hash,omitempty"`
	Inputs     []struct {
		PrevHash    string `json:"prev_hash"`
		OutputIndex int    `json:"output_index"`
	} `json:"inputs,omitempty"`
	Outputs []struct {
		Value   int    `json:"value"`
		Address string `json:"address"`
	} `json:"outputs,omitempty"`
	Fees int `json:"fees,omitempty"`
}

//Addr represents information about the state
//of a public address.
type Addr struct {
	Address            string   `json:"address,omitempty"`
	Wallet             Wallet   `json:"wallet,omitempty"`
	HDWallet           HDWallet `json:"hd_wallet,omitempty"`
	TotalReceived      int      `json:"total_received"`
	TotalSent          int      `json:"total_sent"`
	Balance            int      `json:"balance"`
	UnconfirmedBalance int      `json:"unconfirmed_balance"`
	FinalBalance       int      `json:"final_balance"`
	NumTX              int      `json:"n_tx"`
	UnconfirmedNumTX   int      `json:"unconfirmed_n_tx"`
	FinalNumTX         int      `json:"final_n_tx"`
	TXs                []TX     `json:"txs,omitempty"`
	TXRefs             []TXRef  `json:"txrefs,omitempty"`
	UnconfirmedTXRefs  []TXRef  `json:"unconfirmed_txrefs,omitempty"`
	HasMore            bool     `json:"hasMore,omitempty"`
}

//AddrKeychain represents information about a generated
//public-private key pair from BlockCypher's address
//generation API. Large amounts are not recommended to be
//stored with these addresses.
type AddrKeychain struct {
	Address         string   `json:"address,omitempty"`
	Private         string   `json:"private,omitempty"`
	Public          string   `json:"public,omitempty"`
	Wif             string   `json:"wif,omitempty"`
	PubKeys         []string `json:"pubkeys,omitempty"`
	ScriptType      string   `json:"script_type,omitempty"`
	OriginalAddress string   `json:"original_address,omitempty"`
	OAPAddress      string   `json:"oap_address,omitempty"`
}

//Wallet represents information about a standard wallet.
//Typically, wallets can be used wherever an address can be
//used within the API.
type Wallet struct {
	Name      string   `json:"name,omitempty"`
	Addresses []string `json:"addresses,omitempty"`
}

//HDWallet represents information about a Hierarchical Deterministic
//(HD) wallet. Like regular Wallets, HDWallets can be used wherever an
//address can be used within the API.
type HDWallet struct {
	Name            string `json:"name,omitempty"`
	ExtPubKey       string `json:"extended_public_key,omitempty"`
	SubchainIndexes []int  `json:"subchain_indexes,omitempty"`
	Chains          []struct {
		ChainAddr []struct {
			Address string `json:"address,omitempty"`
			Path    string `json:"path,omitempty"`
			Public  string `json:"public,omitempty"`
		} `json:"chain_addresses,omitempty"`
		Index int `json:"index,omitempty"`
	} `json:"chains,omitempty"`
}

//Hook represents a WebHook/WebSockets event.
//BlockCypher supports the following events:
//	Event = "unconfirmed-tx"
//	Event = "new-block"
//	Event = "confirmed-tx"
//	Event = "tx-confirmation"
//	Event = "double-spend-tx"
//  Event = "tx-confidence"
//Hash, Address, and Script are all optional; creating
//a WebHook with any of them will filter the resulting
//notifications, if appropriate. ID is returned by
//BlockCyphers servers after Posting a new WebHook; you
//shouldn't manually generate this field.
type Hook struct {
	ID            string  `json:"id,omitempty"`
	Event         string  `json:"event"`
	Hash          string  `json:"hash,omitempty"`
	WalletName    string  `json:"wallet_name,omitempty"`
	Address       string  `json:"address,omitempty"`
	Confirmations int     `json:"confirmations,omitempty"`
	Confidence    float32 `json:"confidence,omitempty"`
	Script        string  `json:"script,omitempty"`
	URL           string  `json:"url,omitempty"`
	CallbackErrs  int     `json:"callback_errors,omitempty"`
}

//PayFwd represents a reference to
//a Payment Forwarding request.
type PayFwd struct {
	ID             string   `json:"id,omitempty"`
	Destination    string   `json:"destination"`
	InputAddr      string   `json:"input_address,omitempty"`
	ProcessAddr    string   `json:"process_fees_address,omitempty"`
	ProcessPercent float64  `json:"process_fees_percent,omitempty"`
	ProcessValue   int      `json:"process_fees_satoshis,omitempty"`
	CallbackURL    string   `json:"callback_url,omitempty"`
	EnableConfirm  bool     `json:"enable_confirmations,omitempty"`
	MiningFees     int      `json:"mining_fees_satoshis,omitempty"`
	TXHistory      []string `json:"transactions,omitempty"`
}

//Payback represents a Payment Forwarding Callback.
//It's more fun to call it a "payback."
type Payback struct {
	Value       int    `json:"value"`
	Destination string `json:"destination"`
	DestHash    string `json:"transaction_hash"`
	InputAddr   string `json:"input_address"`
	InputHash   string `json:"input_transaction_hash"`
}

//OAPIssue represents a request for issuance or transfer of
//an Open Asset on a blockchain.
type OAPIssue struct {
	Priv     string `json:"from_private"`
	ToAddr   string `json:"to_address"`
	Amount   int    `json:"amount"`
	Metadata string `json:"metadata,omitempty"`
}

//OAPTX represents an Open Asset protocol transaction, generated
//when issuing or transferring assets.
type OAPTX struct {
	Ver         int       `json:"ver"`
	AssetID     string    `json:"assetid"`
	Hash        string    `json:"hash"`
	Confirmed   time.Time `json:"confirmed,omitempty"`
	Received    time.Time `json:"received"`
	Metadata    string    `json:"oap_meta,omitempty"`
	DoubleSpend bool      `json:"double_spend"`
	Inputs      []struct {
		PrevHash    string `json:"prev_hash"`
		OutputIndex int    `json:"output_index"`
		OAPAddress  string `json:"address"`
		OutputValue int    `json:"output_value"`
	} `json:"inputs"`
	Outputs []struct {
		OAPAddress      string `json:"address"`
		Value           int    `json:"value"`
		OrigOutputIndex int    `json:"original_output_index"`
	} `json:"outputs"`
}
<|endoftext|>


<commit_before>package wmi

type Win32_Process struct {
	Name        string
	Description string
	OSName      string
}
<commit_msg>Full Win32_Process type supported<commit_after>package wmi

import "time"

type Win32_Process struct {
	CSCreationClassName        string
	CSName                     string
	Caption                    string
	CommandLine                string
	CreationClassName          string
	CreationDate               time.Time
	Description                string
	ExecutablePath             string
	ExecutionState             uint16
	Handle                     string
	HandleCount                uint32
	InstallDate                time.Time
	KernelModeTime             uint64
	MaximumWorkingSetSize      uint32
	MinimumWorkingSetSize      uint32
	Name                       string
	OSCreationClassName        string
	OSName                     string
	OtherOperationCount        uint64
	OtherTransferCount         uint64
	PageFaults                 uint32
	PageFileUsage              uint32
	ParentProcessId            uint32
	PeakPageFileUsage          uint32
	PeakVirtualSize            uint64
	PeakWorkingSetSize         uint32
	Priority                   uint32
	PrivatePageCount           uint64
	ProcessId                  uint32
	QuotaNonPagedPoolUsage     uint32
	QuotaPagedPoolUsage        uint32
	QuotaPeakNonPagedPoolUsage uint32
	QuotaPeakPagedPoolUsage    uint32
	ReadOperationCount         uint64
	ReadTransferCount          uint64
	SessionId                  uint32
	Status                     string
	TerminationDate            time.Time
	ThreadCount                uint32
	UserModeTime               uint64
	VirtualSize                uint64
	WindowsVersion             string
	WorkingSetSize             uint64
	WriteOperationCount        uint64
	WriteTransferCount         uint64
}
<|endoftext|>


<commit_before>// +build linux,seccomp

package native

import "github.com/opencontainers/runc/libcontainer/configs"

var defaultSeccompProfile = &configs.Seccomp{
	DefaultAction: configs.Allow,
	Syscalls: []*configs.Syscall{
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "acct",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "add_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Similar to clock_settime and settimeofday
			// Time/Date is not namespaced
			Name:   "adjtimex",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_adjtime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_settime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny cloning new namespaces
			Name:   "clone",
			Action: configs.Errno,
			Args: []*configs.Arg{
				{
					// flags from sched.h
					// CLONE_NEWUTS		0x04000000
					// CLONE_NEWIPC		0x08000000
					// CLONE_NEWUSER	0x10000000
					// CLONE_NEWPID		0x20000000
					// CLONE_NEWNET		0x40000000
					Index: 0,
					Value: uint64(0x04000000),
					Op:    configs.GreaterThanOrEqualTo,
				},
				{
					// flags from sched.h
					// CLONE_NEWNS		0x00020000
					Index: 0,
					Value: uint64(0x00020000),
					Op:    configs.EqualTo,
				},
			},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "create_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "delete_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "finit_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny retrieval of exported kernel and module symbols
			Name:   "get_kernel_syms",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "get_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "init_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "ioperm",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "iopl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Sister syscall of kexec_load that does the same thing,
			// slightly different arguments
			Name:   "kexec_file_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny loading a new kernel for later execution
			Name:   "kexec_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "keyctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "lookup_dcookie",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "mbind",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "migrate_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Old syscall only used in 16-bit code,
			// and a potential information leak
			Name:   "modify_ldt",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny mount
			Name:   "mount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "move_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny interaction with the kernel nfs daemon
			Name:   "nfsservctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Cause of an old container breakout,
			// might as well restrict it to be on the safe side
			Name:   "open_by_handle_at",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "perf_event_open",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent container from enabling BSD emulation.
			// Not inherently dangerous, but poorly tested,
			// potential for a lot of kernel vulns in this.
			Name:   "personality",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny pivot_root
			Name:   "pivot_root",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Already blocked by dropping CAP_PTRACE
			Name:   "ptrace",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "query_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "quotactl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers reboot the host
			Name:   "reboot",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers restart a syscall.
			// Possible seccomp bypass, see: https://code.google.com/p/chromium/issues/detail?id=408827.
			Name:   "restart_syscall",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "request_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// meta, deny seccomp
			Name:   "seccomp",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "set_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// deny associating a thread with a namespace
			Name:   "setns",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "settimeofday",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "stime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapon",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapoff",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny read/write system parameters
			Name:   "_sysctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount2",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Same as clone
			Name:   "unshare",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Older syscall related to shared libraries, unused for a long time
			Name:   "uselib",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
	},
}
<commit_msg>remove seccomp from seccomp profile<commit_after>// +build linux,seccomp

package native

import "github.com/opencontainers/runc/libcontainer/configs"

var defaultSeccompProfile = &configs.Seccomp{
	DefaultAction: configs.Allow,
	Syscalls: []*configs.Syscall{
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "acct",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "add_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Similar to clock_settime and settimeofday
			// Time/Date is not namespaced
			Name:   "adjtimex",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_adjtime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_settime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny cloning new namespaces
			Name:   "clone",
			Action: configs.Errno,
			Args: []*configs.Arg{
				{
					// flags from sched.h
					// CLONE_NEWUTS		0x04000000
					// CLONE_NEWIPC		0x08000000
					// CLONE_NEWUSER	0x10000000
					// CLONE_NEWPID		0x20000000
					// CLONE_NEWNET		0x40000000
					Index: 0,
					Value: uint64(0x04000000),
					Op:    configs.GreaterThanOrEqualTo,
				},
				{
					// flags from sched.h
					// CLONE_NEWNS		0x00020000
					Index: 0,
					Value: uint64(0x00020000),
					Op:    configs.EqualTo,
				},
			},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "create_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "delete_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "finit_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny retrieval of exported kernel and module symbols
			Name:   "get_kernel_syms",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "get_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "init_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "ioperm",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "iopl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Sister syscall of kexec_load that does the same thing,
			// slightly different arguments
			Name:   "kexec_file_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny loading a new kernel for later execution
			Name:   "kexec_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "keyctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "lookup_dcookie",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "mbind",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "migrate_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Old syscall only used in 16-bit code,
			// and a potential information leak
			Name:   "modify_ldt",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny mount
			Name:   "mount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "move_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny interaction with the kernel nfs daemon
			Name:   "nfsservctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Cause of an old container breakout,
			// might as well restrict it to be on the safe side
			Name:   "open_by_handle_at",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "perf_event_open",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent container from enabling BSD emulation.
			// Not inherently dangerous, but poorly tested,
			// potential for a lot of kernel vulns in this.
			Name:   "personality",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny pivot_root
			Name:   "pivot_root",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Already blocked by dropping CAP_PTRACE
			Name:   "ptrace",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "query_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "quotactl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers reboot the host
			Name:   "reboot",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers restart a syscall.
			// Possible seccomp bypass, see: https://code.google.com/p/chromium/issues/detail?id=408827.
			Name:   "restart_syscall",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "request_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "set_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// deny associating a thread with a namespace
			Name:   "setns",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "settimeofday",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "stime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapon",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapoff",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny read/write system parameters
			Name:   "_sysctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount2",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Same as clone
			Name:   "unshare",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Older syscall related to shared libraries, unused for a long time
			Name:   "uselib",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
	},
}
<|endoftext|>


<commit_before>// This file defines the static data types exported by package
// musicmanager.

package musicmanager

import (
	"fmt"
	"net/http"

	mmdspb "github.com/lxr/go.google.musicmanager/internal/download_proto/service"
	mmssjs "github.com/lxr/go.google.musicmanager/internal/session_json"
	mmuspb "github.com/lxr/go.google.musicmanager/internal/upload_proto/service"
)

// BUG(lor): The protobuf status enums should probably be exported as
// individual error variables, rather than types, for ease of
// comparison.

// A RegisterError is returned by Client.Register if the server refuses
// to register the client for some reason.
type RegisterError mmuspb.UploadResponse_AuthStatus

func (e RegisterError) Error() string {
	return fmt.Sprint("musicmanager register error: ", mmuspb.UploadResponse_AuthStatus(e))
}

// A ListError is returned by Client.ListTracks if the server refuses
// to list the tracks for some reason.
type ListError mmdspb.GetTracksToExportResponse_TracksToExportStatus

func (e ListError) Error() string {
	return fmt.Sprint("musicmanager list error: ", mmdspb.GetTracksToExportResponse_TracksToExportStatus(e))
}

// An ImportError is returned by Client.ImportTracks if the server
// rejects a track based on its metadata or audio sample.
type ImportError mmuspb.TrackSampleResponse_ResponseCode

func (e ImportError) Error() string {
	return fmt.Sprint("musicmanager import error: ", mmuspb.TrackSampleResponse_ResponseCode(e))
}

// A RequestError is returned by all Client methods if an HTTP request
// is responded to with a non-2xx status code.
type RequestError mmssjs.SessionError

func (e *RequestError) Error() string {
	return fmt.Sprint("musicmanager request error: ", http.StatusText(e.Code))
}

// TrackChannels represents the number of channels a Track can have.
type TrackChannels int

const (
	Mono   TrackChannels = 1
	Stereo TrackChannels = 2
)

// TrackRating represents the rating of a track.
type TrackRating int

const (
	NoRating TrackRating = 1 + iota

	OneStar // thumbs down
	TwoStars
	ThreeStars
	FourStars
	FiveStars // thumbs up
)

// TrackType defines the origin of a track.
type TrackType int

const (
	Matched TrackType = 1 + iota
	Unmatched
	Local
	Purchased
	MetadataOnlyMatched
	Promotional
)

// A Track represents metadata about a track.  When in a TrackList,
// only a subset of the fields are populated.
type Track struct {
	// There fields are present inside a TrackList.
	Id          string
	Title       string
	Artist      string
	Album       string
	AlbumArtist string
	TrackNumber int
	TrackSize   int64

	// Additional fields that can be given on import.
	ClientId        string
	Composer        string
	Genre           string
	Comment         string
	Year            int
	TotalTrackCount int
	DiscNumber      int
	TotalDiscCount  int
	PlayCount       int
	BeatsPerMinute  int
	Channels        TrackChannels
	Rating          TrackRating
	TrackType       TrackType
	// BUG(lor): Album art cannot be uploaded.

	// BitRate is the bitrate of the track in kbps, or 0 if don't
	// care.
	BitRate int

	// SampleFunc can be optionally used to provide the server with
	// a 128kbps MP3 sample of the track if requested.  It takes the
	// start and length of the desired sample in milliseconds.  If
	// SampleFunc is nil, an empty sample is sent.
	SampleFunc func(start, duration int) []byte
}

// A TrackList is one page of a track listing.
type TrackList struct {
	// The actual page of tracks.
	Items []*Track `convert:"/DownloadTrackInfo"`

	// Page token for the next page of tracks.
	PageToken string `convert:"/ContinuationToken"`

	// The last time one of the tracks in the list was modified,
	// expressed as a Unix timestamp in microseconds.
	UpdatedMin int64 `convert:"/UpdatedMin"`

	// Whether this listing contains only purchased or promotional
	// tracks.
	PurchasedOnly bool `convert:"-"`
}
<commit_msg>Define constants for the error types<commit_after>// This file defines the static data types exported by package
// musicmanager.

package musicmanager

import (
	"fmt"
	"net/http"

	mmdspb "github.com/lxr/go.google.musicmanager/internal/download_proto/service"
	mmssjs "github.com/lxr/go.google.musicmanager/internal/session_json"
	mmuspb "github.com/lxr/go.google.musicmanager/internal/upload_proto/service"
)

// A RegisterError is returned by Client.Register if the server refuses
// to register the client for some reason.
type RegisterError int32

const (
	ErrMaxLimitReached RegisterError = 9 + iota
	ErrClientBoundToOtherAccount
	ErrClientNotAuthorized
	ErrMaxPerMachineUsersExceeded
	ErrClientPleaseRetry
	ErrNotSubscribed
	ErrInvalidRequest
	ErrUpgradeMusicManager
)

func (e RegisterError) Error() string {
	return fmt.Sprint("musicmanager register error: ", mmuspb.UploadResponse_AuthStatus(e))
}

// A ListError is returned by Client.ListTracks if the server refuses
// to list the tracks for some reason.
type ListError int32

const (
	ErrTransientList ListError = 2 + iota
	ErrMaxNumClientsReached
	ErrUnableToAuthenticateClient
	ErrUnableToRegisterClient
)

func (e ListError) Error() string {
	return fmt.Sprint("musicmanager list error: ", mmdspb.GetTracksToExportResponse_TracksToExportStatus(e))
}

// An ImportError is returned by Client.ImportTracks if the server
// rejects a track based on its metadata or audio sample.
type ImportError int32

const (
	ErrMatched ImportError = 1 + iota
	_
	ErrInvalidSignature
	ErrAlreadyExists
	ErrTransientImport
	ErrPermanentImport
	ErrTrackCountLimitReached
	ErrRejectStoreTrack
	ErrRejectStoreTrackByLabel
	ErrRejectDrmTrack
)

func (e ImportError) Error() string {
	return fmt.Sprint("musicmanager import error: ", mmuspb.TrackSampleResponse_ResponseCode(e))
}

// A RequestError is returned by all Client methods if an HTTP request
// is responded to with a non-2xx status code.
type RequestError mmssjs.SessionError

func (e *RequestError) Error() string {
	return fmt.Sprint("musicmanager request error: ", http.StatusText(e.Code))
}

// TrackChannels represents the number of channels a Track can have.
type TrackChannels int

const (
	Mono   TrackChannels = 1
	Stereo TrackChannels = 2
)

// TrackRating represents the rating of a track.
type TrackRating int

const (
	NoRating TrackRating = 1 + iota

	OneStar // thumbs down
	TwoStars
	ThreeStars
	FourStars
	FiveStars // thumbs up
)

// TrackType defines the origin of a track.
type TrackType int

const (
	Matched TrackType = 1 + iota
	Unmatched
	Local
	Purchased
	MetadataOnlyMatched
	Promotional
)

// A Track represents metadata about a track.  When in a TrackList,
// only a subset of the fields are populated.
type Track struct {
	// There fields are present inside a TrackList.
	Id          string
	Title       string
	Artist      string
	Album       string
	AlbumArtist string
	TrackNumber int
	TrackSize   int64

	// Additional fields that can be given on import.
	ClientId        string
	Composer        string
	Genre           string
	Comment         string
	Year            int
	TotalTrackCount int
	DiscNumber      int
	TotalDiscCount  int
	PlayCount       int
	BeatsPerMinute  int
	Channels        TrackChannels
	Rating          TrackRating
	TrackType       TrackType
	// BUG(lor): Album art cannot be uploaded.

	// BitRate is the bitrate of the track in kbps, or 0 if don't
	// care.
	BitRate int

	// SampleFunc can be optionally used to provide the server with
	// a 128kbps MP3 sample of the track if requested.  It takes the
	// start and length of the desired sample in milliseconds.  If
	// SampleFunc is nil, an empty sample is sent.
	SampleFunc func(start, duration int) []byte
}

// A TrackList is one page of a track listing.
type TrackList struct {
	// The actual page of tracks.
	Items []*Track `convert:"/DownloadTrackInfo"`

	// Page token for the next page of tracks.
	PageToken string `convert:"/ContinuationToken"`

	// The last time one of the tracks in the list was modified,
	// expressed as a Unix timestamp in microseconds.
	UpdatedMin int64 `convert:"/UpdatedMin"`

	// Whether this listing contains only purchased or promotional
	// tracks.
	PurchasedOnly bool `convert:"-"`
}
<|endoftext|>


<commit_before>package rpc

import (
	"bytes"
	"context"
	"encoding/json"
	"io"
	"net/http"
	"strings"
	"time"

	"github.com/gobwas/httphead"
	"github.com/gobwas/ws"
	"github.com/gobwas/ws/wsutil"
	"github.com/micro/go-micro/v2/api"
	"github.com/micro/go-micro/v2/client"
	"github.com/micro/go-micro/v2/client/selector"
	raw "github.com/micro/go-micro/v2/codec/bytes"
	"github.com/micro/go-micro/v2/logger"
)

// serveWebsocket will stream rpc back over websockets assuming json
func serveWebsocket(ctx context.Context, w http.ResponseWriter, r *http.Request, service *api.Service, c client.Client) {
	var op ws.OpCode

	ct := r.Header.Get("Content-Type")
	// Strip charset from Content-Type (like `application/json; charset=UTF-8`)
	if idx := strings.IndexRune(ct, ';'); idx >= 0 {
		ct = ct[:idx]
	}

	// check proto from request
	switch ct {
	case "application/json":
		op = ws.OpText
	default:
		op = ws.OpBinary
	}

	hdr := make(http.Header)
	if proto, ok := r.Header["Sec-WebSocket-Protocol"]; ok {
		for _, p := range proto {
			switch p {
			case "binary":
				hdr["Sec-WebSocket-Protocol"] = []string{"binary"}
				op = ws.OpBinary
			}
		}
	}
	payload, err := requestPayload(r)
	if err != nil {
		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
			logger.Error(err)
		}
		return
	}

	upgrader := ws.HTTPUpgrader{Timeout: 5 * time.Second,
		Protocol: func(proto string) bool {
			if strings.Contains(proto, "binary") {
				return true
			}
			// fallback to support all protocols now
			return true
		},
		Extension: func(httphead.Option) bool {
			// disable extensions for compatibility
			return false
		},
		Header: hdr,
	}

	conn, rw, _, err := upgrader.Upgrade(r, w)
	if err != nil {
		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
			logger.Error(err)
		}
		return
	}

	defer func() {
		if err := conn.Close(); err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}
	}()

	var request interface{}
	if !bytes.Equal(payload, []byte(`{}`)) {
		switch ct {
		case "application/json", "":
			m := json.RawMessage(payload)
			request = &m
		default:
			request = &raw.Frame{Data: payload}
		}
	}

	// we always need to set content type for message
	if ct == "" {
		ct = "application/json"
	}
	req := c.NewRequest(
		service.Name,
		service.Endpoint.Name,
		request,
		client.WithContentType(ct),
		client.StreamingRequest(),
	)

	so := selector.WithStrategy(strategy(service.Services))
	// create a new stream
	stream, err := c.Stream(ctx, req, client.WithSelectOption(so))
	if err != nil {
		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
			logger.Error(err)
		}
		return
	}

	if request != nil {
		if err = stream.Send(request); err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}
	}

	go writeLoop(rw, stream)

	rsp := stream.Response()

	// receive from stream and send to client
	for {
		// read backend response body
		buf, err := rsp.Read()
		if err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}

		// write the response
		if err := wsutil.WriteServerMessage(rw, op, buf); err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}
		if err = rw.Flush(); err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}
	}
}

// writeLoop
func writeLoop(rw io.ReadWriter, stream client.Stream) {
	// close stream when done
	defer stream.Close()

	for {
		buf, op, err := wsutil.ReadClientData(rw)
		if err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}
		switch op {
		default:
			// not relevant
			continue
		case ws.OpText, ws.OpBinary:
			break
		}
		// send to backend
		// default to trying json
		// if the extracted payload isn't empty lets use it
		request := &raw.Frame{Data: buf}

		if err := stream.Send(request); err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}
	}
}

func isStream(r *http.Request, srv *api.Service) bool {
	// check if it's a web socket
	if !isWebSocket(r) {
		return false
	}
	// check if the endpoint supports streaming
	for _, service := range srv.Services {
		for _, ep := range service.Endpoints {
			// skip if it doesn't match the name
			if ep.Name != srv.Endpoint.Name {
				continue
			}
			// matched if the name
			if v := ep.Metadata["stream"]; v == "true" {
				return true
			}
		}
	}
	return false
}

func isWebSocket(r *http.Request) bool {
	contains := func(key, val string) bool {
		vv := strings.Split(r.Header.Get(key), ",")
		for _, v := range vv {
			if val == strings.ToLower(strings.TrimSpace(v)) {
				return true
			}
		}
		return false
	}

	if contains("Connection", "upgrade") && contains("Upgrade", "websocket") {
		return true
	}

	return false
}
<commit_msg>api/handler/rpc: not log error on client disconnect (#1482)<commit_after>package rpc

import (
	"bytes"
	"context"
	"encoding/json"
	"io"
	"net/http"
	"strings"
	"time"

	"github.com/gobwas/httphead"
	"github.com/gobwas/ws"
	"github.com/gobwas/ws/wsutil"
	"github.com/micro/go-micro/v2/api"
	"github.com/micro/go-micro/v2/client"
	"github.com/micro/go-micro/v2/client/selector"
	raw "github.com/micro/go-micro/v2/codec/bytes"
	"github.com/micro/go-micro/v2/logger"
)

// serveWebsocket will stream rpc back over websockets assuming json
func serveWebsocket(ctx context.Context, w http.ResponseWriter, r *http.Request, service *api.Service, c client.Client) {
	var op ws.OpCode

	ct := r.Header.Get("Content-Type")
	// Strip charset from Content-Type (like `application/json; charset=UTF-8`)
	if idx := strings.IndexRune(ct, ';'); idx >= 0 {
		ct = ct[:idx]
	}

	// check proto from request
	switch ct {
	case "application/json":
		op = ws.OpText
	default:
		op = ws.OpBinary
	}

	hdr := make(http.Header)
	if proto, ok := r.Header["Sec-WebSocket-Protocol"]; ok {
		for _, p := range proto {
			switch p {
			case "binary":
				hdr["Sec-WebSocket-Protocol"] = []string{"binary"}
				op = ws.OpBinary
			}
		}
	}
	payload, err := requestPayload(r)
	if err != nil {
		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
			logger.Error(err)
		}
		return
	}

	upgrader := ws.HTTPUpgrader{Timeout: 5 * time.Second,
		Protocol: func(proto string) bool {
			if strings.Contains(proto, "binary") {
				return true
			}
			// fallback to support all protocols now
			return true
		},
		Extension: func(httphead.Option) bool {
			// disable extensions for compatibility
			return false
		},
		Header: hdr,
	}

	conn, rw, _, err := upgrader.Upgrade(r, w)
	if err != nil {
		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
			logger.Error(err)
		}
		return
	}

	defer func() {
		if err := conn.Close(); err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}
	}()

	var request interface{}
	if !bytes.Equal(payload, []byte(`{}`)) {
		switch ct {
		case "application/json", "":
			m := json.RawMessage(payload)
			request = &m
		default:
			request = &raw.Frame{Data: payload}
		}
	}

	// we always need to set content type for message
	if ct == "" {
		ct = "application/json"
	}
	req := c.NewRequest(
		service.Name,
		service.Endpoint.Name,
		request,
		client.WithContentType(ct),
		client.StreamingRequest(),
	)

	so := selector.WithStrategy(strategy(service.Services))
	// create a new stream
	stream, err := c.Stream(ctx, req, client.WithSelectOption(so))
	if err != nil {
		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
			logger.Error(err)
		}
		return
	}

	if request != nil {
		if err = stream.Send(request); err != nil {
			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
				logger.Error(err)
			}
			return
		}
	}

	go writeLoop(rw, stream)

	rsp := stream.Response()

	// receive from stream and send to client
	for {
		select {
		case <-ctx.Done():
			return
		case <-stream.Context().Done():
			return
		default:
			// read backend response body
			buf, err := rsp.Read()
			if err != nil {
				// wants to avoid import  grpc/status.Status
				if strings.Contains(err.Error(), "context canceled") {
					return
				}
				if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
					logger.Error(err)
				}
				return
			}

			// write the response
			if err := wsutil.WriteServerMessage(rw, op, buf); err != nil {
				if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
					logger.Error(err)
				}
				return
			}
			if err = rw.Flush(); err != nil {
				if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
					logger.Error(err)
				}
				return
			}
		}
	}
}

// writeLoop
func writeLoop(rw io.ReadWriter, stream client.Stream) {
	// close stream when done
	defer stream.Close()

	for {
		select {
		case <-stream.Context().Done():
			return
		default:
			buf, op, err := wsutil.ReadClientData(rw)
			if err != nil {
				wserr := err.(wsutil.ClosedError)
				switch wserr.Code {
				case ws.StatusNormalClosure, ws.StatusNoStatusRcvd:
					return
				default:
					if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
						logger.Error(err)
					}
					return
				}
			}
			switch op {
			default:
				// not relevant
				continue
			case ws.OpText, ws.OpBinary:
				break
			}
			// send to backend
			// default to trying json
			// if the extracted payload isn't empty lets use it
			request := &raw.Frame{Data: buf}
			if err := stream.Send(request); err != nil {
				if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
					logger.Error(err)
				}
				return
			}
		}
	}
}

func isStream(r *http.Request, srv *api.Service) bool {
	// check if it's a web socket
	if !isWebSocket(r) {
		return false
	}
	// check if the endpoint supports streaming
	for _, service := range srv.Services {
		for _, ep := range service.Endpoints {
			// skip if it doesn't match the name
			if ep.Name != srv.Endpoint.Name {
				continue
			}
			// matched if the name
			if v := ep.Metadata["stream"]; v == "true" {
				return true
			}
		}
	}
	return false
}

func isWebSocket(r *http.Request) bool {
	contains := func(key, val string) bool {
		vv := strings.Split(r.Header.Get(key), ",")
		for _, v := range vv {
			if val == strings.ToLower(strings.TrimSpace(v)) {
				return true
			}
		}
		return false
	}

	if contains("Connection", "upgrade") && contains("Upgrade", "websocket") {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>package image

import (
	"io"
	"io/ioutil"
	"os"
	"strings"

	"github.com/dnephin/dobi/config"
	"github.com/dnephin/dobi/tasks/context"
	"github.com/dnephin/dobi/utils/fs"
	"github.com/docker/cli/cli/command/image/build"
	"github.com/docker/docker/pkg/archive"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/pkg/errors"
)

// RunBuild builds an image if it is out of date
func RunBuild(ctx *context.ExecuteContext, t *Task, hasModifiedDeps bool) (bool, error) {
	if !hasModifiedDeps {
		stale, err := buildIsStale(ctx, t)
		switch {
		case err != nil:
			return false, err
		case !stale:
			t.logger().Info("is fresh")
			return false, nil
		}
	}
	t.logger().Debug("is stale")

	if !t.config.IsBuildable() {
		return false, errors.Errorf(
			"%s is not buildable, missing required fields", t.name.Resource())
	}

	if err := buildImage(ctx, t); err != nil {
		return false, err
	}

	image, err := GetImage(ctx, t.config)
	if err != nil {
		return false, err
	}

	record := imageModifiedRecord{ImageID: image.ID}
	if err := updateImageRecord(recordPath(ctx, t.config), record); err != nil {
		t.logger().Warnf("Failed to update image record: %s", err)
	}
	t.logger().Info("Created")
	return true, nil
}

// TODO: this cyclo problem should be fixed
// nolint: gocyclo
func buildIsStale(ctx *context.ExecuteContext, t *Task) (bool, error) {
	image, err := GetImage(ctx, t.config)
	switch err {
	case docker.ErrNoSuchImage:
		t.logger().Debug("Image does not exist")
		return true, nil
	case nil:
	default:
		return true, err
	}

	paths := []string{t.config.Context}
	// TODO: polymorphic config for different types of images
	if t.config.Steps != "" && ctx.ConfigFile != "" {
		paths = append(paths, ctx.ConfigFile)
	}

	excludes, err := build.ReadDockerignore(t.config.Context)
	if err != nil {
		t.logger().Warnf("Failed to read .dockerignore file.")
	}
	excludes = append(excludes, ".dobi")

	mtime, err := fs.LastModified(&fs.LastModifiedSearch{
		Root:     ctx.WorkingDir,
		Excludes: excludes,
		Paths:    paths,
	})
	if err != nil {
		t.logger().Warnf("Failed to get last modified time of context.")
		return true, err
	}

	record, err := getImageRecord(recordPath(ctx, t.config))
	if err != nil {
		t.logger().Warnf("Failed to get image record: %s", err)
		if image.Created.Before(mtime) {
			t.logger().Debug("Image older than context")
			return true, nil
		}
		return false, nil
	}

	if image.ID != record.ImageID || record.Info.ModTime().Before(mtime) {
		t.logger().Debug("Image record older than context")
		return true, nil
	}
	return false, nil
}

func buildImage(ctx *context.ExecuteContext, t *Task) error {
	var err error
	if t.config.Steps != "" {
		err = t.buildImageFromSteps(ctx)
	} else {
		err = t.buildImageFromDockerfile(ctx)
	}
	if err != nil {
		return err
	}
	image, err := GetImage(ctx, t.config)
	if err != nil {
		return err
	}
	record := imageModifiedRecord{ImageID: image.ID}
	return updateImageRecord(recordPath(ctx, t.config), record)
}

func (t *Task) buildImageFromDockerfile(ctx *context.ExecuteContext) error {
	return Stream(os.Stdout, func(out io.Writer) error {
		opts := t.commonBuildImageOptions(ctx, out)
		opts.Dockerfile = t.config.Dockerfile
		opts.ContextDir = t.config.Context
		return ctx.Client.BuildImage(opts)
	})
}

func (t *Task) commonBuildImageOptions(
	ctx *context.ExecuteContext,
	out io.Writer,
) docker.BuildImageOptions {
	return docker.BuildImageOptions{
		Name:           GetImageName(ctx, t.config),
		BuildArgs:      buildArgs(t.config.Args),
		Target:         t.config.Target,
		Pull:           t.config.PullBaseImageOnBuild,
		NetworkMode:    t.config.NetworkMode,
		CacheFrom:      t.config.CacheFrom,
		RmTmpContainer: true,
		OutputStream:   out,
		RawJSONStream:  true,
		SuppressOutput: ctx.Settings.Quiet,
		AuthConfigs:    ctx.GetAuthConfigs(),
	}
}

func buildArgs(args map[string]string) []docker.BuildArg {
	out := []docker.BuildArg{}
	for key, value := range args {
		out = append(out, docker.BuildArg{Name: key, Value: value})
	}
	return out
}

func (t *Task) buildImageFromSteps(ctx *context.ExecuteContext) error {
	buildContext, dockerfile, err := getBuildContext(t.config)
	if err != nil {
		return err
	}
	return Stream(os.Stdout, func(out io.Writer) error {
		opts := t.commonBuildImageOptions(ctx, out)
		opts.InputStream = buildContext
		opts.Dockerfile = dockerfile
		return ctx.Client.BuildImage(opts)
	})
}

func getBuildContext(config *config.ImageConfig) (io.Reader, string, error) {
	contextDir := config.Context
	excludes, err := build.ReadDockerignore(contextDir)
	if err != nil {
		return nil, "", err
	}
	if err = build.ValidateContextDirectory(contextDir, excludes); err != nil {
		return nil, "", err

	}
	buildCtx, err := archive.TarWithOptions(contextDir, &archive.TarOptions{
		ExcludePatterns: excludes,
	})
	if err != nil {
		return nil, "", err
	}
	dockerfileCtx := ioutil.NopCloser(strings.NewReader(config.Steps))
	return build.AddDockerfileToBuildContext(dockerfileCtx, buildCtx)
}
<commit_msg>Optionally make context absolute<commit_after>package image

import (
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/dnephin/dobi/config"
	"github.com/dnephin/dobi/tasks/context"
	"github.com/dnephin/dobi/utils/fs"
	"github.com/docker/cli/cli/command/image/build"
	"github.com/docker/docker/pkg/archive"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/pkg/errors"
)

// RunBuild builds an image if it is out of date
func RunBuild(ctx *context.ExecuteContext, t *Task, hasModifiedDeps bool) (bool, error) {
	if !hasModifiedDeps {
		stale, err := buildIsStale(ctx, t)
		switch {
		case err != nil:
			return false, err
		case !stale:
			t.logger().Info("is fresh")
			return false, nil
		}
	}
	t.logger().Debug("is stale")

	if !t.config.IsBuildable() {
		return false, errors.Errorf(
			"%s is not buildable, missing required fields", t.name.Resource())
	}

	if err := buildImage(ctx, t); err != nil {
		return false, err
	}

	image, err := GetImage(ctx, t.config)
	if err != nil {
		return false, err
	}

	record := imageModifiedRecord{ImageID: image.ID}
	if err := updateImageRecord(recordPath(ctx, t.config), record); err != nil {
		t.logger().Warnf("Failed to update image record: %s", err)
	}
	t.logger().Info("Created")
	return true, nil
}

// TODO: this cyclo problem should be fixed
// nolint: gocyclo
func buildIsStale(ctx *context.ExecuteContext, t *Task) (bool, error) {
	image, err := GetImage(ctx, t.config)
	switch err {
	case docker.ErrNoSuchImage:
		t.logger().Debug("Image does not exist")
		return true, nil
	case nil:
	default:
		return true, err
	}

	paths := []string{t.config.Context}
	// TODO: polymorphic config for different types of images
	if t.config.Steps != "" && ctx.ConfigFile != "" {
		paths = append(paths, ctx.ConfigFile)
	}

	excludes, err := build.ReadDockerignore(t.config.Context)
	if err != nil {
		t.logger().Warnf("Failed to read .dockerignore file.")
	}
	excludes = append(excludes, ".dobi")

	mtime, err := fs.LastModified(&fs.LastModifiedSearch{
		Root:     absPath(ctx.WorkingDir, t.config.Context),
		Excludes: excludes,
		Paths:    paths,
	})
	if err != nil {
		t.logger().Warnf("Failed to get last modified time of context.")
		return true, err
	}

	record, err := getImageRecord(recordPath(ctx, t.config))
	if err != nil {
		t.logger().Warnf("Failed to get image record: %s", err)
		if image.Created.Before(mtime) {
			t.logger().Debug("Image older than context")
			return true, nil
		}
		return false, nil
	}

	if image.ID != record.ImageID || record.Info.ModTime().Before(mtime) {
		t.logger().Debug("Image record older than context")
		return true, nil
	}
	return false, nil
}

func absPath(path string, wd string) string {
	if filepath.IsAbs(path) {
		return filepath.Clean(path)
	}
	return filepath.Join(wd, path)
}

func buildImage(ctx *context.ExecuteContext, t *Task) error {
	var err error
	if t.config.Steps != "" {
		err = t.buildImageFromSteps(ctx)
	} else {
		err = t.buildImageFromDockerfile(ctx)
	}
	if err != nil {
		return err
	}
	image, err := GetImage(ctx, t.config)
	if err != nil {
		return err
	}
	record := imageModifiedRecord{ImageID: image.ID}
	return updateImageRecord(recordPath(ctx, t.config), record)
}

func (t *Task) buildImageFromDockerfile(ctx *context.ExecuteContext) error {
	return Stream(os.Stdout, func(out io.Writer) error {
		opts := t.commonBuildImageOptions(ctx, out)
		opts.Dockerfile = t.config.Dockerfile
		opts.ContextDir = t.config.Context
		return ctx.Client.BuildImage(opts)
	})
}

func (t *Task) commonBuildImageOptions(
	ctx *context.ExecuteContext,
	out io.Writer,
) docker.BuildImageOptions {
	return docker.BuildImageOptions{
		Name:           GetImageName(ctx, t.config),
		BuildArgs:      buildArgs(t.config.Args),
		Target:         t.config.Target,
		Pull:           t.config.PullBaseImageOnBuild,
		NetworkMode:    t.config.NetworkMode,
		CacheFrom:      t.config.CacheFrom,
		RmTmpContainer: true,
		OutputStream:   out,
		RawJSONStream:  true,
		SuppressOutput: ctx.Settings.Quiet,
		AuthConfigs:    ctx.GetAuthConfigs(),
	}
}

func buildArgs(args map[string]string) []docker.BuildArg {
	out := []docker.BuildArg{}
	for key, value := range args {
		out = append(out, docker.BuildArg{Name: key, Value: value})
	}
	return out
}

func (t *Task) buildImageFromSteps(ctx *context.ExecuteContext) error {
	buildContext, dockerfile, err := getBuildContext(t.config)
	if err != nil {
		return err
	}
	return Stream(os.Stdout, func(out io.Writer) error {
		opts := t.commonBuildImageOptions(ctx, out)
		opts.InputStream = buildContext
		opts.Dockerfile = dockerfile
		return ctx.Client.BuildImage(opts)
	})
}

func getBuildContext(config *config.ImageConfig) (io.Reader, string, error) {
	contextDir := config.Context
	excludes, err := build.ReadDockerignore(contextDir)
	if err != nil {
		return nil, "", err
	}
	if err = build.ValidateContextDirectory(contextDir, excludes); err != nil {
		return nil, "", err

	}
	buildCtx, err := archive.TarWithOptions(contextDir, &archive.TarOptions{
		ExcludePatterns: excludes,
	})
	if err != nil {
		return nil, "", err
	}
	dockerfileCtx := ioutil.NopCloser(strings.NewReader(config.Steps))
	return build.AddDockerfileToBuildContext(dockerfileCtx, buildCtx)
}
<|endoftext|>