<commit_before>// Copyright 2015 The Mangos Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use 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 nanomsg

import (
	"testing"
	"time"
)

type creqTest struct {
	cur   uint32
	tot   uint32
	ok    bool
	debug bool
	addr  string
	sock  *Socket
	done  chan struct{}
	t     *testing.T
}

type crepTest struct {
	cur   uint32
	tot   uint32
	ok    bool
	debug bool
	addr  string
	sock  *Socket
	done  chan struct{}
	t     *testing.T
}

// For now, we take a very simple pairwise approach to req/rep.  We should
// consider additional tests for raw mode multiple responders.

func (rt *creqTest) Init(t *testing.T, addr string, num uint32) bool {
	var e error
	if rt.sock, e = NewSocket(AF_SP, REQ); e != nil {
		t.Errorf("NewSocket(): %v", e)
		return false
	}
	if e = rt.sock.SetSendTimeout(time.Second); e != nil {
		t.Errorf("Failed SetSendTimeout: %s", e)
		return false
	}
	if e = rt.sock.SetRecvTimeout(time.Second); e != nil {
		t.Errorf("Failed SetRecvTimeout: %s", e)
		return false
	}
	rt.t = t
	rt.cur = 0
	rt.tot = num
	rt.addr = addr
	rt.done = make(chan struct{})
	return true
}

func (rt *creqTest) Finish() {
	rt.ok = rt.cur == rt.tot
	close(rt.done)
}

func (rt *creqTest) DoTest() bool {
	defer rt.Finish()
	if _, err := rt.sock.Connect(rt.addr); err != nil {
		rt.t.Fatalf("Failed to connect: %s", err)
	}
	for rt.cur < rt.tot {
		var e error
		var n int
		m := make([]byte, 1)
		m[0] = byte(rt.cur)

		if rt.debug {
			rt.t.Logf("Send request %d", rt.cur)
		}
		if n, e = rt.sock.Send(m, 0); n != 1 || e != nil {
			rt.t.Errorf("%d/%d: Failed to send, %d sent, err %s", rt.cur, rt.tot, n, e)
			return false
		}
		if rt.debug {
			rt.t.Logf("Sent request %d", rt.cur)
		}

		m, e = rt.sock.Recv(0)
		if e != nil {
			rt.t.Errorf("%d/%d: Failed to recv reply: %s", rt.cur, rt.tot, e)
			return false
		}
		if len(m) != 1 {
			rt.t.Errorf("%d/%d: Got wrong length: %d != 1", rt.cur, rt.tot, len(m))
			return false
		}
		if m[0] != byte(rt.cur) {
			rt.t.Errorf("%d/%d: Got wrong reply: %d != %d", rt.cur, rt.tot, m[0], byte(rt.cur))
			return false
		}
		if rt.debug {
			rt.t.Logf("Got good reply %d", rt.cur)
		}
		rt.cur++
	}
	rt.t.Logf("Req got all %d replies", rt.cur)
	return true
}

func (rt *crepTest) Init(t *testing.T, addr string, num uint32) bool {
	var e error
	if rt.sock, e = NewSocket(AF_SP, REP); e != nil {
		t.Errorf("NewSocket(): %v", e)
		return false
	}
	if e = rt.sock.SetSendTimeout(time.Second); e != nil {
		t.Errorf("Failed SetSendTimeout: %s", e)
		return false
	}
	if e = rt.sock.SetRecvTimeout(time.Second); e != nil {
		t.Errorf("Failed SetRecvTimeout: %s", e)
		return false
	}
	rt.t = t
	rt.cur = 0
	rt.tot = num
	rt.addr = addr
	rt.done = make(chan struct{})
	return true
}

func (rt *crepTest) Finish() {
	rt.sock.Close()
	rt.ok = rt.cur == rt.tot
	if !rt.ok {
		close(rt.done)
	}
}

func (rt *crepTest) DoTest() bool {
	defer rt.Finish()
	if _, err := rt.sock.Bind(rt.addr); err != nil {
		rt.t.Errorf("Failed Bind: %s", err)
		return false
	}

	for rt.cur < rt.tot {
		var m []byte
		var e error
		var n int

		if rt.debug {
			rt.t.Logf("Wait for request %d", rt.cur)
		}
		if m, e = rt.sock.Recv(0); e != nil {
			rt.t.Errorf("%d/%d: Failed to recv request: %s", rt.cur, rt.tot, e)
			return false
		}
		if len(m) != 1 {
			rt.t.Errorf("%d/%d: Got wrong length: %d != 1", rt.cur, rt.tot, len(m))
			return false
		}
		if m[0] != byte(rt.cur) {
			rt.t.Errorf("%d/%d: Got wrong request: %d != %d", rt.cur, rt.tot, m[0], byte(rt.cur))
			return false
		}
		if rt.debug {
			rt.t.Logf("Got good request %d", rt.cur)
		}

		if n, e = rt.sock.Send(m, 0); e != nil || n != 1 {
			rt.t.Errorf("%d/%d: Failed to send reply: %v", rt.cur, rt.tot, e)
			return false
		}
		if rt.debug {
			rt.t.Logf("Sent reply %d", rt.cur)
		}
		rt.cur++
	}
	rt.t.Logf("Rep sent %d replies", rt.cur)
	return true
}

func ReqRepCompat(t *testing.T, addr string, num uint32) {
	req := &creqTest{}
	rep := &crepTest{}
	req.Init(t, addr, num)
	rep.Init(t, addr, num)

	t.Logf("Doing %d exchanges", num)

	go func() {
		rep.ok = rep.DoTest()
	}()

	go func() {
		req.ok = req.DoTest()
	}()

	t.Logf("Waiting for tests to complete")

	select {
	case <-req.done:
		t.Logf("Req complete")
		break
	case <-rep.done:
		t.Logf("Rep complete")
		break
	}

	req.sock.Close()
	rep.sock.Close()
}

func TestCompatTCP(t *testing.T) {
	addr := "tcp://127.0.0.1:34444"
	ReqRepCompat(t, addr, 50000)
}

func TestCompatInp(t *testing.T) {
	addr := "inproc:///SOMENAME"
	ReqRepCompat(t, addr, 500000)
}

// Don't do this right now.  There was a request at one point for send to
// timeout when no transport was present.  But that semantic is diametrically
// opposed with guaranteed delivery.  The only time we block or timeout is
// if there is backpressure.
func TestCompatSendTimeout(t *testing.T) {

	addr := "tcp://127.0.0.1:19"
	push, err := NewSocket(AF_SP, PUSH)
	if err != nil {
		t.Errorf("NewSocket: %v", err)
		return
	}
	if err = push.SetSendTimeout(time.Duration(3000) * time.Millisecond); err != nil {
		t.Errorf("SetSendTimeout: %v", err)
		return
	}
	if _, err = push.Connect(addr); err != nil {
		t.Errorf("Connect: %v", err)
		return
	}
	t.Logf("Trying to send (should timeout)")
	_, err = push.Send([]byte("TEST"), 0)
	if err == nil {
		t.Errorf("Passed, but should have timed out")
		return
	}
	t.Logf("Expected timeout, got %v", err)
}
<commit_msg>fixes #192 Fail in go 1.6 test<commit_after>// Copyright 2016 The Mangos Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use 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 nanomsg

import (
	"testing"
	"time"
)

type creqTest struct {
	cur   uint32
	tot   uint32
	ok    bool
	debug bool
	addr  string
	sock  *Socket
	done  chan struct{}
	t     *testing.T
}

type crepTest struct {
	cur   uint32
	tot   uint32
	ok    bool
	debug bool
	addr  string
	sock  *Socket
	done  chan struct{}
	t     *testing.T
}

// For now, we take a very simple pairwise approach to req/rep.  We should
// consider additional tests for raw mode multiple responders.

func (rt *creqTest) Init(t *testing.T, addr string, num uint32) bool {
	var e error
	if rt.sock, e = NewSocket(AF_SP, REQ); e != nil {
		t.Errorf("NewSocket(): %v", e)
		return false
	}
	if e = rt.sock.SetSendTimeout(time.Second); e != nil {
		t.Errorf("Failed SetSendTimeout: %s", e)
		return false
	}
	if e = rt.sock.SetRecvTimeout(time.Second); e != nil {
		t.Errorf("Failed SetRecvTimeout: %s", e)
		return false
	}
	rt.t = t
	rt.cur = 0
	rt.tot = num
	rt.addr = addr
	rt.done = make(chan struct{})
	return true
}

func (rt *creqTest) Finish() {
	rt.ok = rt.cur == rt.tot
	close(rt.done)
}

func (rt *creqTest) DoTest() bool {
	defer rt.Finish()
	if _, err := rt.sock.Connect(rt.addr); err != nil {
		rt.t.Fatalf("Failed to connect: %s", err)
	}
	for rt.cur < rt.tot {
		var e error
		var n int
		m := make([]byte, 1)
		m[0] = byte(rt.cur)

		if rt.debug {
			rt.t.Logf("Send request %d", rt.cur)
		}
		if n, e = rt.sock.Send(m, 0); n != 1 || e != nil {
			rt.t.Errorf("%d/%d: Failed to send, %d sent, err %s", rt.cur, rt.tot, n, e)
			return false
		}
		if rt.debug {
			rt.t.Logf("Sent request %d", rt.cur)
		}

		m, e = rt.sock.Recv(0)
		if e != nil {
			rt.t.Errorf("%d/%d: Failed to recv reply: %s", rt.cur, rt.tot, e)
			return false
		}
		if len(m) != 1 {
			rt.t.Errorf("%d/%d: Got wrong length: %d != 1", rt.cur, rt.tot, len(m))
			return false
		}
		if m[0] != byte(rt.cur) {
			rt.t.Errorf("%d/%d: Got wrong reply: %d != %d", rt.cur, rt.tot, m[0], byte(rt.cur))
			return false
		}
		if rt.debug {
			rt.t.Logf("Got good reply %d", rt.cur)
		}
		rt.cur++
	}
	rt.t.Logf("Req got all %d replies", rt.cur)
	return true
}

func (rt *crepTest) Init(t *testing.T, addr string, num uint32) bool {
	var e error
	if rt.sock, e = NewSocket(AF_SP, REP); e != nil {
		t.Errorf("NewSocket(): %v", e)
		return false
	}
	if e = rt.sock.SetSendTimeout(time.Second); e != nil {
		t.Errorf("Failed SetSendTimeout: %s", e)
		return false
	}
	if e = rt.sock.SetRecvTimeout(time.Second); e != nil {
		t.Errorf("Failed SetRecvTimeout: %s", e)
		return false
	}
	rt.t = t
	rt.cur = 0
	rt.tot = num
	rt.addr = addr
	rt.done = make(chan struct{})
	return true
}

func (rt *crepTest) Finish() {
	rt.ok = rt.cur == rt.tot
	close(rt.done)
}

func (rt *crepTest) DoTest() bool {
	defer rt.Finish()
	if _, err := rt.sock.Bind(rt.addr); err != nil {
		rt.t.Errorf("Failed Bind: %s", err)
		return false
	}

	for rt.cur < rt.tot {
		var m []byte
		var e error
		var n int

		if rt.debug {
			rt.t.Logf("Wait for request %d", rt.cur)
		}
		if m, e = rt.sock.Recv(0); e != nil {
			rt.t.Errorf("%d/%d: Failed to recv request: %s", rt.cur, rt.tot, e)
			return false
		}
		if len(m) != 1 {
			rt.t.Errorf("%d/%d: Got wrong length: %d != 1", rt.cur, rt.tot, len(m))
			return false
		}
		if m[0] != byte(rt.cur) {
			rt.t.Errorf("%d/%d: Got wrong request: %d != %d", rt.cur, rt.tot, m[0], byte(rt.cur))
			return false
		}
		if rt.debug {
			rt.t.Logf("Got good request %d", rt.cur)
		}

		if n, e = rt.sock.Send(m, 0); e != nil || n != 1 {
			rt.t.Errorf("%d/%d: Failed to send reply: %v", rt.cur, rt.tot, e)
			return false
		}
		if rt.debug {
			rt.t.Logf("Sent reply %d", rt.cur)
		}
		rt.cur++
	}
	rt.t.Logf("Rep sent %d replies", rt.cur)
	return true
}

func ReqRepCompat(t *testing.T, addr string, num uint32) {
	req := &creqTest{}
	rep := &crepTest{}
	req.Init(t, addr, num)
	rep.Init(t, addr, num)

	t.Logf("Doing %d exchanges", num)

	go func() {
		rep.ok = rep.DoTest()
	}()

	go func() {
		req.ok = req.DoTest()
	}()

	t.Logf("Waiting for tests to complete")

	<-rep.done
	t.Logf("Rep complete")

	<-req.done
	t.Logf("Req complete")

	req.sock.Close()
	rep.sock.Close()
}

func TestCompatTCP(t *testing.T) {
	addr := "tcp://127.0.0.1:34444"
	ReqRepCompat(t, addr, 50000)
}

func TestCompatInp(t *testing.T) {
	addr := "inproc:///SOMENAME"
	ReqRepCompat(t, addr, 500000)
}

// Don't do this right now.  There was a request at one point for send to
// timeout when no transport was present.  But that semantic is diametrically
// opposed with guaranteed delivery.  The only time we block or timeout is
// if there is backpressure.
func TestCompatSendTimeout(t *testing.T) {

	addr := "tcp://127.0.0.1:19"
	push, err := NewSocket(AF_SP, PUSH)
	if err != nil {
		t.Errorf("NewSocket: %v", err)
		return
	}
	if err = push.SetSendTimeout(time.Duration(3000) * time.Millisecond); err != nil {
		t.Errorf("SetSendTimeout: %v", err)
		return
	}
	if _, err = push.Connect(addr); err != nil {
		t.Errorf("Connect: %v", err)
		return
	}
	t.Logf("Trying to send (should timeout)")
	_, err = push.Send([]byte("TEST"), 0)
	if err == nil {
		t.Errorf("Passed, but should have timed out")
		return
	}
	t.Logf("Expected timeout, got %v", err)
}
<|endoftext|>


<commit_before>package discovery

import (
	"context"
	"time"

	cid "github.com/ipfs/go-cid"
	pstore "github.com/libp2p/go-libp2p-peerstore"
	routing "github.com/libp2p/go-libp2p-routing"
	mh "github.com/multiformats/go-multihash"
)

// RoutingDiscovery is an implementation of discovery using ContentRouting
// Namespaces are translated to Cids using the SHA256 hash.
type RoutingDiscovery struct {
	routing.ContentRouting
}

func NewRoutingDiscovery(router routing.ContentRouting) *RoutingDiscovery {
	return &RoutingDiscovery{router}
}

func (d *RoutingDiscovery) Advertise(ctx context.Context, ns string, opts ...Option) (time.Duration, error) {
	cid, err := nsToCid(ns)
	if err != nil {
		return 0, err
	}

	// this context requires a timeout or else the DHT may never find any peers
	pctx, cancel := context.WithTimeout(ctx, 60*time.Second)
	defer cancel()

	err = d.Provide(pctx, cid, true)
	if err != nil {
		return 0, err
	}

	// the DHT provider record validity is 24hrs, but it is recommnded to republish every 6hrs
	return 6 * time.Hour, nil
}

func (d *RoutingDiscovery) FindPeers(ctx context.Context, ns string, opts ...Option) (<-chan pstore.PeerInfo, error) {
	var options Options
	err := options.Apply(opts...)
	if err != nil {
		return nil, err
	}

	limit := options.Limit
	if limit == 0 {
		limit = 100 // that's just arbitrary, but FindProvidersAsync needs a count
	}

	cid, err := nsToCid(ns)
	if err != nil {
		return nil, err
	}

	return d.FindProvidersAsync(ctx, cid, limit), nil
}

func nsToCid(ns string) (cid.Cid, error) {
	h, err := mh.Sum([]byte(ns), mh.SHA2_256, -1)
	if err != nil {
		return cid.Undef, err
	}

	return cid.NewCidV1(cid.Raw, h), nil
}
<commit_msg>clarify comment.<commit_after>package discovery

import (
	"context"
	"time"

	cid "github.com/ipfs/go-cid"
	pstore "github.com/libp2p/go-libp2p-peerstore"
	routing "github.com/libp2p/go-libp2p-routing"
	mh "github.com/multiformats/go-multihash"
)

// RoutingDiscovery is an implementation of discovery using ContentRouting
// Namespaces are translated to Cids using the SHA256 hash.
type RoutingDiscovery struct {
	routing.ContentRouting
}

func NewRoutingDiscovery(router routing.ContentRouting) *RoutingDiscovery {
	return &RoutingDiscovery{router}
}

func (d *RoutingDiscovery) Advertise(ctx context.Context, ns string, opts ...Option) (time.Duration, error) {
	cid, err := nsToCid(ns)
	if err != nil {
		return 0, err
	}

	// this context requires a timeout; it determines how long the DHT looks for
	// closest peers to the key/CID before it goes on to provide the record to them.
	// Not setting a timeout here will make the DHT wander forever.
	pctx, cancel := context.WithTimeout(ctx, 60*time.Second)
	defer cancel()

	err = d.Provide(pctx, cid, true)
	if err != nil {
		return 0, err
	}

	// the DHT provider record validity is 24hrs, but it is recommnded to republish every 6hrs
	return 6 * time.Hour, nil
}

func (d *RoutingDiscovery) FindPeers(ctx context.Context, ns string, opts ...Option) (<-chan pstore.PeerInfo, error) {
	var options Options
	err := options.Apply(opts...)
	if err != nil {
		return nil, err
	}

	limit := options.Limit
	if limit == 0 {
		limit = 100 // that's just arbitrary, but FindProvidersAsync needs a count
	}

	cid, err := nsToCid(ns)
	if err != nil {
		return nil, err
	}

	return d.FindProvidersAsync(ctx, cid, limit), nil
}

func nsToCid(ns string) (cid.Cid, error) {
	h, err := mh.Sum([]byte(ns), mh.SHA2_256, -1)
	if err != nil {
		return cid.Undef, err
	}

	return cid.NewCidV1(cid.Raw, h), nil
}
<|endoftext|>


<commit_before>package bst

import (
	"fmt"
	"testing"
)

func TestDelete(t *testing.T) {
	root := NewNode(Float64(1))
	data := New(root)

	slice := []float64{3, 9, 13, 17, 20, 25, 39, 16, 15, 2, 2.5}
	for _, num := range slice {
		data.Insert(NewNode(Float64(num)))
	}

	if fmt.Sprintf("%s", data) != "[1 [[2 [2.5]] 3 [9 [13 [[[15] 16] 17 [20 [25 [39]]]]]]]]" {
		t.Fatalf("Not expected output: %s\n", data)
	}

	if fmt.Sprintf("%s", data.Search(Float64(20))) != "[20 [25 [39]]]" {
		t.Fatalf("Not expected output: %s\n", data)
	}

	if data.Max().Key != Float64(39.0) {
		t.Fatalf("Expected 39.0 but %f", data.Max().Key)
	}

	if data.Min().Key != Float64(1.0) {
		t.Fatalf("Expected 1.0 but %f", data.Min().Key)
	}

	if data.SearchParent(Float64(16)).Key != Float64(17.0) {
		t.Fatalf("Expected 17.0 but %f", data.SearchParent(Float64(16)).Key)
	}

	if data.Search(Float64(39)).Right != nil {
		t.Fatal("39's Right child must be nil")
	}
	if data.Search(Float64(25)).Left != nil {
		t.Fatal("25's Left child must be nil")
	}

	deletes := []float64{13, 17, 3, 15, 1}
	for _, num := range deletes {
		data.Delete(data.Search(Float64(num)))

		t.Logf("Deleted: %f\n", num)

		if data.Search(Float64(num)) != nil {
			t.Fatal(num, "must be nil")
		}
		if data.Search(Float64(1000.12)) != nil {
			t.Fatal(1000.12, "must be nil")
		}

		switch num {
		case 13:
			if data.Search(Float64(9)).Right.Key != Float64(17) {
				t.Fatal("9's Right child must be 17")
			}
			if data.SearchParent(Float64(17)).Key != Float64(9) {
				t.Fatal("17's Parent must be 9")
			}
			if data.Search(Float64(17)).Left.Key != Float64(16) {
				t.Fatal("17's Left child must be 16")
			}

		case 17:
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left.Key != Float64(15) {
				t.Fatal("16's Left must be 15")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.SearchParent(Float64(15)).Key != Float64(16) {
				t.Fatal("15's Parent must be 16")
			}

		case 3:
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left.Key != Float64(15) {
				t.Fatal("16's Left must be 15")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.SearchParent(Float64(15)).Key != Float64(16) {
				t.Fatal("15's Parent must be 16")
			}
			if data.SearchParent(Float64(2)).Key != Float64(2.5) {
				t.Fatal("2's Parent must be 2.5")
			}
			if data.Search(Float64(2.5)).Left.Key != Float64(2) {
				t.Fatal("2.5's Left must be 2")
			}
			if data.Search(Float64(2.5)).Right.Key != Float64(9) {
				t.Fatal("2.5's Right must be 9")
			}
			if data.Search(Float64(1)).Right.Key != Float64(2.5) {
				t.Fatal("1's Right must be 2.5")
			}
			if data.Search(Float64(1)).Left != nil {
				t.Fatal("1's Left must be nil")
			}

		case 15:
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.SearchParent(Float64(2)).Key != Float64(2.5) {
				t.Fatal("2's Parent must be 2.5")
			}
			if data.Search(Float64(2.5)).Left.Key != Float64(2) {
				t.Fatal("2.5's Left must be 2")
			}
			if data.Search(Float64(2.5)).Right.Key != Float64(9) {
				t.Fatal("2.5's Right must be 9")
			}
			if data.Search(Float64(1)).Right.Key != Float64(2.5) {
				t.Fatal("1's Right must be 2.5")
			}
			if data.Search(Float64(1)).Left != nil {
				t.Fatal("1's Left must be nil")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}

		case 1:
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.Search(Float64(2.5)).Right.Key != Float64(9) {
				t.Fatal("2.5's Right must be 9")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}
			if data.Search(Float64(2.5)).Left.Key != Float64(2) {
				t.Fatalf("2.5's Left must be 2 but %s\n", data.Search(Float64(2.5)).Left)
			}
			if data.SearchParent(Float64(2)).Key != Float64(2.5) {
				t.Fatal("2's Parent must be 2.5")
			}
			if data.Search(Float64(2)).Right != nil {
				t.Fatal("2's Right must be nil")
			}
			if data.SearchParent(Float64(2.5)) != nil {
				t.Fatal("2.5's Parent must be nil")
			}
			if data.Root.Key != Float64(2.5) {
				t.Fatal("Root must be 2")
			}

		default:
			t.Fatal(num, "shouldn't be there...")
		}
	}
}
<commit_msg>add more tests<commit_after>package bst

import (
	"fmt"
	"testing"
)

func TestDelete(t *testing.T) {
	root := NewNode(Float64(1))
	data := New(root)

	slice := []float64{3, 9, 13, 17, 20, 25, 39, 16, 15, 2, 2.5}
	for _, num := range slice {
		data.Insert(NewNode(Float64(num)))
	}

	if fmt.Sprintf("%s", data) != "[1 [[2 [2.5]] 3 [9 [13 [[[15] 16] 17 [20 [25 [39]]]]]]]]" {
		t.Fatalf("Not expected output: %s\n", data)
	}

	if fmt.Sprintf("%s", data.Search(Float64(20))) != "[20 [25 [39]]]" {
		t.Fatalf("Not expected output: %s\n", data)
	}

	if data.Max().Key != Float64(39.0) {
		t.Fatalf("Expected 39.0 but %f", data.Max().Key)
	}

	if data.Min().Key != Float64(1.0) {
		t.Fatalf("Expected 1.0 but %f", data.Min().Key)
	}

	if data.SearchParent(Float64(16)).Key != Float64(17.0) {
		t.Fatalf("Expected 17.0 but %f", data.SearchParent(Float64(16)).Key)
	}

	if data.Search(Float64(39)).Right != nil {
		t.Fatal("39's Right child must be nil")
	}
	if data.Search(Float64(25)).Left != nil {
		t.Fatal("25's Left child must be nil")
	}

	deletes := []float64{13, 17, 3, 15, 1, 2.5}
	for _, num := range deletes {
		data.Delete(data.Search(Float64(num)))

		t.Logf("Deleted: %f\n", num)

		if data.Search(Float64(num)) != nil {
			t.Fatal(num, "must be nil")
		}
		if data.Search(Float64(1000.12)) != nil {
			t.Fatal(1000.12, "must be nil")
		}

		switch num {
		case 13:
			if data.Search(Float64(9)).Right.Key != Float64(17) {
				t.Fatal("9's Right child must be 17")
			}
			if data.SearchParent(Float64(17)).Key != Float64(9) {
				t.Fatal("17's Parent must be 9")
			}
			if data.Search(Float64(17)).Left.Key != Float64(16) {
				t.Fatal("17's Left child must be 16")
			}

		case 17:
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left.Key != Float64(15) {
				t.Fatal("16's Left must be 15")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.SearchParent(Float64(15)).Key != Float64(16) {
				t.Fatal("15's Parent must be 16")
			}

		case 3:
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left.Key != Float64(15) {
				t.Fatal("16's Left must be 15")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.SearchParent(Float64(15)).Key != Float64(16) {
				t.Fatal("15's Parent must be 16")
			}
			if data.SearchParent(Float64(2)).Key != Float64(2.5) {
				t.Fatal("2's Parent must be 2.5")
			}
			if data.Search(Float64(2.5)).Left.Key != Float64(2) {
				t.Fatal("2.5's Left must be 2")
			}
			if data.Search(Float64(2.5)).Right.Key != Float64(9) {
				t.Fatal("2.5's Right must be 9")
			}
			if data.Search(Float64(1)).Right.Key != Float64(2.5) {
				t.Fatal("1's Right must be 2.5")
			}
			if data.Search(Float64(1)).Left != nil {
				t.Fatal("1's Left must be nil")
			}

		case 15:
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.SearchParent(Float64(2)).Key != Float64(2.5) {
				t.Fatal("2's Parent must be 2.5")
			}
			if data.Search(Float64(2.5)).Left.Key != Float64(2) {
				t.Fatal("2.5's Left must be 2")
			}
			if data.Search(Float64(2.5)).Right.Key != Float64(9) {
				t.Fatal("2.5's Right must be 9")
			}
			if data.Search(Float64(1)).Right.Key != Float64(2.5) {
				t.Fatal("1's Right must be 2.5")
			}
			if data.Search(Float64(1)).Left != nil {
				t.Fatal("1's Left must be nil")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}

		case 1:
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.Search(Float64(2.5)).Right.Key != Float64(9) {
				t.Fatal("2.5's Right must be 9")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}
			if data.Search(Float64(2.5)).Left.Key != Float64(2) {
				t.Fatalf("2.5's Left must be 2 but %s\n", data.Search(Float64(2.5)).Left)
			}
			if data.SearchParent(Float64(2)).Key != Float64(2.5) {
				t.Fatal("2's Parent must be 2.5")
			}
			if data.Search(Float64(2)).Right != nil {
				t.Fatal("2's Right must be nil")
			}
			if data.SearchParent(Float64(2.5)) != nil {
				t.Fatal("2.5's Parent must be nil")
			}
			if data.Root.Key != Float64(2.5) {
				t.Fatal("Root must be 2.5")
			}

		case 2.5:
			if data.Search(Float64(2)).Right.Key != Float64(9) {
				t.Fatal("2's Right child must be 9")
			}
			if data.Search(Float64(9)).Right.Key != Float64(16) {
				t.Fatal("9's Right child must be 16")
			}
			if data.SearchParent(Float64(2)) != nil {
				t.Fatal("2's Parent must be nil")
			}
			if data.SearchParent(Float64(16)).Key != Float64(9) {
				t.Fatal("16's Parent must be 9")
			}
			if data.Search(Float64(16)).Right.Key != Float64(20) {
				t.Fatal("16's Right child must be 20")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}
			if data.SearchParent(Float64(20)).Key != Float64(16) {
				t.Fatal("20's Parent must be 16")
			}
			if data.Search(Float64(2.5)) != nil {
				t.Fatal("2.5's Right must be nil")
			}
			if data.Search(Float64(16)).Left != nil {
				t.Fatal("16's Left must be nil")
			}
			if data.Search(Float64(2)).Right.Key != Float64(9) {
				t.Fatal("2's Right must be 9")
			}
			if data.Root.Key != Float64(2) {
				t.Fatal("Root must be 2")
			}

		default:
			t.Fatal(num, "shouldn't be there...")
		}
	}
}
<|endoftext|>


<commit_before>package crypto

import (
	"crypto/x509"
	"errors"

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

// CertManager manages the certificates sent by the server
type CertManager interface {
	SetData([]byte) error
	GetLeafCert() []byte
	VerifyServerProof(proof, chlo, serverConfigData []byte) (bool, error)
	Verify(hostname string) error
}

type certManager struct {
	chain []*x509.Certificate
}

var _ CertManager = &certManager{}

var errNoCertificateChain = errors.New("CertManager BUG: No certicifate chain loaded")

// NewCertManager creates a new CertManager
func NewCertManager() CertManager {
	return &certManager{}
}

// SetData takes the byte-slice sent in the SHLO and decompresses it into the certificate chain
func (c *certManager) SetData(data []byte) error {
	byteChain, err := decompressChain(data)
	if err != nil {
		return qerr.Error(qerr.InvalidCryptoMessageParameter, "Certificate data invalid")
	}

	chain := make([]*x509.Certificate, len(byteChain), len(byteChain))
	for i, data := range byteChain {
		cert, err := x509.ParseCertificate(data)
		if err != nil {
			return err
		}
		chain[i] = cert
	}

	c.chain = chain
	return nil
}

// GetLeafCert returns the leaf certificate of the certificate chain
// it errors if the certificate chain has not yet been set
func (c *certManager) GetLeafCert() []byte {
	if len(c.chain) == 0 {
		return nil
	}
	return c.chain[0].Raw
}

func (c *certManager) VerifyServerProof(proof, chlo, serverConfigData []byte) (bool, error) {
	if len(c.chain) == 0 {
		return false, errNoCertificateChain
	}

	return verifyServerProof(proof, c.chain[0], chlo, serverConfigData), nil
}

func (c *certManager) Verify(hostname string) error {
	if len(c.chain) == 0 {
		return errNoCertificateChain
	}

	leafCert, err := x509.ParseCertificate(c.GetLeafCert())
	if err != nil {
		return err
	}

	opts := x509.VerifyOptions{DNSName: hostname}

	// the first certificate is the leaf certificate, all others are intermediates
	if len(c.chain) > 1 {
		intermediates := x509.NewCertPool()
		for i := 1; i < len(c.chain); i++ {
			intermediates.AddCert(c.chain[i])
		}
		opts.Intermediates = intermediates
	}

	_, err = leafCert.Verify(opts)
	return err
}
<commit_msg>simplify certificate verification in certManager<commit_after>package crypto

import (
	"crypto/x509"
	"errors"

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

// CertManager manages the certificates sent by the server
type CertManager interface {
	SetData([]byte) error
	GetLeafCert() []byte
	VerifyServerProof(proof, chlo, serverConfigData []byte) (bool, error)
	Verify(hostname string) error
}

type certManager struct {
	chain []*x509.Certificate
}

var _ CertManager = &certManager{}

var errNoCertificateChain = errors.New("CertManager BUG: No certicifate chain loaded")

// NewCertManager creates a new CertManager
func NewCertManager() CertManager {
	return &certManager{}
}

// SetData takes the byte-slice sent in the SHLO and decompresses it into the certificate chain
func (c *certManager) SetData(data []byte) error {
	byteChain, err := decompressChain(data)
	if err != nil {
		return qerr.Error(qerr.InvalidCryptoMessageParameter, "Certificate data invalid")
	}

	chain := make([]*x509.Certificate, len(byteChain), len(byteChain))
	for i, data := range byteChain {
		cert, err := x509.ParseCertificate(data)
		if err != nil {
			return err
		}
		chain[i] = cert
	}

	c.chain = chain
	return nil
}

// GetLeafCert returns the leaf certificate of the certificate chain
// it errors if the certificate chain has not yet been set
func (c *certManager) GetLeafCert() []byte {
	if len(c.chain) == 0 {
		return nil
	}
	return c.chain[0].Raw
}

func (c *certManager) VerifyServerProof(proof, chlo, serverConfigData []byte) (bool, error) {
	if len(c.chain) == 0 {
		return false, errNoCertificateChain
	}

	return verifyServerProof(proof, c.chain[0], chlo, serverConfigData), nil
}

// Verify verifies the certificate chain
func (c *certManager) Verify(hostname string) error {
	if len(c.chain) == 0 {
		return errNoCertificateChain
	}

	leafCert := c.chain[0]
	opts := x509.VerifyOptions{DNSName: hostname}

	// the first certificate is the leaf certificate, all others are intermediates
	if len(c.chain) > 1 {
		intermediates := x509.NewCertPool()
		for i := 1; i < len(c.chain); i++ {
			intermediates.AddCert(c.chain[i])
		}
		opts.Intermediates = intermediates
	}

	_, err := leafCert.Verify(opts)
	return err
}
<|endoftext|>


<commit_before>// +build linux, arm

// **********************************************************************
//    Copyright (c) 2017 Henry Seurer
//
//   Permission is hereby granted, free of charge, to any person
//    obtaining a copy of this software and associated documentation
//    files (the "Software"), to deal in the Software without
//    restriction, including without limitation the rights to use,
//    copy, modify, merge, publish, distribute, sublicense, and/or sell
//    copies of the Software, and to permit persons to whom the
//    Software is furnished to do so, subject to the following
//    conditions:
//
//   The above copyright notice and this permission notice shall be
//   included in all copies or substantial portions of the Software.
//
//    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//    OTHER DEALINGS IN THE SOFTWARE.
//
// **********************************************************************

package wiringpi

/*
#cgo LDFLAGS: -lwiringPi
#cgo CFLAGS: -O0

#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>
#include <stdlib.h>
#define nil ((void*)0)

#define GEN_INTERRUPTER(PIN) static void interrupt_handler_##PIN() { \
	context ctxt;   \
	ctxt.pin = PIN;  \
	ctxt.ret = PIN;  \
	callback_func(goCallback, &ctxt); \
}

typedef struct context context;
struct context {
	int pin;
	int ret;
};

static void(*callback_func)(void (*f)(void*), void*);

extern void goCallback(void *);

GEN_INTERRUPTER(0)
GEN_INTERRUPTER(1)
GEN_INTERRUPTER(2)
GEN_INTERRUPTER(3)
GEN_INTERRUPTER(4)
GEN_INTERRUPTER(5)
GEN_INTERRUPTER(6)
GEN_INTERRUPTER(7)
GEN_INTERRUPTER(8)
GEN_INTERRUPTER(9)
GEN_INTERRUPTER(10)
GEN_INTERRUPTER(11)
GEN_INTERRUPTER(12)
GEN_INTERRUPTER(13)
GEN_INTERRUPTER(14)
GEN_INTERRUPTER(15)
GEN_INTERRUPTER(16)
GEN_INTERRUPTER(17)
GEN_INTERRUPTER(18)
GEN_INTERRUPTER(19)
GEN_INTERRUPTER(20)

static int native_wiring_isr(int pin, int mode) {
	switch(pin) {
		case 0: return wiringPiISR(pin, mode, &interrupt_handler_0);
		case 1: return wiringPiISR(pin, mode, &interrupt_handler_1);
		case 2: return wiringPiISR(pin, mode, &interrupt_handler_2);
		case 3: return wiringPiISR(pin, mode, &interrupt_handler_3);
		case 4: return wiringPiISR(pin, mode, &interrupt_handler_4);
		case 5: return wiringPiISR(pin, mode, &interrupt_handler_5);
		case 6: return wiringPiISR(pin, mode, &interrupt_handler_6);
		case 7: return wiringPiISR(pin, mode, &interrupt_handler_7);
		case 8: return wiringPiISR(pin, mode, &interrupt_handler_8);
		case 9: return wiringPiISR(pin, mode, &interrupt_handler_9);
		case 10: return wiringPiISR(pin, mode, &interrupt_handler_10);
		case 11: return wiringPiISR(pin, mode, &interrupt_handler_11);
		case 12: return wiringPiISR(pin, mode, &interrupt_handler_12);
		case 13: return wiringPiISR(pin, mode, &interrupt_handler_13);
		case 14: return wiringPiISR(pin, mode, &interrupt_handler_14);
		case 15: return wiringPiISR(pin, mode, &interrupt_handler_15);
		case 16: return wiringPiISR(pin, mode, &interrupt_handler_16);
		case 17: return wiringPiISR(pin, mode, &interrupt_handler_17);
		case 18: return wiringPiISR(pin, mode, &interrupt_handler_18);
		case 19: return wiringPiISR(pin, mode, &interrupt_handler_19);
		case 20: return wiringPiISR(pin, mode, &interrupt_handler_20);
	}
	return -1;
}

static void init(void *p) {
	callback_func = p;
}
*/
import "C"
import "unsafe"

import (
	"sync"
)

const (
	WPI_MODE_PINS          = C.WPI_MODE_PINS
	WPI_MODE_GPIO          = C.WPI_MODE_GPIO
	WPI_MODE_GPIO_SYS      = C.WPI_MODE_GPIO_SYS
	WPI_MODE_PIFACE        = C.WPI_MODE_PIFACE
	WPI_MODE_UNINITIALISED = C.WPI_MODE_UNINITIALISED

	INPUT      = C.INPUT
	OUTPUT     = C.OUTPUT
	PWM_OUTPUT = C.PWM_OUTPUT
	GPIO_CLOCK = C.GPIO_CLOCK

	LOW  = C.LOW
	HIGH = C.HIGH

	PUD_OFF  = C.PUD_OFF
	PUD_DOWN = C.PUD_DOWN
	PUD_UP   = C.PUD_UP

	PWM_MODE_MS  = C.PWM_MODE_MS
	PWM_MODE_BAL = C.PWM_MODE_BAL

	INT_EDGE_SETUP   = C.INT_EDGE_SETUP
	INT_EDGE_FALLING = C.INT_EDGE_FALLING
	INT_EDGE_RISING  = C.INT_EDGE_RISING
	INT_EDGE_BOTH    = C.INT_EDGE_BOTH
)

var mutex = &sync.Mutex{}

func internalPinToGpio(pin int) int {
	return int(C.wpiPinToGpio(C.int(pin)))
}

func internalSetup() int {
	return int(C.wiringPiSetup())
}

func internalSetupGpio() int {
	return int(C.wiringPiSetupGpio())
}

func internalSetupPhys() int {
	return int(C.wiringPiSetupPhys())
}

func internalSetupSys() int {
	return int(C.wiringPiSetupSys())
}

func internalPinMode(pin int, mode int) {
	C.pinMode(C.int(pin), C.int(mode))
}

func internalPullUpDnControl(pin int, pud int) {
	C.pullUpDnControl(C.int(pin), C.int(pud))
}

func internalPwmWrite(pin int, value int) {
	C.pwmWrite(C.int(pin), C.int(value))
}

func internalDigitalWrite(pin int, mode int) {
	C.digitalWrite(C.int(pin), C.int(mode))
}

func internalDigitalRead(pin int) int {
	println("internalDigitalRead")
	return int(C.digitalRead(C.int(pin)))
}

func internalGetMode(pin int) int {
	return int(C.getAlt(C.int(pin)))
}

func internalDelay(ms int) {
	C.delay(C.uint(ms))
}

func internalDelayMicroseconds(microSec int) {
	C.delayMicroseconds(C.uint(microSec))
}

func internalWiringISR(pin int, mode int) chan int {
	mutex.Lock()
	defer mutex.Unlock()
	if interrupt_channels[pin] == nil {
		interrupt_channels[pin] = make(chan int)
	}
	C.native_wiring_isr(C.int(pin), C.int(mode))
	return interrupt_channels[pin]
}

func init() {
	C.init(callback.Func)
}

var interrupt_channels = [64]chan int{}

//export goCallback
func goCallback(arg unsafe.Pointer) {
	ctxt := (*C.context)(arg)
	interrupt_channels[int(ctxt.pin)] <- int(ctxt.ret)
}

// This initialises the I2C system with your given device identifier.
// The ID is the I2C number of the device and you can use the i2cdetect
// program to find this out. wiringPiI2CSetup() will work out which
// revision Raspberry Pi you have and open the appropriate device in /dev.
//
// The return value is the standard Linux filehandle, or -1 if any
// error – in which case, you can consult errno as usual.
//
func internalSetupI2C(devId int) int {
	return int(C.wiringPiI2CSetup(C.int(devId)))
}

// Simple device read. Some devices present data when you read them
// without having to do any register transactions.
//
func internalI2CRead(fd int) int {
	return int(C.wiringPiI2CRead(C.int(fd)))
}
<commit_msg>	"github.com/henryse/go-callback"<commit_after>// +build linux, arm

// **********************************************************************
//    Copyright (c) 2017 Henry Seurer
//
//   Permission is hereby granted, free of charge, to any person
//    obtaining a copy of this software and associated documentation
//    files (the "Software"), to deal in the Software without
//    restriction, including without limitation the rights to use,
//    copy, modify, merge, publish, distribute, sublicense, and/or sell
//    copies of the Software, and to permit persons to whom the
//    Software is furnished to do so, subject to the following
//    conditions:
//
//   The above copyright notice and this permission notice shall be
//   included in all copies or substantial portions of the Software.
//
//    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//    OTHER DEALINGS IN THE SOFTWARE.
//
// **********************************************************************

package wiringpi

/*
#cgo LDFLAGS: -lwiringPi
#cgo CFLAGS: -O0

#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>
#include <stdlib.h>
#define nil ((void*)0)

#define GEN_INTERRUPTER(PIN) static void interrupt_handler_##PIN() { \
	context ctxt;   \
	ctxt.pin = PIN;  \
	ctxt.ret = PIN;  \
	callback_func(goCallback, &ctxt); \
}

typedef struct context context;
struct context {
	int pin;
	int ret;
};

static void(*callback_func)(void (*f)(void*), void*);

extern void goCallback(void *);

GEN_INTERRUPTER(0)
GEN_INTERRUPTER(1)
GEN_INTERRUPTER(2)
GEN_INTERRUPTER(3)
GEN_INTERRUPTER(4)
GEN_INTERRUPTER(5)
GEN_INTERRUPTER(6)
GEN_INTERRUPTER(7)
GEN_INTERRUPTER(8)
GEN_INTERRUPTER(9)
GEN_INTERRUPTER(10)
GEN_INTERRUPTER(11)
GEN_INTERRUPTER(12)
GEN_INTERRUPTER(13)
GEN_INTERRUPTER(14)
GEN_INTERRUPTER(15)
GEN_INTERRUPTER(16)
GEN_INTERRUPTER(17)
GEN_INTERRUPTER(18)
GEN_INTERRUPTER(19)
GEN_INTERRUPTER(20)

static int native_wiring_isr(int pin, int mode) {
	switch(pin) {
		case 0: return wiringPiISR(pin, mode, &interrupt_handler_0);
		case 1: return wiringPiISR(pin, mode, &interrupt_handler_1);
		case 2: return wiringPiISR(pin, mode, &interrupt_handler_2);
		case 3: return wiringPiISR(pin, mode, &interrupt_handler_3);
		case 4: return wiringPiISR(pin, mode, &interrupt_handler_4);
		case 5: return wiringPiISR(pin, mode, &interrupt_handler_5);
		case 6: return wiringPiISR(pin, mode, &interrupt_handler_6);
		case 7: return wiringPiISR(pin, mode, &interrupt_handler_7);
		case 8: return wiringPiISR(pin, mode, &interrupt_handler_8);
		case 9: return wiringPiISR(pin, mode, &interrupt_handler_9);
		case 10: return wiringPiISR(pin, mode, &interrupt_handler_10);
		case 11: return wiringPiISR(pin, mode, &interrupt_handler_11);
		case 12: return wiringPiISR(pin, mode, &interrupt_handler_12);
		case 13: return wiringPiISR(pin, mode, &interrupt_handler_13);
		case 14: return wiringPiISR(pin, mode, &interrupt_handler_14);
		case 15: return wiringPiISR(pin, mode, &interrupt_handler_15);
		case 16: return wiringPiISR(pin, mode, &interrupt_handler_16);
		case 17: return wiringPiISR(pin, mode, &interrupt_handler_17);
		case 18: return wiringPiISR(pin, mode, &interrupt_handler_18);
		case 19: return wiringPiISR(pin, mode, &interrupt_handler_19);
		case 20: return wiringPiISR(pin, mode, &interrupt_handler_20);
	}
	return -1;
}

static void init(void *p) {
	callback_func = p;
}
*/
import "C"
import "unsafe"

import (
	"github.com/henryse/go-callback"
	"sync"
)

const (
	WPI_MODE_PINS          = C.WPI_MODE_PINS
	WPI_MODE_GPIO          = C.WPI_MODE_GPIO
	WPI_MODE_GPIO_SYS      = C.WPI_MODE_GPIO_SYS
	WPI_MODE_PIFACE        = C.WPI_MODE_PIFACE
	WPI_MODE_UNINITIALISED = C.WPI_MODE_UNINITIALISED

	INPUT      = C.INPUT
	OUTPUT     = C.OUTPUT
	PWM_OUTPUT = C.PWM_OUTPUT
	GPIO_CLOCK = C.GPIO_CLOCK

	LOW  = C.LOW
	HIGH = C.HIGH

	PUD_OFF  = C.PUD_OFF
	PUD_DOWN = C.PUD_DOWN
	PUD_UP   = C.PUD_UP

	PWM_MODE_MS  = C.PWM_MODE_MS
	PWM_MODE_BAL = C.PWM_MODE_BAL

	INT_EDGE_SETUP   = C.INT_EDGE_SETUP
	INT_EDGE_FALLING = C.INT_EDGE_FALLING
	INT_EDGE_RISING  = C.INT_EDGE_RISING
	INT_EDGE_BOTH    = C.INT_EDGE_BOTH
)

var mutex = &sync.Mutex{}

func internalPinToGpio(pin int) int {
	return int(C.wpiPinToGpio(C.int(pin)))
}

func internalSetup() int {
	return int(C.wiringPiSetup())
}

func internalSetupGpio() int {
	return int(C.wiringPiSetupGpio())
}

func internalSetupPhys() int {
	return int(C.wiringPiSetupPhys())
}

func internalSetupSys() int {
	return int(C.wiringPiSetupSys())
}

func internalPinMode(pin int, mode int) {
	C.pinMode(C.int(pin), C.int(mode))
}

func internalPullUpDnControl(pin int, pud int) {
	C.pullUpDnControl(C.int(pin), C.int(pud))
}

func internalPwmWrite(pin int, value int) {
	C.pwmWrite(C.int(pin), C.int(value))
}

func internalDigitalWrite(pin int, mode int) {
	C.digitalWrite(C.int(pin), C.int(mode))
}

func internalDigitalRead(pin int) int {
	println("internalDigitalRead")
	return int(C.digitalRead(C.int(pin)))
}

func internalGetMode(pin int) int {
	return int(C.getAlt(C.int(pin)))
}

func internalDelay(ms int) {
	C.delay(C.uint(ms))
}

func internalDelayMicroseconds(microSec int) {
	C.delayMicroseconds(C.uint(microSec))
}

func internalWiringISR(pin int, mode int) chan int {
	mutex.Lock()
	defer mutex.Unlock()
	if interrupt_channels[pin] == nil {
		interrupt_channels[pin] = make(chan int)
	}
	C.native_wiring_isr(C.int(pin), C.int(mode))
	return interrupt_channels[pin]
}

func init() {
	C.init(callback.Func)
}

var interrupt_channels = [64]chan int{}

//export goCallback
func goCallback(arg unsafe.Pointer) {
	ctxt := (*C.context)(arg)
	interrupt_channels[int(ctxt.pin)] <- int(ctxt.ret)
}

// This initialises the I2C system with your given device identifier.
// The ID is the I2C number of the device and you can use the i2cdetect
// program to find this out. wiringPiI2CSetup() will work out which
// revision Raspberry Pi you have and open the appropriate device in /dev.
//
// The return value is the standard Linux filehandle, or -1 if any
// error – in which case, you can consult errno as usual.
//
func internalSetupI2C(devId int) int {
	return int(C.wiringPiI2CSetup(C.int(devId)))
}

// Simple device read. Some devices present data when you read them
// without having to do any register transactions.
//
func internalI2CRead(fd int) int {
	return int(C.wiringPiI2CRead(C.int(fd)))
}
<|endoftext|>


<commit_before>/* https://leetcode.com/problems/binary-tree-inorder-traversal/description/
Given a binary tree, return the inorder traversal of its nodes' values.

For example:
Given binary tree [1,null,2,3],
   1
    \
     2
    /
   3
return [1,3,2].

Note: Recursive solution is trivial, could you do it iteratively?
*/

package leetcode

func inorderTraversal(root *TreeNode) []int {
	if root == nil {
		return []int{}
	}

	left := inorderTraversal(root.Left)
	right := inorderTraversal(root.Right)

	return append(append(left, root.Val), right...)
}

/* 0ms
func inorderTraversal(root *TreeNode) []int {
	res := []int{}

	var inorder func(root *TreeNode, res *[]int)
	inorder = func(root *TreeNode, res *[]int) {
		if root != nil {
			inorder(root.Left, res)
			*res = append(*res, root.Val)
			inorder(root.Right, res)
		}
	}

	inorder(root, &res)
	return res
}
*/
<commit_msg>add another thinking: use stack<commit_after>/* https://leetcode.com/problems/binary-tree-inorder-traversal/description/
Given a binary tree, return the inorder traversal of its nodes' values.

For example:
Given binary tree [1,null,2,3],
   1
    \
     2
    /
   3
return [1,3,2].

Note: Recursive solution is trivial, could you do it iteratively?
*/

package leetcode

import "github.com/TTWShell/algorithms/stack" // need copy stack.go when run in leetcode online

func inorderTraversal(root *TreeNode) []int {
	res := []int{}
	s := stack.Constructor()

	for root != nil || !s.IsEmpty() {
		for root != nil {
			s.Push(root)
			root = root.Left
		}
		root = s.Pop().(*TreeNode)
		res = append(res, root.Val)
		root = root.Right
	}

	return res
}

/* 0ms
func inorderTraversal(root *TreeNode) []int {
	if root == nil {
		return []int{}
	}

	left := inorderTraversal(root.Left)
	right := inorderTraversal(root.Right)

	return append(append(left, root.Val), right...)
}
*/

/* 0ms
func inorderTraversal(root *TreeNode) []int {
	res := []int{}

	var inorder func(root *TreeNode, res *[]int)
	inorder = func(root *TreeNode, res *[]int) {
		if root != nil {
			inorder(root.Left, res)
			*res = append(*res, root.Val)
			inorder(root.Right, res)
		}
	}

	inorder(root, &res)
	return res
}
*/
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"github.com/juju/errors"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"gopkg.in/mgo.v2/txn"

	"github.com/juju/juju/network"
)

// AddressState represents the states an IP address can be in. They are created
// in an unknown state and then either become allocated or unavailable if
// allocation fails.
type AddressState string

const (
	// AddressStateUnknown is the initial state an IP address is
	// created with.
	AddressStateUnknown AddressState = ""

	// AddressStateAllocated means that the IP address has
	// successfully been allocated by the provider and is now in use
	// by an interface on a machine.
	AddressStateAllocated AddressState = "allocated"

	// AddressStateUnavailable means that allocating the address with
	// the provider failed. We shouldn't use this address, nor should
	// we attempt to allocate it again in the future.
	AddressStateUnavailable AddressState = "unavailable"
)

// String implements fmt.Stringer.
func (s AddressState) String() string {
	if s == AddressStateUnknown {
		return "<unknown>"
	}
	return string(s)
}

// GoString implements fmt.GoStringer.
func (i *IPAddress) GoString() string {
	return i.String()
}

// IPAddress represents the state of an IP address.
type IPAddress struct {
	st  *State
	doc ipaddressDoc
}

type ipaddressDoc struct {
	DocID       string       `bson:"_id"`
	EnvUUID     string       `bson:"env-uuid"`
	Life        Life         `bson:"life"`
	SubnetId    string       `bson:"subnetid,omitempty"`
	MachineId   string       `bson:"machineid,omitempty"`
	InterfaceId string       `bson:"interfaceid,omitempty"`
	Value       string       `bson:"value"`
	Type        string       `bson:"type"`
	Scope       string       `bson:"networkscope,omitempty"`
	State       AddressState `bson:"state"`
}

// Life returns whether the IP address is Alive, Dying or Dead.
func (i *IPAddress) Life() Life {
	return i.doc.Life
}

// SubnetId returns the ID of the subnet the IP address is associated with. If
// the address is not associated with a subnet this returns "".
func (i *IPAddress) SubnetId() string {
	return i.doc.SubnetId
}

// MachineId returns the ID of the machine the IP address is associated with. If
// the address is not associated with a machine this returns "".
func (i *IPAddress) MachineId() string {
	return i.doc.MachineId
}

// InterfaceId returns the ID of the network interface the IP address is
// associated with. If the address is not associated with a netowrk interface
// this returns "".
func (i *IPAddress) InterfaceId() string {
	return i.doc.InterfaceId
}

// Value returns the IP address.
func (i *IPAddress) Value() string {
	return i.doc.Value
}

// Address returns the network.Address represent the IP address
func (i *IPAddress) Address() network.Address {
	return network.NewAddress(i.doc.Value, i.Scope())
}

// Type returns the type of the IP address. The IP address will have a type of
// IPv4, IPv6 or hostname.
func (i *IPAddress) Type() network.AddressType {
	return network.AddressType(i.doc.Type)
}

// Scope returns the scope of the IP address. If the scope is not set this
// returns "".
func (i *IPAddress) Scope() network.Scope {
	return network.Scope(i.doc.Scope)
}

// State returns the state of an IP address.
func (i *IPAddress) State() AddressState {
	return i.doc.State
}

// String implements fmt.Stringer.
func (i *IPAddress) String() string {
	return i.Address().String()
}

// EnsureDead sets the Life of the IP address to Dead, if it's Alive. It
// does nothing otherwise.
func (i *IPAddress) EnsureDead() (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot set address %q to dead", i)

	if i.doc.Life == Dead {
		return nil
	}

	ops := []txn.Op{{
		C:      ipaddressesC,
		Id:     i.doc.DocID,
		Update: bson.D{{"$set", bson.D{{"life", Dead}}}},
		Assert: isAliveDoc,
	}}
	buildTxn := func(attempt int) ([]txn.Op, error) {
		if attempt > 0 {
			if err := i.Refresh(); err != nil {
				// Address is either gone or
				// another error occurred.
				return nil, err
			}
			if i.Life() == Dead {
				return nil, jujutxn.ErrNoOperations
			}
			return nil, errors.Errorf("unexpected life value: %s", i.Life().String())
		}
		return []txn.Op{{
			C:      ipaddressesC,
			Id:     i.doc.DocID,
			Update: bson.D{{"$set", bson.D{{"life", Dead}}}},
			Assert: isAliveDoc,
		}}, nil
	}

	err = i.st.run(buildTxn)
	if err != nil {
		return err
	}

	i.doc.Life = Dead
	return nil
}

// Remove removes an existing IP address. Trying to remove a missing
// address is not an error.
func (i *IPAddress) Remove() (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot remove IP address %q", i)

	if i.doc.Life != Dead {
		return errors.New("IP address is not dead")
	}

	ops := []txn.Op{{
		C:      ipaddressesC,
		Id:     i.doc.DocID,
		Assert: isDeadDoc,
		Remove: true,
	}}
	return i.st.runTransaction(ops)
}

// SetState sets the State of an IPAddress. Valid state transitions
// are Unknown to Allocated or Unavailable, as well as setting the
// same state more than once. Any other transition will result in
// returning an error satisfying errors.IsNotValid().
func (i *IPAddress) SetState(newState AddressState) (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot set IP address %q to state %q", i, newState)

	validStates := []AddressState{AddressStateUnknown, newState}
	unknownOrSame := bson.D{{"state", bson.D{{"$in", validStates}}}}
	ops := []txn.Op{{
		C:      ipaddressesC,
		Id:     i.doc.DocID,
		Assert: unknownOrSame,
		Update: bson.D{{"$set", bson.D{{"state", string(newState)}}}},
	}}
	if err = i.st.runTransaction(ops); err != nil {
		return onAbort(
			err,
			errors.NotValidf("transition from %q", i.doc.State),
		)
	}
	i.doc.State = newState
	return nil
}

// AllocateTo sets the machine ID and interface ID of the IP address.
// It will fail if the state is not AddressStateUnknown. On success,
// the address state will also change to AddressStateAllocated.
func (i *IPAddress) AllocateTo(machineId, interfaceId string) (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot allocate IP address %q to machine %q, interface %q", i, machineId, interfaceId)

	ops := []txn.Op{{
		C:      ipaddressesC,
		Id:     i.doc.DocID,
		Assert: bson.D{{"state", AddressStateUnknown}},
		Update: bson.D{{"$set", bson.D{
			{"machineid", machineId},
			{"interfaceid", interfaceId},
			{"state", string(AddressStateAllocated)},
		}}},
	}}

	if err = i.st.runTransaction(ops); err != nil {
		return onAbort(
			err,
			errors.Errorf("already allocated or unavailable"),
		)
	}
	i.doc.MachineId = machineId
	i.doc.InterfaceId = interfaceId
	i.doc.State = AddressStateAllocated
	return nil
}

// Refresh refreshes the contents of the IPAddress from the underlying
// state. It an error that satisfies errors.IsNotFound if the Subnet has
// been removed.
func (i *IPAddress) Refresh() error {
	addresses, closer := i.st.getCollection(ipaddressesC)
	defer closer()

	err := addresses.FindId(i.doc.DocID).One(&i.doc)
	if err == mgo.ErrNotFound {
		return errors.NotFoundf("IP address %q", i)
	}
	if err != nil {
		return errors.Errorf("cannot refresh IP address %q: %v", i, err)
	}
	return nil
}
<commit_msg>Handle same condition in Remove<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"github.com/juju/errors"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"gopkg.in/mgo.v2/txn"

	"github.com/juju/juju/network"
	jujutxn "github.com/juju/txn"
)

// AddressState represents the states an IP address can be in. They are created
// in an unknown state and then either become allocated or unavailable if
// allocation fails.
type AddressState string

const (
	// AddressStateUnknown is the initial state an IP address is
	// created with.
	AddressStateUnknown AddressState = ""

	// AddressStateAllocated means that the IP address has
	// successfully been allocated by the provider and is now in use
	// by an interface on a machine.
	AddressStateAllocated AddressState = "allocated"

	// AddressStateUnavailable means that allocating the address with
	// the provider failed. We shouldn't use this address, nor should
	// we attempt to allocate it again in the future.
	AddressStateUnavailable AddressState = "unavailable"
)

// String implements fmt.Stringer.
func (s AddressState) String() string {
	if s == AddressStateUnknown {
		return "<unknown>"
	}
	return string(s)
}

// GoString implements fmt.GoStringer.
func (i *IPAddress) GoString() string {
	return i.String()
}

// IPAddress represents the state of an IP address.
type IPAddress struct {
	st  *State
	doc ipaddressDoc
}

type ipaddressDoc struct {
	DocID       string       `bson:"_id"`
	EnvUUID     string       `bson:"env-uuid"`
	Life        Life         `bson:"life"`
	SubnetId    string       `bson:"subnetid,omitempty"`
	MachineId   string       `bson:"machineid,omitempty"`
	InterfaceId string       `bson:"interfaceid,omitempty"`
	Value       string       `bson:"value"`
	Type        string       `bson:"type"`
	Scope       string       `bson:"networkscope,omitempty"`
	State       AddressState `bson:"state"`
}

// Life returns whether the IP address is Alive, Dying or Dead.
func (i *IPAddress) Life() Life {
	return i.doc.Life
}

// SubnetId returns the ID of the subnet the IP address is associated with. If
// the address is not associated with a subnet this returns "".
func (i *IPAddress) SubnetId() string {
	return i.doc.SubnetId
}

// MachineId returns the ID of the machine the IP address is associated with. If
// the address is not associated with a machine this returns "".
func (i *IPAddress) MachineId() string {
	return i.doc.MachineId
}

// InterfaceId returns the ID of the network interface the IP address is
// associated with. If the address is not associated with a netowrk interface
// this returns "".
func (i *IPAddress) InterfaceId() string {
	return i.doc.InterfaceId
}

// Value returns the IP address.
func (i *IPAddress) Value() string {
	return i.doc.Value
}

// Address returns the network.Address represent the IP address
func (i *IPAddress) Address() network.Address {
	return network.NewAddress(i.doc.Value, i.Scope())
}

// Type returns the type of the IP address. The IP address will have a type of
// IPv4, IPv6 or hostname.
func (i *IPAddress) Type() network.AddressType {
	return network.AddressType(i.doc.Type)
}

// Scope returns the scope of the IP address. If the scope is not set this
// returns "".
func (i *IPAddress) Scope() network.Scope {
	return network.Scope(i.doc.Scope)
}

// State returns the state of an IP address.
func (i *IPAddress) State() AddressState {
	return i.doc.State
}

// String implements fmt.Stringer.
func (i *IPAddress) String() string {
	return i.Address().String()
}

// EnsureDead sets the Life of the IP address to Dead, if it's Alive. It
// does nothing otherwise.
func (i *IPAddress) EnsureDead() (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot set address %q to dead", i)

	if i.doc.Life == Dead {
		return nil
	}

	buildTxn := func(attempt int) ([]txn.Op, error) {
		if attempt > 0 {
			if err := i.Refresh(); err != nil {
				// Address is either gone or
				// another error occurred.
				return nil, err
			}
			if i.Life() == Dead {
				return nil, jujutxn.ErrNoOperations
			}
			return nil, errors.Errorf("unexpected life value: %s", i.Life().String())
		}
		return []txn.Op{{
			C:      ipaddressesC,
			Id:     i.doc.DocID,
			Update: bson.D{{"$set", bson.D{{"life", Dead}}}},
			Assert: isAliveDoc,
		}}, nil
	}

	err = i.st.run(buildTxn)
	if err != nil {
		return err
	}

	i.doc.Life = Dead
	return nil
}

// Remove removes an existing IP address. Trying to remove a missing
// address is not an error.
func (i *IPAddress) Remove() (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot remove IP address %q", i)

	if i.doc.Life != Dead {
		return errors.New("IP address is not dead")
	}

	buildTxn := func(attempt int) ([]txn.Op, error) {
		if attempt > 0 {
			if err := i.Refresh(); errors.IsNotFound(err) {
				return nil, jujutxn.ErrNoOperations
			} else if err != nil {
				return nil, err
			}
			if i.Life() != Dead {
				return nil, errors.New("address is not dead")
			}
		}
		return []txn.Op{{
			C:      ipaddressesC,
			Id:     i.doc.DocID,
			Assert: isDeadDoc,
			Remove: true,
		}}, nil
	}

	return i.st.run(buildTxn)
}

// SetState sets the State of an IPAddress. Valid state transitions
// are Unknown to Allocated or Unavailable, as well as setting the
// same state more than once. Any other transition will result in
// returning an error satisfying errors.IsNotValid().
func (i *IPAddress) SetState(newState AddressState) (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot set IP address %q to state %q", i, newState)

	validStates := []AddressState{AddressStateUnknown, newState}
	unknownOrSame := bson.D{{"state", bson.D{{"$in", validStates}}}}
	ops := []txn.Op{{
		C:      ipaddressesC,
		Id:     i.doc.DocID,
		Assert: unknownOrSame,
		Update: bson.D{{"$set", bson.D{{"state", string(newState)}}}},
	}}
	if err = i.st.runTransaction(ops); err != nil {
		return onAbort(
			err,
			errors.NotValidf("transition from %q", i.doc.State),
		)
	}
	i.doc.State = newState
	return nil
}

// AllocateTo sets the machine ID and interface ID of the IP address.
// It will fail if the state is not AddressStateUnknown. On success,
// the address state will also change to AddressStateAllocated.
func (i *IPAddress) AllocateTo(machineId, interfaceId string) (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot allocate IP address %q to machine %q, interface %q", i, machineId, interfaceId)

	ops := []txn.Op{{
		C:      ipaddressesC,
		Id:     i.doc.DocID,
		Assert: bson.D{{"state", AddressStateUnknown}},
		Update: bson.D{{"$set", bson.D{
			{"machineid", machineId},
			{"interfaceid", interfaceId},
			{"state", string(AddressStateAllocated)},
		}}},
	}}

	if err = i.st.runTransaction(ops); err != nil {
		return onAbort(
			err,
			errors.Errorf("already allocated or unavailable"),
		)
	}
	i.doc.MachineId = machineId
	i.doc.InterfaceId = interfaceId
	i.doc.State = AddressStateAllocated
	return nil
}

// Refresh refreshes the contents of the IPAddress from the underlying
// state. It an error that satisfies errors.IsNotFound if the Subnet has
// been removed.
func (i *IPAddress) Refresh() error {
	addresses, closer := i.st.getCollection(ipaddressesC)
	defer closer()

	err := addresses.FindId(i.doc.DocID).One(&i.doc)
	if err == mgo.ErrNotFound {
		return errors.NotFoundf("IP address %q", i)
	}
	if err != nil {
		return errors.Errorf("cannot refresh IP address %q: %v", i, err)
	}
	return nil
}
<|endoftext|>


<commit_before>package models

import "socialapi/request"

type ChannelMessageContainer struct {
	Message      *ChannelMessage                  `json:"message"`
	Interactions map[string]*InteractionContainer `json:"interactions"`
	RepliesCount int                              `json:"repliesCount"`
	// Replies should stay as   ChannelMessageContainers
	// not as a pointer
	Replies            ChannelMessageContainers `json:"replies"`
	AccountOldId       string                   `json:"accountOldId"`
	IsFollowed         bool                     `json:"isFollowed"`
	UnreadRepliesCount int                      `json:"unreadRepliesCount,omitempty"`
	Err                error                    `json:"-"`
}

func NewChannelMessageContainer() *ChannelMessageContainer {
	container := &ChannelMessageContainer{}
	container.Interactions = make(map[string]*InteractionContainer)
	container.Interactions["like"] = NewInteractionContainer()

	return container
}

type InteractionContainer struct {
	IsInteracted  bool     `json:"isInteracted"`
	ActorsPreview []string `json:"actorsPreview"`
	ActorsCount   int      `json:"actorsCount"`
}

func NewInteractionContainer() *InteractionContainer {
	interactionContainer := &InteractionContainer{}
	interactionContainer.ActorsPreview = make([]string, 0)
	interactionContainer.IsInteracted = false
	interactionContainer.ActorsCount = 0

	return interactionContainer
}

func withChannelMessageContainerChecks(cmc *ChannelMessageContainer, f func(c *ChannelMessageContainer) error) *ChannelMessageContainer {
	if cmc == nil {
		cmc = NewChannelMessageContainer()
		cmc.Err = ErrMessageIsNotSet
		return cmc
	}

	if cmc.Err != nil {
		return cmc
	}

	cmc.Err = f(cmc)

	return cmc
}

func (c *ChannelMessageContainer) PopulateWith(m *ChannelMessage) *ChannelMessageContainer {
	c.Message = m
	c.AddAccountOldId()
	return c
}

func (cc *ChannelMessageContainer) AddAccountOldId() *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {

		if c.AccountOldId != "" {
			return c
		}

		oldId, err := FetchAccountOldIdByIdFromCache(c.Message.AccountId)
		if err != nil {
			c.Err = err
			return c
		}

		c.AccountOldId = oldId
	})
}

func (c *ChannelMessageContainer) SetGenerics(query *request.Query) *ChannelMessageContainer {
	c.AddReplies(query)
	c.AddRepliesCount(query)
	c.AddInteractions(query)
	return c
}

func (cc *ChannelMessageContainer) AddReplies(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {

		if c.Message != nil && c.Message.TypeConstant == ChannelMessage_TYPE_REPLY {
			// if message itself already a reply, no need to add replies to it
			return c
		}

		// fetch the replies
		mr := NewMessageReply()
		mr.MessageId = c.Message.Id

		q := query.Clone()
		q.Limit = query.ReplyLimit
		q.Skip = query.ReplySkip

		replies, err := mr.List(q)
		if err != nil {
			c.Err = err
			return c
		}

		// populate the replies as containers
		rs := NewChannelMessageContainers()
		rs.PopulateWith(replies, query)

		// set channel message containers
		c.Replies = *rs
		return c
	})

}
	}

	// fetch the replies
	mr := NewMessageReply()
	mr.MessageId = c.Message.Id

func (cc *ChannelMessageContainer) AddRepliesCount(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {
		// fetch the replies
		mr := NewMessageReply()
		mr.MessageId = c.Message.Id

		repliesCount, err := mr.Count(query)
		c.Err = err
		c.RepliesCount = repliesCount

		return c
	})
}

func (cc *ChannelMessageContainer) AddInteractions(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {

		// get preview
		q := query.Clone()
		q.Type = "like"
		q.Limit = 3

		// if the message is reply do not add  isInteracted data
		if c.Message.TypeConstant == ChannelMessage_TYPE_REPLY {
			q.AddIsInteracted = false
		}

		i := NewInteraction()
		i.MessageId = c.Message.Id
		interactionContainer, err := i.FetchInteractionContainer(q)
		if err != nil {
			c.Err = err
			return c
		}

		c.Interactions[q.Type] = interactionContainer

		return c
	})
}

func (c *ChannelMessageContainer) AddIsInteracted(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {
		i := NewInteraction()
		i.MessageId = c.Message.Id
		isInteracted, err := i.IsInteracted(query.AccountId)
		if err != nil {
			c.Err = err
			return c
		}

		c.Interactions["like"].IsInteracted = isInteracted

		return c
	})
}

func (cc *ChannelMessageContainer) AddIsFollowed(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {
		isFollowed, err := c.Message.CheckIsMessageFollowed(query)
		c.IsFollowed = isFollowed
		c.Err = err
		return c
	})
}

func (c *ChannelMessageContainer) AddUnreadRepliesCount() *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {
		panic("method not implemented")
		return c
	})
}

type ChannelMessageContainers []ChannelMessageContainer

func NewChannelMessageContainers() *ChannelMessageContainers {
	return &ChannelMessageContainers{}
}

func (c *ChannelMessageContainers) PopulateWith(cms []ChannelMessage, query *request.Query) *ChannelMessageContainers {
	for i, _ := range cms {
		cmc := NewChannelMessageContainer()
		cmc.PopulateWith(&cms[i])
		cmc.SetGenerics(query)
		c.Add(cmc)
	}

	return c
}

func (c *ChannelMessageContainers) Add(containers ...*ChannelMessageContainer) *ChannelMessageContainers {
	for _, cc := range containers {
		*c = append(*c, *cc)
	}
	return c
}
<commit_msg>Social: enable caching for message container<commit_after>package models

import (
	"socialapi/request"

	"github.com/koding/bongo"
)

type ChannelMessageContainer struct {
	Message      *ChannelMessage                  `json:"message"`
	Interactions map[string]*InteractionContainer `json:"interactions"`
	RepliesCount int                              `json:"repliesCount"`
	// Replies should stay as   ChannelMessageContainers
	// not as a pointer
	Replies            ChannelMessageContainers `json:"replies"`
	AccountOldId       string                   `json:"accountOldId"`
	IsFollowed         bool                     `json:"isFollowed"`
	UnreadRepliesCount int                      `json:"unreadRepliesCount,omitempty"`
	Err                error                    `json:"-"`
}

func NewChannelMessageContainer() *ChannelMessageContainer {
	container := &ChannelMessageContainer{}
	container.Interactions = make(map[string]*InteractionContainer)
	container.Interactions["like"] = NewInteractionContainer()

	return container
}

type InteractionContainer struct {
	IsInteracted  bool     `json:"isInteracted"`
	ActorsPreview []string `json:"actorsPreview"`
	ActorsCount   int      `json:"actorsCount"`
}

func NewInteractionContainer() *InteractionContainer {
	interactionContainer := &InteractionContainer{}
	interactionContainer.ActorsPreview = make([]string, 0)
	interactionContainer.IsInteracted = false
	interactionContainer.ActorsCount = 0

	return interactionContainer
}

func withChannelMessageContainerChecks(cmc *ChannelMessageContainer, f func(c *ChannelMessageContainer) error) *ChannelMessageContainer {
	if cmc == nil {
		cmc = NewChannelMessageContainer()
		cmc.Err = ErrMessageIsNotSet
		return cmc
	}

	// do not process from now on, if the container has Err
	if cmc.Err != nil {
		return cmc
	}

	cmc.Err = f(cmc)

	return cmc
}

func (c *ChannelMessageContainer) Fetch(id int64, q *request.Query) error {
	if q.ShowExempt {
		cmc, err := BuildChannelMessageContainer(id, q)
		if err != nil {
			return err
		}
		c = cmc

	} else {
		if err := bongo.B.Fetch(c, id); err != nil {
			return err
		}

		return c.UpdateReplies(q).Err
	}

	return nil
}

func (c *ChannelMessageContainer) TableName() string {
	return "api.channel_message"
}

func (c *ChannelMessageContainer) GetId() int64 {
	if c.Message != nil {
		return c.Message.Id
	}

	return 0
}

func (c *ChannelMessageContainer) PopulateWith(m *ChannelMessage) *ChannelMessageContainer {
	c.Message = m
	c.AddAccountOldId()
	return c
}

func (cc *ChannelMessageContainer) AddAccountOldId() *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {

		if c.AccountOldId != "" {
			return c
		}

		oldId, err := FetchAccountOldIdByIdFromCache(c.Message.AccountId)
		if err != nil {
			c.Err = err
			return c
		}

		c.AccountOldId = oldId
	})
}

func (c *ChannelMessageContainer) SetGenerics(query *request.Query) *ChannelMessageContainer {
	c.AddReplies(query)
	c.AddRepliesCount(query)
	c.AddInteractions(query)
	return c
}

func (cc *ChannelMessageContainer) AddReplies(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {

		if c.Message != nil && c.Message.TypeConstant == ChannelMessage_TYPE_REPLY {
			// if message itself already a reply, no need to add replies to it
			return c
		}

		// fetch the replies
		mr := NewMessageReply()
		mr.MessageId = c.Message.Id

		q := query.Clone()
		q.Limit = query.ReplyLimit
		q.Skip = query.ReplySkip

		replies, err := mr.List(q)
		if err != nil {
			c.Err = err
			return c
		}

		// populate the replies as containers
		rs := NewChannelMessageContainers()
		rs.PopulateWith(replies, query)

		// set channel message containers
		c.Replies = *rs
		return c
	})

}

func (c *ChannelMessageContainer) UpdateReplies(q *request.Query) *ChannelMessageContainer {
	if len(c.Replies) > 0 {
		for i, _ := range c.Replies {
			if err := c.Replies[i].Fetch(c.Replies[i].GetId(), q); err != nil {
				c.Replies[i].Err = err
			}
		}
	}

	return c
}

func (cc *ChannelMessageContainer) AddRepliesCount(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {
		// fetch the replies
		mr := NewMessageReply()
		mr.MessageId = c.Message.Id

		repliesCount, err := mr.Count(query)
		c.Err = err
		c.RepliesCount = repliesCount

		return c
	})
}

func (cc *ChannelMessageContainer) AddInteractions(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {

		// get preview
		q := query.Clone()
		q.Type = "like"
		q.Limit = 3

		// if the message is reply do not add  isInteracted data
		if c.Message.TypeConstant == ChannelMessage_TYPE_REPLY {
			q.AddIsInteracted = false
		}

		i := NewInteraction()
		i.MessageId = c.Message.Id
		interactionContainer, err := i.FetchInteractionContainer(q)
		if err != nil {
			c.Err = err
			return c
		}

		c.Interactions[q.Type] = interactionContainer

		return c
	})
}

func (c *ChannelMessageContainer) AddIsInteracted(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {
		i := NewInteraction()
		i.MessageId = c.Message.Id
		isInteracted, err := i.IsInteracted(query.AccountId)
		if err != nil {
			c.Err = err
			return c
		}

		c.Interactions["like"].IsInteracted = isInteracted

		return c
	})
}

func (cc *ChannelMessageContainer) AddIsFollowed(query *request.Query) *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {
		isFollowed, err := c.Message.CheckIsMessageFollowed(query)
		c.IsFollowed = isFollowed
		c.Err = err
		return c
	})
}

func (c *ChannelMessageContainer) AddUnreadRepliesCount() *ChannelMessageContainer {
	return withChannelMessageContainerChecks(cc, func(c *ChannelMessageContainer) error {
		panic("method not implemented")
		return c
	})
}

type ChannelMessageContainers []ChannelMessageContainer

func NewChannelMessageContainers() *ChannelMessageContainers {
	return &ChannelMessageContainers{}
}

func (c *ChannelMessageContainers) PopulateWith(cms []ChannelMessage, query *request.Query) *ChannelMessageContainers {
	for i, _ := range cms {
		cmc := NewChannelMessageContainer()
		cmc.PopulateWith(&cms[i])
		cmc.SetGenerics(query)
		c.Add(cmc)
	}

	return c
}

func (c *ChannelMessageContainers) Add(containers ...*ChannelMessageContainer) *ChannelMessageContainers {
	for _, cc := range containers {
		*c = append(*c, *cc)
	}
	return c
}
<|endoftext|>


<commit_before><commit_msg>db update<commit_after><|endoftext|>


<commit_before><commit_msg>Initial commit.<commit_after><|endoftext|>


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

// Package oauth2 provides support for making
// OAuth2 authorized and authenticated HTTP requests.
// It can additionally grant authorization with Bearer JWT.
package oauth2

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type tokenRespBody struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int64  `json:"expires_in"` // in seconds
	IdToken      string `json:"id_token"`
}

// TokenFetcher refreshes or fetches a new access token from the
// provider. It should return an error if it's not capable of
// retrieving a token.
type TokenFetcher interface {
	// FetchToken retrieves a new access token for the provider.
	// If the implementation doesn't know how to retrieve a new token,
	// it returns an error. The existing token may be nil.
	FetchToken(existing *Token) (*Token, error)
}

// Options represents options to provide OAuth 2.0 client credentials
// and access level. A sample configuration:
//
//    opts := &oauth2.Options{
//        ClientID: "<clientID>",
//        ClientSecret: "ad4364309eff",
//        RedirectURL: "https://homepage/oauth2callback",
//        Scopes: []string{"scope1", "scope2"},
//        AccessType: "offline", // retrieves a refresh token
//    }
//
type Options struct {
	// ClientID is the OAuth client identifier used when communicating with
	// the configured OAuth provider.
	ClientID string `json:"client_id"`

	// ClientSecret is the OAuth client secret used when communicating with
	// the configured OAuth provider.
	ClientSecret string `json:"client_secret"`

	// RedirectURL is the URL to which the user will be returned after
	// granting (or denying) access.
	RedirectURL string `json:"redirect_url"`

	// Scopes optionally specifies a list of requested permission scopes.
	Scopes []string `json:"scopes,omitempty"`

	// AccessType is an OAuth extension that gets sent as the
	// "access_type" field in the URL from AuthCodeURL.
	// See https://developers.google.com/accounts/docs/OAuth2WebServer.
	// It may be "online" (the default) or "offline".
	// If your application needs to refresh access tokens when the
	// user is not present at the browser, then use offline. This
	// will result in your application obtaining a refresh token
	// the first time your application exchanges an authorization
	// code for a user.
	AccessType string `json:"access_type,omitempty"`

	// ApprovalPrompt indicates whether the user should be
	// re-prompted for consent. If set to "auto" (default) the
	// user will be prompted only if they haven't previously
	// granted consent and the code can only be exchanged for an
	// access token.
	// If set to "force" the user will always be prompted, and the
	// code can be exchanged for a refresh token.
	ApprovalPrompt string `json:"-"`
}

// NewConfig creates a generic OAuth 2.0 configuration that talks
// to an OAuth 2.0 provider specified with authURL and tokenURL.
func NewConfig(opts *Options, authURL, tokenURL string) (*Config, error) {
	aURL, err := url.Parse(authURL)
	if err != nil {
		return nil, err
	}
	tURL, err := url.Parse(tokenURL)
	if err != nil {
		return nil, err
	}
	conf := &Config{
		opts:     opts,
		authURL:  aURL,
		tokenURL: tURL,
	}
	if err = conf.validate(); err != nil {
		return nil, err
	}
	return conf, nil
}

// Config represents the configuration of an OAuth 2.0 consumer client.
type Config struct {
	// Client is the HTTP client to be used to retrieve
	// tokens from the OAuth 2.0 provider.
	Client *http.Client

	// Transport is the http.RoundTripper to be used
	// to construct new oauth2.Transport instances from
	// this configuration.
	Transport http.RoundTripper

	opts *Options
	// AuthURL is the URL the user will be directed to
	// in order to grant access.
	authURL *url.URL
	// TokenURL is the URL used to retrieve OAuth tokens.
	tokenURL *url.URL
}

// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
// that asks for permissions for the required scopes explicitly.
func (c *Config) AuthCodeURL(state string) (authURL string) {
	u := *c.authURL
	vals := url.Values{
		"response_type": {"code"},
		"client_id":     {c.opts.ClientID},
		"scope":         {strings.Join(c.opts.Scopes, " ")},
		"state":         {state},
	}
	if c.opts.AccessType != "" {
		vals.Set("access_type", c.opts.AccessType)
	}
	if c.opts.ApprovalPrompt != "" {
		vals.Set("approval_prompt", c.opts.ApprovalPrompt)
	}
	if c.opts.RedirectURL != "" {
		vals.Set("redirect_uri", c.opts.RedirectURL)
	}
	q := vals.Encode()
	if u.RawQuery == "" {
		u.RawQuery = q
	} else {
		u.RawQuery += "&" + q
	}
	return u.String()
}

// NewTransport creates a new authorizable transport. It doesn't
// initialize the new transport with a token, so after creation,
// you need to set a valid token (or an expired token with a valid
// refresh token) in order to be able to do authorized requests.
func (c *Config) NewTransport() *Transport {
	return NewTransport(c.transport(), c, nil)
}

// NewTransportWithCode exchanges the OAuth 2.0 authorization code with
// the provider to fetch a new access token (and refresh token). Once
// it succesffully retrieves a new token, creates a new transport
// authorized with it.
func (c *Config) NewTransportWithCode(code string) (*Transport, error) {
	token, err := c.Exchange(code)
	if err != nil {
		return nil, err
	}
	return NewTransport(c.transport(), c, token), nil
}

// FetchToken retrieves a new access token and updates the existing token
// with the newly fetched credentials. If existing token doesn't
// contain a refresh token, it returns an error.
func (c *Config) FetchToken(existing *Token) (*Token, error) {
	if existing == nil || existing.RefreshToken == "" {
		return nil, errors.New("cannot fetch access token without refresh token.")
	}
	return c.retrieveToken(url.Values{
		"grant_type":    {"refresh_token"},
		"client_secret": {c.opts.ClientSecret},
		"refresh_token": {existing.RefreshToken},
	})
}

// Checks if all required configuration fields have non-zero values.
func (c *Config) validate() error {
	if c.opts.ClientID == "" {
		return errors.New("oauth2: missing client ID")
	}
	if c.opts.ClientSecret == "" {
		return errors.New("oauth2: missing client secret")
	}
	return nil
}

// Exchange exchanges the authorization code with the OAuth 2.0 provider
// to retrieve a new access token.
func (c *Config) Exchange(code string) (*Token, error) {
	vals := url.Values{
		"grant_type":    {"authorization_code"},
		"client_secret": {c.opts.ClientSecret},
		"code":          {code},
	}
	if len(c.opts.Scopes) != 0 {
		vals.Set("scope", strings.Join(c.opts.Scopes, " "))
	}
	if c.opts.RedirectURL != "" {
		vals.Set("redirect_uri", c.opts.RedirectURL)
	}
	return c.retrieveToken(vals)
}

func (c *Config) retrieveToken(v url.Values) (*Token, error) {
	v.Set("client_id", c.opts.ClientID)
	// Note that we're not setting v's client_secret to t.ClientSecret, due
	// to https://code.google.com/p/goauth2/issues/detail?id=31
	// Reddit only accepts client_secret in Authorization header.
	// Dropbox accepts either, but not both.
	// The spec requires servers to always support the Authorization header,
	// so that's all we use.
	r, err := c.client().PostForm(c.tokenURL.String(), v)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if r.StatusCode != 200 {
		// TODO(jbd): Add status code or error message
		return nil, errors.New("error during updating token")
	}

	resp := &tokenRespBody{}
	content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
	switch content {
	case "application/x-www-form-urlencoded", "text/plain":
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			return nil, err
		}
		vals, err := url.ParseQuery(string(body))
		if err != nil {
			return nil, err
		}
		resp.AccessToken = vals.Get("access_token")
		resp.TokenType = vals.Get("token_type")
		resp.RefreshToken = vals.Get("refresh_token")
		resp.ExpiresIn, _ = strconv.ParseInt(vals.Get("expires_in"), 10, 64)
		resp.IdToken = vals.Get("id_token")
	default:
		if err = json.NewDecoder(r.Body).Decode(&resp); err != nil {
			return nil, err
		}
	}
	token := &Token{
		AccessToken:  resp.AccessToken,
		TokenType:    resp.TokenType,
		RefreshToken: resp.RefreshToken,
	}
	// Don't overwrite `RefreshToken` with an empty value
	// if this was a token refreshing request.
	if resp.RefreshToken == "" {
		token.RefreshToken = v.Get("refresh_token")
	}
	if resp.ExpiresIn == 0 {
		token.Expiry = time.Time{}
	} else {
		token.Expiry = time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second)
	}
	if resp.IdToken != "" {
		if token.Extra == nil {
			token.Extra = make(map[string]string)
		}
		token.Extra["id_token"] = resp.IdToken
	}
	return token, nil
}

func (c *Config) transport() http.RoundTripper {
	if c.Transport != nil {
		return c.Transport
	}
	return http.DefaultTransport
}

func (c *Config) client() *http.Client {
	if c.Client != nil {
		return c.Client
	}
	return http.DefaultClient
}
<commit_msg>client_secret should be optional.<commit_after>// Copyright 2014 The oauth2 Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package oauth2 provides support for making
// OAuth2 authorized and authenticated HTTP requests.
// It can additionally grant authorization with Bearer JWT.
package oauth2

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type tokenRespBody struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int64  `json:"expires_in"` // in seconds
	IdToken      string `json:"id_token"`
}

// TokenFetcher refreshes or fetches a new access token from the
// provider. It should return an error if it's not capable of
// retrieving a token.
type TokenFetcher interface {
	// FetchToken retrieves a new access token for the provider.
	// If the implementation doesn't know how to retrieve a new token,
	// it returns an error. The existing token may be nil.
	FetchToken(existing *Token) (*Token, error)
}

// Options represents options to provide OAuth 2.0 client credentials
// and access level. A sample configuration:
//
//    opts := &oauth2.Options{
//        ClientID: "<clientID>",
//        ClientSecret: "ad4364309eff",
//        RedirectURL: "https://homepage/oauth2callback",
//        Scopes: []string{"scope1", "scope2"},
//        AccessType: "offline", // retrieves a refresh token
//    }
//
type Options struct {
	// ClientID is the OAuth client identifier used when communicating with
	// the configured OAuth provider.
	ClientID string `json:"client_id"`

	// ClientSecret is the OAuth client secret used when communicating with
	// the configured OAuth provider.
	ClientSecret string `json:"client_secret"`

	// RedirectURL is the URL to which the user will be returned after
	// granting (or denying) access.
	RedirectURL string `json:"redirect_url"`

	// Scopes optionally specifies a list of requested permission scopes.
	Scopes []string `json:"scopes,omitempty"`

	// AccessType is an OAuth extension that gets sent as the
	// "access_type" field in the URL from AuthCodeURL.
	// See https://developers.google.com/accounts/docs/OAuth2WebServer.
	// It may be "online" (the default) or "offline".
	// If your application needs to refresh access tokens when the
	// user is not present at the browser, then use offline. This
	// will result in your application obtaining a refresh token
	// the first time your application exchanges an authorization
	// code for a user.
	AccessType string `json:"access_type,omitempty"`

	// ApprovalPrompt indicates whether the user should be
	// re-prompted for consent. If set to "auto" (default) the
	// user will be prompted only if they haven't previously
	// granted consent and the code can only be exchanged for an
	// access token.
	// If set to "force" the user will always be prompted, and the
	// code can be exchanged for a refresh token.
	ApprovalPrompt string `json:"-"`
}

// NewConfig creates a generic OAuth 2.0 configuration that talks
// to an OAuth 2.0 provider specified with authURL and tokenURL.
func NewConfig(opts *Options, authURL, tokenURL string) (*Config, error) {
	aURL, err := url.Parse(authURL)
	if err != nil {
		return nil, err
	}
	tURL, err := url.Parse(tokenURL)
	if err != nil {
		return nil, err
	}
	if opts.ClientID == "" {
		return nil, errors.New("oauth2: missing client ID")
	}
	return &Config{
		opts:     opts,
		authURL:  aURL,
		tokenURL: tURL,
	}, nil
}

// Config represents the configuration of an OAuth 2.0 consumer client.
type Config struct {
	// Client is the HTTP client to be used to retrieve
	// tokens from the OAuth 2.0 provider.
	Client *http.Client

	// Transport is the http.RoundTripper to be used
	// to construct new oauth2.Transport instances from
	// this configuration.
	Transport http.RoundTripper

	opts *Options
	// AuthURL is the URL the user will be directed to
	// in order to grant access.
	authURL *url.URL
	// TokenURL is the URL used to retrieve OAuth tokens.
	tokenURL *url.URL
}

// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
// that asks for permissions for the required scopes explicitly.
func (c *Config) AuthCodeURL(state string) (authURL string) {
	u := *c.authURL
	vals := url.Values{
		"response_type": {"code"},
		"client_id":     {c.opts.ClientID},
		"scope":         {strings.Join(c.opts.Scopes, " ")},
		"state":         {state},
	}
	if c.opts.AccessType != "" {
		vals.Set("access_type", c.opts.AccessType)
	}
	if c.opts.ApprovalPrompt != "" {
		vals.Set("approval_prompt", c.opts.ApprovalPrompt)
	}
	if c.opts.RedirectURL != "" {
		vals.Set("redirect_uri", c.opts.RedirectURL)
	}
	q := vals.Encode()
	if u.RawQuery == "" {
		u.RawQuery = q
	} else {
		u.RawQuery += "&" + q
	}
	return u.String()
}

// NewTransport creates a new authorizable transport. It doesn't
// initialize the new transport with a token, so after creation,
// you need to set a valid token (or an expired token with a valid
// refresh token) in order to be able to do authorized requests.
func (c *Config) NewTransport() *Transport {
	return NewTransport(c.transport(), c, nil)
}

// NewTransportWithCode exchanges the OAuth 2.0 authorization code with
// the provider to fetch a new access token (and refresh token). Once
// it succesffully retrieves a new token, creates a new transport
// authorized with it.
func (c *Config) NewTransportWithCode(code string) (*Transport, error) {
	token, err := c.Exchange(code)
	if err != nil {
		return nil, err
	}
	return NewTransport(c.transport(), c, token), nil
}

// FetchToken retrieves a new access token and updates the existing token
// with the newly fetched credentials. If existing token doesn't
// contain a refresh token, it returns an error.
func (c *Config) FetchToken(existing *Token) (*Token, error) {
	if existing == nil || existing.RefreshToken == "" {
		return nil, errors.New("cannot fetch access token without refresh token.")
	}
	return c.retrieveToken(url.Values{
		"grant_type":    {"refresh_token"},
		"client_secret": {c.opts.ClientSecret},
		"refresh_token": {existing.RefreshToken},
	})
}

// Exchange exchanges the authorization code with the OAuth 2.0 provider
// to retrieve a new access token.
func (c *Config) Exchange(code string) (*Token, error) {
	vals := url.Values{
		"grant_type":    {"authorization_code"},
		"client_secret": {c.opts.ClientSecret},
		"code":          {code},
	}
	if len(c.opts.Scopes) != 0 {
		vals.Set("scope", strings.Join(c.opts.Scopes, " "))
	}
	if c.opts.RedirectURL != "" {
		vals.Set("redirect_uri", c.opts.RedirectURL)
	}
	return c.retrieveToken(vals)
}

func (c *Config) retrieveToken(v url.Values) (*Token, error) {
	v.Set("client_id", c.opts.ClientID)
	// Note that we're not setting v's client_secret to t.ClientSecret, due
	// to https://code.google.com/p/goauth2/issues/detail?id=31
	// Reddit only accepts client_secret in Authorization header.
	// Dropbox accepts either, but not both.
	// The spec requires servers to always support the Authorization header,
	// so that's all we use.
	r, err := c.client().PostForm(c.tokenURL.String(), v)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	if r.StatusCode != 200 {
		// TODO(jbd): Add status code or error message
		return nil, errors.New("error during updating token")
	}

	resp := &tokenRespBody{}
	content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
	switch content {
	case "application/x-www-form-urlencoded", "text/plain":
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			return nil, err
		}
		vals, err := url.ParseQuery(string(body))
		if err != nil {
			return nil, err
		}
		resp.AccessToken = vals.Get("access_token")
		resp.TokenType = vals.Get("token_type")
		resp.RefreshToken = vals.Get("refresh_token")
		resp.ExpiresIn, _ = strconv.ParseInt(vals.Get("expires_in"), 10, 64)
		resp.IdToken = vals.Get("id_token")
	default:
		if err = json.NewDecoder(r.Body).Decode(&resp); err != nil {
			return nil, err
		}
	}
	token := &Token{
		AccessToken:  resp.AccessToken,
		TokenType:    resp.TokenType,
		RefreshToken: resp.RefreshToken,
	}
	// Don't overwrite `RefreshToken` with an empty value
	// if this was a token refreshing request.
	if resp.RefreshToken == "" {
		token.RefreshToken = v.Get("refresh_token")
	}
	if resp.ExpiresIn == 0 {
		token.Expiry = time.Time{}
	} else {
		token.Expiry = time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second)
	}
	if resp.IdToken != "" {
		if token.Extra == nil {
			token.Extra = make(map[string]string)
		}
		token.Extra["id_token"] = resp.IdToken
	}
	return token, nil
}

func (c *Config) transport() http.RoundTripper {
	if c.Transport != nil {
		return c.Transport
	}
	return http.DefaultTransport
}

func (c *Config) client() *http.Client {
	if c.Client != nil {
		return c.Client
	}
	return http.DefaultClient
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 HenryLee. 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.

package tp

// Packet Header types
const (
	TypeUndefined int32 = 0
	TypePull      int32 = 1
	TypeReply     int32 = 2 // reply to pull
	TypePush      int32 = 3
	// TypeAuth      int32 = 4
	// TypeHeartbeat int32 = 5
)

// Response Header status codes as registered with IANA.
const (
	StatusWriteFailed = 100
	StatusConnClosed  = 101

	StatusOK = 200

	StatusBadUri               = 400
	StatusUnauthorized         = 401
	StatusNotFound             = 404
	StatusUnsupportedTx        = 410
	StatusUnsupportedCodecType = 415
	StatusFailedPlugin         = 424

	StatusInternalServerError           = 500
	StatusNotImplemented                = 501
	StatusBadGateway                    = 502
	StatusServiceUnavailable            = 503
	StatusGatewayTimeout                = 504
	StatusVariantAlsoNegotiates         = 506
	StatusInsufficientStorage           = 507
	StatusLoopDetected                  = 508
	StatusNotExtended                   = 510
	StatusNetworkAuthenticationRequired = 511
)

var statusText = map[int]string{
	StatusWriteFailed:          "write failed",
	StatusConnClosed:           "Connection Closed",
	StatusOK:                   "OK",
	StatusBadUri:               "Bad URI",
	StatusUnauthorized:         "Unauthorized",
	StatusNotFound:             "Not Found",
	StatusUnsupportedTx:        "Unsupported transaction type",
	StatusUnsupportedCodecType: "Unsupported codec type",
	StatusFailedPlugin:         "Failed Plugin",

	StatusInternalServerError:           "Internal Server Error",
	StatusNotImplemented:                "Not Implemented",
	StatusBadGateway:                    "Bad Gateway",
	StatusServiceUnavailable:            "Service Unavailable",
	StatusGatewayTimeout:                "Gateway Timeout",
	StatusVariantAlsoNegotiates:         "Variant Also Negotiates",
	StatusInsufficientStorage:           "Insufficient Storage",
	StatusLoopDetected:                  "Loop Detected",
	StatusNotExtended:                   "Not Extended",
	StatusNetworkAuthenticationRequired: "Network Authentication Required",
}

// StatusText returns a text for the Response Header status code. It returns the empty
// string if the code is unknown.
func StatusText(code int) string {
	return statusText[code]
}
<commit_msg>add TypeText()<commit_after>// Copyright 2015-2017 HenryLee. 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.

package tp

// Packet Header types
const (
	TypeUndefined int32 = 0
	TypePull      int32 = 1
	TypeReply     int32 = 2 // reply to pull
	TypePush      int32 = 3
	// TypeAuth      int32 = 4
	// TypeHeartbeat int32 = 5
)

// TypeText returns the packet type text.
// If the type is undefined returns 'Undefined'.
func TypeText(typ int32) string {
	switch typ {
	case TypePull:
		return "PULL"
	case TypeReply:
		return "REPLY"
	case TypePush:
		return "PUSH"
	default:
		return "Undefined"
	}
}

// Response Header status codes as registered with IANA.
const (
	StatusWriteFailed = 100
	StatusConnClosed  = 101

	StatusOK = 200

	StatusBadUri               = 400
	StatusUnauthorized         = 401
	StatusNotFound             = 404
	StatusUnsupportedTx        = 410
	StatusUnsupportedCodecType = 415
	StatusFailedPlugin         = 424

	StatusInternalServerError           = 500
	StatusNotImplemented                = 501
	StatusBadGateway                    = 502
	StatusServiceUnavailable            = 503
	StatusGatewayTimeout                = 504
	StatusVariantAlsoNegotiates         = 506
	StatusInsufficientStorage           = 507
	StatusLoopDetected                  = 508
	StatusNotExtended                   = 510
	StatusNetworkAuthenticationRequired = 511
)

var statusText = map[int]string{
	StatusWriteFailed:          "write failed",
	StatusConnClosed:           "Connection Closed",
	StatusOK:                   "OK",
	StatusBadUri:               "Bad URI",
	StatusUnauthorized:         "Unauthorized",
	StatusNotFound:             "Not Found",
	StatusUnsupportedTx:        "Unsupported transaction type",
	StatusUnsupportedCodecType: "Unsupported codec type",
	StatusFailedPlugin:         "Failed Plugin",

	StatusInternalServerError:           "Internal Server Error",
	StatusNotImplemented:                "Not Implemented",
	StatusBadGateway:                    "Bad Gateway",
	StatusServiceUnavailable:            "Service Unavailable",
	StatusGatewayTimeout:                "Gateway Timeout",
	StatusVariantAlsoNegotiates:         "Variant Also Negotiates",
	StatusInsufficientStorage:           "Insufficient Storage",
	StatusLoopDetected:                  "Loop Detected",
	StatusNotExtended:                   "Not Extended",
	StatusNetworkAuthenticationRequired: "Network Authentication Required",
}

// StatusText returns a text for the Response Header status code. It returns the empty
// string if the code is unknown.
func StatusText(code int) string {
	return statusText[code]
}
<|endoftext|>