<commit_before>package rtda

import (
	rtc "github.com/zxh0/jvm.go/jvmgo/jvm/rtda/class"
)

// home for interned Strings
var _stringPool = []StringItem{}

type StringItem struct {
	chars []uint16
	str   *rtc.Obj
}

func getInternedString(chars []uint16) *rtc.Obj {
	index := _binarySearch(chars)
	if index >= 0 {
		return _stringPool[index].str
	} else {
		return nil
	}
}

func InternString(chars []uint16, str *rtc.Obj) *rtc.Obj {
	index := _binarySearch(chars)
	if index >= 0 {
		return _stringPool[index].str
	} else {
		_insert(-index-1, chars, str)
		return str
	}
}

func _binarySearch(chars []uint16) int {
	low := 0
	high := len(_stringPool) - 1

	for low <= high {
		mid := (low + high) / 2
		midVal := _stringPool[mid].chars

		c := _compare(midVal, chars)
		if c < 0 {
			low = mid + 1
		} else if c > 0 {
			high = mid - 1
		} else {
			return mid // key found
		}
	}
	return -(low + 1) // key not found.
}

func _compare(a, b []uint16) int {
	aLen, bLen := len(a), len(b)
	minLen := _min(aLen, bLen)
	for i := 0; i < minLen; i++ {
		x, y := a[i], b[i]
		if x < y {
			return -1
		} else if x > y {
			return 1
		}
	}
	return aLen - bLen
}

func _min(a, b int) int {
	if a <= b {
		return a
	} else {
		return b
	}
}

func _insert(index int, chars []uint16, str *rtc.Obj) {
	poolLen := len(_stringPool)
	if poolLen == cap(_stringPool) {
		_expandPool()
	}

	_stringPool = _stringPool[:poolLen+1]
	src := _stringPool[index:poolLen]
	dst := _stringPool[index+1 : poolLen+1]
	copy(dst, src)

	_stringPool[index] = StringItem{chars, str}
}

func _expandPool() {
	poolLen := len(_stringPool)
	newPool := make([]StringItem, poolLen, poolLen+100)
	copy(newPool, _stringPool) // func copy(dst, src []T) int
	_stringPool = newPool
}
<commit_msg>rename StringItem to PooledString<commit_after>package rtda

import (
	rtc "github.com/zxh0/jvm.go/jvmgo/jvm/rtda/class"
)

// home for interned Strings
var _stringPool = []PooledString{}

type PooledString struct {
	chars []uint16
	str   *rtc.Obj
}

func getInternedString(chars []uint16) *rtc.Obj {
	index := _binarySearch(chars)
	if index >= 0 {
		return _stringPool[index].str
	} else {
		return nil
	}
}

func InternString(chars []uint16, str *rtc.Obj) *rtc.Obj {
	index := _binarySearch(chars)
	if index >= 0 {
		return _stringPool[index].str
	} else {
		_insert(-index-1, chars, str)
		return str
	}
}

func _binarySearch(chars []uint16) int {
	low := 0
	high := len(_stringPool) - 1

	for low <= high {
		mid := (low + high) / 2
		midVal := _stringPool[mid].chars

		c := _compare(midVal, chars)
		if c < 0 {
			low = mid + 1
		} else if c > 0 {
			high = mid - 1
		} else {
			return mid // key found
		}
	}
	return -(low + 1) // key not found.
}

func _compare(a, b []uint16) int {
	aLen, bLen := len(a), len(b)
	minLen := _min(aLen, bLen)
	for i := 0; i < minLen; i++ {
		x, y := a[i], b[i]
		if x < y {
			return -1
		} else if x > y {
			return 1
		}
	}
	return aLen - bLen
}

func _min(a, b int) int {
	if a <= b {
		return a
	} else {
		return b
	}
}

func _insert(index int, chars []uint16, str *rtc.Obj) {
	poolLen := len(_stringPool)
	if poolLen == cap(_stringPool) {
		_expandPool()
	}

	_stringPool = _stringPool[:poolLen+1]
	src := _stringPool[index:poolLen]
	dst := _stringPool[index+1 : poolLen+1]
	copy(dst, src)

	_stringPool[index] = PooledString{chars, str}
}

func _expandPool() {
	poolLen := len(_stringPool)
	newPool := make([]PooledString, poolLen, poolLen+100)
	copy(newPool, _stringPool) // func copy(dst, src []T) int
	_stringPool = newPool
}
<|endoftext|>


<commit_before>package handlers

import (
	"net/http"
	"time"

	"appengine"
	"appengine/user"

	"github.com/icco/natnatnat/models"
	"github.com/pilu/traffic"
)

type RootData struct {
	Posts   interface{}
	IsAdmin bool
}

func RootHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	entries, err := models.AllPosts(c)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	data := &RootData{Posts: entries, IsAdmin: user.IsAdmin(c)}
	w.Render("index", data)
}

func AboutHandler(w traffic.ResponseWriter, r *traffic.Request) {
	http.Redirect(w, r.Request, "http://natwelch.com", 301)
}

func UnimplementedHandler(w traffic.ResponseWriter, r *traffic.Request) {
	http.Error(w, "Sorry, I haven't implemented this yet", 500)
}

func MarkdownHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)

	in := r.Param("text")
	md := models.Markdown(in)

	c.Infof("Markdown Recieved: %s", in)
	c.Infof("Markdown Rendered: %s", md)
	w.WriteText(string(md))
}

type ArchiveData struct {
	Years   map[int]Year
	IsAdmin bool
}

// TODO(icco): Rewrite to fix map iteration problems.
type Year map[time.Month]Month
type Month map[int]Day
type Day []models.Entry

func ArchiveHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	entries, err := models.Posts(c, -1, false)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	years := make(map[int]Year)

	for _, p := range *entries {
		year := p.Datetime.Year()
		month := p.Datetime.Month()
		day := p.Datetime.Day()

		if years[year] == nil {
			years[year] = make(Year)
		}

		if years[year][month] == nil {
			years[year][month] = make(Month)
		}

		if years[year][month][day] == nil {
			years[year][month][day] = make(Day, 0)
		}

		years[year][month][day] = append(years[year][month][day], p)
	}

	data := &ArchiveData{Years: years, IsAdmin: user.IsAdmin(c)}
	w.Render("archive", data)
}
<commit_msg>attempt to fix md<commit_after>package handlers

import (
	"net/http"
	"time"

	"appengine"
	"appengine/user"

	"github.com/icco/natnatnat/models"
	"github.com/pilu/traffic"
)

type RootData struct {
	Posts   interface{}
	IsAdmin bool
}

func RootHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	entries, err := models.AllPosts(c)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	data := &RootData{Posts: entries, IsAdmin: user.IsAdmin(c)}
	w.Render("index", data)
}

func AboutHandler(w traffic.ResponseWriter, r *traffic.Request) {
	http.Redirect(w, r.Request, "http://natwelch.com", 301)
}

func UnimplementedHandler(w traffic.ResponseWriter, r *traffic.Request) {
	http.Error(w, "Sorry, I haven't implemented this yet", 500)
}

func MarkdownHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)

	err := r.ParseForm()
	if err != nil {
		c.Warningf("Couldn't parse form: %v", r)
		http.Error(w, "Unable to parse request.", 500)
		return
	}

	in := r.Request.FormValue("text")
	md := models.Markdown(in)

	c.Infof("Markdown Recieved: %s", in)
	c.Infof("Markdown Rendered: %s", md)
	w.WriteText(string(md))
}

type ArchiveData struct {
	Years   map[int]Year
	IsAdmin bool
}

// TODO(icco): Rewrite to fix map iteration problems.
type Year map[time.Month]Month
type Month map[int]Day
type Day []models.Entry

func ArchiveHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	entries, err := models.Posts(c, -1, false)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	years := make(map[int]Year)

	for _, p := range *entries {
		year := p.Datetime.Year()
		month := p.Datetime.Month()
		day := p.Datetime.Day()

		if years[year] == nil {
			years[year] = make(Year)
		}

		if years[year][month] == nil {
			years[year][month] = make(Month)
		}

		if years[year][month][day] == nil {
			years[year][month][day] = make(Day, 0)
		}

		years[year][month][day] = append(years[year][month][day], p)
	}

	data := &ArchiveData{Years: years, IsAdmin: user.IsAdmin(c)}
	w.Render("archive", data)
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.

// load is an example client of the bigquery client library.
// It loads a file from Google Cloud Storage into a BigQuery table.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"time"

	"cloud.google.com/go/bigquery"
	"golang.org/x/net/context"
)

var (
	project  = flag.String("project", "", "The ID of a Google Cloud Platform project")
	dataset  = flag.String("dataset", "", "The ID of a BigQuery dataset")
	table    = flag.String("table", "", "The ID of a BigQuery table to load data into")
	bucket   = flag.String("bucket", "", "The name of a Google Cloud Storage bucket to load data from")
	object   = flag.String("object", "", "The name of a Google Cloud Storage object to load data from. Must exist within the bucket specified by --bucket")
	skiprows = flag.Int64("skiprows", 0, "The number of rows of the source data to skip when loading")
	pollint  = flag.Duration("pollint", 10*time.Second, "Polling interval for checking job status")
)

func main() {
	flag.Parse()

	flagsOk := true
	for _, f := range []string{"project", "dataset", "table", "bucket", "object"} {
		if flag.Lookup(f).Value.String() == "" {
			fmt.Fprintf(os.Stderr, "Flag --%s is required\n", f)
			flagsOk = false
		}
	}
	if !flagsOk {
		os.Exit(1)
	}

	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, *project)
	if err != nil {
		log.Fatalf("Creating bigquery client: %v", err)
	}

	table := client.Dataset(*dataset).Table(*table)

	gcs := client.NewGCSReference(fmt.Sprintf("gs://%s/%s", *bucket, *object))
	gcs.SkipLeadingRows = *skiprows

	// Load data from Google Cloud Storage into a BigQuery table.
	job, err := client.Copy(
		ctx, table, gcs,
		bigquery.MaxBadRecords(1),
		bigquery.AllowQuotedNewlines(),
		bigquery.WriteTruncate)

	if err != nil {
		log.Fatalf("Loading data: %v", err)
	}

	fmt.Printf("Job for data load operation: %+v\n", job)
	fmt.Printf("Waiting for job to complete.\n")

	for range time.Tick(*pollint) {
		status, err := job.Status(ctx)
		if err != nil {
			fmt.Printf("Failure determining status: %v", err)
			break
		}
		if !status.Done() {
			continue
		}
		if err := status.Err(); err == nil {
			fmt.Printf("Success\n")
		} else {
			fmt.Printf("Failure: %+v\n", err)
		}
		break
	}
}
<commit_msg>bigquery: update example to use Loader.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.

// load is an example client of the bigquery client library.
// It loads a file from Google Cloud Storage into a BigQuery table.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"time"

	"cloud.google.com/go/bigquery"
	"golang.org/x/net/context"
)

var (
	project  = flag.String("project", "", "The ID of a Google Cloud Platform project")
	dataset  = flag.String("dataset", "", "The ID of a BigQuery dataset")
	table    = flag.String("table", "", "The ID of a BigQuery table to load data into")
	bucket   = flag.String("bucket", "", "The name of a Google Cloud Storage bucket to load data from")
	object   = flag.String("object", "", "The name of a Google Cloud Storage object to load data from. Must exist within the bucket specified by --bucket")
	skiprows = flag.Int64("skiprows", 0, "The number of rows of the source data to skip when loading")
	pollint  = flag.Duration("pollint", 10*time.Second, "Polling interval for checking job status")
)

func main() {
	flag.Parse()

	flagsOk := true
	for _, f := range []string{"project", "dataset", "table", "bucket", "object"} {
		if flag.Lookup(f).Value.String() == "" {
			fmt.Fprintf(os.Stderr, "Flag --%s is required\n", f)
			flagsOk = false
		}
	}
	if !flagsOk {
		os.Exit(1)
	}

	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, *project)
	if err != nil {
		log.Fatalf("Creating bigquery client: %v", err)
	}

	table := client.Dataset(*dataset).Table(*table)

	gcs := client.NewGCSReference(fmt.Sprintf("gs://%s/%s", *bucket, *object))
	gcs.SkipLeadingRows = *skiprows
	gcs.MaxBadRecords = 1
	gcs.AllowQuotedNewlines = true

	// Load data from Google Cloud Storage into a BigQuery table.
	loader := table.LoaderFrom(gcs)
	loader.TableWriteDisposition = bigquery.WriteTruncate
	job, err := loader.Run(ctx)

	if err != nil {
		log.Fatalf("Loading data: %v", err)
	}

	fmt.Printf("Job for data load operation: %+v\n", job)
	fmt.Printf("Waiting for job to complete.\n")

	for range time.Tick(*pollint) {
		status, err := job.Status(ctx)
		if err != nil {
			fmt.Printf("Failure determining status: %v", err)
			break
		}
		if !status.Done() {
			continue
		}
		if err := status.Err(); err == nil {
			fmt.Printf("Success\n")
		} else {
			fmt.Printf("Failure: %+v\n", err)
		}
		break
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014, Yawning Angel <yawning at torproject dot org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

// Go language Tor Pluggable Transport suite.  Works only as a managed
// client/server.
package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/url"
	"os"
	"os/signal"
	"path"
	"sync"
	"syscall"

	"code.google.com/p/go.net/proxy"

	"git.torproject.org/pluggable-transports/goptlib.git"
	"git.torproject.org/pluggable-transports/obfs4.git/transports"
	"git.torproject.org/pluggable-transports/obfs4.git/transports/base"
)

const (
	obfs4proxyLogFile = "obfs4proxy.log"
	socksAddr         = "127.0.0.1:0"
	elidedAddr        = "[scrubbed]"
)

var enableLogging bool
var unsafeLogging bool
var stateDir string
var handlerChan chan int

// DialFn is a function pointer to a function that matches the net.Dialer.Dial
// interface.
type DialFn func(string, string) (net.Conn, error)

func elideAddr(addrStr string) string {
	if unsafeLogging {
		return addrStr
	}

	if addr, err := resolveAddrStr(addrStr); err == nil {
		// Only scrub off the address so that it's slightly easier to follow
		// the logs by looking at the port.
		return fmt.Sprintf("%s:%d", elidedAddr, addr.Port)
	}

	return elidedAddr
}

func clientSetup() (launched bool, listeners []net.Listener) {
	ptClientInfo, err := pt.ClientSetup(transports.Transports())
	if err != nil {
		log.Fatal(err)
	}

	ptClientProxy, err := ptGetProxy()
	if err != nil {
		log.Fatal(err)
	} else if ptClientProxy != nil {
		ptProxyDone()
	}

	// Launch each of the client listeners.
	for _, name := range ptClientInfo.MethodNames {
		t := transports.Get(name)
		if t == nil {
			pt.CmethodError(name, "no such transport is supported")
			continue
		}

		f, err := t.ClientFactory(stateDir)
		if err != nil {
			pt.CmethodError(name, "failed to get ClientFactory")
			continue
		}

		ln, err := pt.ListenSocks("tcp", socksAddr)
		if err != nil {
			pt.CmethodError(name, err.Error())
			continue
		}

		go clientAcceptLoop(f, ln, ptClientProxy)
		pt.Cmethod(name, ln.Version(), ln.Addr())

		log.Printf("[INFO]: %s - registered listener: %s", name, ln.Addr())

		listeners = append(listeners, ln)
		launched = true
	}
	pt.CmethodsDone()

	return
}

func clientAcceptLoop(f base.ClientFactory, ln *pt.SocksListener, proxyURI *url.URL) error {
	defer ln.Close()
	for {
		conn, err := ln.AcceptSocks()
		if err != nil {
			if e, ok := err.(net.Error); ok && !e.Temporary() {
				return err
			}
			continue
		}
		go clientHandler(f, conn, proxyURI)
	}
}

func clientHandler(f base.ClientFactory, conn *pt.SocksConn, proxyURI *url.URL) {
	defer conn.Close()
	handlerChan <- 1
	defer func() {
		handlerChan <- -1
	}()

	name := f.Transport().Name()
	addrStr := elideAddr(conn.Req.Target)
	log.Printf("[INFO]: %s(%s) - new connection", name, addrStr)

	// Deal with arguments.
	args, err := f.ParseArgs(&conn.Req.Args)
	if err != nil {
		log.Printf("[ERROR]: %s(%s) - invalid arguments: %s", name, addrStr, err)
		conn.Reject()
		return
	}

	// Obtain the proxy dialer if any, and create the outgoing TCP connection.
	var dialFn DialFn
	if proxyURI == nil {
		dialFn = proxy.Direct.Dial
	} else {
		// This is unlikely to happen as the proxy protocol is verified during
		// the configuration phase.
		dialer, err := proxy.FromURL(proxyURI, proxy.Direct)
		if err != nil {
			log.Printf("[ERROR]: %s(%s) - failed to obtain proxy dialer: %s", name, addrStr, err)
			conn.Reject()
			return
		}
		dialFn = dialer.Dial
	}
	remoteConn, err := dialFn("tcp", conn.Req.Target) // XXX: Allow UDP?
	if err != nil {
		// Note: The error message returned from the dialer can include the IP
		// address/port of the remote peer.
		if unsafeLogging {
			log.Printf("[ERROR]: %s(%s) - outgoing connection failed: %s", name, addrStr, err)
		} else {
			log.Printf("[ERROR]: %s(%s) - outgoing connection failed", name, addrStr)
		}
		conn.Reject()
		return
	}
	defer remoteConn.Close()

	// Instantiate the client transport method, handshake, and start pushing
	// bytes back and forth.
	remote, err := f.WrapConn(remoteConn, args)
	if err != nil {
		log.Printf("[ERROR]: %s(%s) - handshake failed: %s", name, addrStr, err)
		conn.Reject()
		return
	}
	err = conn.Grant(remoteConn.RemoteAddr().(*net.TCPAddr))
	if err != nil {
		log.Printf("[ERROR]: %s(%s) - SOCKS grant failed: %s", name, addrStr, err)
		return
	}

	err = copyLoop(conn, remote)
	if err != nil {
		log.Printf("[INFO]: %s(%s) - closed connection: %s", name, addrStr, err)
	} else {
		log.Printf("[INFO]: %s(%s) - closed connection", name, addrStr)
	}

	return
}

func serverSetup() (launched bool, listeners []net.Listener) {
	ptServerInfo, err := pt.ServerSetup(transports.Transports())
	if err != nil {
		log.Fatal(err)
	}

	for _, bindaddr := range ptServerInfo.Bindaddrs {
		name := bindaddr.MethodName
		t := transports.Get(name)
		if t == nil {
			pt.SmethodError(name, "no such transport is supported")
			continue
		}

		f, err := t.ServerFactory(stateDir, &bindaddr.Options)
		if err != nil {
			pt.SmethodError(name, err.Error())
			continue
		}

		ln, err := net.ListenTCP("tcp", bindaddr.Addr)
		if err != nil {
			pt.SmethodError(name, err.Error())
			continue
		}

		go serverAcceptLoop(f, ln, &ptServerInfo)
		if args := f.Args(); args != nil {
			pt.SmethodArgs(name, ln.Addr(), *args)
		} else {
			pt.SmethodArgs(name, ln.Addr(), nil)
		}

		log.Printf("[INFO]: %s - registered listener: %s", name, elideAddr(ln.Addr().String()))

		listeners = append(listeners, ln)
		launched = true
	}
	pt.SmethodsDone()

	return
}

func serverAcceptLoop(f base.ServerFactory, ln net.Listener, info *pt.ServerInfo) error {
	defer ln.Close()
	for {
		conn, err := ln.Accept()
		if err != nil {
			if e, ok := err.(net.Error); ok && !e.Temporary() {
				return err
			}
			continue
		}
		go serverHandler(f, conn, info)
	}
}

func serverHandler(f base.ServerFactory, conn net.Conn, info *pt.ServerInfo) {
	defer conn.Close()
	handlerChan <- 1
	defer func() {
		handlerChan <- -1
	}()

	name := f.Transport().Name()
	addrStr := elideAddr(conn.RemoteAddr().String())
	log.Printf("[INFO]: %s(%s) - new connection", name, addrStr)

	// Instantiate the server transport method and handshake.
	remote, err := f.WrapConn(conn)
	if err != nil {
		log.Printf("[ERROR]: %s(%s) - handshake failed: %s", name, addrStr, err)
		return
	}

	// Connect to the orport.
	orConn, err := pt.DialOr(info, conn.RemoteAddr().String(), name)
	if err != nil {
		log.Printf("[ERROR]: %s(%s) - failed to connect to ORPort: %s", name, addrStr, err)
		return
	}
	defer orConn.Close()

	err = copyLoop(orConn, remote)
	if err != nil {
		log.Printf("[INFO]: %s(%s) - closed connection: %s", name, addrStr, err)
	} else {
		log.Printf("[INFO]: %s(%s) - closed connection", name, addrStr)
	}

	return
}

func copyLoop(a net.Conn, b net.Conn) error {
	// Note: b is always the pt connection.  a is the SOCKS/ORPort connection.
	errChan := make(chan error, 2)

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()
		defer b.Close()
		defer a.Close()
		_, err := io.Copy(b, a)
		errChan <- err
	}()
	go func() {
		defer wg.Done()
		defer a.Close()
		defer b.Close()
		_, err := io.Copy(a, b)
		errChan <- err
	}()

	// Wait for both upstream and downstream to close.  Since one side
	// terminating closes the other, the second error in the channel will be
	// something like EINVAL (though io.Copy() will swallow EOF), so only the
	// first error is returned.
	wg.Wait()
	if len(errChan) > 0 {
		return <-errChan
	}

	return nil
}

func ptInitializeLogging(enable bool) error {
	if enable {
		// While we could just exit, log an ENV-ERROR so it will propagate to
		// the tor log.
		f, err := os.OpenFile(path.Join(stateDir, obfs4proxyLogFile), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
		if err != nil {
			return ptEnvError(fmt.Sprintf("failed to open log file: %s\n", err))
		}
		log.SetOutput(f)
	} else {
		log.SetOutput(ioutil.Discard)
	}

	return nil
}

func main() {
	// Handle the command line arguments.
	_, execName := path.Split(os.Args[0])
	flag.BoolVar(&enableLogging, "enableLogging", false, "Log to TOR_PT_STATE_LOCATION/"+obfs4proxyLogFile)
	flag.BoolVar(&unsafeLogging, "unsafeLogging", false, "Disable the address scrubber")
	flag.Parse()

	// Determine if this is a client or server, initialize logging, and finish
	// the pt configuration.
	var ptListeners []net.Listener
	handlerChan = make(chan int)
	launched := false
	isClient, err := ptIsClient()
	if err != nil {
		log.Fatalf("[ERROR]: %s - must be run as a managed transport", execName)
	}
	if stateDir, err = pt.MakeStateDir(); err != nil {
		log.Fatalf("[ERROR]: %s - No state directory: %s", execName, err)
	}
	if err = ptInitializeLogging(enableLogging); err != nil {
		log.Fatalf("[ERROR]: %s - failed to initialize logging", execName)
	}
	if isClient {
		log.Printf("[INFO]: %s - initializing client transport listeners", execName)
		launched, ptListeners = clientSetup()
	} else {
		log.Printf("[INFO]: %s - initializing server transport listeners", execName)
		launched, ptListeners = serverSetup()
	}
	if !launched {
		// Initialization failed, the client or server setup routines should
		// have logged, so just exit here.
		os.Exit(-1)
	}

	log.Printf("[INFO]: %s - launched and accepting connections", execName)
	defer func() {
		log.Printf("[INFO]: %s - terminated", execName)
	}()

	// At this point, the pt config protocol is finished, and incoming
	// connections will be processed.  Per the pt spec, on sane platforms
	// termination is signaled via SIGINT (or SIGTERM), so wait on tor to
	// request a shutdown of some sort.

	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	// Wait for the first SIGINT (close listeners).
	var sig os.Signal
	numHandlers := 0
	for sig == nil {
		select {
		case n := <-handlerChan:
			numHandlers += n
		case sig = <-sigChan:
			if sig == syscall.SIGTERM {
				// SIGTERM causes immediate termination.
				return
			}
		}
	}
	for _, ln := range ptListeners {
		ln.Close()
	}

	// Wait for the 2nd SIGINT (or a SIGTERM), or for all current sessions to
	// finish.
	sig = nil
	for sig == nil && numHandlers != 0 {
		select {
		case n := <-handlerChan:
			numHandlers += n
		case sig = <-sigChan:
		}
	}
}
<commit_msg>Elide the error out from most logs unless unsafeLogging is set.<commit_after>/*
 * Copyright (c) 2014, Yawning Angel <yawning at torproject dot org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

// Go language Tor Pluggable Transport suite.  Works only as a managed
// client/server.
package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/url"
	"os"
	"os/signal"
	"path"
	"sync"
	"syscall"

	"code.google.com/p/go.net/proxy"

	"git.torproject.org/pluggable-transports/goptlib.git"
	"git.torproject.org/pluggable-transports/obfs4.git/transports"
	"git.torproject.org/pluggable-transports/obfs4.git/transports/base"
)

const (
	obfs4proxyLogFile = "obfs4proxy.log"
	socksAddr         = "127.0.0.1:0"
	elidedAddr        = "[scrubbed]"
)

var enableLogging bool
var unsafeLogging bool
var stateDir string
var handlerChan chan int

// DialFn is a function pointer to a function that matches the net.Dialer.Dial
// interface.
type DialFn func(string, string) (net.Conn, error)

func elideAddr(addrStr string) string {
	if unsafeLogging {
		return addrStr
	}

	if addr, err := resolveAddrStr(addrStr); err == nil {
		// Only scrub off the address so that it's slightly easier to follow
		// the logs by looking at the port.
		return fmt.Sprintf("%s:%d", elidedAddr, addr.Port)
	}

	return elidedAddr
}

func clientSetup() (launched bool, listeners []net.Listener) {
	ptClientInfo, err := pt.ClientSetup(transports.Transports())
	if err != nil {
		log.Fatal(err)
	}

	ptClientProxy, err := ptGetProxy()
	if err != nil {
		log.Fatal(err)
	} else if ptClientProxy != nil {
		ptProxyDone()
	}

	// Launch each of the client listeners.
	for _, name := range ptClientInfo.MethodNames {
		t := transports.Get(name)
		if t == nil {
			pt.CmethodError(name, "no such transport is supported")
			continue
		}

		f, err := t.ClientFactory(stateDir)
		if err != nil {
			pt.CmethodError(name, "failed to get ClientFactory")
			continue
		}

		ln, err := pt.ListenSocks("tcp", socksAddr)
		if err != nil {
			pt.CmethodError(name, err.Error())
			continue
		}

		go clientAcceptLoop(f, ln, ptClientProxy)
		pt.Cmethod(name, ln.Version(), ln.Addr())

		log.Printf("[INFO]: %s - registered listener: %s", name, ln.Addr())

		listeners = append(listeners, ln)
		launched = true
	}
	pt.CmethodsDone()

	return
}

func clientAcceptLoop(f base.ClientFactory, ln *pt.SocksListener, proxyURI *url.URL) error {
	defer ln.Close()
	for {
		conn, err := ln.AcceptSocks()
		if err != nil {
			if e, ok := err.(net.Error); ok && !e.Temporary() {
				return err
			}
			continue
		}
		go clientHandler(f, conn, proxyURI)
	}
}

func clientHandler(f base.ClientFactory, conn *pt.SocksConn, proxyURI *url.URL) {
	defer conn.Close()
	handlerChan <- 1
	defer func() {
		handlerChan <- -1
	}()

	name := f.Transport().Name()
	addrStr := elideAddr(conn.Req.Target)
	log.Printf("[INFO]: %s(%s) - new connection", name, addrStr)

	// Deal with arguments.
	args, err := f.ParseArgs(&conn.Req.Args)
	if err != nil {
		log.Printf("[ERROR]: %s(%s) - invalid arguments: %s", name, addrStr, err)
		conn.Reject()
		return
	}

	// Obtain the proxy dialer if any, and create the outgoing TCP connection.
	var dialFn DialFn
	if proxyURI == nil {
		dialFn = proxy.Direct.Dial
	} else {
		// This is unlikely to happen as the proxy protocol is verified during
		// the configuration phase.
		dialer, err := proxy.FromURL(proxyURI, proxy.Direct)
		if err != nil {
			if unsafeLogging {
				log.Printf("[ERROR]: %s(%s) - failed to obtain proxy dialer: %s", name, addrStr, err)
			} else {
				log.Printf("[ERROR]: %s(%s) - failed to obtain proxy dialer", name, addrStr)
			}
			conn.Reject()
			return
		}
		dialFn = dialer.Dial
	}
	remoteConn, err := dialFn("tcp", conn.Req.Target) // XXX: Allow UDP?
	if err != nil {
		// Note: The error message returned from the dialer can include the IP
		// address/port of the remote peer.
		if unsafeLogging {
			log.Printf("[ERROR]: %s(%s) - outgoing connection failed: %s", name, addrStr, err)
		} else {
			log.Printf("[ERROR]: %s(%s) - outgoing connection failed", name, addrStr)
		}
		conn.Reject()
		return
	}
	defer remoteConn.Close()

	// Instantiate the client transport method, handshake, and start pushing
	// bytes back and forth.
	remote, err := f.WrapConn(remoteConn, args)
	if err != nil {
		if unsafeLogging {
			log.Printf("[ERROR]: %s(%s) - handshake failed: %s", name, addrStr, err)
		} else {
			log.Printf("[ERROR]: %s(%s) - handshake failed", name, addrStr)
		}
		conn.Reject()
		return
	}
	err = conn.Grant(remoteConn.RemoteAddr().(*net.TCPAddr))
	if err != nil {
		if unsafeLogging {
			log.Printf("[ERROR]: %s(%s) - SOCKS grant failed: %s", name, addrStr, err)
		} else {
			log.Printf("[ERROR]: %s(%s) - SOCKS grant failed", name, addrStr)
		}
		return
	}

	err = copyLoop(conn, remote)
	if err != nil && unsafeLogging {
		log.Printf("[INFO]: %s(%s) - closed connection: %s", name, addrStr, err)
	} else {
		log.Printf("[INFO]: %s(%s) - closed connection", name, addrStr)
	}

	return
}

func serverSetup() (launched bool, listeners []net.Listener) {
	ptServerInfo, err := pt.ServerSetup(transports.Transports())
	if err != nil {
		log.Fatal(err)
	}

	for _, bindaddr := range ptServerInfo.Bindaddrs {
		name := bindaddr.MethodName
		t := transports.Get(name)
		if t == nil {
			pt.SmethodError(name, "no such transport is supported")
			continue
		}

		f, err := t.ServerFactory(stateDir, &bindaddr.Options)
		if err != nil {
			pt.SmethodError(name, err.Error())
			continue
		}

		ln, err := net.ListenTCP("tcp", bindaddr.Addr)
		if err != nil {
			pt.SmethodError(name, err.Error())
			continue
		}

		go serverAcceptLoop(f, ln, &ptServerInfo)
		if args := f.Args(); args != nil {
			pt.SmethodArgs(name, ln.Addr(), *args)
		} else {
			pt.SmethodArgs(name, ln.Addr(), nil)
		}

		log.Printf("[INFO]: %s - registered listener: %s", name, elideAddr(ln.Addr().String()))

		listeners = append(listeners, ln)
		launched = true
	}
	pt.SmethodsDone()

	return
}

func serverAcceptLoop(f base.ServerFactory, ln net.Listener, info *pt.ServerInfo) error {
	defer ln.Close()
	for {
		conn, err := ln.Accept()
		if err != nil {
			if e, ok := err.(net.Error); ok && !e.Temporary() {
				return err
			}
			continue
		}
		go serverHandler(f, conn, info)
	}
}

func serverHandler(f base.ServerFactory, conn net.Conn, info *pt.ServerInfo) {
	defer conn.Close()
	handlerChan <- 1
	defer func() {
		handlerChan <- -1
	}()

	name := f.Transport().Name()
	addrStr := elideAddr(conn.RemoteAddr().String())
	log.Printf("[INFO]: %s(%s) - new connection", name, addrStr)

	// Instantiate the server transport method and handshake.
	remote, err := f.WrapConn(conn)
	if err != nil {
		if unsafeLogging {
			log.Printf("[ERROR]: %s(%s) - handshake failed: %s", name, addrStr, err)
		} else {
			log.Printf("[ERROR]: %s(%s) - handshake failed", name, addrStr)
		}
		return
	}

	// Connect to the orport.
	orConn, err := pt.DialOr(info, conn.RemoteAddr().String(), name)
	if err != nil {
		if unsafeLogging {
			log.Printf("[ERROR]: %s(%s) - failed to connect to ORPort: %s", name, addrStr, err)
		} else {
			log.Printf("[ERROR]: %s(%s) - failed to connect to ORPort", name, addrStr)
		}
		return
	}
	defer orConn.Close()

	err = copyLoop(orConn, remote)
	if err != nil && unsafeLogging {
		log.Printf("[INFO]: %s(%s) - closed connection: %s", name, addrStr, err)
	} else {
		log.Printf("[INFO]: %s(%s) - closed connection", name, addrStr)
	}

	return
}

func copyLoop(a net.Conn, b net.Conn) error {
	// Note: b is always the pt connection.  a is the SOCKS/ORPort connection.
	errChan := make(chan error, 2)

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()
		defer b.Close()
		defer a.Close()
		_, err := io.Copy(b, a)
		errChan <- err
	}()
	go func() {
		defer wg.Done()
		defer a.Close()
		defer b.Close()
		_, err := io.Copy(a, b)
		errChan <- err
	}()

	// Wait for both upstream and downstream to close.  Since one side
	// terminating closes the other, the second error in the channel will be
	// something like EINVAL (though io.Copy() will swallow EOF), so only the
	// first error is returned.
	wg.Wait()
	if len(errChan) > 0 {
		return <-errChan
	}

	return nil
}

func ptInitializeLogging(enable bool) error {
	if enable {
		// While we could just exit, log an ENV-ERROR so it will propagate to
		// the tor log.
		f, err := os.OpenFile(path.Join(stateDir, obfs4proxyLogFile), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
		if err != nil {
			return ptEnvError(fmt.Sprintf("failed to open log file: %s\n", err))
		}
		log.SetOutput(f)
	} else {
		log.SetOutput(ioutil.Discard)
	}

	return nil
}

func main() {
	// Handle the command line arguments.
	_, execName := path.Split(os.Args[0])
	flag.BoolVar(&enableLogging, "enableLogging", false, "Log to TOR_PT_STATE_LOCATION/"+obfs4proxyLogFile)
	flag.BoolVar(&unsafeLogging, "unsafeLogging", false, "Disable the address scrubber")
	flag.Parse()

	// Determine if this is a client or server, initialize logging, and finish
	// the pt configuration.
	var ptListeners []net.Listener
	handlerChan = make(chan int)
	launched := false
	isClient, err := ptIsClient()
	if err != nil {
		log.Fatalf("[ERROR]: %s - must be run as a managed transport", execName)
	}
	if stateDir, err = pt.MakeStateDir(); err != nil {
		log.Fatalf("[ERROR]: %s - No state directory: %s", execName, err)
	}
	if err = ptInitializeLogging(enableLogging); err != nil {
		log.Fatalf("[ERROR]: %s - failed to initialize logging", execName)
	}
	if isClient {
		log.Printf("[INFO]: %s - initializing client transport listeners", execName)
		launched, ptListeners = clientSetup()
	} else {
		log.Printf("[INFO]: %s - initializing server transport listeners", execName)
		launched, ptListeners = serverSetup()
	}
	if !launched {
		// Initialization failed, the client or server setup routines should
		// have logged, so just exit here.
		os.Exit(-1)
	}

	log.Printf("[INFO]: %s - launched and accepting connections", execName)
	defer func() {
		log.Printf("[INFO]: %s - terminated", execName)
	}()

	// At this point, the pt config protocol is finished, and incoming
	// connections will be processed.  Per the pt spec, on sane platforms
	// termination is signaled via SIGINT (or SIGTERM), so wait on tor to
	// request a shutdown of some sort.

	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	// Wait for the first SIGINT (close listeners).
	var sig os.Signal
	numHandlers := 0
	for sig == nil {
		select {
		case n := <-handlerChan:
			numHandlers += n
		case sig = <-sigChan:
			if sig == syscall.SIGTERM {
				// SIGTERM causes immediate termination.
				return
			}
		}
	}
	for _, ln := range ptListeners {
		ln.Close()
	}

	// Wait for the 2nd SIGINT (or a SIGTERM), or for all current sessions to
	// finish.
	sig = nil
	for sig == nil && numHandlers != 0 {
		select {
		case n := <-handlerChan:
			numHandlers += n
		case sig = <-sigChan:
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0

package oci

import (
	"context"

	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"

	oci_core "github.com/oracle/oci-go-sdk/v28/core"
)

func init() {
	RegisterResource("oci_core_vcn", CoreVcnResource())
}

func CoreVcnResource() *schema.Resource {
	return &schema.Resource{
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		Timeouts: DefaultTimeout,
		Create:   createCoreVcn,
		Read:     readCoreVcn,
		Update:   updateCoreVcn,
		Delete:   deleteCoreVcn,
		Schema: map[string]*schema.Schema{
			// Required
			"compartment_id": {
				Type:     schema.TypeString,
				Required: true,
			},

			// Optional
			"cidr_block": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},
			"cidr_blocks": {
				Type:     schema.TypeList,
				Optional: true,
				Computed: true,
				ForceNew: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},
			"defined_tags": {
				Type:             schema.TypeMap,
				Optional:         true,
				Computed:         true,
				DiffSuppressFunc: definedTagsDiffSuppressFunction,
				Elem:             schema.TypeString,
			},
			"display_name": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"dns_label": {
				Type:             schema.TypeString,
				Optional:         true,
				Computed:         true,
				ForceNew:         true,
				DiffSuppressFunc: EqualIgnoreCaseSuppressDiff,
			},
			"freeform_tags": {
				Type:     schema.TypeMap,
				Optional: true,
				Computed: true,
				Elem:     schema.TypeString,
			},
			"ipv6cidr_block": {
				Type:             schema.TypeString,
				Optional:         true,
				Computed:         true,
				ForceNew:         true,
				DiffSuppressFunc: ipv6CompressionDiffSuppressFunction,
			},
			"is_ipv6enabled": {
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			// Computed
			"default_dhcp_options_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"default_route_table_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"default_security_list_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"ipv6public_cidr_block": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"state": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"time_created": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"vcn_domain_name": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func createCoreVcn(d *schema.ResourceData, m interface{}) error {
	sync := &CoreVcnResourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).virtualNetworkClient()

	return CreateResource(d, sync)
}

func readCoreVcn(d *schema.ResourceData, m interface{}) error {
	sync := &CoreVcnResourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).virtualNetworkClient()

	return ReadResource(sync)
}

func updateCoreVcn(d *schema.ResourceData, m interface{}) error {
	sync := &CoreVcnResourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).virtualNetworkClient()

	return UpdateResource(d, sync)
}

func deleteCoreVcn(d *schema.ResourceData, m interface{}) error {
	sync := &CoreVcnResourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).virtualNetworkClient()
	sync.DisableNotFoundRetries = true

	return DeleteResource(d, sync)
}

type CoreVcnResourceCrud struct {
	BaseCrud
	Client                 *oci_core.VirtualNetworkClient
	Res                    *oci_core.Vcn
	DisableNotFoundRetries bool
}

func (s *CoreVcnResourceCrud) ID() string {
	return *s.Res.Id
}

func (s *CoreVcnResourceCrud) CreatedPending() []string {
	return []string{
		string(oci_core.VcnLifecycleStateProvisioning),
	}
}

func (s *CoreVcnResourceCrud) CreatedTarget() []string {
	return []string{
		string(oci_core.VcnLifecycleStateAvailable),
	}
}

func (s *CoreVcnResourceCrud) DeletedPending() []string {
	return []string{
		string(oci_core.VcnLifecycleStateTerminating),
	}
}

func (s *CoreVcnResourceCrud) DeletedTarget() []string {
	return []string{
		string(oci_core.VcnLifecycleStateTerminated),
	}
}

func (s *CoreVcnResourceCrud) Create() error {
	request := oci_core.CreateVcnRequest{}

	if cidrBlock, ok := s.D.GetOkExists("cidr_block"); ok {
		tmp := cidrBlock.(string)
		request.CidrBlock = &tmp
	}

	if cidrBlocks, ok := s.D.GetOkExists("cidr_blocks"); ok {
		interfaces := cidrBlocks.([]interface{})
		tmp := make([]string, len(interfaces))
		for i := range interfaces {
			if interfaces[i] != nil {
				tmp[i] = interfaces[i].(string)
			}
		}
		if len(tmp) != 0 || s.D.HasChange("cidr_blocks") {
			request.CidrBlocks = tmp
		}
	}

	if compartmentId, ok := s.D.GetOkExists("compartment_id"); ok {
		tmp := compartmentId.(string)
		request.CompartmentId = &tmp
	}

	if definedTags, ok := s.D.GetOkExists("defined_tags"); ok {
		convertedDefinedTags, err := mapToDefinedTags(definedTags.(map[string]interface{}))
		if err != nil {
			return err
		}
		request.DefinedTags = convertedDefinedTags
	}

	if displayName, ok := s.D.GetOkExists("display_name"); ok {
		tmp := displayName.(string)
		request.DisplayName = &tmp
	}

	if dnsLabel, ok := s.D.GetOkExists("dns_label"); ok {
		tmp := dnsLabel.(string)
		request.DnsLabel = &tmp
	}

	if freeformTags, ok := s.D.GetOkExists("freeform_tags"); ok {
		request.FreeformTags = objectMapToStringMap(freeformTags.(map[string]interface{}))
	}

	if ipv6CidrBlock, ok := s.D.GetOkExists("ipv6cidr_block"); ok {
		tmp := ipv6CidrBlock.(string)
		request.Ipv6CidrBlock = &tmp
	}

	if isIpv6Enabled, ok := s.D.GetOkExists("is_ipv6enabled"); ok {
		tmp := isIpv6Enabled.(bool)
		request.IsIpv6Enabled = &tmp
	}

	request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	response, err := s.Client.CreateVcn(context.Background(), request)
	if err != nil {
		return err
	}

	s.Res = &response.Vcn
	return nil
}

func (s *CoreVcnResourceCrud) Get() error {
	request := oci_core.GetVcnRequest{}

	tmp := s.D.Id()
	request.VcnId = &tmp

	request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	response, err := s.Client.GetVcn(context.Background(), request)
	if err != nil {
		return err
	}

	s.Res = &response.Vcn
	return nil
}

func (s *CoreVcnResourceCrud) Update() error {
	if compartment, ok := s.D.GetOkExists("compartment_id"); ok && s.D.HasChange("compartment_id") {
		oldRaw, newRaw := s.D.GetChange("compartment_id")
		if newRaw != "" && oldRaw != "" {
			err := s.updateCompartment(compartment)
			if err != nil {
				return err
			}
		}
	}
	request := oci_core.UpdateVcnRequest{}

	if definedTags, ok := s.D.GetOkExists("defined_tags"); ok {
		convertedDefinedTags, err := mapToDefinedTags(definedTags.(map[string]interface{}))
		if err != nil {
			return err
		}
		request.DefinedTags = convertedDefinedTags
	}

	if displayName, ok := s.D.GetOkExists("display_name"); ok {
		tmp := displayName.(string)
		request.DisplayName = &tmp
	}

	if freeformTags, ok := s.D.GetOkExists("freeform_tags"); ok {
		request.FreeformTags = objectMapToStringMap(freeformTags.(map[string]interface{}))
	}

	tmp := s.D.Id()
	request.VcnId = &tmp

	request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	response, err := s.Client.UpdateVcn(context.Background(), request)
	if err != nil {
		return err
	}

	s.Res = &response.Vcn
	return nil
}

func (s *CoreVcnResourceCrud) Delete() error {
	request := oci_core.DeleteVcnRequest{}

	tmp := s.D.Id()
	request.VcnId = &tmp

	request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	_, err := s.Client.DeleteVcn(context.Background(), request)
	return err
}

func (s *CoreVcnResourceCrud) SetData() error {
	if s.Res.CidrBlock != nil {
		s.D.Set("cidr_block", *s.Res.CidrBlock)
	}

	if s.Res.CidrBlocks != nil {
		s.D.Set("cidr_blocks", s.Res.CidrBlocks)
	}

	if s.Res.CompartmentId != nil {
		s.D.Set("compartment_id", *s.Res.CompartmentId)
	}

	if s.Res.DefaultDhcpOptionsId != nil {
		s.D.Set("default_dhcp_options_id", *s.Res.DefaultDhcpOptionsId)
	}

	if s.Res.DefaultRouteTableId != nil {
		s.D.Set("default_route_table_id", *s.Res.DefaultRouteTableId)
	}

	if s.Res.DefaultSecurityListId != nil {
		s.D.Set("default_security_list_id", *s.Res.DefaultSecurityListId)
	}

	if s.Res.DefinedTags != nil {
		s.D.Set("defined_tags", definedTagsToMap(s.Res.DefinedTags))
	}

	if s.Res.DisplayName != nil {
		s.D.Set("display_name", *s.Res.DisplayName)
	}

	if s.Res.DnsLabel != nil {
		s.D.Set("dns_label", *s.Res.DnsLabel)
	}

	s.D.Set("freeform_tags", s.Res.FreeformTags)

	if s.Res.Ipv6CidrBlock != nil {
		s.D.Set("ipv6cidr_block", *s.Res.Ipv6CidrBlock)
		s.D.Set("is_ipv6enabled", true)
	}

	if s.Res.Ipv6PublicCidrBlock != nil {
		s.D.Set("ipv6public_cidr_block", *s.Res.Ipv6PublicCidrBlock)
	}

	s.D.Set("state", s.Res.LifecycleState)

	if s.Res.TimeCreated != nil {
		s.D.Set("time_created", s.Res.TimeCreated.String())
	}

	if s.Res.VcnDomainName != nil {
		s.D.Set("vcn_domain_name", *s.Res.VcnDomainName)
	}

	return nil
}

func (s *CoreVcnResourceCrud) updateCompartment(compartment interface{}) error {
	changeCompartmentRequest := oci_core.ChangeVcnCompartmentRequest{}

	compartmentTmp := compartment.(string)
	changeCompartmentRequest.CompartmentId = &compartmentTmp

	idTmp := s.D.Id()
	changeCompartmentRequest.VcnId = &idTmp

	changeCompartmentRequest.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	_, err := s.Client.ChangeVcnCompartment(context.Background(), changeCompartmentRequest)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>fix for vcn cidr_blocks<commit_after>// Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0

package oci

import (
	"context"

	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"

	oci_core "github.com/oracle/oci-go-sdk/v28/core"
)

func init() {
	RegisterResource("oci_core_vcn", CoreVcnResource())
}

func CoreVcnResource() *schema.Resource {
	return &schema.Resource{
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		Timeouts: DefaultTimeout,
		Create:   createCoreVcn,
		Read:     readCoreVcn,
		Update:   updateCoreVcn,
		Delete:   deleteCoreVcn,
		Schema: map[string]*schema.Schema{
			// Required
			"compartment_id": {
				Type:     schema.TypeString,
				Required: true,
			},

			// Optional
			"cidr_block": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},
			"cidr_blocks": {
				Type:     schema.TypeList,
				Optional: true,
				Computed: true,
				ForceNew: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},
			"defined_tags": {
				Type:             schema.TypeMap,
				Optional:         true,
				Computed:         true,
				DiffSuppressFunc: definedTagsDiffSuppressFunction,
				Elem:             schema.TypeString,
			},
			"display_name": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"dns_label": {
				Type:             schema.TypeString,
				Optional:         true,
				Computed:         true,
				ForceNew:         true,
				DiffSuppressFunc: EqualIgnoreCaseSuppressDiff,
			},
			"freeform_tags": {
				Type:     schema.TypeMap,
				Optional: true,
				Computed: true,
				Elem:     schema.TypeString,
			},
			"ipv6cidr_block": {
				Type:             schema.TypeString,
				Optional:         true,
				Computed:         true,
				ForceNew:         true,
				DiffSuppressFunc: ipv6CompressionDiffSuppressFunction,
			},
			"is_ipv6enabled": {
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			// Computed
			"default_dhcp_options_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"default_route_table_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"default_security_list_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"ipv6public_cidr_block": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"state": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"time_created": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"vcn_domain_name": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func createCoreVcn(d *schema.ResourceData, m interface{}) error {
	sync := &CoreVcnResourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).virtualNetworkClient()

	return CreateResource(d, sync)
}

func readCoreVcn(d *schema.ResourceData, m interface{}) error {
	sync := &CoreVcnResourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).virtualNetworkClient()

	return ReadResource(sync)
}

func updateCoreVcn(d *schema.ResourceData, m interface{}) error {
	sync := &CoreVcnResourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).virtualNetworkClient()

	return UpdateResource(d, sync)
}

func deleteCoreVcn(d *schema.ResourceData, m interface{}) error {
	sync := &CoreVcnResourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).virtualNetworkClient()
	sync.DisableNotFoundRetries = true

	return DeleteResource(d, sync)
}

type CoreVcnResourceCrud struct {
	BaseCrud
	Client                 *oci_core.VirtualNetworkClient
	Res                    *oci_core.Vcn
	DisableNotFoundRetries bool
}

func (s *CoreVcnResourceCrud) ID() string {
	return *s.Res.Id
}

func (s *CoreVcnResourceCrud) CreatedPending() []string {
	return []string{
		string(oci_core.VcnLifecycleStateProvisioning),
	}
}

func (s *CoreVcnResourceCrud) CreatedTarget() []string {
	return []string{
		string(oci_core.VcnLifecycleStateAvailable),
	}
}

func (s *CoreVcnResourceCrud) DeletedPending() []string {
	return []string{
		string(oci_core.VcnLifecycleStateTerminating),
	}
}

func (s *CoreVcnResourceCrud) DeletedTarget() []string {
	return []string{
		string(oci_core.VcnLifecycleStateTerminated),
	}
}

func (s *CoreVcnResourceCrud) Create() error {
	request := oci_core.CreateVcnRequest{}

	if cidrBlock, ok := s.D.GetOkExists("cidr_block"); ok {
		tmp := cidrBlock.(string)
		request.CidrBlock = &tmp
	}

	if cidrBlocks, ok := s.D.GetOkExists("cidr_blocks"); ok {
		interfaces := cidrBlocks.([]interface{})
		tmp := make([]string, len(interfaces))
		for i := range interfaces {
			if interfaces[i] != nil {
				tmp[i] = interfaces[i].(string)
			}
		}
		if len(tmp) != 0 || s.D.HasChange("cidr_blocks") {
			request.CidrBlocks = tmp
		}
	}

	if compartmentId, ok := s.D.GetOkExists("compartment_id"); ok {
		tmp := compartmentId.(string)
		request.CompartmentId = &tmp
	}

	if definedTags, ok := s.D.GetOkExists("defined_tags"); ok {
		convertedDefinedTags, err := mapToDefinedTags(definedTags.(map[string]interface{}))
		if err != nil {
			return err
		}
		request.DefinedTags = convertedDefinedTags
	}

	if displayName, ok := s.D.GetOkExists("display_name"); ok {
		tmp := displayName.(string)
		request.DisplayName = &tmp
	}

	if dnsLabel, ok := s.D.GetOkExists("dns_label"); ok {
		tmp := dnsLabel.(string)
		request.DnsLabel = &tmp
	}

	if freeformTags, ok := s.D.GetOkExists("freeform_tags"); ok {
		request.FreeformTags = objectMapToStringMap(freeformTags.(map[string]interface{}))
	}

	if ipv6CidrBlock, ok := s.D.GetOkExists("ipv6cidr_block"); ok {
		tmp := ipv6CidrBlock.(string)
		request.Ipv6CidrBlock = &tmp
	}

	if isIpv6Enabled, ok := s.D.GetOkExists("is_ipv6enabled"); ok {
		tmp := isIpv6Enabled.(bool)
		request.IsIpv6Enabled = &tmp
	}

	request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	response, err := s.Client.CreateVcn(context.Background(), request)
	if err != nil {
		return err
	}

	s.Res = &response.Vcn
	return nil
}

func (s *CoreVcnResourceCrud) Get() error {
	request := oci_core.GetVcnRequest{}

	tmp := s.D.Id()
	request.VcnId = &tmp

	request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	response, err := s.Client.GetVcn(context.Background(), request)
	if err != nil {
		return err
	}

	s.Res = &response.Vcn
	return nil
}

func (s *CoreVcnResourceCrud) Update() error {
	if compartment, ok := s.D.GetOkExists("compartment_id"); ok && s.D.HasChange("compartment_id") {
		oldRaw, newRaw := s.D.GetChange("compartment_id")
		if newRaw != "" && oldRaw != "" {
			err := s.updateCompartment(compartment)
			if err != nil {
				return err
			}
		}
	}
	request := oci_core.UpdateVcnRequest{}

	if definedTags, ok := s.D.GetOkExists("defined_tags"); ok {
		convertedDefinedTags, err := mapToDefinedTags(definedTags.(map[string]interface{}))
		if err != nil {
			return err
		}
		request.DefinedTags = convertedDefinedTags
	}

	if displayName, ok := s.D.GetOkExists("display_name"); ok {
		tmp := displayName.(string)
		request.DisplayName = &tmp
	}

	if freeformTags, ok := s.D.GetOkExists("freeform_tags"); ok {
		request.FreeformTags = objectMapToStringMap(freeformTags.(map[string]interface{}))
	}

	tmp := s.D.Id()
	request.VcnId = &tmp

	request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	response, err := s.Client.UpdateVcn(context.Background(), request)
	if err != nil {
		return err
	}

	s.Res = &response.Vcn
	return nil
}

func (s *CoreVcnResourceCrud) Delete() error {
	request := oci_core.DeleteVcnRequest{}

	tmp := s.D.Id()
	request.VcnId = &tmp

	request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	_, err := s.Client.DeleteVcn(context.Background(), request)
	return err
}

func (s *CoreVcnResourceCrud) SetData() error {
	if s.Res.CidrBlock != nil {
		s.D.Set("cidr_block", *s.Res.CidrBlock)
	}

	s.D.Set("cidr_blocks", s.Res.CidrBlocks)

	if s.Res.CompartmentId != nil {
		s.D.Set("compartment_id", *s.Res.CompartmentId)
	}

	if s.Res.DefaultDhcpOptionsId != nil {
		s.D.Set("default_dhcp_options_id", *s.Res.DefaultDhcpOptionsId)
	}

	if s.Res.DefaultRouteTableId != nil {
		s.D.Set("default_route_table_id", *s.Res.DefaultRouteTableId)
	}

	if s.Res.DefaultSecurityListId != nil {
		s.D.Set("default_security_list_id", *s.Res.DefaultSecurityListId)
	}

	if s.Res.DefinedTags != nil {
		s.D.Set("defined_tags", definedTagsToMap(s.Res.DefinedTags))
	}

	if s.Res.DisplayName != nil {
		s.D.Set("display_name", *s.Res.DisplayName)
	}

	if s.Res.DnsLabel != nil {
		s.D.Set("dns_label", *s.Res.DnsLabel)
	}

	s.D.Set("freeform_tags", s.Res.FreeformTags)

	if s.Res.Ipv6CidrBlock != nil {
		s.D.Set("ipv6cidr_block", *s.Res.Ipv6CidrBlock)
		s.D.Set("is_ipv6enabled", true)
	}

	if s.Res.Ipv6PublicCidrBlock != nil {
		s.D.Set("ipv6public_cidr_block", *s.Res.Ipv6PublicCidrBlock)
	}

	s.D.Set("state", s.Res.LifecycleState)

	if s.Res.TimeCreated != nil {
		s.D.Set("time_created", s.Res.TimeCreated.String())
	}

	if s.Res.VcnDomainName != nil {
		s.D.Set("vcn_domain_name", *s.Res.VcnDomainName)
	}

	return nil
}

func (s *CoreVcnResourceCrud) updateCompartment(compartment interface{}) error {
	changeCompartmentRequest := oci_core.ChangeVcnCompartmentRequest{}

	compartmentTmp := compartment.(string)
	changeCompartmentRequest.CompartmentId = &compartmentTmp

	idTmp := s.D.Id()
	changeCompartmentRequest.VcnId = &idTmp

	changeCompartmentRequest.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "core")

	_, err := s.Client.ChangeVcnCompartment(context.Background(), changeCompartmentRequest)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package service

import (
	"bytes"
	"context"
	"encoding/json"
	"os"
	"sync"
	"unicode/utf8"

	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
	pdebug "github.com/lestrrat/go-pdebug"
	"github.com/pkg/errors"
	"golang.org/x/oauth2"
)

var twitterSvc TwitterSvc
var twitterOnce sync.Once

func Twitter() *TwitterSvc {
	twitterOnce.Do(twitterSvc.Init)
	return &twitterSvc
}

func (v *TwitterSvc) Init() {
	twitterSvc.Client = NewTwitterClientFromToken(os.Getenv("TWITTER_OAUTH2_ACCESS_TOKEN"))
}

func NewTwitterClientFromToken(s string) *twitter.Client {
	var config oauth2.Config
	var token oauth2.Token

	token.AccessToken = s
	httpClient := config.Client(oauth2.NoContext, &token)
	return twitter.NewClient(httpClient)
}

func (v *TwitterSvc) TweetAsConference(confID, tweet string) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("TwitterSvc.TweetAsConference %s", confID).BindError(&err)
		defer g.End()
	}

	// Post to twitter, but we can only do so if we have a valid
	// credential information. This is stored in Google storage
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// twitter credentials
	credentialsKey := "conferences/" + confID + "/credentials/twitter"
	var credentialsBuf bytes.Buffer
	if err := CredentialStorage.Download(ctx, credentialsKey, &credentialsBuf); err != nil {
		return errors.Wrap(err, "failed to download twitter credentials")
	}

	if pdebug.Enabled {
		pdebug.Printf(credentialsBuf.String())
	}

	// ...and they are in JSON
	var creds struct {
		AccessToken  string `json:"access_token"`
		AccessSecret string `json:"access_scret"`
	}

	if err := json.Unmarshal(credentialsBuf.Bytes(), &creds); err != nil {
		return errors.Wrap(err, "failed to unmarshal twitter credentials")
	}

	// Consumer key and secret are from env vars
	consumerKey := os.Getenv("TWITTER_OAUTH1_CONSUMER_KEY")
	consumerSecret := os.Getenv("TWITTER_OAUTH1_CONSUMER_SECRET")

	config := oauth1.NewConfig(consumerKey, consumerSecret)
	token := oauth1.NewToken(creds.AccessToken, creds.AccessSecret)

	httpClient := config.Client(oauth1.NoContext, token)

	client := twitter.NewClient(httpClient)

	if utf8.RuneCountInString(tweet) > 140 {
		var truncated bytes.Buffer
		for i := 1; i < 140; i++ { // 139 runes
			r, n := utf8.DecodeRuneInString(tweet)
			if r == utf8.RuneError {
				break
			}
			tweet = tweet[n:]
			truncated.WriteRune(r)
		}
		truncated.WriteRune('…')
		tweet = truncated.String()
	}

	_, _, err = client.Statuses.Update(tweet, nil)
	return err
}
<commit_msg>wrong JSON field<commit_after>package service

import (
	"bytes"
	"context"
	"encoding/json"
	"os"
	"sync"
	"unicode/utf8"

	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
	pdebug "github.com/lestrrat/go-pdebug"
	"github.com/pkg/errors"
	"golang.org/x/oauth2"
)

var twitterSvc TwitterSvc
var twitterOnce sync.Once

func Twitter() *TwitterSvc {
	twitterOnce.Do(twitterSvc.Init)
	return &twitterSvc
}

func (v *TwitterSvc) Init() {
	twitterSvc.Client = NewTwitterClientFromToken(os.Getenv("TWITTER_OAUTH2_ACCESS_TOKEN"))
}

func NewTwitterClientFromToken(s string) *twitter.Client {
	var config oauth2.Config
	var token oauth2.Token

	token.AccessToken = s
	httpClient := config.Client(oauth2.NoContext, &token)
	return twitter.NewClient(httpClient)
}

func (v *TwitterSvc) TweetAsConference(confID, tweet string) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("TwitterSvc.TweetAsConference %s", confID).BindError(&err)
		defer g.End()
	}

	// Post to twitter, but we can only do so if we have a valid
	// credential information. This is stored in Google storage
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// twitter credentials
	credentialsKey := "conferences/" + confID + "/credentials/twitter"
	var credentialsBuf bytes.Buffer
	if err := CredentialStorage.Download(ctx, credentialsKey, &credentialsBuf); err != nil {
		return errors.Wrap(err, "failed to download twitter credentials")
	}

	if pdebug.Enabled {
		pdebug.Printf(credentialsBuf.String())
	}

	// ...and they are in JSON
	var creds struct {
		AccessToken  string `json:"access_token"`
		AccessSecret string `json:"access_token_secret"`
	}

	if err := json.Unmarshal(credentialsBuf.Bytes(), &creds); err != nil {
		return errors.Wrap(err, "failed to unmarshal twitter credentials")
	}

	// Consumer key and secret are from env vars
	consumerKey := os.Getenv("TWITTER_OAUTH1_CONSUMER_KEY")
	consumerSecret := os.Getenv("TWITTER_OAUTH1_CONSUMER_SECRET")

	config := oauth1.NewConfig(consumerKey, consumerSecret)
	token := oauth1.NewToken(creds.AccessToken, creds.AccessSecret)

	httpClient := config.Client(oauth1.NoContext, token)

	client := twitter.NewClient(httpClient)

	if utf8.RuneCountInString(tweet) > 140 {
		var truncated bytes.Buffer
		for i := 1; i < 140; i++ { // 139 runes
			r, n := utf8.DecodeRuneInString(tweet)
			if r == utf8.RuneError {
				break
			}
			tweet = tweet[n:]
			truncated.WriteRune(r)
		}
		truncated.WriteRune('…')
		tweet = truncated.String()
	}

	_, _, err = client.Statuses.Update(tweet, nil)
	return err
}
<|endoftext|>


<commit_before>// Copyright 2017 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package entry

import (
	"fmt"
	"strings"

	"github.com/issue9/mux/internal/syntax"
)

// 表示命名参数中的某个节点
type node struct {
	value    string // 当前节点的值。
	endByte  byte   // 下一个节点的起始字符
	isString bool   // 当前节点是否为一个字符串
}

// 命名参数是正则表达式的简化版本，
// 在一个参数中未指定正则表达式，默认使用此类型，
// 性能会比用正则好一些。
type named struct {
	*base
	nodes []*node
}

// 声明一个新的 named 实例。
func newNamed(s *syntax.Syntax) *named {
	b := newBase(s)

	str := s.Patterns[len(s.Patterns)-1]
	if b.wildcard {
		str = str[:len(str)-2]
		if len(str) == 0 {
			s.Patterns = s.Patterns[:len(s.Patterns)-1]
		} else {
			s.Patterns[len(s.Patterns)-1] = str
		}
	}

	nodes := make([]*node, 0, len(s.Patterns))
	for index, str := range s.Patterns {
		if str[0] == syntax.Start {
			endByte := byte('/')
			if index < len(s.Patterns)-1 {
				endByte = s.Patterns[index+1][0]
			}
			nodes = append(nodes, &node{
				value:    str[1 : len(str)-1],
				isString: false,
				endByte:  endByte,
			})
		} else {
			nodes = append(nodes, &node{
				value:    str,
				isString: true,
			})
		}
	}

	return &named{
		base:  b,
		nodes: nodes,
	}
}

func (n *named) Priority() int {
	return syntax.TypeNamed
}

func (n *named) Match(path string) (bool, map[string]string) {
	rawPath := path
	for i, name := range n.nodes {
		islast := (i == len(n.nodes)-1)

		if name.isString { // 普通字符串节点
			if !strings.HasPrefix(path, name.value) {
				return false, nil
			}

			if islast {
				return (path == name.value), n.params(rawPath)
			}

			path = path[len(name.value):]
		} else { // 带命名的节点
			index := strings.IndexByte(path, name.endByte)
			if !islast {
				if index == -1 {
					return false, nil
				}

				path = path[index:]
			} else { // 最后一个节点了
				if index == -1 {
					if n.wildcard {
						return false, nil
					}
					return true, n.params(rawPath)
				}

				if !n.wildcard {
					return false, nil
				}
				return true, n.params(rawPath)
			}
		} // end if
	} // end for

	return true, n.params(rawPath)
}

func (n *named) params(path string) map[string]string {
	// 由调用者 n.match() 保证 path 参数始终是与当前路由项匹配的。
	// 所以以下代码不再作是否匹配的检测工作。

	params := make(map[string]string, len(n.nodes))
	for i, name := range n.nodes {
		islast := (i == len(n.nodes)-1)

		if name.isString { // 普通字符串节点
			if islast {
				return params
			}

			path = path[len(name.value):]
		} else { // 带命名的节点
			index := strings.IndexByte(path, name.endByte)
			if !islast {
				params[name.value] = path[:index]
				path = path[index:]
			} else { // 最后一个节点了
				if index == -1 {
					params[name.value] = path
					return params
				}

				params[name.value] = path[:index]
				return params
			}
		} // end if
	} // end for

	return params
}

func (n *named) URL(params map[string]string, path string) (string, error) {
	ret := ""
	for _, name := range n.nodes {
		if name.isString {
			ret += name.value
			continue
		}

		if param, exists := params[name.value]; exists {
			ret += param
		} else {
			return "", fmt.Errorf("参数 %v 未指定", name.value)
		}
	}

	if n.wildcard {
		ret += "/" + path
	}

	return ret, nil
}
<commit_msg>[internal/entry] named.Match 在返回 false 时，不再计算 params 的值<commit_after>// Copyright 2017 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package entry

import (
	"fmt"
	"strings"

	"github.com/issue9/mux/internal/syntax"
)

// 表示命名参数中的某个节点
type node struct {
	value    string // 当前节点的值。
	endByte  byte   // 下一个节点的起始字符
	isString bool   // 当前节点是否为一个字符串
}

// 命名参数是正则表达式的简化版本，
// 在一个参数中未指定正则表达式，默认使用此类型，
// 性能会比用正则好一些。
type named struct {
	*base
	nodes []*node
}

// 声明一个新的 named 实例。
func newNamed(s *syntax.Syntax) *named {
	b := newBase(s)

	str := s.Patterns[len(s.Patterns)-1]
	if b.wildcard {
		str = str[:len(str)-2]
		if len(str) == 0 {
			s.Patterns = s.Patterns[:len(s.Patterns)-1]
		} else {
			s.Patterns[len(s.Patterns)-1] = str
		}
	}

	nodes := make([]*node, 0, len(s.Patterns))
	for index, str := range s.Patterns {
		if str[0] == syntax.Start {
			endByte := byte('/')
			if index < len(s.Patterns)-1 {
				endByte = s.Patterns[index+1][0]
			}
			nodes = append(nodes, &node{
				value:    str[1 : len(str)-1],
				isString: false,
				endByte:  endByte,
			})
		} else {
			nodes = append(nodes, &node{
				value:    str,
				isString: true,
			})
		}
	}

	return &named{
		base:  b,
		nodes: nodes,
	}
}

func (n *named) Priority() int {
	return syntax.TypeNamed
}

func (n *named) Match(path string) (bool, map[string]string) {
	rawPath := path
	for i, name := range n.nodes {
		islast := (i == len(n.nodes)-1)

		if name.isString { // 普通字符串节点
			if !strings.HasPrefix(path, name.value) {
				return false, nil
			}

			if islast {
				if path == name.value {
					return true, n.params(rawPath)
				}
				return false, nil
			}

			path = path[len(name.value):]
		} else { // 带命名的节点
			index := strings.IndexByte(path, name.endByte)
			if !islast {
				if index == -1 {
					return false, nil
				}

				path = path[index:]
			} else { // 最后一个节点了
				if index == -1 {
					if n.wildcard {
						return false, nil
					}
					return true, n.params(rawPath)
				}

				if !n.wildcard {
					return false, nil
				}
				return true, n.params(rawPath)
			}
		} // end if
	} // end for

	return true, n.params(rawPath)
}

func (n *named) params(path string) map[string]string {
	// 由调用者 n.match() 保证 path 参数始终是与当前路由项匹配的。
	// 所以以下代码不再作是否匹配的检测工作。

	params := make(map[string]string, len(n.nodes))
	for i, name := range n.nodes {
		islast := (i == len(n.nodes)-1)

		if name.isString { // 普通字符串节点
			if islast {
				return params
			}

			path = path[len(name.value):]
		} else { // 带命名的节点
			index := strings.IndexByte(path, name.endByte)
			if !islast {
				params[name.value] = path[:index]
				path = path[index:]
			} else { // 最后一个节点了
				if index == -1 {
					params[name.value] = path
					return params
				}

				params[name.value] = path[:index]
				return params
			}
		} // end if
	} // end for

	return params
}

func (n *named) URL(params map[string]string, path string) (string, error) {
	ret := ""
	for _, name := range n.nodes {
		if name.isString {
			ret += name.value
			continue
		}

		if param, exists := params[name.value]; exists {
			ret += param
		} else {
			return "", fmt.Errorf("参数 %v 未指定", name.value)
		}
	}

	if n.wildcard {
		ret += "/" + path
	}

	return ret, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Qubit Digital Ltd.
// 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 logspray is a collection of tools for streaming and indexing
// large volumes of dynamic logs.

package sources

import (
	"context"
	"io"
	"sync"
	"time"

	"github.com/QubitProducts/logspray/sinks"
	"github.com/cloudflare/backoff"
	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	uuid "github.com/satori/go.uuid"
)

var (
	lineCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: "logspray_reader_read_lines_total",
		Help: "Counter of total lines read since process start.",
	}, []string{"logspray_job"})
	bytesCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: "logspray_reader_read_bytes_total",
		Help: "Counter of total bytes read since process start.",
	}, []string{"logspray_job"})
	sourcesActive = prometheus.NewGauge(prometheus.GaugeOpts{
		Name: "logspray_reader_active_sources",
		Help: "Gauge of number of active sources.",
	})
	sourcesOpened = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "logspray_reader_opened_sources_total",
		Help: "Counter of number of sources since process start.",
	})
)

func init() {
	prometheus.MustRegister(lineCount)
	prometheus.MustRegister(bytesCount)
	prometheus.MustRegister(sourcesActive)
	prometheus.MustRegister(sourcesOpened)
}

// ReadAllTargets drains a source of log data
func ReadAllTargets(ctx context.Context, snk sinks.Sinker, src Sourcer) error {
	var err error

	targets := &targetSet{Sourcer: src}
	defer targets.cancelAll()

	existing, err := src.Next(ctx)
	if err != nil {
		return err
	}

	for _, u := range existing {
		if glog.V(2) {
			glog.Infof("Found pre-existing job: %#v", *u)
		}

		go targets.addSource(ctx, snk, u, false)
	}

	for us, err := src.Next(ctx); err == nil; us, err = src.Next(ctx) {
		if err != nil {
			return err
		}
		for _, u := range us {
			switch u.Action {
			case Remove:
				if glog.V(2) {
					glog.Infof("Removing job: %#v", *u)
				}
				targets.cancelTarget(u.Target)
			case Add:
				if glog.V(2) {
					glog.Infof("Found new job: %#v", *u)
				}
				go targets.addSource(ctx, snk, u, true)
			}
		}
	}
	return err
}

func (ts *targetSet) addSource(ctx context.Context, snk sinks.Sinker, u *Update, fromStart bool) {
	b := backoff.New(10*time.Second, 1*time.Second)
	for {
		select {
		case <-ctx.Done():
			return
		default:
			streamID := uuid.NewV1()

			w, err := snk.AddSource(string(streamID.Bytes()), u.Labels)
			if err != nil {
				if glog.V(2) {
					glog.Errorf("addsource error: %#v , %v", *u, err)
				}
				<-time.After(b.Duration())
				continue
			}
			b.Reset()

			err = ts.readAllFromTarget(ctx, w, u, fromStart)
			switch err {
			case nil, io.EOF, context.Canceled:
				return
			}
		}
	}
}

func (ts *targetSet) readAllFromTarget(ctx context.Context, w sinks.MessageWriter, u *Update, fromStart bool) error {
	sourcesOpened.Inc()
	sourcesActive.Inc()
	defer sourcesActive.Dec()

	fctx := ts.setTarget(ctx, u.Target)
	defer w.Close()
	// Start at 1, control messages like setheader then all get 0s
	msgid := uint64(1)

	r, err := ts.ReadTarget(fctx, u.Target, fromStart)
	if err != nil {
		return err
	}

	for {
		msg, err := r.MessageRead(fctx)
		if err == io.EOF {
			if glog.V(2) {
				glog.Infof("Stream ended %v\n", u.Target)
			}
			return err
		}

		if err != nil {
			if glog.V(1) {
				glog.Errorf("read message error: %#v , %v", *u, err)
			}
		}
		lineCount.WithLabelValues(u.Labels["job"]).Inc()
		bytesCount.WithLabelValues(u.Labels["job"]).Add(float64(len(msg.Text)))
		msg.Index = msgid
		msgid++
		if err := w.WriteMessage(ctx, msg); err != nil {
			if glog.V(1) {
				glog.Errorf("write message error: %#v , %v", *u, err)
			}
		}
	}
}

type targetSet struct {
	Sourcer
	sinks.Sinker

	sync.Mutex
	cfs map[string]context.CancelFunc
}

func (ts *targetSet) setTarget(ctx context.Context, id string) context.Context {
	fctx, cf := context.WithCancel(ctx)

	ts.Lock()
	defer ts.Unlock()
	if ts.cfs == nil {
		ts.cfs = map[string]context.CancelFunc{}
	}

	ts.cfs[id] = cf
	return fctx
}

func (ts *targetSet) cancelTarget(id string) {
	ts.Lock()
	defer ts.Unlock()

	if cf, ok := ts.cfs[id]; ok {
		delete(ts.cfs, id)
		cf()
	}
}

func (ts *targetSet) cancelAll() {
	ts.Lock()
	defer ts.Unlock()
	for _, cf := range ts.cfs {
		cf()
	}
}
<commit_msg>source: continue on failed read<commit_after>// Copyright 2016 Qubit Digital Ltd.
// 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 logspray is a collection of tools for streaming and indexing
// large volumes of dynamic logs.

package sources

import (
	"context"
	"io"
	"sync"
	"time"

	"github.com/QubitProducts/logspray/sinks"
	"github.com/cloudflare/backoff"
	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	uuid "github.com/satori/go.uuid"
)

var (
	lineCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: "logspray_reader_read_lines_total",
		Help: "Counter of total lines read since process start.",
	}, []string{"logspray_job"})
	bytesCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: "logspray_reader_read_bytes_total",
		Help: "Counter of total bytes read since process start.",
	}, []string{"logspray_job"})
	sourcesActive = prometheus.NewGauge(prometheus.GaugeOpts{
		Name: "logspray_reader_active_sources",
		Help: "Gauge of number of active sources.",
	})
	sourcesOpened = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "logspray_reader_opened_sources_total",
		Help: "Counter of number of sources since process start.",
	})
)

func init() {
	prometheus.MustRegister(lineCount)
	prometheus.MustRegister(bytesCount)
	prometheus.MustRegister(sourcesActive)
	prometheus.MustRegister(sourcesOpened)
}

// ReadAllTargets drains a source of log data
func ReadAllTargets(ctx context.Context, snk sinks.Sinker, src Sourcer) error {
	var err error

	targets := &targetSet{Sourcer: src}
	defer targets.cancelAll()

	existing, err := src.Next(ctx)
	if err != nil {
		return err
	}

	for _, u := range existing {
		if glog.V(2) {
			glog.Infof("Found pre-existing job: %#v", *u)
		}

		go targets.addSource(ctx, snk, u, false)
	}

	for us, err := src.Next(ctx); err == nil; us, err = src.Next(ctx) {
		if err != nil {
			return err
		}
		for _, u := range us {
			switch u.Action {
			case Remove:
				if glog.V(2) {
					glog.Infof("Removing job: %#v", *u)
				}
				targets.cancelTarget(u.Target)
			case Add:
				if glog.V(2) {
					glog.Infof("Found new job: %#v", *u)
				}
				go targets.addSource(ctx, snk, u, true)
			}
		}
	}
	return err
}

func (ts *targetSet) addSource(ctx context.Context, snk sinks.Sinker, u *Update, fromStart bool) {
	b := backoff.New(10*time.Second, 1*time.Second)
	for {
		select {
		case <-ctx.Done():
			return
		default:
			streamID := uuid.NewV1()

			w, err := snk.AddSource(string(streamID.Bytes()), u.Labels)
			if err != nil {
				if glog.V(2) {
					glog.Errorf("addsource error: %#v , %v", *u, err)
				}
				<-time.After(b.Duration())
				continue
			}
			b.Reset()

			err = ts.readAllFromTarget(ctx, w, u, fromStart)
			switch err {
			case nil, io.EOF, context.Canceled:
				return
			}
		}
	}
}

func (ts *targetSet) readAllFromTarget(ctx context.Context, w sinks.MessageWriter, u *Update, fromStart bool) error {
	sourcesOpened.Inc()
	sourcesActive.Inc()
	defer sourcesActive.Dec()

	fctx := ts.setTarget(ctx, u.Target)
	defer w.Close()
	// Start at 1, control messages like setheader then all get 0s
	msgid := uint64(1)

	r, err := ts.ReadTarget(fctx, u.Target, fromStart)
	if err != nil {
		return err
	}

	for {
		msg, err := r.MessageRead(fctx)
		if err == io.EOF {
			if glog.V(2) {
				glog.Infof("Stream ended %v\n", u.Target)
			}
			return err
		}

		if err != nil {
			if glog.V(1) {
				glog.Errorf("read message error: %#v , %v", *u, err)
			}
			continue
		}
		lineCount.WithLabelValues(u.Labels["job"]).Inc()
		bytesCount.WithLabelValues(u.Labels["job"]).Add(float64(len(msg.Text)))
		msg.Index = msgid
		msgid++
		if err := w.WriteMessage(ctx, msg); err != nil {
			if glog.V(1) {
				glog.Errorf("write message error: %#v , %v", *u, err)
			}
		}
	}
}

type targetSet struct {
	Sourcer
	sinks.Sinker

	sync.Mutex
	cfs map[string]context.CancelFunc
}

func (ts *targetSet) setTarget(ctx context.Context, id string) context.Context {
	fctx, cf := context.WithCancel(ctx)

	ts.Lock()
	defer ts.Unlock()
	if ts.cfs == nil {
		ts.cfs = map[string]context.CancelFunc{}
	}

	ts.cfs[id] = cf
	return fctx
}

func (ts *targetSet) cancelTarget(id string) {
	ts.Lock()
	defer ts.Unlock()

	if cf, ok := ts.cfs[id]; ok {
		delete(ts.cfs, id)
		cf()
	}
}

func (ts *targetSet) cancelAll() {
	ts.Lock()
	defer ts.Unlock()
	for _, cf := range ts.cfs {
		cf()
	}
}
<|endoftext|>


<commit_before>package lib

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"text/template"

	"github.com/fatih/color"
)

// TLSDescription has the basic information about a TLS connection
type TLSDescription struct {
	Version string
	Cipher  string
}

var tlsLayout = `** TLS Connection **
Version: {{.Version}}
Cipher Suite: {{.Cipher}}`

func tlscolor(d description) string {
	c, ok := qualityColors[d.Quality]
	if !ok {
		return d.Name
	}
	return c.SprintFunc()(d.Name)
}

// EncodeTLSToText returns a human readable string, suitable for certigo console output.
func EncodeTLSToText(tcs *tls.ConnectionState) string {
	version := tlsVersions[tcs.Version]
	cipher := cipherSuites[tcs.CipherSuite]
	description := TLSDescription{
		Version: tlscolor(version),
		Cipher:  tlscolor(cipher),
	}
	t := template.New("TLS template")
	t, err := t.Parse(tlsLayout)
	if err != nil {
		// Should never happen
		panic(err)
	}
	var buffer bytes.Buffer
	w := bufio.NewWriter(&buffer)
	err = t.Execute(w, description)
	if err != nil {
		// Should never happen
		panic(err)
	}
	w.Flush()
	return string(buffer.Bytes())
}

// EncodeTLSToObject returns a JSON-marshallable description of a TLS connection
func EncodeTLSToObject(t *tls.ConnectionState) interface{} {
	version := tlsVersions[t.Version]
	cipher := cipherSuites[t.CipherSuite]
	return &TLSDescription{
		version.Slug,
		cipher.Slug,
	}
}

type description struct {
	Name    string // a human-friendly string
	Slug    string // a machine-friendly string
	Quality uint8  // 0 = insecure, 1 = ok, 2 = good
}

var qualityColors = map[uint8]*color.Color{
	0: red,
	1: yellow,
	2: green,
}

var tlsVersions = map[uint16]description{
	tls.VersionSSL30: {"SSL 3.0", "ssl_3_0", 0},
	tls.VersionTLS10: {"TLS 1.0", "tls_1_0", 0},
	tls.VersionTLS11: {"TLS 1.1", "tls_1_1", 1},
	tls.VersionTLS12: {"TLS 1.2", "tls_1_2", 2},
}

var cipherSuites = map[uint16]description{
	tls.TLS_RSA_WITH_RC4_128_SHA: {"TLS_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_RC4_128_SHA", 0},
	tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: {"TLS_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_RSA_WITH_3DES_EDE_CBC_SHA", 0},
	tls.TLS_RSA_WITH_AES_128_CBC_SHA: {"TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", 0},
	tls.TLS_RSA_WITH_AES_256_CBC_SHA: {"TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA", 0},
	tls.TLS_RSA_WITH_AES_128_CBC_SHA256: {"TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", 0},
	tls.TLS_RSA_WITH_AES_128_GCM_SHA256: {"TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_128_GCM_SHA256", 0},
	tls.TLS_RSA_WITH_AES_256_GCM_SHA384: {"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_256_GCM_SHA384", 0},
	tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: {"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 0},
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 0},
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: {"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 0},
	tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: {"TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", 0},
	tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: {"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 0},
	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 0},
	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: {"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 0},
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 0},
	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 0},
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: {"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0},
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: {"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0},
	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: {"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0},
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: {"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0},
	tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: {"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", 0},
	tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: {"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", 0},
}
<commit_msg>Add quality tags<commit_after>package lib

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"text/template"

	"github.com/fatih/color"
)

// TLSDescription has the basic information about a TLS connection
type TLSDescription struct {
	Version string
	Cipher  string
}

var tlsLayout = `** TLS Connection **
Version: {{.Version}}
Cipher Suite: {{.Cipher}}`

func tlscolor(d description) string {
	c, ok := qualityColors[d.Quality]
	if !ok {
		return d.Name
	}
	return c.SprintFunc()(d.Name)
}

// EncodeTLSToText returns a human readable string, suitable for certigo console output.
func EncodeTLSToText(tcs *tls.ConnectionState) string {
	version := tlsVersions[tcs.Version]
	cipher := cipherSuites[tcs.CipherSuite]
	description := TLSDescription{
		Version: tlscolor(version),
		Cipher:  tlscolor(cipher),
	}
	t := template.New("TLS template")
	t, err := t.Parse(tlsLayout)
	if err != nil {
		// Should never happen
		panic(err)
	}
	var buffer bytes.Buffer
	w := bufio.NewWriter(&buffer)
	err = t.Execute(w, description)
	if err != nil {
		// Should never happen
		panic(err)
	}
	w.Flush()
	return string(buffer.Bytes())
}

// EncodeTLSToObject returns a JSON-marshallable description of a TLS connection
func EncodeTLSToObject(t *tls.ConnectionState) interface{} {
	version := tlsVersions[t.Version]
	cipher := cipherSuites[t.CipherSuite]
	return &TLSDescription{
		version.Slug,
		cipher.Slug,
	}
}

type description struct {
	Name    string // a human-friendly string
	Slug    string // a machine-friendly string
	Quality uint8  // 0 = insecure, 1 = ok, 2 = good
}

var qualityColors = map[uint8]*color.Color{
	0: red,
	1: yellow,
	2: green,
}

var tlsVersions = map[uint16]description{
	tls.VersionSSL30: {"SSL 3.0", "ssl_3_0", 0},
	tls.VersionTLS10: {"TLS 1.0", "tls_1_0", 0},
	tls.VersionTLS11: {"TLS 1.1", "tls_1_1", 1},
	tls.VersionTLS12: {"TLS 1.2", "tls_1_2", 2},
}

var cipherSuites = map[uint16]description{
	tls.TLS_RSA_WITH_RC4_128_SHA: {"TLS_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_RC4_128_SHA", 0},
	tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: {"TLS_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_RSA_WITH_3DES_EDE_CBC_SHA", 0},
	tls.TLS_RSA_WITH_AES_128_CBC_SHA: {"TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", 1},
	tls.TLS_RSA_WITH_AES_256_CBC_SHA: {"TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA", 1},
	tls.TLS_RSA_WITH_AES_128_CBC_SHA256: {"TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", 1},
	tls.TLS_RSA_WITH_AES_128_GCM_SHA256: {"TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_128_GCM_SHA256", 1},
	tls.TLS_RSA_WITH_AES_256_GCM_SHA384: {"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_256_GCM_SHA384", 1},
	tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: {"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 0},
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 1},
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: {"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 1},
	tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: {"TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", 0},
	tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: {"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 0},
	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 1},
	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: {"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 1},
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 1},
	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 1},
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: {"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 2},
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: {"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 2},
	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: {"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 2},
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: {"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 2},
	tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: {"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", 2},
	tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: {"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", 2},
}
<|endoftext|>


<commit_before>package docker

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"

	"github.com/apex/log"
	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/goreleaser/goreleaser/pipeline"
	"github.com/stretchr/testify/assert"
)

func killAndRm() {
	log.Info("killing registry")
	_ = exec.Command("docker", "kill", "registry").Run()
	_ = exec.Command("docker", "rm", "registry").Run()
}

func TestMain(m *testing.M) {
	killAndRm()
	if err := exec.Command(
		"docker", "run", "-d", "-p", "5000:5000", "--name", "registry", "registry:2",
	).Run(); err != nil {
		log.WithError(err).Fatal("failed to start docker registry")
	}
	defer killAndRm()
	os.Exit(m.Run())
}

func TestRunPipe(t *testing.T) {
	folder, err := ioutil.TempDir("", "archivetest")
	assert.NoError(t, err)
	var dist = filepath.Join(folder, "dist")
	assert.NoError(t, os.Mkdir(dist, 0755))
	assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
	var binPath = filepath.Join(dist, "mybin", "mybin")
	_, err = os.Create(binPath)
	assert.NoError(t, err)

	var table = map[string]struct {
		docker config.Docker
		err    string
	}{
		"valid": {
			docker: config.Docker{
				Image:       "localhost:5000/goreleaser/test_run_pipe",
				Goos:        "linux",
				Goarch:      "amd64",
				Dockerfile:  "testdata/Dockerfile",
				Binary:      "mybin",
				Latest:      true,
				TagTemplate: "{{.Tag}}-{{.Env.FOO}}",
			},
			err: "",
		},
		"invalid": {
			docker: config.Docker{
				Image:       "localhost:5000/goreleaser/test_run_pipe_nope",
				Goos:        "linux",
				Goarch:      "amd64",
				Dockerfile:  "testdata/Dockerfile",
				Binary:      "otherbin",
				TagTemplate: "{{.Version}}",
			},
			err: "",
		},
		"template_error": {
			docker: config.Docker{
				Image:       "localhost:5000/goreleaser/test_run_pipe_template_error",
				Goos:        "linux",
				Goarch:      "amd64",
				Dockerfile:  "testdata/Dockerfile",
				Binary:      "mybin",
				Latest:      true,
				TagTemplate: "{{.Tag}",
			},
			err: `template: tag:1: unexpected "}" in operand`,
		},
	}
	var images = []string{
		"localhost:5000/goreleaser/test_run_pipe:v1.0.0-123",
		"localhost:5000/goreleaser/test_run_pipe:latest",
	}
	// this might fail as the image doesnt exist yet, so lets ignore the error
	for _, img := range images {
		_ = exec.Command("docker", "rmi", img).Run()
	}

	for name, docker := range table {
		t.Run(name, func(t *testing.T) {
			var ctx = &context.Context{
				Version: "1.0.0",
				Publish: true,
				Git: context.GitInfo{
					CurrentTag: "v1.0.0",
				},
				Config: config.Project{
					ProjectName: "mybin",
					Dist:        dist,
					Dockers: []config.Docker{
						docker.docker,
					},
				},
				Env: map[string]string{"FOO": "123"},
			}
			for _, plat := range []string{"linuxamd64", "linux386", "darwinamd64"} {
				ctx.AddBinary(plat, "mybin", "mybin", binPath)
			}
			if docker.err == "" {
				assert.NoError(t, Pipe{}.Run(ctx))
			} else {
				assert.EqualError(t, Pipe{}.Run(ctx), docker.err)
			}
		})
	}

	// this might should not fail as the image should have been created when
	// the step ran
	for _, img := range images {
		assert.NoError(t, exec.Command("docker", "rmi", img).Run())
	}
	// the test_run_pipe_nope image should not have been created, so deleting
	// it should fail
	assert.Error(t,
		exec.Command(
			"docker", "rmi", "localhost:5000/goreleaser/test_run_pipe_nope:1.0.0",
		).Run(),
	)
}

func TestDescription(t *testing.T) {
	assert.NotEmpty(t, Pipe{}.String())
}

func TestNoDockers(t *testing.T) {
	assert.True(t, pipeline.IsSkip(Pipe{}.Run(context.New(config.Project{}))))
}

func TestNoDockerWithoutImageName(t *testing.T) {
	assert.True(t, pipeline.IsSkip(Pipe{}.Run(context.New(config.Project{
		Dockers: []config.Docker{
			{
				Goos: "linux",
			},
		},
	}))))
}

func TestDockerNotInPath(t *testing.T) {
	var path = os.Getenv("PATH")
	defer func() {
		assert.NoError(t, os.Setenv("PATH", path))
	}()
	assert.NoError(t, os.Setenv("PATH", ""))
	var ctx = &context.Context{
		Version: "1.0.0",
		Config: config.Project{
			Dockers: []config.Docker{
				{
					Image: "a/b",
				},
			},
		},
	}
	assert.EqualError(t, Pipe{}.Run(ctx), ErrNoDocker.Error())
}

func TestDefault(t *testing.T) {
	var ctx = &context.Context{
		Config: config.Project{
			Builds: []config.Build{
				{
					Binary: "foo",
				},
			},
			Dockers: []config.Docker{
				{
					Latest: true,
				},
			},
		},
	}
	assert.NoError(t, Pipe{}.Default(ctx))
	assert.Len(t, ctx.Config.Dockers, 1)
	var docker = ctx.Config.Dockers[0]
	assert.Equal(t, "linux", docker.Goos)
	assert.Equal(t, "amd64", docker.Goarch)
	assert.Equal(t, ctx.Config.Builds[0].Binary, docker.Binary)
	assert.Equal(t, "Dockerfile", docker.Dockerfile)
	assert.Equal(t, "{{ .Version }}", docker.TagTemplate)
}

func TestDefaultNoDockers(t *testing.T) {
	var ctx = &context.Context{
		Config: config.Project{
			Dockers: []config.Docker{},
		},
	}
	assert.NoError(t, Pipe{}.Default(ctx))
	assert.Empty(t, ctx.Config.Dockers)
}

func TestDefaultSet(t *testing.T) {
	var ctx = &context.Context{
		Config: config.Project{
			Dockers: []config.Docker{
				{
					Goos:       "windows",
					Goarch:     "i386",
					Binary:     "bar",
					Dockerfile: "Dockerfile.foo",
				},
			},
		},
	}
	assert.NoError(t, Pipe{}.Default(ctx))
	assert.Len(t, ctx.Config.Dockers, 1)
	var docker = ctx.Config.Dockers[0]
	assert.Equal(t, "windows", docker.Goos)
	assert.Equal(t, "i386", docker.Goarch)
	assert.Equal(t, "bar", docker.Binary)
	assert.Equal(t, "{{ .Version }}", docker.TagTemplate)
	assert.Equal(t, "Dockerfile.foo", docker.Dockerfile)
}
<commit_msg>test: fixed docker pipe tests<commit_after>package docker

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"

	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/goreleaser/goreleaser/internal/artifact"
	"github.com/goreleaser/goreleaser/pipeline"
	"github.com/stretchr/testify/assert"
)

func killAndRm(t *testing.T) {
	t.Log("killing registry")
	_ = exec.Command("docker", "kill", "registry").Run()
	_ = exec.Command("docker", "rm", "registry").Run()
}

func TestRunPipe(t *testing.T) {
	folder, err := ioutil.TempDir("", "archivetest")
	assert.NoError(t, err)
	var dist = filepath.Join(folder, "dist")
	assert.NoError(t, os.Mkdir(dist, 0755))
	assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
	var binPath = filepath.Join(dist, "mybin", "mybin")
	_, err = os.Create(binPath)
	assert.NoError(t, err)

	var table = map[string]struct {
		docker config.Docker
		err    string
	}{
		"valid": {
			docker: config.Docker{
				Image:       "localhost:5000/goreleaser/test_run_pipe",
				Goos:        "linux",
				Goarch:      "amd64",
				Dockerfile:  "testdata/Dockerfile",
				Binary:      "mybin",
				Latest:      true,
				TagTemplate: "{{.Tag}}-{{.Env.FOO}}",
			},
			err: "",
		},
		"invalid": {
			docker: config.Docker{
				Image:       "localhost:5000/goreleaser/test_run_pipe_nope",
				Goos:        "linux",
				Goarch:      "amd64",
				Dockerfile:  "testdata/Dockerfile",
				Binary:      "otherbin",
				TagTemplate: "{{.Version}}",
			},
			err: "",
		},
		"template_error": {
			docker: config.Docker{
				Image:       "localhost:5000/goreleaser/test_run_pipe_template_error",
				Goos:        "linux",
				Goarch:      "amd64",
				Dockerfile:  "testdata/Dockerfile",
				Binary:      "mybin",
				Latest:      true,
				TagTemplate: "{{.Tag}",
			},
			err: `template: tag:1: unexpected "}" in operand`,
		},
	}
	var images = []string{
		"localhost:5000/goreleaser/test_run_pipe:v1.0.0-123",
		"localhost:5000/goreleaser/test_run_pipe:latest",
	}
	// this might fail as the image doesnt exist yet, so lets ignore the error
	for _, img := range images {
		_ = exec.Command("docker", "rmi", img).Run()
	}

	killAndRm(t)
	if err := exec.Command(
		"docker", "run", "-d", "-p", "5000:5000", "--name", "registry", "registry:2",
	).Run(); err != nil {
		t.Log("failed to start docker registry", err)
		t.FailNow()
	}
	defer killAndRm(t)

	for name, docker := range table {
		t.Run(name, func(tt *testing.T) {
			var ctx = &context.Context{
				Version:   "1.0.0",
				Publish:   true,
				Artifacts: artifact.New(),
				Git: context.GitInfo{
					CurrentTag: "v1.0.0",
				},
				Config: config.Project{
					ProjectName: "mybin",
					Dist:        dist,
					Dockers: []config.Docker{
						docker.docker,
					},
				},
				Env: map[string]string{"FOO": "123"},
			}
			for _, os := range []string{"linux", "darwin"} {
				for _, arch := range []string{"amd64", "386"} {
					ctx.Artifacts.Add(artifact.Artifact{
						Name:   "mybin",
						Path:   binPath,
						Goarch: arch,
						Goos:   os,
						Type:   artifact.Binary,
						Extra: map[string]string{
							"Binary": "mybin",
						},
					})
				}
			}
			if docker.err == "" {
				assert.NoError(tt, Pipe{}.Run(ctx))
			} else {
				assert.EqualError(tt, Pipe{}.Run(ctx), docker.err)
			}
		})
	}

	// this might should not fail as the image should have been created when
	// the step ran
	for _, img := range images {
		assert.NoError(t, exec.Command("docker", "rmi", img).Run())
	}
	// the test_run_pipe_nope image should not have been created, so deleting
	// it should fail
	assert.Error(t,
		exec.Command(
			"docker", "rmi", "localhost:5000/goreleaser/test_run_pipe_nope:1.0.0",
		).Run(),
	)
}

func TestDescription(t *testing.T) {
	assert.NotEmpty(t, Pipe{}.String())
}

func TestNoDockers(t *testing.T) {
	assert.True(t, pipeline.IsSkip(Pipe{}.Run(context.New(config.Project{}))))
}

func TestNoDockerWithoutImageName(t *testing.T) {
	assert.True(t, pipeline.IsSkip(Pipe{}.Run(context.New(config.Project{
		Dockers: []config.Docker{
			{
				Goos: "linux",
			},
		},
	}))))
}

func TestDockerNotInPath(t *testing.T) {
	var path = os.Getenv("PATH")
	defer func() {
		assert.NoError(t, os.Setenv("PATH", path))
	}()
	assert.NoError(t, os.Setenv("PATH", ""))
	var ctx = &context.Context{
		Version: "1.0.0",
		Config: config.Project{
			Dockers: []config.Docker{
				{
					Image: "a/b",
				},
			},
		},
	}
	assert.EqualError(t, Pipe{}.Run(ctx), ErrNoDocker.Error())
}

func TestDefault(t *testing.T) {
	var ctx = &context.Context{
		Config: config.Project{
			Builds: []config.Build{
				{
					Binary: "foo",
				},
			},
			Dockers: []config.Docker{
				{
					Latest: true,
				},
			},
		},
	}
	assert.NoError(t, Pipe{}.Default(ctx))
	assert.Len(t, ctx.Config.Dockers, 1)
	var docker = ctx.Config.Dockers[0]
	assert.Equal(t, "linux", docker.Goos)
	assert.Equal(t, "amd64", docker.Goarch)
	assert.Equal(t, ctx.Config.Builds[0].Binary, docker.Binary)
	assert.Equal(t, "Dockerfile", docker.Dockerfile)
	assert.Equal(t, "{{ .Version }}", docker.TagTemplate)
}

func TestDefaultNoDockers(t *testing.T) {
	var ctx = &context.Context{
		Config: config.Project{
			Dockers: []config.Docker{},
		},
	}
	assert.NoError(t, Pipe{}.Default(ctx))
	assert.Empty(t, ctx.Config.Dockers)
}

func TestDefaultSet(t *testing.T) {
	var ctx = &context.Context{
		Config: config.Project{
			Dockers: []config.Docker{
				{
					Goos:       "windows",
					Goarch:     "i386",
					Binary:     "bar",
					Dockerfile: "Dockerfile.foo",
				},
			},
		},
	}
	assert.NoError(t, Pipe{}.Default(ctx))
	assert.Len(t, ctx.Config.Dockers, 1)
	var docker = ctx.Config.Dockers[0]
	assert.Equal(t, "windows", docker.Goos)
	assert.Equal(t, "i386", docker.Goarch)
	assert.Equal(t, "bar", docker.Binary)
	assert.Equal(t, "{{ .Version }}", docker.TagTemplate)
	assert.Equal(t, "Dockerfile.foo", docker.Dockerfile)
}
<|endoftext|>