<commit_before>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pubsub

import (
	"fmt"
	"reflect"
	"testing"
	"time"

	gax "github.com/googleapis/gax-go"

	"golang.org/x/net/context"

	"cloud.google.com/go/iam"
	"cloud.google.com/go/internal"
	"cloud.google.com/go/internal/testutil"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
)

// messageData is used to hold the contents of a message so that it can be compared against the contents
// of another message without regard to irrelevant fields.
type messageData struct {
	ID         string
	Data       []byte
	Attributes map[string]string
}

func extractMessageData(m *Message) *messageData {
	return &messageData{
		ID:         m.ID,
		Data:       m.Data,
		Attributes: m.Attributes,
	}
}

func TestAll(t *testing.T) {
	t.Parallel()
	if testing.Short() {
		t.Skip("Integration tests skipped in short mode")
	}
	ctx := context.Background()
	ts := testutil.TokenSource(ctx, ScopePubSub, ScopeCloudPlatform)
	if ts == nil {
		t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
	}

	now := time.Now()
	topicName := fmt.Sprintf("topic-%d", now.Unix())
	subName := fmt.Sprintf("subscription-%d", now.Unix())

	client, err := NewClient(ctx, testutil.ProjID(), option.WithTokenSource(ts))
	if err != nil {
		t.Fatalf("Creating client error: %v", err)
	}
	defer client.Close()

	var topic *Topic
	if topic, err = client.CreateTopic(ctx, topicName); err != nil {
		t.Errorf("CreateTopic error: %v", err)
	}
	defer topic.Stop()

	var sub *Subscription
	if sub, err = client.CreateSubscription(ctx, subName, SubscriptionConfig{Topic: topic}); err != nil {
		t.Errorf("CreateSub error: %v", err)
	}

	exists, err := topic.Exists(ctx)
	if err != nil {
		t.Fatalf("TopicExists error: %v", err)
	}
	if !exists {
		t.Errorf("topic %s should exist, but it doesn't", topic)
	}

	exists, err = sub.Exists(ctx)
	if err != nil {
		t.Fatalf("SubExists error: %v", err)
	}
	if !exists {
		t.Errorf("subscription %s should exist, but it doesn't", subName)
	}

	msgs := []*Message{}
	for i := 0; i < 10; i++ {
		text := fmt.Sprintf("a message with an index %d", i)
		attrs := make(map[string]string)
		attrs["foo"] = "bar"
		msgs = append(msgs, &Message{
			Data:       []byte(text),
			Attributes: attrs,
		})
	}

	// Publish the messages.
	type pubResult struct {
		m *Message
		r *PublishResult
	}
	var rs []pubResult
	for _, m := range msgs {
		r := topic.Publish(ctx, m)
		rs = append(rs, pubResult{m, r})
	}
	want := make(map[string]*messageData)
	for _, res := range rs {
		id, err := res.r.Get(ctx)
		if err != nil {
			t.Fatal(err)
		}
		md := extractMessageData(res.m)
		md.ID = id
		want[md.ID] = md
	}

	// Use a timeout to ensure that Pull does not block indefinitely if there are unexpectedly few messages available.
	timeoutCtx, _ := context.WithTimeout(ctx, time.Minute)
	gotMsgs, err := pullN(timeoutCtx, sub, len(want), func(ctx context.Context, m *Message) {
		m.Ack()
	})
	if err != nil {
		t.Fatalf("Pull: %v", err)
	}
	got := make(map[string]*messageData)
	for _, m := range gotMsgs {
		md := extractMessageData(m)
		got[md.ID] = md
	}
	if !reflect.DeepEqual(got, want) {
		t.Errorf("messages: got: %v ; want: %v", got, want)
	}

	if msg, ok := testIAM(ctx, topic.IAM(), "pubsub.topics.get"); !ok {
		t.Errorf("topic IAM: %s", msg)
	}
	if msg, ok := testIAM(ctx, sub.IAM(), "pubsub.subscriptions.get"); !ok {
		t.Errorf("sub IAM: %s", msg)
	}

	snap, err := sub.createSnapshot(ctx, "")
	if err != nil {
		t.Fatalf("CreateSnapshot error: %v", err)
	}

	timeoutCtx, _ = context.WithTimeout(ctx, time.Minute)
	err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (bool, error) {
		snapIt := client.snapshots(timeoutCtx)
		for {
			s, err := snapIt.Next()
			if err == nil && s.name == snap.name {
				return true, nil
			}
			if err == iterator.Done {
				return false, fmt.Errorf("cannot find snapshot: %q", snap.name)
			}
			if err != nil {
				return false, err
			}
		}
	})
	if err != nil {
		t.Error(err)
	}

	err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (bool, error) {
		err := sub.seekToSnapshot(timeoutCtx, snap.snapshot)
		return err == nil, err
	})
	if err != nil {
		t.Error(err)
	}

	err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (bool, error) {
		err := sub.seekToTime(timeoutCtx, time.Now())
		return err == nil, err
	})
	if err != nil {
		t.Error(err)
	}

	err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (bool, error) {
		snapHandle := client.snapshot(snap.ID())
		err := snapHandle.delete(timeoutCtx)
		return err == nil, err
	})
	if err != nil {
		t.Error(err)
	}

	if err := sub.Delete(ctx); err != nil {
		t.Errorf("DeleteSub error: %v", err)
	}

	if err := topic.Delete(ctx); err != nil {
		t.Errorf("DeleteTopic error: %v", err)
	}
}

// IAM tests.
// NOTE: for these to succeed, the test runner identity must have the Pub/Sub Admin or Owner roles.
// To set, visit https://console.developers.google.com, select "IAM & Admin" from the top-left
// menu, choose the account, click the Roles dropdown, and select "Pub/Sub > Pub/Sub Admin".
// TODO(jba): move this to a testing package within cloud.google.com/iam, so we can re-use it.
func testIAM(ctx context.Context, h *iam.Handle, permission string) (msg string, ok bool) {
	// Attempting to add an non-existent identity  (e.g. "alice@example.com") causes the service
	// to return an internal error, so use a real identity.
	const member = "domain:google.com"

	var policy *iam.Policy
	var err error

	if policy, err = h.Policy(ctx); err != nil {
		return fmt.Sprintf("Policy: %v", err), false
	}
	// The resource is new, so the policy should be empty.
	if got := policy.Roles(); len(got) > 0 {
		return fmt.Sprintf("initially: got roles %v, want none", got), false
	}
	// Add a member, set the policy, then check that the member is present.
	policy.Add(member, iam.Viewer)
	if err := h.SetPolicy(ctx, policy); err != nil {
		return fmt.Sprintf("SetPolicy: %v", err), false
	}
	if policy, err = h.Policy(ctx); err != nil {
		return fmt.Sprintf("Policy: %v", err), false
	}
	if got, want := policy.Members(iam.Viewer), []string{member}; !reflect.DeepEqual(got, want) {
		return fmt.Sprintf("after Add: got %v, want %v", got, want), false
	}
	// Now remove that member, set the policy, and check that it's empty again.
	policy.Remove(member, iam.Viewer)
	if err := h.SetPolicy(ctx, policy); err != nil {
		return fmt.Sprintf("SetPolicy: %v", err), false
	}
	if policy, err = h.Policy(ctx); err != nil {
		return fmt.Sprintf("Policy: %v", err), false
	}
	if got := policy.Roles(); len(got) > 0 {
		return fmt.Sprintf("after Remove: got roles %v, want none", got), false
	}
	// Call TestPermissions.
	// Because this user is an admin, it has all the permissions on the
	// resource type. Note: the service fails if we ask for inapplicable
	// permissions (e.g. a subscription permission on a topic, or a topic
	// create permission on a topic rather than its parent).
	wantPerms := []string{permission}
	gotPerms, err := h.TestPermissions(ctx, wantPerms)
	if err != nil {
		return fmt.Sprintf("TestPermissions: %v", err), false
	}
	if !reflect.DeepEqual(gotPerms, wantPerms) {
		return fmt.Sprintf("TestPermissions: got %v, want %v", gotPerms, wantPerms), false
	}
	return "", true
}
<commit_msg>pubsub: add test for ModifyPushConfig<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pubsub

import (
	"fmt"
	"reflect"
	"testing"
	"time"

	gax "github.com/googleapis/gax-go"

	"golang.org/x/net/context"

	"cloud.google.com/go/iam"
	"cloud.google.com/go/internal"
	"cloud.google.com/go/internal/testutil"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
)

// messageData is used to hold the contents of a message so that it can be compared against the contents
// of another message without regard to irrelevant fields.
type messageData struct {
	ID         string
	Data       []byte
	Attributes map[string]string
}

func extractMessageData(m *Message) *messageData {
	return &messageData{
		ID:         m.ID,
		Data:       m.Data,
		Attributes: m.Attributes,
	}
}

func TestAll(t *testing.T) {
	t.Parallel()
	if testing.Short() {
		t.Skip("Integration tests skipped in short mode")
	}
	projID := testutil.ProjID()
	if projID == "" {
		t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
	}
	ctx := context.Background()
	ts := testutil.TokenSource(ctx, ScopePubSub, ScopeCloudPlatform)
	if ts == nil {
		t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
	}

	now := time.Now()
	topicName := fmt.Sprintf("topic-%d", now.Unix())
	subName := fmt.Sprintf("subscription-%d", now.Unix())

	client, err := NewClient(ctx, projID, option.WithTokenSource(ts))
	if err != nil {
		t.Fatalf("Creating client error: %v", err)
	}
	defer client.Close()

	var topic *Topic
	if topic, err = client.CreateTopic(ctx, topicName); err != nil {
		t.Errorf("CreateTopic error: %v", err)
	}
	defer topic.Stop()

	var sub *Subscription
	if sub, err = client.CreateSubscription(ctx, subName, SubscriptionConfig{Topic: topic}); err != nil {
		t.Errorf("CreateSub error: %v", err)
	}

	exists, err := topic.Exists(ctx)
	if err != nil {
		t.Fatalf("TopicExists error: %v", err)
	}
	if !exists {
		t.Errorf("topic %s should exist, but it doesn't", topic)
	}

	exists, err = sub.Exists(ctx)
	if err != nil {
		t.Fatalf("SubExists error: %v", err)
	}
	if !exists {
		t.Errorf("subscription %s should exist, but it doesn't", subName)
	}

	msgs := []*Message{}
	for i := 0; i < 10; i++ {
		text := fmt.Sprintf("a message with an index %d", i)
		attrs := make(map[string]string)
		attrs["foo"] = "bar"
		msgs = append(msgs, &Message{
			Data:       []byte(text),
			Attributes: attrs,
		})
	}

	// Publish the messages.
	type pubResult struct {
		m *Message
		r *PublishResult
	}
	var rs []pubResult
	for _, m := range msgs {
		r := topic.Publish(ctx, m)
		rs = append(rs, pubResult{m, r})
	}
	want := make(map[string]*messageData)
	for _, res := range rs {
		id, err := res.r.Get(ctx)
		if err != nil {
			t.Fatal(err)
		}
		md := extractMessageData(res.m)
		md.ID = id
		want[md.ID] = md
	}

	// Use a timeout to ensure that Pull does not block indefinitely if there are unexpectedly few messages available.
	timeoutCtx, _ := context.WithTimeout(ctx, time.Minute)
	gotMsgs, err := pullN(timeoutCtx, sub, len(want), func(ctx context.Context, m *Message) {
		m.Ack()
	})
	if err != nil {
		t.Fatalf("Pull: %v", err)
	}
	got := make(map[string]*messageData)
	for _, m := range gotMsgs {
		md := extractMessageData(m)
		got[md.ID] = md
	}
	if !reflect.DeepEqual(got, want) {
		t.Errorf("messages: got: %v ; want: %v", got, want)
	}

	if msg, ok := testIAM(ctx, topic.IAM(), "pubsub.topics.get"); !ok {
		t.Errorf("topic IAM: %s", msg)
	}
	if msg, ok := testIAM(ctx, sub.IAM(), "pubsub.subscriptions.get"); !ok {
		t.Errorf("sub IAM: %s", msg)
	}

	snap, err := sub.createSnapshot(ctx, "")
	if err != nil {
		t.Fatalf("CreateSnapshot error: %v", err)
	}

	timeoutCtx, _ = context.WithTimeout(ctx, time.Minute)
	err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (bool, error) {
		snapIt := client.snapshots(timeoutCtx)
		for {
			s, err := snapIt.Next()
			if err == nil && s.name == snap.name {
				return true, nil
			}
			if err == iterator.Done {
				return false, fmt.Errorf("cannot find snapshot: %q", snap.name)
			}
			if err != nil {
				return false, err
			}
		}
	})
	if err != nil {
		t.Error(err)
	}

	err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (bool, error) {
		err := sub.seekToSnapshot(timeoutCtx, snap.snapshot)
		return err == nil, err
	})
	if err != nil {
		t.Error(err)
	}

	err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (bool, error) {
		err := sub.seekToTime(timeoutCtx, time.Now())
		return err == nil, err
	})
	if err != nil {
		t.Error(err)
	}

	err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (bool, error) {
		snapHandle := client.snapshot(snap.ID())
		err := snapHandle.delete(timeoutCtx)
		return err == nil, err
	})
	if err != nil {
		t.Error(err)
	}

	if err := sub.Delete(ctx); err != nil {
		t.Errorf("DeleteSub error: %v", err)
	}

	if err := topic.Delete(ctx); err != nil {
		t.Errorf("DeleteTopic error: %v", err)
	}
}

// IAM tests.
// NOTE: for these to succeed, the test runner identity must have the Pub/Sub Admin or Owner roles.
// To set, visit https://console.developers.google.com, select "IAM & Admin" from the top-left
// menu, choose the account, click the Roles dropdown, and select "Pub/Sub > Pub/Sub Admin".
// TODO(jba): move this to a testing package within cloud.google.com/iam, so we can re-use it.
func testIAM(ctx context.Context, h *iam.Handle, permission string) (msg string, ok bool) {
	// Attempting to add an non-existent identity  (e.g. "alice@example.com") causes the service
	// to return an internal error, so use a real identity.
	const member = "domain:google.com"

	var policy *iam.Policy
	var err error

	if policy, err = h.Policy(ctx); err != nil {
		return fmt.Sprintf("Policy: %v", err), false
	}
	// The resource is new, so the policy should be empty.
	if got := policy.Roles(); len(got) > 0 {
		return fmt.Sprintf("initially: got roles %v, want none", got), false
	}
	// Add a member, set the policy, then check that the member is present.
	policy.Add(member, iam.Viewer)
	if err := h.SetPolicy(ctx, policy); err != nil {
		return fmt.Sprintf("SetPolicy: %v", err), false
	}
	if policy, err = h.Policy(ctx); err != nil {
		return fmt.Sprintf("Policy: %v", err), false
	}
	if got, want := policy.Members(iam.Viewer), []string{member}; !reflect.DeepEqual(got, want) {
		return fmt.Sprintf("after Add: got %v, want %v", got, want), false
	}
	// Now remove that member, set the policy, and check that it's empty again.
	policy.Remove(member, iam.Viewer)
	if err := h.SetPolicy(ctx, policy); err != nil {
		return fmt.Sprintf("SetPolicy: %v", err), false
	}
	if policy, err = h.Policy(ctx); err != nil {
		return fmt.Sprintf("Policy: %v", err), false
	}
	if got := policy.Roles(); len(got) > 0 {
		return fmt.Sprintf("after Remove: got roles %v, want none", got), false
	}
	// Call TestPermissions.
	// Because this user is an admin, it has all the permissions on the
	// resource type. Note: the service fails if we ask for inapplicable
	// permissions (e.g. a subscription permission on a topic, or a topic
	// create permission on a topic rather than its parent).
	wantPerms := []string{permission}
	gotPerms, err := h.TestPermissions(ctx, wantPerms)
	if err != nil {
		return fmt.Sprintf("TestPermissions: %v", err), false
	}
	if !reflect.DeepEqual(gotPerms, wantPerms) {
		return fmt.Sprintf("TestPermissions: got %v, want %v", gotPerms, wantPerms), false
	}
	return "", true
}

func TestModifyPushConfig(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	if testing.Short() {
		t.Skip("Integration tests skipped in short mode")
	}
	projID := testutil.ProjID()
	if projID == "" {
		t.Skip("Integration tests skipped. See CONTRIBUTING.md for details.")
	}
	ts := testutil.TokenSource(ctx, ScopePubSub, ScopeCloudPlatform)
	if ts == nil {
		t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
	}

	now := time.Now()
	topicName := fmt.Sprintf("topic-modify-%d", now.Unix())
	subName := fmt.Sprintf("subscription-modify-%d", now.Unix())

	client, err := NewClient(ctx, projID, option.WithTokenSource(ts))
	if err != nil {
		t.Fatalf("Creating client error: %v", err)
	}
	defer client.Close()

	var topic *Topic
	if topic, err = client.CreateTopic(ctx, topicName); err != nil {
		t.Fatalf("CreateTopic error: %v", err)
	}
	defer topic.Stop()
	defer topic.Delete(ctx)

	var sub *Subscription
	if sub, err = client.CreateSubscription(ctx, subName, SubscriptionConfig{Topic: topic}); err != nil {
		t.Fatalf("CreateSub error: %v", err)
	}
	defer sub.Delete(ctx)

	getConfig := func() SubscriptionConfig {
		sc, err := sub.Config(ctx)
		if err != nil {
			t.Fatal(err)
		}
		return sc
	}

	sc := getConfig()
	if !reflect.DeepEqual(sc.PushConfig, PushConfig{}) {
		t.Fatalf("got %+v, want empty PushConfig")
	}
	// Add a PushConfig.
	pc := PushConfig{
		Endpoint:   "https://" + projID + ".appspot.com/_ah/push-handlers/push",
		Attributes: map[string]string{"x-goog-version": "v1"},
	}
	if err := sub.ModifyPushConfig(ctx, pc); err != nil {
		t.Fatal(err)
	}
	// Despite the docs which say that Get always returns a valid "x-goog-version"
	// attribute, none is returned. See
	// https://cloud.google.com/pubsub/docs/reference/rpc/google.pubsub.v1#google.pubsub.v1.PushConfig
	pc.Attributes = nil
	if got, want := getConfig().PushConfig, pc; !reflect.DeepEqual(got, want) {
		t.Fatalf("setting push config: got\n%+v\nwant\n%+v", got, want)
	}
	// Remove the PushConfig, turning the subscription back into pull mode.
	pc = PushConfig{}
	if err := sub.ModifyPushConfig(ctx, pc); err != nil {
		t.Fatal(err)
	}
	if got, want := getConfig().PushConfig, pc; !reflect.DeepEqual(got, want) {
		t.Fatalf("removing push config: got\n%+v\nwant %+v", got, want)
	}
}
<|endoftext|>


<commit_before>package visualizer

import (
	log "github.com/Sirupsen/logrus"
	"github.com/hkparker/Wave/helpers"
	"github.com/hkparker/Wave/models"
	"strings"
	"sync"
)

const (
	DEVICE_ISAP           = "IsAP"
	DEVICE_MAC            = "MAC"
	DEVICE_NULLPROBE      = "NullProbe"
	DEVICE_PROBE          = "ProbedFor"
	DEVICE_POWERSTATE     = "PowerState"
	DEVICE_POWERSTATE_ON  = "online"
	DEVICE_POWERSTATE_OFF = "offline"

	TYPE_NULL_PROBE_REQUEST = "NullProbeRequest"
	TYPE_PROBE_REQUEST      = "ProbeRequest"
	TYPE_UPDATE_AP          = "UpdateAccessPoint"

	EVENT = "Event"
	SSID  = "SSID"
	TYPE  = "type"
)

type VisualEvent map[string]string

var VisualEvents = make(chan VisualEvent, 0)

var Devices = make(map[string]models.Device)
var DevicesMux sync.Mutex
var Networks = make(map[string]models.Network)
var NetworksMux sync.Mutex
var VendorBytes = make(map[string]string)

func init() {
	loadMetadata()
}

func loadMetadata() {
	prefix_path := "engines/visualizer/metadata/nmap-mac-prefixes"
	vendor_data, err := helpers.Asset(prefix_path)
	if err != nil {
		log.WithFields(log.Fields{
			"at":    "visualizer.loadMetadata",
			"error": err.Error(),
		}).Error("unable to load vendor bytes")
		return
	}
	lines := strings.Split(string(vendor_data), "\n")
	for _, line := range lines {
		if len(line) == 0 || string(line[0]) == "#" {
			continue
		}
		raw_mac := line[0:6]
		name := line[7:]
		mac := raw_mac[0:2] + ":" +
			raw_mac[2:4] + ":" +
			raw_mac[4:6]
		VendorBytes[strings.ToUpper(mac)] = name
	}
}

func Insert(frame models.Wireless80211Frame) {
	//	DevicesMux.Lock()
	//	defer DevicesMux.Unlock()
	//	NetworksMux.Lock()
	//	defer NetworksMux.Unlock()
	updateKnownDevices(frame)

	if len(frame.Type) < 4 {
		log.WithFields(log.Fields{}).Warn("frame type too small")
		return
	}
	switch frame.Type[:4] {
	case "Mgmt":
		insertMgmt(frame)
	case "Data":
		insertData(frame)
	case "Ctrl":
		insertCtrl(frame)
	//case "Rese":
	default:
		log.WithFields(log.Fields{
			"at":         "visualizer.Insert",
			"frame.Type": frame.Type,
		}).Warn("unknown frame type")
	}
}

func insertMgmt(frame models.Wireless80211Frame) {
	switch frame.Type {
	case "MgmtAssociationReq":
	case "MgmtAssociationResp":
	case "MgmtReassociationReq":
	case "MgmtReassociationResp":
	case "MgmtProbeReq":
		updateProbeRequests(frame)
	case "MgmtProbeResp":
	case "MgmtMeasurementPilot":
	case "MgmtBeacon":
		updateAccessPoints(frame)
	case "MgmtATIM":
	case "MgmtDisassociation":
	case "MgmtAuthentication":
	case "MgmtDeauthentication":
	case "MgmtAction":
	case "MgmtActionNoAck":
	default:
		log.WithFields(log.Fields{
			"at":   "visualizer.insertMgmt",
			"type": frame.Type,
		}).Warn("unknown frame type")
	}
}

func insertData(frame models.Wireless80211Frame) {
	//updateNetworkAssociations(frames)
	//updateTx()
	switch frame.Type {
	case "Data":
	case "DataCFAck":
	case "DataCFPoll":
	case "DataCFAckPoll":
	case "DataNull":
		updateDataNull(frame)
	case "DataCFAckNoData":
	case "DataCFPollNoData":
	case "DataCFAckPollNoData":
	case "DataQOSData":
	case "DataQOSDataCFAck":
	case "DataQOSDataCFPoll":
	case "DataQOSDataCFAckPoll":
	case "DataQOSNull":
	case "DataQOSCFPollNoData":
	case "DataQOSCFAckPollNoData":
	default:
		log.WithFields(log.Fields{
			"at":   "visualizer.insertData",
			"type": frame.Type,
		}).Warn("unknown frame type")
	}
}

func insertCtrl(frame models.Wireless80211Frame) {
	switch frame.Type {
	case "CtrlWrapper":
	case "CtrlBlockAckReq":
	case "CtrlBlockAck":
	case "CtrlPowersavePoll":
	case "CtrlRTS":
	case "CtrlCTS":
	case "CtrlAck":
	case "CtrlCFEnd":
	case "CtrlCFEndAck":
	default:
		log.WithFields(log.Fields{
			"at":   "visualizer.insertCtrl",
			"type": frame.Type,
		}).Warn("unknown frame type")
	}
}

func CatchupEvents() []VisualEvent {
	catchup_events := make([]VisualEvent, 0)
	//for _, device := range Devices {
	//	catchup_events = append(catchup_events, device.VisualData())
	//}
	//for _, network := range Networks {
	//	ssid_set := network.VisualData()
	//	for _, network_event := range ssid_set {
	//		catchup_events = append(catchup_events, VisualEvent(network_event))
	//	}
	//}
	// add other resources, create other events
	return catchup_events
}
<commit_msg>use mutex, catchup events again<commit_after>package visualizer

import (
	log "github.com/Sirupsen/logrus"
	"github.com/hkparker/Wave/helpers"
	"github.com/hkparker/Wave/models"
	"strings"
	"sync"
)

const (
	DEVICE_ISAP           = "IsAP"
	DEVICE_MAC            = "MAC"
	DEVICE_NULLPROBE      = "NullProbe"
	DEVICE_PROBE          = "ProbedFor"
	DEVICE_POWERSTATE     = "PowerState"
	DEVICE_POWERSTATE_ON  = "online"
	DEVICE_POWERSTATE_OFF = "offline"

	TYPE_NULL_PROBE_REQUEST = "NullProbeRequest"
	TYPE_PROBE_REQUEST      = "ProbeRequest"
	TYPE_UPDATE_AP          = "UpdateAccessPoint"

	EVENT = "Event"
	SSID  = "SSID"
	TYPE  = "type"
)

type VisualEvent map[string]string

var VisualEvents = make(chan VisualEvent, 0)

var Devices = make(map[string]models.Device)
var DevicesMux sync.Mutex
var Networks = make(map[string]models.Network)
var NetworksMux sync.Mutex
var VendorBytes = make(map[string]string)

func init() {
	loadMetadata()
}

func loadMetadata() {
	prefix_path := "engines/visualizer/metadata/nmap-mac-prefixes"
	vendor_data, err := helpers.Asset(prefix_path)
	if err != nil {
		log.WithFields(log.Fields{
			"at":    "visualizer.loadMetadata",
			"error": err.Error(),
		}).Error("unable to load vendor bytes")
		return
	}
	lines := strings.Split(string(vendor_data), "\n")
	for _, line := range lines {
		if len(line) == 0 || string(line[0]) == "#" {
			continue
		}
		raw_mac := line[0:6]
		name := line[7:]
		mac := raw_mac[0:2] + ":" +
			raw_mac[2:4] + ":" +
			raw_mac[4:6]
		VendorBytes[strings.ToUpper(mac)] = name
	}
}

func Insert(frame models.Wireless80211Frame) {
	DevicesMux.Lock()
	defer DevicesMux.Unlock()
	NetworksMux.Lock()
	defer NetworksMux.Unlock()
	updateKnownDevices(frame)

	if len(frame.Type) < 4 {
		log.WithFields(log.Fields{}).Warn("frame type too small")
		return
	}
	switch frame.Type[:4] {
	case "Mgmt":
		insertMgmt(frame)
	case "Data":
		insertData(frame)
	case "Ctrl":
		insertCtrl(frame)
	//case "Rese":
	default:
		log.WithFields(log.Fields{
			"at":         "visualizer.Insert",
			"frame.Type": frame.Type,
		}).Warn("unknown frame type")
	}
}

func insertMgmt(frame models.Wireless80211Frame) {
	switch frame.Type {
	case "MgmtAssociationReq":
	case "MgmtAssociationResp":
	case "MgmtReassociationReq":
	case "MgmtReassociationResp":
	case "MgmtProbeReq":
		updateProbeRequests(frame)
	case "MgmtProbeResp":
	case "MgmtMeasurementPilot":
	case "MgmtBeacon":
		updateAccessPoints(frame)
	case "MgmtATIM":
	case "MgmtDisassociation":
	case "MgmtAuthentication":
	case "MgmtDeauthentication":
	case "MgmtAction":
	case "MgmtActionNoAck":
	default:
		log.WithFields(log.Fields{
			"at":   "visualizer.insertMgmt",
			"type": frame.Type,
		}).Warn("unknown frame type")
	}
}

func insertData(frame models.Wireless80211Frame) {
	//updateNetworkAssociations(frames)
	//updateTx()
	switch frame.Type {
	case "Data":
	case "DataCFAck":
	case "DataCFPoll":
	case "DataCFAckPoll":
	case "DataNull":
		updateDataNull(frame)
	case "DataCFAckNoData":
	case "DataCFPollNoData":
	case "DataCFAckPollNoData":
	case "DataQOSData":
	case "DataQOSDataCFAck":
	case "DataQOSDataCFPoll":
	case "DataQOSDataCFAckPoll":
	case "DataQOSNull":
	case "DataQOSCFPollNoData":
	case "DataQOSCFAckPollNoData":
	default:
		log.WithFields(log.Fields{
			"at":   "visualizer.insertData",
			"type": frame.Type,
		}).Warn("unknown frame type")
	}
}

func insertCtrl(frame models.Wireless80211Frame) {
	switch frame.Type {
	case "CtrlWrapper":
	case "CtrlBlockAckReq":
	case "CtrlBlockAck":
	case "CtrlPowersavePoll":
	case "CtrlRTS":
	case "CtrlCTS":
	case "CtrlAck":
	case "CtrlCFEnd":
	case "CtrlCFEndAck":
	default:
		log.WithFields(log.Fields{
			"at":   "visualizer.insertCtrl",
			"type": frame.Type,
		}).Warn("unknown frame type")
	}
}

func CatchupEvents() []VisualEvent {
	catchup_events := make([]VisualEvent, 0)
	for _, device := range Devices {
		catchup_events = append(catchup_events, device.VisualData())
	}
	for _, network := range Networks {
		ssid_set := network.VisualData()
		for _, network_event := range ssid_set {
			catchup_events = append(catchup_events, VisualEvent(network_event))
		}
	}
	// add other resources, create other events
	return catchup_events
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

type thing struct {
	name string
}

func readVulnerableField(t *thing) {
	fmt.Println(t.name)
}

func readSafeField(t thing) {
	fmt.Println(t.name)
}

func writeVulnerableField(t *thing) {
	t.name = "car"
}

func writeSafeField(t thing) {
	t.name = "boat"
}

func (t *thing) readFromPointer() {
	fmt.Println(t.name)
}

func (t *thing) writeToPointer(name string) {
	t.name = name
}

// Concurrent read and writes to a field of a copy of an instance of thing. No Issue
func concurrentCopyReadWrites() {

	t := thing{"Object"}

	readSafeField(t)

	go readSafeField(t)

	go func(t thing) {
		fmt.Println(t.name)
	}(t)

	go func(t thing) {
		t.name = "bus"
	}(t)
}

// Concurrent reads to a field of a copy of an instance of thing. No Issue
func concurrentCopyReads() {

	t := thing{"Object"}

	readSafeField(t)

	go readSafeField(t)

	go func(t thing) {
		fmt.Println(t.name)
	}(t)
}

// Concurrent writes to a field of a copy of an instance of thing. No Issue
func concurrentCopyWrites() {

	t := thing{"Object"}

	writeSafeField(t)

	go writeSafeField(t)

	go func(t thing) {
		t.name = "plane"
	}(t)
}

// Concurrent reads to a field of a pointer to an instance of thing. No Issue
func concurrentPointerReads() {

	t := &thing{"Pointer"}

	readVulnerableField(t)

	go readVulnerableField(t)

	go func(t *thing) {
		fmt.Println(t.name)
	}(t)
}

// Concurrent writes to a field of a pointer to an instance of thing. Issue
func concurrentPointerWrites() {

	t := &thing{"Pointer"}

	writeVulnerableField(t)

	go writeVulnerableField(t)

	go func(t *thing) {
		t.name = "bus"
	}(t)
}

// Concurrent reads and writes to a field of a pointer to an instance of thing. Issue
func concurrentPointerReadWrites() {

	t := &thing{"Pointer"}

	readVulnerableField(t)

	go readVulnerableField(t)

	go writeVulnerableField(t)

	go func(t *thing) {
		fmt.Println(t.name)
	}(t)

	go func(t *thing) {
		t.name = "car"
	}(t)

	t.readFromPointer()

	t.writeToPointer("plane")

	go t.writeToPointer("boat")
}

func main() {
	concurrentCopyReads()
	concurrentCopyWrites()
	concurrentCopyReadWrites()
	concurrentPointerReads()
	concurrentPointerWrites()
	concurrentPointerReadWrites()
}
<commit_msg>Remove uneeded parts of example file<commit_after>package main

import (
	"fmt"
)

type thing struct {
	name string
}

func readVulnerableField(t *thing) {
	fmt.Println(t.name)
}

func readSafeField(t thing) {
	fmt.Println(t.name)
}

func writeVulnerableField(t *thing) {
	t.name = "car"
}

func writeSafeField(t thing) {
	t.name = "boat"
}

// Concurrent read and writes to a field of a copy of an instance of thing. No Issue
func concurrentCopyReadWrites() {

	t := thing{"Object"}

	readSafeField(t)

	go readSafeField(t)

	go func(t thing) {
		fmt.Println(t.name)
	}(t)

	go func(t thing) {
		t.name = "bus"
	}(t)
}

// Concurrent reads to a field of a copy of an instance of thing. No Issue
func concurrentCopyReads() {

	t := thing{"Object"}

	readSafeField(t)

	go readSafeField(t)

	go func(t thing) {
		fmt.Println(t.name)
	}(t)
}

// Concurrent writes to a field of a copy of an instance of thing. No Issue
func concurrentCopyWrites() {

	t := thing{"Object"}

	writeSafeField(t)

	go writeSafeField(t)

	go func(t thing) {
		t.name = "plane"
	}(t)
}

// Concurrent reads to a field of a pointer to an instance of thing. No Issue
func concurrentPointerReads() {

	t := &thing{"Pointer"}

	readVulnerableField(t)

	go readVulnerableField(t)

	go func(t *thing) {
		fmt.Println(t.name)
	}(t)
}

// Concurrent writes to a field of a pointer to an instance of thing. Issue
func concurrentPointerWrites() {

	t := &thing{"Pointer"}

	go writeVulnerableField(t)

	go func(t *thing) {
		t.name = "bus"
	}(t)
}

// Concurrent reads and writes to a field of a pointer to an instance of thing. Issue
func concurrentPointerReadWrites() {

	t := &thing{"Pointer"}

	go readVulnerableField(t)

	go writeVulnerableField(t)

	go func(t *thing) {
		fmt.Println(t.name)
	}(t)

	go func(t *thing) {
		t.name = "car"
	}(t)

}

func main() {
	concurrentCopyReads()
	concurrentCopyWrites()
	concurrentCopyReadWrites()
	concurrentPointerReads()
	concurrentPointerWrites()
	concurrentPointerReadWrites()
}
<|endoftext|>


<commit_before>// Copyright 2016 The etcd Authors
//
// 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 command

import (
	"errors"
	"fmt"
	"strings"

	pb "go.etcd.io/etcd/api/v3/etcdserverpb"
	v3 "go.etcd.io/etcd/client/v3"
	"go.etcd.io/etcd/pkg/v3/cobrautl"

	"github.com/dustin/go-humanize"
)

type printer interface {
	Del(v3.DeleteResponse)
	Get(v3.GetResponse)
	Put(v3.PutResponse)
	Txn(v3.TxnResponse)
	Watch(v3.WatchResponse)

	Grant(r v3.LeaseGrantResponse)
	Revoke(id v3.LeaseID, r v3.LeaseRevokeResponse)
	KeepAlive(r v3.LeaseKeepAliveResponse)
	TimeToLive(r v3.LeaseTimeToLiveResponse, keys bool)
	Leases(r v3.LeaseLeasesResponse)

	MemberAdd(v3.MemberAddResponse)
	MemberRemove(id uint64, r v3.MemberRemoveResponse)
	MemberUpdate(id uint64, r v3.MemberUpdateResponse)
	MemberPromote(id uint64, r v3.MemberPromoteResponse)
	MemberList(v3.MemberListResponse)

	EndpointHealth([]epHealth)
	EndpointStatus([]epStatus)
	EndpointHashKV([]epHashKV)
	MoveLeader(leader, target uint64, r v3.MoveLeaderResponse)

	Alarm(v3.AlarmResponse)

	RoleAdd(role string, r v3.AuthRoleAddResponse)
	RoleGet(role string, r v3.AuthRoleGetResponse)
	RoleDelete(role string, r v3.AuthRoleDeleteResponse)
	RoleList(v3.AuthRoleListResponse)
	RoleGrantPermission(role string, r v3.AuthRoleGrantPermissionResponse)
	RoleRevokePermission(role string, key string, end string, r v3.AuthRoleRevokePermissionResponse)

	UserAdd(user string, r v3.AuthUserAddResponse)
	UserGet(user string, r v3.AuthUserGetResponse)
	UserList(r v3.AuthUserListResponse)
	UserChangePassword(v3.AuthUserChangePasswordResponse)
	UserGrantRole(user string, role string, r v3.AuthUserGrantRoleResponse)
	UserRevokeRole(user string, role string, r v3.AuthUserRevokeRoleResponse)
	UserDelete(user string, r v3.AuthUserDeleteResponse)

	AuthStatus(r v3.AuthStatusResponse)
}

func NewPrinter(printerType string, isHex bool) printer {
	switch printerType {
	case "simple":
		return &simplePrinter{isHex: isHex}
	case "fields":
		return &fieldsPrinter{newPrinterUnsupported("fields")}
	case "json":
		return newJSONPrinter(isHex)
	case "protobuf":
		return newPBPrinter()
	case "table":
		return &tablePrinter{newPrinterUnsupported("table")}
	}
	return nil
}

type printerRPC struct {
	printer
	p func(interface{})
}

func (p *printerRPC) Del(r v3.DeleteResponse)  { p.p((*pb.DeleteRangeResponse)(&r)) }
func (p *printerRPC) Get(r v3.GetResponse)     { p.p((*pb.RangeResponse)(&r)) }
func (p *printerRPC) Put(r v3.PutResponse)     { p.p((*pb.PutResponse)(&r)) }
func (p *printerRPC) Txn(r v3.TxnResponse)     { p.p((*pb.TxnResponse)(&r)) }
func (p *printerRPC) Watch(r v3.WatchResponse) { p.p(&r) }

func (p *printerRPC) Grant(r v3.LeaseGrantResponse)                      { p.p(r) }
func (p *printerRPC) Revoke(id v3.LeaseID, r v3.LeaseRevokeResponse)     { p.p(r) }
func (p *printerRPC) KeepAlive(r v3.LeaseKeepAliveResponse)              { p.p(r) }
func (p *printerRPC) TimeToLive(r v3.LeaseTimeToLiveResponse, keys bool) { p.p(&r) }
func (p *printerRPC) Leases(r v3.LeaseLeasesResponse)                    { p.p(&r) }

func (p *printerRPC) MemberAdd(r v3.MemberAddResponse) { p.p((*pb.MemberAddResponse)(&r)) }
func (p *printerRPC) MemberRemove(id uint64, r v3.MemberRemoveResponse) {
	p.p((*pb.MemberRemoveResponse)(&r))
}
func (p *printerRPC) MemberUpdate(id uint64, r v3.MemberUpdateResponse) {
	p.p((*pb.MemberUpdateResponse)(&r))
}
func (p *printerRPC) MemberList(r v3.MemberListResponse) { p.p((*pb.MemberListResponse)(&r)) }
func (p *printerRPC) Alarm(r v3.AlarmResponse)           { p.p((*pb.AlarmResponse)(&r)) }
func (p *printerRPC) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) {
	p.p((*pb.MoveLeaderResponse)(&r))
}
func (p *printerRPC) RoleAdd(_ string, r v3.AuthRoleAddResponse) { p.p((*pb.AuthRoleAddResponse)(&r)) }
func (p *printerRPC) RoleGet(_ string, r v3.AuthRoleGetResponse) { p.p((*pb.AuthRoleGetResponse)(&r)) }
func (p *printerRPC) RoleDelete(_ string, r v3.AuthRoleDeleteResponse) {
	p.p((*pb.AuthRoleDeleteResponse)(&r))
}
func (p *printerRPC) RoleList(r v3.AuthRoleListResponse) { p.p((*pb.AuthRoleListResponse)(&r)) }
func (p *printerRPC) RoleGrantPermission(_ string, r v3.AuthRoleGrantPermissionResponse) {
	p.p((*pb.AuthRoleGrantPermissionResponse)(&r))
}
func (p *printerRPC) RoleRevokePermission(_ string, _ string, _ string, r v3.AuthRoleRevokePermissionResponse) {
	p.p((*pb.AuthRoleRevokePermissionResponse)(&r))
}
func (p *printerRPC) UserAdd(_ string, r v3.AuthUserAddResponse) { p.p((*pb.AuthUserAddResponse)(&r)) }
func (p *printerRPC) UserGet(_ string, r v3.AuthUserGetResponse) { p.p((*pb.AuthUserGetResponse)(&r)) }
func (p *printerRPC) UserList(r v3.AuthUserListResponse)         { p.p((*pb.AuthUserListResponse)(&r)) }
func (p *printerRPC) UserChangePassword(r v3.AuthUserChangePasswordResponse) {
	p.p((*pb.AuthUserChangePasswordResponse)(&r))
}
func (p *printerRPC) UserGrantRole(_ string, _ string, r v3.AuthUserGrantRoleResponse) {
	p.p((*pb.AuthUserGrantRoleResponse)(&r))
}
func (p *printerRPC) UserRevokeRole(_ string, _ string, r v3.AuthUserRevokeRoleResponse) {
	p.p((*pb.AuthUserRevokeRoleResponse)(&r))
}
func (p *printerRPC) UserDelete(_ string, r v3.AuthUserDeleteResponse) {
	p.p((*pb.AuthUserDeleteResponse)(&r))
}
func (p *printerRPC) AuthStatus(r v3.AuthStatusResponse) {
	p.p((*pb.AuthStatusResponse)(&r))
}

type printerUnsupported struct{ printerRPC }

func newPrinterUnsupported(n string) printer {
	f := func(interface{}) {
		cobrautl.ExitWithError(cobrautl.ExitBadFeature, errors.New(n+" not supported as output format"))
	}
	return &printerUnsupported{printerRPC{nil, f}}
}

func (p *printerUnsupported) EndpointHealth([]epHealth) { p.p(nil) }
func (p *printerUnsupported) EndpointStatus([]epStatus) { p.p(nil) }
func (p *printerUnsupported) EndpointHashKV([]epHashKV) { p.p(nil) }

func (p *printerUnsupported) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) { p.p(nil) }

func makeMemberListTable(r v3.MemberListResponse) (hdr []string, rows [][]string) {
	hdr = []string{"ID", "Status", "Name", "Peer Addrs", "Client Addrs", "Is Learner"}
	for _, m := range r.Members {
		status := "started"
		if len(m.Name) == 0 {
			status = "unstarted"
		}
		isLearner := "false"
		if m.IsLearner {
			isLearner = "true"
		}
		rows = append(rows, []string{
			fmt.Sprintf("%x", m.ID),
			status,
			m.Name,
			strings.Join(m.PeerURLs, ","),
			strings.Join(m.ClientURLs, ","),
			isLearner,
		})
	}
	return hdr, rows
}

func makeEndpointHealthTable(healthList []epHealth) (hdr []string, rows [][]string) {
	hdr = []string{"endpoint", "health", "took", "error"}
	for _, h := range healthList {
		rows = append(rows, []string{
			h.Ep,
			fmt.Sprintf("%v", h.Health),
			h.Took,
			h.Error,
		})
	}
	return hdr, rows
}

func makeEndpointStatusTable(statusList []epStatus) (hdr []string, rows [][]string) {
	hdr = []string{"endpoint", "ID", "version", "db size", "is leader", "is learner", "raft term",
		"raft index", "raft applied index", "errors"}
	for _, status := range statusList {
		rows = append(rows, []string{
			status.Ep,
			fmt.Sprintf("%x", status.Resp.Header.MemberId),
			status.Resp.Version,
			humanize.Bytes(uint64(status.Resp.DbSize)),
			fmt.Sprint(status.Resp.Leader == status.Resp.Header.MemberId),
			fmt.Sprint(status.Resp.IsLearner),
			fmt.Sprint(status.Resp.RaftTerm),
			fmt.Sprint(status.Resp.RaftIndex),
			fmt.Sprint(status.Resp.RaftAppliedIndex),
			fmt.Sprint(strings.Join(status.Resp.Errors, ", ")),
		})
	}
	return hdr, rows
}

func makeEndpointHashKVTable(hashList []epHashKV) (hdr []string, rows [][]string) {
	hdr = []string{"endpoint", "hash"}
	for _, h := range hashList {
		rows = append(rows, []string{
			h.Ep,
			fmt.Sprint(h.Resp.Hash),
		})
	}
	return hdr, rows
}
<commit_msg>ctlv3: add forgotten member promote method to printerRPC<commit_after>// Copyright 2016 The etcd Authors
//
// 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 command

import (
	"errors"
	"fmt"
	"strings"

	pb "go.etcd.io/etcd/api/v3/etcdserverpb"
	v3 "go.etcd.io/etcd/client/v3"
	"go.etcd.io/etcd/pkg/v3/cobrautl"

	"github.com/dustin/go-humanize"
)

type printer interface {
	Del(v3.DeleteResponse)
	Get(v3.GetResponse)
	Put(v3.PutResponse)
	Txn(v3.TxnResponse)
	Watch(v3.WatchResponse)

	Grant(r v3.LeaseGrantResponse)
	Revoke(id v3.LeaseID, r v3.LeaseRevokeResponse)
	KeepAlive(r v3.LeaseKeepAliveResponse)
	TimeToLive(r v3.LeaseTimeToLiveResponse, keys bool)
	Leases(r v3.LeaseLeasesResponse)

	MemberAdd(v3.MemberAddResponse)
	MemberRemove(id uint64, r v3.MemberRemoveResponse)
	MemberUpdate(id uint64, r v3.MemberUpdateResponse)
	MemberPromote(id uint64, r v3.MemberPromoteResponse)
	MemberList(v3.MemberListResponse)

	EndpointHealth([]epHealth)
	EndpointStatus([]epStatus)
	EndpointHashKV([]epHashKV)
	MoveLeader(leader, target uint64, r v3.MoveLeaderResponse)

	Alarm(v3.AlarmResponse)

	RoleAdd(role string, r v3.AuthRoleAddResponse)
	RoleGet(role string, r v3.AuthRoleGetResponse)
	RoleDelete(role string, r v3.AuthRoleDeleteResponse)
	RoleList(v3.AuthRoleListResponse)
	RoleGrantPermission(role string, r v3.AuthRoleGrantPermissionResponse)
	RoleRevokePermission(role string, key string, end string, r v3.AuthRoleRevokePermissionResponse)

	UserAdd(user string, r v3.AuthUserAddResponse)
	UserGet(user string, r v3.AuthUserGetResponse)
	UserList(r v3.AuthUserListResponse)
	UserChangePassword(v3.AuthUserChangePasswordResponse)
	UserGrantRole(user string, role string, r v3.AuthUserGrantRoleResponse)
	UserRevokeRole(user string, role string, r v3.AuthUserRevokeRoleResponse)
	UserDelete(user string, r v3.AuthUserDeleteResponse)

	AuthStatus(r v3.AuthStatusResponse)
}

func NewPrinter(printerType string, isHex bool) printer {
	switch printerType {
	case "simple":
		return &simplePrinter{isHex: isHex}
	case "fields":
		return &fieldsPrinter{newPrinterUnsupported("fields")}
	case "json":
		return newJSONPrinter(isHex)
	case "protobuf":
		return newPBPrinter()
	case "table":
		return &tablePrinter{newPrinterUnsupported("table")}
	}
	return nil
}

type printerRPC struct {
	printer
	p func(interface{})
}

func (p *printerRPC) Del(r v3.DeleteResponse)  { p.p((*pb.DeleteRangeResponse)(&r)) }
func (p *printerRPC) Get(r v3.GetResponse)     { p.p((*pb.RangeResponse)(&r)) }
func (p *printerRPC) Put(r v3.PutResponse)     { p.p((*pb.PutResponse)(&r)) }
func (p *printerRPC) Txn(r v3.TxnResponse)     { p.p((*pb.TxnResponse)(&r)) }
func (p *printerRPC) Watch(r v3.WatchResponse) { p.p(&r) }

func (p *printerRPC) Grant(r v3.LeaseGrantResponse)                      { p.p(r) }
func (p *printerRPC) Revoke(id v3.LeaseID, r v3.LeaseRevokeResponse)     { p.p(r) }
func (p *printerRPC) KeepAlive(r v3.LeaseKeepAliveResponse)              { p.p(r) }
func (p *printerRPC) TimeToLive(r v3.LeaseTimeToLiveResponse, keys bool) { p.p(&r) }
func (p *printerRPC) Leases(r v3.LeaseLeasesResponse)                    { p.p(&r) }

func (p *printerRPC) MemberAdd(r v3.MemberAddResponse) { p.p((*pb.MemberAddResponse)(&r)) }
func (p *printerRPC) MemberRemove(id uint64, r v3.MemberRemoveResponse) {
	p.p((*pb.MemberRemoveResponse)(&r))
}
func (p *printerRPC) MemberUpdate(id uint64, r v3.MemberUpdateResponse) {
	p.p((*pb.MemberUpdateResponse)(&r))
}
func (p *printerRPC) MemberPromote(id uint64, r v3.MemberPromoteResponse) {
	p.p((*pb.MemberPromoteResponse)(&r))
}
func (p *printerRPC) MemberList(r v3.MemberListResponse) { p.p((*pb.MemberListResponse)(&r)) }
func (p *printerRPC) Alarm(r v3.AlarmResponse)           { p.p((*pb.AlarmResponse)(&r)) }
func (p *printerRPC) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) {
	p.p((*pb.MoveLeaderResponse)(&r))
}
func (p *printerRPC) RoleAdd(_ string, r v3.AuthRoleAddResponse) { p.p((*pb.AuthRoleAddResponse)(&r)) }
func (p *printerRPC) RoleGet(_ string, r v3.AuthRoleGetResponse) { p.p((*pb.AuthRoleGetResponse)(&r)) }
func (p *printerRPC) RoleDelete(_ string, r v3.AuthRoleDeleteResponse) {
	p.p((*pb.AuthRoleDeleteResponse)(&r))
}
func (p *printerRPC) RoleList(r v3.AuthRoleListResponse) { p.p((*pb.AuthRoleListResponse)(&r)) }
func (p *printerRPC) RoleGrantPermission(_ string, r v3.AuthRoleGrantPermissionResponse) {
	p.p((*pb.AuthRoleGrantPermissionResponse)(&r))
}
func (p *printerRPC) RoleRevokePermission(_ string, _ string, _ string, r v3.AuthRoleRevokePermissionResponse) {
	p.p((*pb.AuthRoleRevokePermissionResponse)(&r))
}
func (p *printerRPC) UserAdd(_ string, r v3.AuthUserAddResponse) { p.p((*pb.AuthUserAddResponse)(&r)) }
func (p *printerRPC) UserGet(_ string, r v3.AuthUserGetResponse) { p.p((*pb.AuthUserGetResponse)(&r)) }
func (p *printerRPC) UserList(r v3.AuthUserListResponse)         { p.p((*pb.AuthUserListResponse)(&r)) }
func (p *printerRPC) UserChangePassword(r v3.AuthUserChangePasswordResponse) {
	p.p((*pb.AuthUserChangePasswordResponse)(&r))
}
func (p *printerRPC) UserGrantRole(_ string, _ string, r v3.AuthUserGrantRoleResponse) {
	p.p((*pb.AuthUserGrantRoleResponse)(&r))
}
func (p *printerRPC) UserRevokeRole(_ string, _ string, r v3.AuthUserRevokeRoleResponse) {
	p.p((*pb.AuthUserRevokeRoleResponse)(&r))
}
func (p *printerRPC) UserDelete(_ string, r v3.AuthUserDeleteResponse) {
	p.p((*pb.AuthUserDeleteResponse)(&r))
}
func (p *printerRPC) AuthStatus(r v3.AuthStatusResponse) {
	p.p((*pb.AuthStatusResponse)(&r))
}

type printerUnsupported struct{ printerRPC }

func newPrinterUnsupported(n string) printer {
	f := func(interface{}) {
		cobrautl.ExitWithError(cobrautl.ExitBadFeature, errors.New(n+" not supported as output format"))
	}
	return &printerUnsupported{printerRPC{nil, f}}
}

func (p *printerUnsupported) EndpointHealth([]epHealth) { p.p(nil) }
func (p *printerUnsupported) EndpointStatus([]epStatus) { p.p(nil) }
func (p *printerUnsupported) EndpointHashKV([]epHashKV) { p.p(nil) }

func (p *printerUnsupported) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) { p.p(nil) }

func makeMemberListTable(r v3.MemberListResponse) (hdr []string, rows [][]string) {
	hdr = []string{"ID", "Status", "Name", "Peer Addrs", "Client Addrs", "Is Learner"}
	for _, m := range r.Members {
		status := "started"
		if len(m.Name) == 0 {
			status = "unstarted"
		}
		isLearner := "false"
		if m.IsLearner {
			isLearner = "true"
		}
		rows = append(rows, []string{
			fmt.Sprintf("%x", m.ID),
			status,
			m.Name,
			strings.Join(m.PeerURLs, ","),
			strings.Join(m.ClientURLs, ","),
			isLearner,
		})
	}
	return hdr, rows
}

func makeEndpointHealthTable(healthList []epHealth) (hdr []string, rows [][]string) {
	hdr = []string{"endpoint", "health", "took", "error"}
	for _, h := range healthList {
		rows = append(rows, []string{
			h.Ep,
			fmt.Sprintf("%v", h.Health),
			h.Took,
			h.Error,
		})
	}
	return hdr, rows
}

func makeEndpointStatusTable(statusList []epStatus) (hdr []string, rows [][]string) {
	hdr = []string{"endpoint", "ID", "version", "db size", "is leader", "is learner", "raft term",
		"raft index", "raft applied index", "errors"}
	for _, status := range statusList {
		rows = append(rows, []string{
			status.Ep,
			fmt.Sprintf("%x", status.Resp.Header.MemberId),
			status.Resp.Version,
			humanize.Bytes(uint64(status.Resp.DbSize)),
			fmt.Sprint(status.Resp.Leader == status.Resp.Header.MemberId),
			fmt.Sprint(status.Resp.IsLearner),
			fmt.Sprint(status.Resp.RaftTerm),
			fmt.Sprint(status.Resp.RaftIndex),
			fmt.Sprint(status.Resp.RaftAppliedIndex),
			fmt.Sprint(strings.Join(status.Resp.Errors, ", ")),
		})
	}
	return hdr, rows
}

func makeEndpointHashKVTable(hashList []epHashKV) (hdr []string, rows [][]string) {
	hdr = []string{"endpoint", "hash"}
	for _, h := range hashList {
		rows = append(rows, []string{
			h.Ep,
			fmt.Sprint(h.Resp.Hash),
		})
	}
	return hdr, rows
}
<|endoftext|>


<commit_before>package rawblock

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"sync"

	"github.com/docker/docker/daemon/graphdriver"
	"github.com/docker/docker/pkg/idtools"
	"github.com/golang/glog"
	"github.com/opencontainers/runc/libcontainer/label"
	//"github.com/docker/docker/pkg/mount"
)

func init() {
	graphdriver.Register("rawblock", Init)
}

// Driver holds information about the driver, home directory of the driver.
// Driver implements graphdriver.ProtoDriver. It uses only basic vfs operations.
// In order to support layering, the block is created via reflink with the the parent layer
// Driver must be wrapped in NaiveDiffDriver to be used as a graphdriver.Driver
type Driver struct {
	home      string
	backingFs string // host filesystem of the storage
	cow       bool
	blockFs   string // filesystem inside the block
	blockSize uint64 // block size in GB
	uid       int
	gid       int

	sync.Mutex // Protects concurrent modification to active
	active     map[string]int
}

// test if the filesystem on @home supports reflink, return false also if unsure.
func testReflinkSupport(home string) bool {
	file1 := filepath.Join(home, "test-reflink-support-src")
	file2 := filepath.Join(home, "test-reflink-support-dest")
	if _, err := exec.Command("truncate", fmt.Sprintf("--size=%d", 16*1024), file1).CombinedOutput(); err != nil {
		return false
	}
	defer os.RemoveAll(file1)
	defer os.RemoveAll(file2)
	if _, err := exec.Command("cp", "-a", "--reflink=always", file1, file2).CombinedOutput(); err != nil {
		return false
	}
	return true
}

// Init returns a new Raw Block driver.
// This sets the home directory for the driver and returns NaiveDiffDriver.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
	backingFs := "<unknown>"
	blockFs := "xfs" // TODO: make it configurable
	cow := true
	supported := "supported"

	fsMagic, err := graphdriver.GetFSMagic(home)
	if err != nil {
		return nil, err
	}
	if fsName, ok := graphdriver.FsNames[fsMagic]; ok {
		backingFs = fsName
	}

	// check if they are running over btrfs or xfs
	switch fsMagic {
	case graphdriver.FsMagicBtrfs: // support
	case graphdriver.FsMagicXfs: // check support
		if testReflinkSupport(home) {
			break
		}
		fallthrough
	default:
		cow = false
		supported = "NOT supported"
	}
	glog.Infof("RawBlock: copy-on-write is %s", supported)

	rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
	if err != nil {
		return nil, err
	}
	if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil {
		return nil, err
	}

	d := &Driver{
		home:      home,
		backingFs: backingFs,
		cow:       cow,
		blockFs:   blockFs,
		blockSize: 10, // TODO: make it configurable
		uid:       rootUID,
		gid:       rootGID,
		active:    map[string]int{},
	}
	return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
}

func (d *Driver) String() string {
	return "rawblock"
}

// Status is used for implementing the graphdriver.ProtoDriver interface.
func (d *Driver) Status() [][2]string {
	return [][2]string{
		{"Backing Filesystem", d.backingFs},
		{"Support Copy-On-Write", fmt.Sprintf("%v", d.cow)},
		{"Block Filesystem", d.blockFs},
		{"Block Size", fmt.Sprintf("%dGB", d.blockSize)},
	}
}

// GetMetadata is used for implementing the graphdriver.ProtoDriver interface.
func (d *Driver) GetMetadata(id string) (map[string]string, error) {
	return nil, nil
}

// Cleanup is used to implement graphdriver.ProtoDriver. There is no cleanup required for this driver.
func (d *Driver) Cleanup() error {
	return nil
}

// Create prepares the filesystem for the rawblock driver and copies the block from the parent.
func (d *Driver) Create(id, parent, mountLabel string) error {
	if err := idtools.MkdirAllAs(filepath.Dir(d.block(id)), 0700, d.uid, d.gid); err != nil {
		return err
	}
	if parent == "" {
		return CreateBlock(d.block(id), d.blockFs, mountLabel, d.blockSize*1024*1024*1024)
	}
	if out, err := exec.Command("cp", "-a", "--reflink=auto", d.block(parent), d.block(id)).CombinedOutput(); err != nil {
		return fmt.Errorf("Failed to reflink:%v:%s", err, string(out))
	}
	return nil
}

func (d *Driver) block(id string) string {
	return filepath.Join(d.home, "blocks", id)
}

func (d *Driver) mntBase() string {
	return filepath.Join(d.home, "mnt")
}

// Remove deletes the content from the directory for a given id.
func (d *Driver) Remove(id string) error {
	if err := os.RemoveAll(d.block(id)); err != nil && !os.IsNotExist(err) {
		return err
	}
	return nil
}

// Get returns the directory for the given id.
func (d *Driver) Get(id, mountLabel string) (string, error) {
	d.Lock()
	defer d.Unlock()
	active := d.active[id]
	if active == 0 {
		if err := GetImage(filepath.Join(d.home, "blocks"), d.mntBase(), id, d.blockFs, mountLabel, d.uid, d.gid); err != nil {
			return "", err
		}
	}
	d.active[id] = active + 1
	return filepath.Join(d.mntBase(), id, "rootfs"), nil
}

func (d *Driver) Put(id string) error {
	d.Lock()
	defer d.Unlock()
	active := d.active[id]
	if active > 1 {
		d.active[id] = active - 1
		return nil
	}
	if err := PutImage(d.mntBase(), id); err != nil {
		return err
	}
	delete(d.active, id)
	return nil
}

// Exists checks to see if the directory exists for the given id.
func (d *Driver) Exists(id string) bool {
	_, err := os.Stat(d.block(id))
	return err == nil
}

func CreateBlock(block, fstype, mountLabel string, size uint64) error {
	//opts := []string{"level:s0"}
	//if _, mountLabel, err := label.InitLabels(opts); err == nil {
	//	label.SetFileLabel(dir, mountLabel)
	//}
	if out, err := exec.Command("truncate", fmt.Sprintf("--size=%d", size), block).CombinedOutput(); err != nil {
		return fmt.Errorf("Failed to create block:%v:%s", err, string(out))
	}
	switch fstype {
	case "xfs":
		if out, err := exec.Command("mkfs.xfs", "-f", block).CombinedOutput(); err != nil {
			os.RemoveAll(block)
			return fmt.Errorf("Failed to mkfs the block:%v:%s", err, string(out))
		}
	case "ext4":
		if out, err := exec.Command("mkfs.ext4", "-F", block).CombinedOutput(); err != nil {
			os.RemoveAll(block)
			return fmt.Errorf("Failed to mkfs the block:%v:%s", err, string(out))
		}
	default:
		os.RemoveAll(block)
		return fmt.Errorf("Unsupported filesystem for the block: %s", fstype)
	}
	return nil
}

func joinMountOptions(a, b string) string {
	if a == "" {
		return b
	}
	if b == "" {
		return a
	}
	return a + "," + b
}

func mount(block, mnt, fstype string, mountLabel string) error {
	options := "loop"

	if fstype == "xfs" {
		// XFS needs nouuid or it can't mount filesystems with the same fs
		options = joinMountOptions(options, "nouuid")
	}

	options = joinMountOptions(options, label.FormatMountLabel("", mountLabel))

	if out, err := exec.Command("mount", "-t", fstype, "-o", options, block, mnt).CombinedOutput(); err != nil {
		return fmt.Errorf("Failed to mount block:%v:%s", err, string(out))
	}
	return nil
}

func GetImage(blockBase, mntBase, id, fstype, mountLabel string, uid, gid int) error {
	block := filepath.Join(blockBase, id)
	mnt := filepath.Join(mntBase, id)
	rootFs := filepath.Join(mntBase, id, "rootfs")

	if err := idtools.MkdirAllAs(mnt, 0755, uid, gid); err != nil {
		return err
	}

	if err := mount(block, mnt, fstype, mountLabel); err != nil {
		os.RemoveAll(mnt)
		return err
	}

	if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) {
		exec.Command("umount", "--detach-loop", mnt).CombinedOutput()
		os.RemoveAll(mnt)
		return err
	}

	return nil
}

func PutImage(mntBase, id string) error {
	mnt := filepath.Join(mntBase, id)
	if out, err := exec.Command("umount", "--detach-loop", mnt).CombinedOutput(); err != nil {
		return fmt.Errorf("Failed to umount block:%v:%s", err, string(out))
	}
	os.RemoveAll(mnt)
	return nil
}
<commit_msg>use -d instead of --detach-loop for detaching loop device<commit_after>package rawblock

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"sync"

	"github.com/docker/docker/daemon/graphdriver"
	"github.com/docker/docker/pkg/idtools"
	"github.com/golang/glog"
	"github.com/opencontainers/runc/libcontainer/label"
	//"github.com/docker/docker/pkg/mount"
)

func init() {
	graphdriver.Register("rawblock", Init)
}

// Driver holds information about the driver, home directory of the driver.
// Driver implements graphdriver.ProtoDriver. It uses only basic vfs operations.
// In order to support layering, the block is created via reflink with the the parent layer
// Driver must be wrapped in NaiveDiffDriver to be used as a graphdriver.Driver
type Driver struct {
	home      string
	backingFs string // host filesystem of the storage
	cow       bool
	blockFs   string // filesystem inside the block
	blockSize uint64 // block size in GB
	uid       int
	gid       int

	sync.Mutex // Protects concurrent modification to active
	active     map[string]int
}

// test if the filesystem on @home supports reflink, return false also if unsure.
func testReflinkSupport(home string) bool {
	file1 := filepath.Join(home, "test-reflink-support-src")
	file2 := filepath.Join(home, "test-reflink-support-dest")
	if _, err := exec.Command("truncate", fmt.Sprintf("--size=%d", 16*1024), file1).CombinedOutput(); err != nil {
		return false
	}
	defer os.RemoveAll(file1)
	defer os.RemoveAll(file2)
	if _, err := exec.Command("cp", "-a", "--reflink=always", file1, file2).CombinedOutput(); err != nil {
		return false
	}
	return true
}

// Init returns a new Raw Block driver.
// This sets the home directory for the driver and returns NaiveDiffDriver.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
	backingFs := "<unknown>"
	blockFs := "xfs" // TODO: make it configurable
	cow := true
	supported := "supported"

	fsMagic, err := graphdriver.GetFSMagic(home)
	if err != nil {
		return nil, err
	}
	if fsName, ok := graphdriver.FsNames[fsMagic]; ok {
		backingFs = fsName
	}

	// check if they are running over btrfs or xfs
	switch fsMagic {
	case graphdriver.FsMagicBtrfs: // support
	case graphdriver.FsMagicXfs: // check support
		if testReflinkSupport(home) {
			break
		}
		fallthrough
	default:
		cow = false
		supported = "NOT supported"
	}
	glog.Infof("RawBlock: copy-on-write is %s", supported)

	rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
	if err != nil {
		return nil, err
	}
	if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil {
		return nil, err
	}

	d := &Driver{
		home:      home,
		backingFs: backingFs,
		cow:       cow,
		blockFs:   blockFs,
		blockSize: 10, // TODO: make it configurable
		uid:       rootUID,
		gid:       rootGID,
		active:    map[string]int{},
	}
	return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
}

func (d *Driver) String() string {
	return "rawblock"
}

// Status is used for implementing the graphdriver.ProtoDriver interface.
func (d *Driver) Status() [][2]string {
	return [][2]string{
		{"Backing Filesystem", d.backingFs},
		{"Support Copy-On-Write", fmt.Sprintf("%v", d.cow)},
		{"Block Filesystem", d.blockFs},
		{"Block Size", fmt.Sprintf("%dGB", d.blockSize)},
	}
}

// GetMetadata is used for implementing the graphdriver.ProtoDriver interface.
func (d *Driver) GetMetadata(id string) (map[string]string, error) {
	return nil, nil
}

// Cleanup is used to implement graphdriver.ProtoDriver. There is no cleanup required for this driver.
func (d *Driver) Cleanup() error {
	return nil
}

// Create prepares the filesystem for the rawblock driver and copies the block from the parent.
func (d *Driver) Create(id, parent, mountLabel string) error {
	if err := idtools.MkdirAllAs(filepath.Dir(d.block(id)), 0700, d.uid, d.gid); err != nil {
		return err
	}
	if parent == "" {
		return CreateBlock(d.block(id), d.blockFs, mountLabel, d.blockSize*1024*1024*1024)
	}
	if out, err := exec.Command("cp", "-a", "--reflink=auto", d.block(parent), d.block(id)).CombinedOutput(); err != nil {
		return fmt.Errorf("Failed to reflink:%v:%s", err, string(out))
	}
	return nil
}

func (d *Driver) block(id string) string {
	return filepath.Join(d.home, "blocks", id)
}

func (d *Driver) mntBase() string {
	return filepath.Join(d.home, "mnt")
}

// Remove deletes the content from the directory for a given id.
func (d *Driver) Remove(id string) error {
	if err := os.RemoveAll(d.block(id)); err != nil && !os.IsNotExist(err) {
		return err
	}
	return nil
}

// Get returns the directory for the given id.
func (d *Driver) Get(id, mountLabel string) (string, error) {
	d.Lock()
	defer d.Unlock()
	active := d.active[id]
	if active == 0 {
		if err := GetImage(filepath.Join(d.home, "blocks"), d.mntBase(), id, d.blockFs, mountLabel, d.uid, d.gid); err != nil {
			return "", err
		}
	}
	d.active[id] = active + 1
	return filepath.Join(d.mntBase(), id, "rootfs"), nil
}

func (d *Driver) Put(id string) error {
	d.Lock()
	defer d.Unlock()
	active := d.active[id]
	if active > 1 {
		d.active[id] = active - 1
		return nil
	}
	if err := PutImage(d.mntBase(), id); err != nil {
		return err
	}
	delete(d.active, id)
	return nil
}

// Exists checks to see if the directory exists for the given id.
func (d *Driver) Exists(id string) bool {
	_, err := os.Stat(d.block(id))
	return err == nil
}

func CreateBlock(block, fstype, mountLabel string, size uint64) error {
	//opts := []string{"level:s0"}
	//if _, mountLabel, err := label.InitLabels(opts); err == nil {
	//	label.SetFileLabel(dir, mountLabel)
	//}
	if out, err := exec.Command("truncate", fmt.Sprintf("--size=%d", size), block).CombinedOutput(); err != nil {
		return fmt.Errorf("Failed to create block:%v:%s", err, string(out))
	}
	switch fstype {
	case "xfs":
		if out, err := exec.Command("mkfs.xfs", "-f", block).CombinedOutput(); err != nil {
			os.RemoveAll(block)
			return fmt.Errorf("Failed to mkfs the block:%v:%s", err, string(out))
		}
	case "ext4":
		if out, err := exec.Command("mkfs.ext4", "-F", block).CombinedOutput(); err != nil {
			os.RemoveAll(block)
			return fmt.Errorf("Failed to mkfs the block:%v:%s", err, string(out))
		}
	default:
		os.RemoveAll(block)
		return fmt.Errorf("Unsupported filesystem for the block: %s", fstype)
	}
	return nil
}

func joinMountOptions(a, b string) string {
	if a == "" {
		return b
	}
	if b == "" {
		return a
	}
	return a + "," + b
}

func mount(block, mnt, fstype string, mountLabel string) error {
	options := "loop"

	if fstype == "xfs" {
		// XFS needs nouuid or it can't mount filesystems with the same fs
		options = joinMountOptions(options, "nouuid")
	}

	options = joinMountOptions(options, label.FormatMountLabel("", mountLabel))

	if out, err := exec.Command("mount", "-t", fstype, "-o", options, block, mnt).CombinedOutput(); err != nil {
		return fmt.Errorf("Failed to mount block:%v:%s", err, string(out))
	}
	return nil
}

func GetImage(blockBase, mntBase, id, fstype, mountLabel string, uid, gid int) error {
	block := filepath.Join(blockBase, id)
	mnt := filepath.Join(mntBase, id)
	rootFs := filepath.Join(mntBase, id, "rootfs")

	if err := idtools.MkdirAllAs(mnt, 0755, uid, gid); err != nil {
		return err
	}

	if err := mount(block, mnt, fstype, mountLabel); err != nil {
		os.RemoveAll(mnt)
		return err
	}

	if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) {
		exec.Command("umount", "-d", mnt).CombinedOutput()
		os.RemoveAll(mnt)
		return err
	}

	return nil
}

func PutImage(mntBase, id string) error {
	mnt := filepath.Join(mntBase, id)
	if out, err := exec.Command("umount", "-d", mnt).CombinedOutput(); err != nil {
		return fmt.Errorf("Failed to umount block:%v:%s", err, string(out))
	}
	os.RemoveAll(mnt)
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The cert-manager Authors.

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 validation

import (
	"context"
	"encoding/pem"
	"strings"
	"testing"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"github.com/jetstack/cert-manager/pkg/api"
	v1 "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
	cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
	"github.com/jetstack/cert-manager/pkg/util/pki"
	"github.com/jetstack/cert-manager/test/integration/framework"
)

var certGVK = schema.GroupVersionKind{
	Group:   "cert-manager.io",
	Version: "v1",
	Kind:    "CertificateRequest",
}

func TestValidationCertificateRequests(t *testing.T) {
	tests := map[string]struct {
		input       runtime.Object
		errorSuffix string // is a suffix as the API server sends the whole value back in the error
		expectError bool
	}{
		"No errors on valid certificaterequest with no usages set": {
			input: &v1.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: v1.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &v1.Certificate{
						Spec: v1.CertificateSpec{
							DNSNames: []string{"example.com"},
						},
					}),
					Usages:    []v1.KeyUsage{},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: false,
		},
		"No errors on valid certificaterequest with special usages set": {
			input: &v1.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: v1.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &v1.Certificate{
						Spec: v1.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []v1.KeyUsage{v1.UsageDigitalSignature, v1.UsageKeyEncipherment, v1.UsageClientAuth},
						},
					}),
					Usages:    []v1.KeyUsage{v1.UsageDigitalSignature, v1.UsageKeyEncipherment, v1.UsageClientAuth},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: false,
		},
		"No errors on valid certificaterequest with special usages set only in CSR": {
			input: &v1.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: v1.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &v1.Certificate{
						Spec: v1.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []v1.KeyUsage{v1.UsageDigitalSignature, v1.UsageKeyEncipherment, v1.UsageClientAuth},
						},
					}),
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: false,
		},
		"No errors on valid certificaterequest with special usages only set in spec": {
			input: &v1.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: v1.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &v1.Certificate{
						Spec: v1.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []v1.KeyUsage{},
						},
					}),
					Usages:    []v1.KeyUsage{v1.UsageDigitalSignature, v1.UsageKeyEncipherment, v1.UsageClientAuth},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: false,
		},
		"Errors on certificaterequest with mismatch of usages": {
			input: &v1.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: v1.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &v1.Certificate{
						Spec: v1.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []v1.KeyUsage{v1.UsageDigitalSignature, v1.UsageKeyEncipherment, v1.UsageClientAuth},
						},
					}),
					Usages:    []v1.KeyUsage{v1.UsageDigitalSignature, v1.UsageKeyEncipherment, v1.UsageCodeSigning},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: true,
			errorSuffix: "csr key usages do not match specified usages, these should match if both are set: [[2]: \"client auth\" != \"code signing\"]",
		},
	}
	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			cert := test.input.(*v1.CertificateRequest)
			cert.SetGroupVersionKind(certGVK)

			config, stop := framework.RunControlPlane(t)
			defer stop()
			framework.WaitForOpenAPIResourcesToBeLoaded(t, config, certGVK)

			// create the object to get any errors back from the webhook
			cl, err := client.New(config, client.Options{Scheme: api.Scheme})
			if err != nil {
				t.Fatal(err)
			}

			err = cl.Create(context.Background(), cert)

			if !test.expectError && err != nil {
				t.Fatalf("Didn't expect error and got error: %v", err)
			} else if test.expectError && err == nil {
				t.Errorf("Expected error %v but got nil", test.errorSuffix)

			} else if test.expectError && !strings.HasSuffix(err.Error(), test.errorSuffix) {
				t.Errorf("Expected error %q but got %q", test.errorSuffix, err)
			}
		})
	}
}

func mustGenerateCSR(t *testing.T, cert *v1.Certificate) []byte {
	request, err := pki.GenerateCSR(cert)
	if err != nil {
		t.Fatal(err)
	}

	sk, err := pki.GenerateRSAPrivateKey(2048)
	if err != nil {
		t.Fatal(err)
	}
	csrBytes, err := pki.EncodeCSR(request, sk)
	if err != nil {
		t.Fatal(err)
	}
	csr := pem.EncodeToMemory(&pem.Block{
		Type: "CERTIFICATE REQUEST", Bytes: csrBytes,
	})

	return csr
}
<commit_msg>Adds a sanity check to the CertificateRequest validation integration tests to ensure that no error happens when applying a CertificateRequest with identities set (they get modified during admission).<commit_after>/*
Copyright 2020 The cert-manager Authors.

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 validation

import (
	"context"
	"encoding/pem"
	"strings"
	"testing"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"github.com/jetstack/cert-manager/pkg/api"
	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
	cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
	"github.com/jetstack/cert-manager/pkg/util/pki"
	"github.com/jetstack/cert-manager/test/integration/framework"
)

var certGVK = schema.GroupVersionKind{
	Group:   "cert-manager.io",
	Version: "v1",
	Kind:    "CertificateRequest",
}

func TestValidationCertificateRequests(t *testing.T) {
	tests := map[string]struct {
		input       runtime.Object
		errorSuffix string // is a suffix as the API server sends the whole value back in the error
		expectError bool
	}{
		"No errors on valid certificaterequest with no usages set": {
			input: &cmapi.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: cmapi.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &cmapi.Certificate{
						Spec: cmapi.CertificateSpec{
							DNSNames: []string{"example.com"},
						},
					}),
					Usages:    []cmapi.KeyUsage{},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: false,
		},
		"No errors on valid certificaterequest with special usages set": {
			input: &cmapi.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: cmapi.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &cmapi.Certificate{
						Spec: cmapi.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth},
						},
					}),
					Usages:    []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: false,
		},
		"No errors on valid certificaterequest with special usages set only in CSR": {
			input: &cmapi.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: cmapi.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &cmapi.Certificate{
						Spec: cmapi.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth},
						},
					}),
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: false,
		},
		"No errors on valid certificaterequest with special usages only set in spec": {
			input: &cmapi.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: cmapi.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &cmapi.Certificate{
						Spec: cmapi.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []cmapi.KeyUsage{},
						},
					}),
					Usages:    []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: false,
		},
		"Errors on certificaterequest with mismatch of usages": {
			input: &cmapi.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: cmapi.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &cmapi.Certificate{
						Spec: cmapi.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth},
						},
					}),
					Usages:    []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageCodeSigning},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
				},
			},
			expectError: true,
			errorSuffix: "csr key usages do not match specified usages, these should match if both are set: [[2]: \"client auth\" != \"code signing\"]",
		},
		"Shouldn't error when setting user info, since this will be overwritten by the mutating webhook": {
			input: &cmapi.CertificateRequest{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "default",
				},
				Spec: cmapi.CertificateRequestSpec{
					Request: mustGenerateCSR(t, &cmapi.Certificate{
						Spec: cmapi.CertificateSpec{
							DNSNames: []string{"example.com"},
							Usages:   []cmapi.KeyUsage{},
						},
					}),
					Usages:    []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth},
					IssuerRef: cmmeta.ObjectReference{Name: "test"},
					Username:  "user-1",
					Groups:    []string{"group-1", "group-2"},
				},
			},
			expectError: false,
		},
	}
	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			cert := test.input.(*cmapi.CertificateRequest)
			cert.SetGroupVersionKind(certGVK)

			config, stop := framework.RunControlPlane(t)
			defer stop()
			framework.WaitForOpenAPIResourcesToBeLoaded(t, config, certGVK)

			// create the object to get any errors back from the webhook
			cl, err := client.New(config, client.Options{Scheme: api.Scheme})
			if err != nil {
				t.Fatal(err)
			}

			err = cl.Create(context.Background(), cert)
			if test.expectError != (err != nil) {
				t.Errorf("unexpected error, exp=%t got=%v",
					test.expectError, err)
			}
			if test.expectError && !strings.HasSuffix(err.Error(), test.errorSuffix) {
				t.Errorf("unexpected error suffix, exp=%s got=%s",
					test.errorSuffix, err)
			}
		})
	}
}

func mustGenerateCSR(t *testing.T, cert *cmapi.Certificate) []byte {
	request, err := pki.GenerateCSR(cert)
	if err != nil {
		t.Fatal(err)
	}

	sk, err := pki.GenerateRSAPrivateKey(2048)
	if err != nil {
		t.Fatal(err)
	}
	csrBytes, err := pki.EncodeCSR(request, sk)
	if err != nil {
		t.Fatal(err)
	}
	csr := pem.EncodeToMemory(&pem.Block{
		Type: "CERTIFICATE REQUEST", Bytes: csrBytes,
	})

	return csr
}
<|endoftext|>


<commit_before>// +build windows
package main

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"strings"
	"time"
	"unsafe"

	"github.com/go-ole/go-ole"
	"github.com/moutend/go-wav"
	"github.com/moutend/go-wca"
)

var version = "latest"
var revision = "latest"

type FilenameFlag struct {
	Value string
}

func (f *FilenameFlag) Set(value string) (err error) {
	if !strings.HasSuffix(value, ".wav") {
		err = fmt.Errorf("specify WAVE audio file (*.wav)")
		return
	}
	f.Value = value
	return
}

func (f *FilenameFlag) String() string {
	return f.Value
}

func main() {
	var err error
	if err = run(os.Args); err != nil {
		log.Fatal(err)
	}
}

func run(args []string) (err error) {
	var filenameFlag FilenameFlag
	var versionFlag bool
	var audio = &wav.File{}
	var file []byte

	f := flag.NewFlagSet(args[0], flag.ExitOnError)
	f.Var(&filenameFlag, "input", "Specify WAVE format audio (e.g. music.wav)")
	f.Var(&filenameFlag, "i", "Alias of --input")
	f.BoolVar(&versionFlag, "version", false, "Show version")
	f.Parse(args[1:])

	if versionFlag {
		fmt.Printf("%s-%s\n", version, revision)
		return
	}
	if filenameFlag.Value == "" {
		return
	}
	if file, err = ioutil.ReadFile(filenameFlag.Value); err != nil {
		return
	}
	if err = wav.Unmarshal(file, audio); err != nil {
		return
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)
	ctx, cancel := context.WithCancel(context.Background())

	go func() {
		select {
		case <-signalChan:
			fmt.Println("Interrupted by SIGINT")
			cancel()
		}
	}()

	if err = renderSharedEventDriven(ctx, audio); err != nil {
		return
	}
	fmt.Println("Successfully done")
	return
}

func renderSharedEventDriven(ctx context.Context, audio *wav.File) (err error) {
	if err = ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED); err != nil {
		return
	}
	defer ole.CoUninitialize()

	var mmde *wca.IMMDeviceEnumerator
	if err = wca.CoCreateInstance(wca.CLSID_MMDeviceEnumerator, 0, wca.CLSCTX_ALL, wca.IID_IMMDeviceEnumerator, &mmde); err != nil {
		return
	}
	defer mmde.Release()

	var mmd *wca.IMMDevice
	if err = mmde.GetDefaultAudioEndpoint(wca.ERender, wca.EConsole, &mmd); err != nil {
		return
	}
	defer mmd.Release()

	var ps *wca.IPropertyStore
	if err = mmd.OpenPropertyStore(wca.STGM_READ, &ps); err != nil {
		return
	}
	defer ps.Release()

	var pv wca.PROPVARIANT
	if err = ps.GetValue(&wca.PKEY_Device_FriendlyName, &pv); err != nil {
		return
	}
	fmt.Printf("Rendering audio to: %s\n", pv.String())

	var ac *wca.IAudioClient
	if err = mmd.Activate(wca.IID_IAudioClient, wca.CLSCTX_ALL, nil, &ac); err != nil {
		return
	}
	defer ac.Release()

	var wfx *wca.WAVEFORMATEX
	if err = ac.GetMixFormat(&wfx); err != nil {
		return
	}
	defer ole.CoTaskMemFree(uintptr(unsafe.Pointer(wfx)))

	wfx.WFormatTag = 1
	wfx.NSamplesPerSec = uint32(audio.SamplesPerSec())
	wfx.WBitsPerSample = uint16(audio.BitsPerSample())
	wfx.NChannels = uint16(audio.Channels())
	wfx.NBlockAlign = uint16(audio.BlockAlign())
	wfx.NAvgBytesPerSec = uint32(audio.AvgBytesPerSec())
	wfx.CbSize = 0

	fmt.Println("--------")
	fmt.Printf("Format: PCM %d bit signed integer\n", wfx.WBitsPerSample)
	fmt.Printf("Rate: %d Hz\n", wfx.NSamplesPerSec)
	fmt.Printf("Channels: %d\n", wfx.NChannels)
	fmt.Println("--------")

	var defaultPeriod wca.REFERENCE_TIME
	var minimumPeriod wca.REFERENCE_TIME
	var renderingPeriod time.Duration
	if err = ac.GetDevicePeriod(&defaultPeriod, &minimumPeriod); err != nil {
		return
	}
	renderingPeriod = time.Duration(defaultPeriod * 100)
	fmt.Printf("Default rendering period: %d ms\n", renderingPeriod/time.Millisecond)

	var latency uint32 = 200 // millisecond
	if err = ac.Initialize(wca.AUDCLNT_SHAREMODE_SHARED, wca.AUDCLNT_STREAMFLAGS_EVENTCALLBACK, wca.REFERENCE_TIME(latency*10000), 0, wfx, nil); err != nil {
		return
	}
	audioReadyEvent := wca.CreateEventExA(0, 0, 0, wca.EVENT_MODIFY_STATE|wca.SYNCHRONIZE)
	defer wca.CloseHandle(audioReadyEvent)

	if err = ac.SetEventHandle(audioReadyEvent); err != nil {
		return
	}

	var bufferFrameSize uint32
	if err = ac.GetBufferSize(&bufferFrameSize); err != nil {
		return
	}
	fmt.Printf("Allocated buffer size: %d\n", bufferFrameSize)

	var arc *wca.IAudioRenderClient
	if err = ac.GetService(wca.IID_IAudioRenderClient, &arc); err != nil {
		return
	}
	defer arc.Release()

	if err = ac.Start(); err != nil {
		return
	}
	fmt.Println("Start rendering audio with shared-event-driven mode")
	fmt.Println("Press Ctrl-C to stop")

	var input = audio.Bytes()
	var b *byte
	var data *byte
	var offset int
	var isPlaying bool = true
	var padding uint32
	var availableFrameSize uint32

	errorChan := make(chan error, 1)

	for {
		if !isPlaying {
			close(errorChan)
			break
		}
		go func() {
			errorChan <- watchEvent(ctx, audioReadyEvent)
		}()
		select {
		case <-ctx.Done():
			isPlaying = false
			<-errorChan
			break
		case err = <-errorChan:
			if err != nil {
				isPlaying = false
				break
			}
			if offset >= audio.Length() {
				isPlaying = false
				break
			}
			if err = ac.GetCurrentPadding(&padding); err != nil {
				return
			}
			if availableFrameSize = bufferFrameSize - padding; availableFrameSize == 0 {
				continue
			}
			if err = arc.GetBuffer(availableFrameSize, &data); err != nil {
				return
			}

			start := unsafe.Pointer(data)
			lim := int(availableFrameSize) * int(wfx.NBlockAlign)
			remaining := audio.Length() - offset

			if remaining < lim {
				lim = remaining
			}
			for n := 0; n < lim; n++ {
				b = (*byte)(unsafe.Pointer(uintptr(start) + uintptr(n)))
				*b = input[offset+n]
			}

			offset += lim

			if err = arc.ReleaseBuffer(availableFrameSize, 0); err != nil {
				return
			}
		}
	}
	if err != nil {
		return
	}
	time.Sleep(time.Duration(latency) * time.Millisecond)
	return ac.Stop()
}

func watchEvent(ctx context.Context, event uintptr) (err error) {
	errorChan := make(chan error, 1)
	go func() {
		errorChan <- eventEmitter(event)
	}()
	select {
	case err = <-errorChan:
		close(errorChan)
		return
	case <-ctx.Done():
		err = ctx.Err()
		return
	}
	return
}

func eventEmitter(event uintptr) (err error) {
	//if err = ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
	//	return
	//}
	dw := wca.WaitForSingleObject(event, wca.INFINITE)
	if dw != 0 {
		return fmt.Errorf("failed to watch event")
	}
	//ole.CoUninitialize()
	return
}
<commit_msg>Refactor<commit_after>// +build windows

package main

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"strings"
	"time"
	"unsafe"

	"github.com/go-ole/go-ole"
	"github.com/moutend/go-wav"
	"github.com/moutend/go-wca"
)

var version = "latest"
var revision = "latest"

type FilenameFlag struct {
	Value string
}

func (f *FilenameFlag) Set(value string) (err error) {
	if !strings.HasSuffix(value, ".wav") {
		err = fmt.Errorf("specify WAVE audio file (*.wav)")
		return
	}
	f.Value = value
	return
}

func (f *FilenameFlag) String() string {
	return f.Value
}

func main() {
	var err error
	if err = run(os.Args); err != nil {
		log.Fatal(err)
	}
}

func run(args []string) (err error) {
	var filenameFlag FilenameFlag
	var versionFlag bool
	var audio = &wav.File{}
	var file []byte

	f := flag.NewFlagSet(args[0], flag.ExitOnError)
	f.Var(&filenameFlag, "input", "Specify WAVE format audio (e.g. music.wav)")
	f.Var(&filenameFlag, "i", "Alias of --input")
	f.BoolVar(&versionFlag, "version", false, "Show version")
	f.Parse(args[1:])

	if versionFlag {
		fmt.Printf("%s-%s\n", version, revision)
		return
	}
	if filenameFlag.Value == "" {
		return
	}
	if file, err = ioutil.ReadFile(filenameFlag.Value); err != nil {
		return
	}
	if err = wav.Unmarshal(file, audio); err != nil {
		return
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)
	ctx, cancel := context.WithCancel(context.Background())

	go func() {
		select {
		case <-signalChan:
			fmt.Println("Interrupted by SIGINT")
			cancel()
		}
	}()

	if err = renderSharedEventDriven(ctx, audio); err != nil {
		return
	}
	fmt.Println("Successfully done")
	return
}

func renderSharedEventDriven(ctx context.Context, audio *wav.File) (err error) {
	if err = ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED); err != nil {
		return
	}
	defer ole.CoUninitialize()

	var mmde *wca.IMMDeviceEnumerator
	if err = wca.CoCreateInstance(wca.CLSID_MMDeviceEnumerator, 0, wca.CLSCTX_ALL, wca.IID_IMMDeviceEnumerator, &mmde); err != nil {
		return
	}
	defer mmde.Release()

	var mmd *wca.IMMDevice
	if err = mmde.GetDefaultAudioEndpoint(wca.ERender, wca.EConsole, &mmd); err != nil {
		return
	}
	defer mmd.Release()

	var ps *wca.IPropertyStore
	if err = mmd.OpenPropertyStore(wca.STGM_READ, &ps); err != nil {
		return
	}
	defer ps.Release()

	var pv wca.PROPVARIANT
	if err = ps.GetValue(&wca.PKEY_Device_FriendlyName, &pv); err != nil {
		return
	}
	fmt.Printf("Rendering audio to: %s\n", pv.String())

	var ac *wca.IAudioClient
	if err = mmd.Activate(wca.IID_IAudioClient, wca.CLSCTX_ALL, nil, &ac); err != nil {
		return
	}
	defer ac.Release()

	var wfx *wca.WAVEFORMATEX
	if err = ac.GetMixFormat(&wfx); err != nil {
		return
	}
	defer ole.CoTaskMemFree(uintptr(unsafe.Pointer(wfx)))

	wfx.WFormatTag = 1
	wfx.NSamplesPerSec = uint32(audio.SamplesPerSec())
	wfx.WBitsPerSample = uint16(audio.BitsPerSample())
	wfx.NChannels = uint16(audio.Channels())
	wfx.NBlockAlign = uint16(audio.BlockAlign())
	wfx.NAvgBytesPerSec = uint32(audio.AvgBytesPerSec())
	wfx.CbSize = 0

	fmt.Println("--------")
	fmt.Printf("Format: PCM %d bit signed integer\n", wfx.WBitsPerSample)
	fmt.Printf("Rate: %d Hz\n", wfx.NSamplesPerSec)
	fmt.Printf("Channels: %d\n", wfx.NChannels)
	fmt.Println("--------")

	var defaultPeriod wca.REFERENCE_TIME
	var minimumPeriod wca.REFERENCE_TIME
	var latency time.Duration
	if err = ac.GetDevicePeriod(&defaultPeriod, &minimumPeriod); err != nil {
		return
	}
	latency = time.Duration(defaultPeriod * 100)

	fmt.Println("Default period: ", defaultPeriod)
	fmt.Println("Minimum period: ", minimumPeriod)
	fmt.Println("Latency: ", latency)

	if err = ac.Initialize(wca.AUDCLNT_SHAREMODE_SHARED, wca.AUDCLNT_STREAMFLAGS_EVENTCALLBACK, defaultPeriod, 0, wfx, nil); err != nil {
		return
	}

	audioReadyEvent := wca.CreateEventExA(0, 0, 0, wca.EVENT_MODIFY_STATE|wca.SYNCHRONIZE)
	defer wca.CloseHandle(audioReadyEvent)

	if err = ac.SetEventHandle(audioReadyEvent); err != nil {
		return
	}

	var bufferFrameSize uint32
	if err = ac.GetBufferSize(&bufferFrameSize); err != nil {
		return
	}
	fmt.Printf("Allocated buffer size: %d\n", bufferFrameSize)

	var arc *wca.IAudioRenderClient
	if err = ac.GetService(wca.IID_IAudioRenderClient, &arc); err != nil {
		return
	}
	defer arc.Release()

	if err = ac.Start(); err != nil {
		return
	}
	fmt.Println("Start rendering audio with shared-event-driven mode")
	fmt.Println("Press Ctrl-C to stop")

	var input = audio.Bytes()
	var b *byte
	var data *byte
	var offset int
	var isPlaying bool = true
	var padding uint32
	var availableFrameSize uint32

	errorChan := make(chan error, 1)

	for {
		if !isPlaying {
			close(errorChan)
			break
		}
		go func() {
			errorChan <- watchEvent(ctx, audioReadyEvent)
		}()
		select {
		case <-ctx.Done():
			isPlaying = false
			<-errorChan
			break
		case err = <-errorChan:
			if err != nil {
				isPlaying = false
				break
			}
			if offset >= audio.Length() {
				isPlaying = false
				break
			}
			if err = ac.GetCurrentPadding(&padding); err != nil {
				return
			}
			if availableFrameSize = bufferFrameSize - padding; availableFrameSize == 0 {
				continue
			}
			if err = arc.GetBuffer(availableFrameSize, &data); err != nil {
				return
			}

			start := unsafe.Pointer(data)
			lim := int(availableFrameSize) * int(wfx.NBlockAlign)
			remaining := audio.Length() - offset

			if remaining < lim {
				lim = remaining
			}
			for n := 0; n < lim; n++ {
				b = (*byte)(unsafe.Pointer(uintptr(start) + uintptr(n)))
				*b = input[offset+n]
			}

			offset += lim

			if err = arc.ReleaseBuffer(availableFrameSize, 0); err != nil {
				return
			}
		}
	}
	if err != nil {
		return
	}

// Render samples remaining in buffer.
	time.Sleep(latency)

	return ac.Stop()
}

func watchEvent(ctx context.Context, event uintptr) (err error) {
	errorChan := make(chan error, 1)
	go func() {
		errorChan <- eventEmitter(event)
	}()
	select {
	case err = <-errorChan:
		close(errorChan)
		return
	case <-ctx.Done():
		err = ctx.Err()
		return
	}
	return
}

func eventEmitter(event uintptr) (err error) {
	//if err = ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
	//	return
	//}
	dw := wca.WaitForSingleObject(event, wca.INFINITE)
	if dw != 0 {
		return fmt.Errorf("failed to watch event")
	}
	//ole.CoUninitialize()
	return
}
<|endoftext|>


<commit_before>// Copyright 2012 The AEGo 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 session provides an interface for Sessions. Currently using
Gorilla sessions

*/
package session

import (
	"code.google.com/p/gorilla/sessions"
	//"config"
)

// Store is a gorilla/session store.
var Store = sessions.NewCookieStore([]byte("123456789"))

//var Store = sessions.NewCookieStore([]byte(config.SecretKey))
<commit_msg>updated package locations<commit_after>// Copyright 2012 The AEGo 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 session provides an interface for Sessions. Currently using
Gorilla sessions

*/
package session

import (
	"github.com/gorilla/sessions"
	//"config"
)

// Store is a gorilla/session store.
var Store = sessions.NewCookieStore([]byte("123456789"))

//var Store = sessions.NewCookieStore([]byte(config.SecretKey))
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"log"
	"time"
)

// In-memory representation of a secret.
type StoreEntry struct {
	Secret    string    `json:"secret"`
	MaxClicks int       `json:"max_clicks"`
	Clicks    int       `json:"clicks"`
	DateAdded time.Time `json:"date_added"`
	ValidFor  int       `json:"valid_for"`
	AuthToken string    `json:"auth_token"`
}

// Secret augmented with computed fields.
type StoreEntryInfo struct {
	StoreEntry
	Id        string `json:"id"`
	PathQuery string `json:"path_query"`
	Url       string `json:"url"`
	ApiUrl    string `json:"api_url"`
}

type secretStore map[string]StoreEntry

// hashStruct returns a hash from an arbitrary structure, usable in a URL.
func hashStruct(data interface{}) (hash string) {
	hashBytes := sha256.Sum256([]byte(fmt.Sprintf("%v", data)))
	hash = base64.RawURLEncoding.EncodeToString(hashBytes[:])
	return
}

// AddEntry adds a secret to the store.
func (st secretStore) AddEntry(e StoreEntry, id string) string {
	e.DateAdded = time.Now()
	if id == "" {
		id = hashStruct(e)
	}
	if e.ValidFor == 0 {
		e.ValidFor = defaultValidity
	}
	st[id] = e
	return id
}

// NewEntry adds a new secret to the store. Set id to ""
// to have it auto-generated by hashing the entry.
func (st secretStore) NewEntry(secret string, maxclicks int, validfor int, at string, id string) string {
	return st.AddEntry(StoreEntry{secret, maxclicks, 0, time.Time{}, validfor, at}, id)
}

// GetEntry retrieves a secret from the store.
func (st secretStore) GetEntry(id string) (se StoreEntry, ok bool) {
	se, ok = st[id]
	return
}

// GetEntryInfo wraps GetEntry and adds some computed fields.
func (st secretStore) GetEntryInfo(id string) (si StoreEntryInfo, ok bool) {
	entry, ok := st.GetEntry(id)
	pathQuery := uGet + "?id=" + id
	url := getURLBase() + pathQuery
	apiurl := getURLBase() + uApiGet + id
	return StoreEntryInfo{entry, id, pathQuery, url, apiurl}, ok
}

// GetEntryInfo wraps GetEntry and adds some computed fields. In addition it
// hides the "secret" value.
func (st secretStore) GetEntryInfoHidden(id string) (si StoreEntryInfo, ok bool) {
	si, ok = st.GetEntryInfo(id)
	si.Secret = "#HIDDEN#"
	return
}

// Click increases the click counter for an entry.
func (st secretStore) Click(id string) {
	entry, ok := st.GetEntry(id)
	if ok {
		if entry.Clicks < entry.MaxClicks-1 {
			entry.Clicks += 1
			st[id] = entry
		} else {
			delete(st, id)
		}
	}
	return
}

// Expiry checks for expired entries at regular intervals
func (st secretStore) Expiry() {
	tck := time.NewTicker(time.Minute * expiryCheck)
	for {
		log.Println("checking expiration")
		now := time.Now()
		for id, e := range st {
			expDate := e.DateAdded
			expDate = expDate.Add(time.Hour * 24 * time.Duration(e.ValidFor))
			if now.After(expDate) {
				log.Printf("%s expired\n", id)
				delete(st, id)
			}
		}
		<-tck.C
	}
}
<commit_msg>use const for magic string<commit_after>package main

import (
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"log"
	"time"
)

const (
	hiddenString = "#HIDDEN#"
)

// In-memory representation of a secret.
type StoreEntry struct {
	Secret    string    `json:"secret"`
	MaxClicks int       `json:"max_clicks"`
	Clicks    int       `json:"clicks"`
	DateAdded time.Time `json:"date_added"`
	ValidFor  int       `json:"valid_for"`
	AuthToken string    `json:"auth_token"`
}

// Secret augmented with computed fields.
type StoreEntryInfo struct {
	StoreEntry
	Id        string `json:"id"`
	PathQuery string `json:"path_query"`
	Url       string `json:"url"`
	ApiUrl    string `json:"api_url"`
}

type secretStore map[string]StoreEntry

// hashStruct returns a hash from an arbitrary structure, usable in a URL.
func hashStruct(data interface{}) (hash string) {
	hashBytes := sha256.Sum256([]byte(fmt.Sprintf("%v", data)))
	hash = base64.RawURLEncoding.EncodeToString(hashBytes[:])
	return
}

// AddEntry adds a secret to the store.
func (st secretStore) AddEntry(e StoreEntry, id string) string {
	e.DateAdded = time.Now()
	if id == "" {
		id = hashStruct(e)
	}
	if e.ValidFor == 0 {
		e.ValidFor = defaultValidity
	}
	st[id] = e
	return id
}

// NewEntry adds a new secret to the store. Set id to ""
// to have it auto-generated by hashing the entry.
func (st secretStore) NewEntry(secret string, maxclicks int, validfor int, at string, id string) string {
	return st.AddEntry(StoreEntry{secret, maxclicks, 0, time.Time{}, validfor, at}, id)
}

// GetEntry retrieves a secret from the store.
func (st secretStore) GetEntry(id string) (se StoreEntry, ok bool) {
	se, ok = st[id]
	return
}

// GetEntryInfo wraps GetEntry and adds some computed fields.
func (st secretStore) GetEntryInfo(id string) (si StoreEntryInfo, ok bool) {
	entry, ok := st.GetEntry(id)
	pathQuery := uGet + "?id=" + id
	url := getURLBase() + pathQuery
	apiurl := getURLBase() + uApiGet + id
	return StoreEntryInfo{entry, id, pathQuery, url, apiurl}, ok
}

// GetEntryInfo wraps GetEntry and adds some computed fields. In addition it
// hides the "secret" value.
func (st secretStore) GetEntryInfoHidden(id string) (si StoreEntryInfo, ok bool) {
	si, ok = st.GetEntryInfo(id)
	si.Secret = hiddenString
	return
}

// Click increases the click counter for an entry.
func (st secretStore) Click(id string) {
	entry, ok := st.GetEntry(id)
	if ok {
		if entry.Clicks < entry.MaxClicks-1 {
			entry.Clicks += 1
			st[id] = entry
		} else {
			delete(st, id)
		}
	}
	return
}

// Expiry checks for expired entries at regular intervals
func (st secretStore) Expiry() {
	tck := time.NewTicker(time.Minute * expiryCheck)
	for {
		log.Println("checking expiration")
		now := time.Now()
		for id, e := range st {
			expDate := e.DateAdded
			expDate = expDate.Add(time.Hour * 24 * time.Duration(e.ValidFor))
			if now.After(expDate) {
				log.Printf("%s expired\n", id)
				delete(st, id)
			}
		}
		<-tck.C
	}
}
<|endoftext|>