<commit_before>// Copyright 2018 Istio 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 sisyphus

import (
	"encoding/json"
	"fmt"
	"log"
	"path/filepath"
	"strconv"
	"time"

	u "istio.io/test-infra/toolbox/util"
)

// CI defines common accessors for continuous integration systems
type CI interface {
	GetLatestRun(jobName string) (int, error)
	GetResult(jobName string, runNo int) (*Result, error)
	Rerun(jobName string, runNo, numRerun int) error
	GetDetailsURL(jobName string, runNo int) string
}

// Result defines the output of each CI run
type Result struct {
	Passed bool   `json:"passed"`
	SHA    string `json:"sha"`
}

const (
	lastBuildTXT = "latest-build.txt"
	finishedJSON = "finished.json"
	startedJSON  = "started.json"
)

// ProwResult matches the structure published in finished.json
type ProwResult struct {
	TimeStamp  int64        `json:"timestamp"`
	Version    string       `json:"version"`
	Result     string       `json:"result"`
	Passed     bool         `json:"passed"`
	JobVersion string       `json:"job-version"`
	Metadata   ProwMetadata `json:"metadata"`
}

// ProwMetadata matches the structure published in finished.json
type ProwMetadata struct {
	Repo       string `json:"repo"`
	RepoCommit string `json:"repo-commit"`
}

// ProwJobConfig matches the structure published in started.json
type ProwJobConfig struct {
	Node        string            `json:"node"`
	JenkinsNode string            `json:"jenkins-node"`
	Version     string            `json:"version"`
	TimeStamp   int64             `json:"timestamp"`
	RepoVersion string            `json:"repo-version"`
	Pull        string            `json:"pull"`
	Repos       map[string]string `json:"repos"`
}

// ProwAccessor provides programmable access to Prow data on GCS
type ProwAccessor struct {
	prowProject   string
	prowZone      string
	gubernatorURL string
	gcsBucket     string
	gcsClient     u.IGCSClient
	rerunCmd      func(node string) error
	presubmitJobs map[string]struct{}
}

// NewProwAccessor creates a new ProwAccessor
func NewProwAccessor(prowProject, prowZone, gubernatorURL, gcsBucket string, client u.IGCSClient) *ProwAccessor {
	return &ProwAccessor{
		prowProject:   prowProject,
		prowZone:      prowZone,
		gubernatorURL: gubernatorURL,
		gcsClient:     client,
		gcsBucket:     gcsBucket,
		presubmitJobs: make(map[string]struct{}),
		rerunCmd: func(node string) error {
			_, e := u.Shell("echo kubectl create -f \"https://prow.istio.io/rerun?prowjob=%s\"", node)
			return e
		},
	}
}

// RegisterPresubmitJobs marks `jobNames` as pre-submit jobs
func (p *ProwAccessor) RegisterPresubmitJobs(presubmitJobNames []string) {
	for _, jobName := range presubmitJobNames {
		p.presubmitJobs[jobName] = struct{}{}
	}
}

func (p *ProwAccessor) buildGCSPath(jobName string) string {
	if _, containsKey := p.presubmitJobs[jobName]; containsKey {
		return filepath.Join("directory", jobName)
	}
	// postsubmit path is just the job name
	return jobName
}

func (p *ProwAccessor) buildGCSPathWithIndirection(jobName string, runNo int) (string, error) {
	if _, containsKey := p.presubmitJobs[jobName]; containsKey {
		redirect := filepath.Join("directory", jobName, fmt.Sprintf("%d.txt", runNo))
		redirectURL, err := p.gcsClient.Read(redirect)
		if err != nil {
			return "", err
		}
		bucketPrefix := fmt.Sprintf("gs://%s/", p.gcsBucket)
		return redirectURL[len(bucketPrefix):], nil
	}
	return filepath.Join(jobName, strconv.Itoa(runNo)), nil
}

// GetLatestRun reads latest run from "latest-build.txt" of a job under the gcs bucket.
// This job is assumed to be a post-submit job unless registered through `RegisterPresubmitJobs()`.
// Such distinction is critical as pre-submit and post-submit jobs have different GCS path
func (p *ProwAccessor) GetLatestRun(jobName string) (int, error) {
	lastBuildFile := filepath.Join(p.buildGCSPath(jobName), lastBuildTXT)
	latestBuildString, err := p.gcsClient.Read(lastBuildFile)
	if err != nil {
		return 0, err
	}
	latestBuildInt, err := strconv.Atoi(latestBuildString)
	if err != nil {
		log.Printf("Failed to convert %s to int: %v\n", latestBuildString, err)
		return 0, err
	}
	return latestBuildInt, nil
}

// GetResult returns the Result of the job at a specific run
func (p *ProwAccessor) GetResult(jobName string, runNo int) (*Result, error) {
	gcsPath, err := p.buildGCSPathWithIndirection(jobName, runNo)
	if err != nil {
		return nil, err
	}
	jobFinishedFile := filepath.Join(gcsPath, finishedJSON)
	prowResultString, err := p.gcsClient.Read(jobFinishedFile)
	if err != nil {
		log.Printf("Cannot access %s on GCS: %v", jobFinishedFile, err)
		return nil, err
	}
	prowResult := ProwResult{}
	if err = json.Unmarshal([]byte(prowResultString), &prowResult); err != nil {
		log.Printf("Failed to unmarshal ProwResult %s: %v", prowResultString, err)
		return nil, err
	}
	return &Result{
		Passed: prowResult.Passed,
		SHA:    prowResult.Metadata.RepoCommit,
	}, nil
}

// GetDetailsURL returns the gubernator URL to that job at the run number
func (p *ProwAccessor) GetDetailsURL(jobName string, runNo int) string {
	return fmt.Sprintf("%s/%s/%d", p.gubernatorURL, jobName, runNo)
}

// Rerun starts on Prow the reruns on specified jobs
func (p *ProwAccessor) Rerun(jobName string, runNo, numRerun int) error {
	cfg, err := p.getProwJobConfig(jobName, runNo)
	if err != nil {
		return err
	}
	if err = p.triggerConcurrentReruns(jobName, cfg.Node, numRerun); err != nil {
		return err
	}
	return nil
}

// getProwJobConfig fetches the config of the job at runNo
func (p *ProwAccessor) getProwJobConfig(jobName string, runNo int) (*ProwJobConfig, error) {
	gcsPath, err := p.buildGCSPathWithIndirection(jobName, runNo)
	if err != nil {
		return nil, err
	}
	jobStartedFile := filepath.Join(gcsPath, startedJSON)
	StartedFileString, err := p.gcsClient.Read(jobStartedFile)
	if err != nil {
		return nil, err
	}
	cfg := ProwJobConfig{}
	if err = json.Unmarshal([]byte(StartedFileString), &cfg); err != nil {
		log.Printf("Failed to unmarshal ProwJobConfig %s: %v\n", StartedFileString, err)
		return nil, err
	}
	return &cfg, nil
}

func (p *ProwAccessor) triggerConcurrentReruns(jobName, node string, numRerun int) error {
	log.Printf("Rerunning %s\n", jobName)
	recess := 1 * time.Minute
	maxRetry := 3
	for i := 0; i < numRerun; i++ {
		if err := u.Retry(recess, maxRetry, func() error {
			return p.rerunCmd(node)
		}); err != nil {
			log.Printf("Unable to trigger the %d-th rerun of job %v", i, jobName)
		}
	}
	return nil
}
<commit_msg>Restore prow rerun command by removing echo (#798)<commit_after>// Copyright 2018 Istio 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 sisyphus

import (
	"encoding/json"
	"fmt"
	"log"
	"path/filepath"
	"strconv"
	"time"

	u "istio.io/test-infra/toolbox/util"
)

// CI defines common accessors for continuous integration systems
type CI interface {
	GetLatestRun(jobName string) (int, error)
	GetResult(jobName string, runNo int) (*Result, error)
	Rerun(jobName string, runNo, numRerun int) error
	GetDetailsURL(jobName string, runNo int) string
}

// Result defines the output of each CI run
type Result struct {
	Passed bool   `json:"passed"`
	SHA    string `json:"sha"`
}

const (
	lastBuildTXT = "latest-build.txt"
	finishedJSON = "finished.json"
	startedJSON  = "started.json"
)

// ProwResult matches the structure published in finished.json
type ProwResult struct {
	TimeStamp  int64        `json:"timestamp"`
	Version    string       `json:"version"`
	Result     string       `json:"result"`
	Passed     bool         `json:"passed"`
	JobVersion string       `json:"job-version"`
	Metadata   ProwMetadata `json:"metadata"`
}

// ProwMetadata matches the structure published in finished.json
type ProwMetadata struct {
	Repo       string `json:"repo"`
	RepoCommit string `json:"repo-commit"`
}

// ProwJobConfig matches the structure published in started.json
type ProwJobConfig struct {
	Node        string            `json:"node"`
	JenkinsNode string            `json:"jenkins-node"`
	Version     string            `json:"version"`
	TimeStamp   int64             `json:"timestamp"`
	RepoVersion string            `json:"repo-version"`
	Pull        string            `json:"pull"`
	Repos       map[string]string `json:"repos"`
}

// ProwAccessor provides programmable access to Prow data on GCS
type ProwAccessor struct {
	prowProject   string
	prowZone      string
	gubernatorURL string
	gcsBucket     string
	gcsClient     u.IGCSClient
	rerunCmd      func(node string) error
	presubmitJobs map[string]struct{}
}

// NewProwAccessor creates a new ProwAccessor
func NewProwAccessor(prowProject, prowZone, gubernatorURL, gcsBucket string, client u.IGCSClient) *ProwAccessor {
	return &ProwAccessor{
		prowProject:   prowProject,
		prowZone:      prowZone,
		gubernatorURL: gubernatorURL,
		gcsClient:     client,
		gcsBucket:     gcsBucket,
		presubmitJobs: make(map[string]struct{}),
		rerunCmd: func(node string) error {
			_, e := u.Shell("kubectl create -f \"https://prow.istio.io/rerun?prowjob=%s\"", node)
			return e
		},
	}
}

// RegisterPresubmitJobs marks `jobNames` as pre-submit jobs
func (p *ProwAccessor) RegisterPresubmitJobs(presubmitJobNames []string) {
	for _, jobName := range presubmitJobNames {
		p.presubmitJobs[jobName] = struct{}{}
	}
}

func (p *ProwAccessor) buildGCSPath(jobName string) string {
	if _, containsKey := p.presubmitJobs[jobName]; containsKey {
		return filepath.Join("directory", jobName)
	}
	// postsubmit path is just the job name
	return jobName
}

func (p *ProwAccessor) buildGCSPathWithIndirection(jobName string, runNo int) (string, error) {
	if _, containsKey := p.presubmitJobs[jobName]; containsKey {
		redirect := filepath.Join("directory", jobName, fmt.Sprintf("%d.txt", runNo))
		redirectURL, err := p.gcsClient.Read(redirect)
		if err != nil {
			return "", err
		}
		bucketPrefix := fmt.Sprintf("gs://%s/", p.gcsBucket)
		return redirectURL[len(bucketPrefix):], nil
	}
	return filepath.Join(jobName, strconv.Itoa(runNo)), nil
}

// GetLatestRun reads latest run from "latest-build.txt" of a job under the gcs bucket.
// This job is assumed to be a post-submit job unless registered through `RegisterPresubmitJobs()`.
// Such distinction is critical as pre-submit and post-submit jobs have different GCS path
func (p *ProwAccessor) GetLatestRun(jobName string) (int, error) {
	lastBuildFile := filepath.Join(p.buildGCSPath(jobName), lastBuildTXT)
	latestBuildString, err := p.gcsClient.Read(lastBuildFile)
	if err != nil {
		return 0, err
	}
	latestBuildInt, err := strconv.Atoi(latestBuildString)
	if err != nil {
		log.Printf("Failed to convert %s to int: %v\n", latestBuildString, err)
		return 0, err
	}
	return latestBuildInt, nil
}

// GetResult returns the Result of the job at a specific run
func (p *ProwAccessor) GetResult(jobName string, runNo int) (*Result, error) {
	gcsPath, err := p.buildGCSPathWithIndirection(jobName, runNo)
	if err != nil {
		return nil, err
	}
	jobFinishedFile := filepath.Join(gcsPath, finishedJSON)
	prowResultString, err := p.gcsClient.Read(jobFinishedFile)
	if err != nil {
		log.Printf("Cannot access %s on GCS: %v", jobFinishedFile, err)
		return nil, err
	}
	prowResult := ProwResult{}
	if err = json.Unmarshal([]byte(prowResultString), &prowResult); err != nil {
		log.Printf("Failed to unmarshal ProwResult %s: %v", prowResultString, err)
		return nil, err
	}
	return &Result{
		Passed: prowResult.Passed,
		SHA:    prowResult.Metadata.RepoCommit,
	}, nil
}

// GetDetailsURL returns the gubernator URL to that job at the run number
func (p *ProwAccessor) GetDetailsURL(jobName string, runNo int) string {
	return fmt.Sprintf("%s/%s/%d", p.gubernatorURL, jobName, runNo)
}

// Rerun starts on Prow the reruns on specified jobs
func (p *ProwAccessor) Rerun(jobName string, runNo, numRerun int) error {
	cfg, err := p.getProwJobConfig(jobName, runNo)
	if err != nil {
		return err
	}
	if err = p.triggerConcurrentReruns(jobName, cfg.Node, numRerun); err != nil {
		return err
	}
	return nil
}

// getProwJobConfig fetches the config of the job at runNo
func (p *ProwAccessor) getProwJobConfig(jobName string, runNo int) (*ProwJobConfig, error) {
	gcsPath, err := p.buildGCSPathWithIndirection(jobName, runNo)
	if err != nil {
		return nil, err
	}
	jobStartedFile := filepath.Join(gcsPath, startedJSON)
	StartedFileString, err := p.gcsClient.Read(jobStartedFile)
	if err != nil {
		return nil, err
	}
	cfg := ProwJobConfig{}
	if err = json.Unmarshal([]byte(StartedFileString), &cfg); err != nil {
		log.Printf("Failed to unmarshal ProwJobConfig %s: %v\n", StartedFileString, err)
		return nil, err
	}
	return &cfg, nil
}

func (p *ProwAccessor) triggerConcurrentReruns(jobName, node string, numRerun int) error {
	log.Printf("Rerunning %s\n", jobName)
	recess := 1 * time.Minute
	maxRetry := 3
	for i := 0; i < numRerun; i++ {
		if err := u.Retry(recess, maxRetry, func() error {
			return p.rerunCmd(node)
		}); err != nil {
			log.Printf("Unable to trigger the %d-th rerun of job %v", i, jobName)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.

package antlr

import (
	"bytes"
	"io"
	"os"
)

//  This is an InputStream that is loaded from a file all at once
//  when you construct the object.

type FileStream struct {
	*InputStream

	filename string
}

func NewFileStream(fileName string) *FileStream {

	buf := bytes.NewBuffer(nil)

	f, _ := os.Open(fileName) // Error handling elided for brevity.
	io.Copy(buf, f)           // Error handling elided for brevity.
	f.Close()

	fs := new(FileStream)

	fs.filename = fileName
	s := string(buf.Bytes())

	fs.InputStream = NewInputStream(s)

	return fs

}

func (f *FileStream) GetSourceName() string {
	return f.filename
}
<commit_msg>Add proper error handling semantics to FileStream.<commit_after>// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.

package antlr

import (
	"bytes"
	"io"
	"os"
)

//  This is an InputStream that is loaded from a file all at once
//  when you construct the object.

type FileStream struct {
	*InputStream

	filename string
}

func NewFileStream(fileName string) (*FileStream, error) {

	buf := bytes.NewBuffer(nil)

	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	err = io.Copy(buf, f)
	if err != nil {
		return nil, er
	}

	fs := new(FileStream)

	fs.filename = fileName
	s := string(buf.Bytes())

	fs.InputStream = NewInputStream(s)

	return fs, nil

}

func (f *FileStream) GetSourceName() string {
	return f.filename
}
<|endoftext|>


<commit_before>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package tests_test

import (
	"flag"
	"fmt"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	v1 "kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/tests"
)

var _ = Describe("DataVolume Integration", func() {
	flag.Parse()

	virtClient, err := kubecli.GetKubevirtClient()
	tests.PanicOnError(err)

	BeforeEach(func() {
		tests.BeforeTestCleanup()
		if !tests.HasCDI() {
			Skip("Skip DataVolume tests when CDI is not present")
		}

	})

	AfterEach(func() {
	})

	runVMIAndExpectLaunch := func(vmi *v1.VirtualMachineInstance, timeout int) *v1.VirtualMachineInstance {
		By("Starting a VirtualMachineInstance with DataVolume")
		var obj *v1.VirtualMachineInstance
		var err error
		Eventually(func() error {
			obj, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			return err
		}, timeout, 1*time.Second).ShouldNot(HaveOccurred())

		By("Checking that the DataVolume has succeeded")
		tests.WaitForSuccessfulDataVolumeImport(obj, timeout)

		By("Waiting until the VirtualMachineInstance will start")
		tests.WaitForSuccessfulVMIStartWithTimeout(obj, timeout)
		return obj
	}

	Describe("Starting a VirtualMachineInstance with a DataVolume as a volume source", func() {
		Context("using Alpine import", func() {
			It("should be successfully started and stopped multiple times", func() {

				dataVolume := tests.NewRandomDataVolumeWithHttpImport(tests.AlpineHttpUrl, tests.NamespaceTestDefault)
				vmi := tests.NewRandomVMIWithDataVolume(dataVolume.Name)

				_, err := virtClient.CdiClient().CdiV1alpha1().DataVolumes(dataVolume.Namespace).Create(dataVolume)
				Expect(err).To(BeNil())

				num := 2
				By("Starting and stopping the VirtualMachineInstance a number of times")
				for i := 1; i <= num; i++ {
					vmi := runVMIAndExpectLaunch(vmi, 240)

					// Verify console on last iteration to verify the VirtualMachineInstance is still booting properly
					// after being restarted multiple times
					if i == num {
						By("Checking that the VirtualMachineInstance console has expected output")
						expecter, err := tests.LoggedInAlpineExpecter(vmi)
						Expect(err).To(BeNil())
						expecter.Close()
					}

					err = virtClient.VirtualMachineInstance(vmi.Namespace).Delete(vmi.Name, &metav1.DeleteOptions{})
					Expect(err).To(BeNil())
					tests.WaitForVirtualMachineToDisappearWithTimeout(vmi, 120)
				}
				err = virtClient.CdiClient().CdiV1alpha1().DataVolumes(dataVolume.Namespace).Delete(dataVolume.Name, &metav1.DeleteOptions{})
				Expect(err).To(BeNil())
			})
		})
	})

	Describe("Starting a VirtualMachine with a DataVolume", func() {
		Context("using Alpine import", func() {
			It("should be successfully started and stopped multiple times", func() {
				vm := tests.NewRandomVMWithDataVolume(tests.AlpineHttpUrl, tests.NamespaceTestDefault)
				vm, err = virtClient.VirtualMachine(tests.NamespaceTestDefault).Create(vm)
				Expect(err).ToNot(HaveOccurred())
				num := 2
				By("Starting and stopping the VirtualMachine number of times")
				for i := 0; i < num; i++ {
					By(fmt.Sprintf("Doing run: %d", i))
					vm = tests.StartVirtualMachine(vm)
					// Verify console on last iteration to verify the VirtualMachineInstance is still booting properly
					// after being restarted multiple times
					if i == num {
						By("Checking that the VirtualMachineInstance console has expected output")
						vmi, err := virtClient.VirtualMachineInstance(vm.Namespace).Get(vm.Name, &metav1.GetOptions{})
						Expect(err).ToNot(HaveOccurred())
						expecter, err := tests.LoggedInAlpineExpecter(vmi)
						Expect(err).To(BeNil())
						expecter.Close()
					}
					vm = tests.StopVirtualMachine(vm)
				}
				Expect(virtClient.VirtualMachine(vm.Namespace).Delete(vm.Name, &metav1.DeleteOptions{})).To(Succeed())
			})

			It("should remove owner references on DataVolume if VM is orphan deleted.", func() {
				vm := tests.NewRandomVMWithDataVolume(tests.AlpineHttpUrl, tests.NamespaceTestDefault)
				vm, err = virtClient.VirtualMachine(tests.NamespaceTestDefault).Create(vm)
				Expect(err).ToNot(HaveOccurred())

				// Check for owner reference
				Eventually(func() []metav1.OwnerReference {
					dataVolume, _ := virtClient.CdiClient().CdiV1alpha1().DataVolumes(vm.Namespace).Get(vm.Spec.DataVolumeTemplates[0].Name, metav1.GetOptions{})
					return dataVolume.OwnerReferences
				}, 100*time.Second, 1*time.Second).ShouldNot(BeEmpty())

				// Delete the VM with orphan Propagation
				orphanPolicy := metav1.DeletePropagationOrphan
				Expect(virtClient.VirtualMachine(vm.Namespace).
					Delete(vm.Name, &metav1.DeleteOptions{PropagationPolicy: &orphanPolicy})).To(Succeed())

				// Wait until the virtual machine instance is deleted
				Eventually(func() bool {
					_, err := virtClient.VirtualMachine(vm.Namespace).Get(vm.Name, &metav1.GetOptions{})
					if errors.IsNotFound(err) {
						return true
					}
					return false
				}, 100*time.Second, 1*time.Second).Should(BeTrue())

				dataVolume, err := virtClient.CdiClient().CdiV1alpha1().DataVolumes(vm.Namespace).Get(vm.Spec.DataVolumeTemplates[0].Name, metav1.GetOptions{})
				Expect(dataVolume.OwnerReferences).To(BeEmpty())
				Expect(err).ToNot(HaveOccurred())

				err = virtClient.CdiClient().CdiV1alpha1().DataVolumes(vm.Namespace).Delete(dataVolume.Name, &metav1.DeleteOptions{})
				Expect(err).ToNot(HaveOccurred())
			})
		})
	})

})
<commit_msg>cdi-1.4.1: Moved the datavolume wait to execute before creating the VMI.<commit_after>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package tests_test

import (
	"flag"
	"fmt"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	v1 "kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/tests"
)

var _ = Describe("DataVolume Integration", func() {
	flag.Parse()

	virtClient, err := kubecli.GetKubevirtClient()
	tests.PanicOnError(err)

	BeforeEach(func() {
		tests.BeforeTestCleanup()
		if !tests.HasCDI() {
			Skip("Skip DataVolume tests when CDI is not present")
		}

	})

	AfterEach(func() {
	})

	runVMIAndExpectLaunch := func(vmi *v1.VirtualMachineInstance, timeout int) *v1.VirtualMachineInstance {
		By("Checking that the DataVolume has succeeded")
		tests.WaitForSuccessfulDataVolumeImport(vmi, timeout)

		By("Starting a VirtualMachineInstance with DataVolume")
		var obj *v1.VirtualMachineInstance
		var err error
		Eventually(func() error {
			obj, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			return err
		}, timeout, 1*time.Second).ShouldNot(HaveOccurred())

		By("Waiting until the VirtualMachineInstance will start")
		tests.WaitForSuccessfulVMIStartWithTimeout(obj, timeout)
		return obj
	}

	Describe("Starting a VirtualMachineInstance with a DataVolume as a volume source", func() {
		Context("using Alpine import", func() {
			It("should be successfully started and stopped multiple times", func() {

				dataVolume := tests.NewRandomDataVolumeWithHttpImport(tests.AlpineHttpUrl, tests.NamespaceTestDefault)
				vmi := tests.NewRandomVMIWithDataVolume(dataVolume.Name)

				_, err := virtClient.CdiClient().CdiV1alpha1().DataVolumes(dataVolume.Namespace).Create(dataVolume)
				Expect(err).To(BeNil())

				num := 2
				By("Starting and stopping the VirtualMachineInstance a number of times")
				for i := 1; i <= num; i++ {
					vmi := runVMIAndExpectLaunch(vmi, 240)

					// Verify console on last iteration to verify the VirtualMachineInstance is still booting properly
					// after being restarted multiple times
					if i == num {
						By("Checking that the VirtualMachineInstance console has expected output")
						expecter, err := tests.LoggedInAlpineExpecter(vmi)
						Expect(err).To(BeNil())
						expecter.Close()
					}

					err = virtClient.VirtualMachineInstance(vmi.Namespace).Delete(vmi.Name, &metav1.DeleteOptions{})
					Expect(err).To(BeNil())
					tests.WaitForVirtualMachineToDisappearWithTimeout(vmi, 120)
				}
				err = virtClient.CdiClient().CdiV1alpha1().DataVolumes(dataVolume.Namespace).Delete(dataVolume.Name, &metav1.DeleteOptions{})
				Expect(err).To(BeNil())
			})
		})
	})

	Describe("Starting a VirtualMachine with a DataVolume", func() {
		Context("using Alpine import", func() {
			It("should be successfully started and stopped multiple times", func() {
				vm := tests.NewRandomVMWithDataVolume(tests.AlpineHttpUrl, tests.NamespaceTestDefault)
				vm, err = virtClient.VirtualMachine(tests.NamespaceTestDefault).Create(vm)
				Expect(err).ToNot(HaveOccurred())
				num := 2
				By("Starting and stopping the VirtualMachine number of times")
				for i := 0; i < num; i++ {
					By(fmt.Sprintf("Doing run: %d", i))
					vm = tests.StartVirtualMachine(vm)
					// Verify console on last iteration to verify the VirtualMachineInstance is still booting properly
					// after being restarted multiple times
					if i == num {
						By("Checking that the VirtualMachineInstance console has expected output")
						vmi, err := virtClient.VirtualMachineInstance(vm.Namespace).Get(vm.Name, &metav1.GetOptions{})
						Expect(err).ToNot(HaveOccurred())
						expecter, err := tests.LoggedInAlpineExpecter(vmi)
						Expect(err).To(BeNil())
						expecter.Close()
					}
					vm = tests.StopVirtualMachine(vm)
				}
				Expect(virtClient.VirtualMachine(vm.Namespace).Delete(vm.Name, &metav1.DeleteOptions{})).To(Succeed())
			})

			It("should remove owner references on DataVolume if VM is orphan deleted.", func() {
				vm := tests.NewRandomVMWithDataVolume(tests.AlpineHttpUrl, tests.NamespaceTestDefault)
				vm, err = virtClient.VirtualMachine(tests.NamespaceTestDefault).Create(vm)
				Expect(err).ToNot(HaveOccurred())

				// Check for owner reference
				Eventually(func() []metav1.OwnerReference {
					dataVolume, _ := virtClient.CdiClient().CdiV1alpha1().DataVolumes(vm.Namespace).Get(vm.Spec.DataVolumeTemplates[0].Name, metav1.GetOptions{})
					return dataVolume.OwnerReferences
				}, 100*time.Second, 1*time.Second).ShouldNot(BeEmpty())

				// Delete the VM with orphan Propagation
				orphanPolicy := metav1.DeletePropagationOrphan
				Expect(virtClient.VirtualMachine(vm.Namespace).
					Delete(vm.Name, &metav1.DeleteOptions{PropagationPolicy: &orphanPolicy})).To(Succeed())

				// Wait until the virtual machine instance is deleted
				Eventually(func() bool {
					_, err := virtClient.VirtualMachine(vm.Namespace).Get(vm.Name, &metav1.GetOptions{})
					if errors.IsNotFound(err) {
						return true
					}
					return false
				}, 100*time.Second, 1*time.Second).Should(BeTrue())

				dataVolume, err := virtClient.CdiClient().CdiV1alpha1().DataVolumes(vm.Namespace).Get(vm.Spec.DataVolumeTemplates[0].Name, metav1.GetOptions{})
				Expect(dataVolume.OwnerReferences).To(BeEmpty())
				Expect(err).ToNot(HaveOccurred())

				err = virtClient.CdiClient().CdiV1alpha1().DataVolumes(vm.Namespace).Delete(dataVolume.Name, &metav1.DeleteOptions{})
				Expect(err).ToNot(HaveOccurred())
			})
		})
	})

})
<|endoftext|>


<commit_before>package datastore

import (
	"errors"
	"sort"
	"time"

	"github.com/kolide/kolide-ose/server/kolide"
)

func (orm *inmem) NewHost(host *kolide.Host) (*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	for _, h := range orm.hosts {
		if host.NodeKey == h.NodeKey || host.UUID == h.UUID {
			return nil, ErrExists
		}
	}

	host.ID = orm.nextID(host)

	return host, nil
}

func (orm *inmem) SaveHost(host *kolide.Host) error {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	if _, ok := orm.hosts[host.ID]; !ok {
		return ErrNotFound
	}

	orm.hosts[host.ID] = host
	return nil
}

func (orm *inmem) DeleteHost(host *kolide.Host) error {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	if _, ok := orm.hosts[host.ID]; !ok {
		return ErrNotFound
	}

	delete(orm.hosts, host.ID)
	return nil
}

func (orm *inmem) Host(id uint) (*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	host, ok := orm.hosts[id]
	if !ok {
		return nil, ErrNotFound
	}

	return host, nil
}

func (orm *inmem) ListHosts(opt kolide.ListOptions) ([]*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	// We need to sort by keys to provide reliable ordering
	keys := []int{}
	for k, _ := range orm.hosts {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)

	hosts := []*kolide.Host{}
	for _, k := range keys {
		hosts = append(hosts, orm.hosts[uint(k)])
	}

	// Apply limit/offset
	low, high := orm.getLimitOffsetSliceBounds(opt, len(hosts))
	hosts = hosts[low:high]

	return hosts, nil
}

func (orm *inmem) EnrollHost(uuid, hostname, ip, platform string, nodeKeySize int) (*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	if uuid == "" {
		return nil, errors.New("missing uuid for host enrollment")
	}

	host := kolide.Host{
		UUID:             uuid,
		HostName:         hostname,
		PrimaryIP:        ip,
		Platform:         platform,
		DetailUpdateTime: time.Unix(0, 0).Add(24 * time.Hour),
	}
	for _, h := range orm.hosts {
		if h.UUID == uuid {
			host = *h
			break
		}
	}

	var err error
	host.NodeKey, err = generateRandomText(nodeKeySize)
	if err != nil {
		return nil, err
	}

	if hostname != "" {
		host.HostName = hostname
	}
	if ip != "" {
		host.PrimaryIP = ip
	}
	if platform != "" {
		host.Platform = platform
	}

	if host.ID == 0 {
		host.ID = orm.nextID(host)
	}
	orm.hosts[host.ID] = &host

	return &host, nil
}

func (orm *inmem) AuthenticateHost(nodeKey string) (*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	for _, host := range orm.hosts {
		if host.NodeKey == nodeKey {
			return host, nil
		}
	}

	return nil, ErrNotFound
}

func (orm *inmem) MarkHostSeen(host *kolide.Host, t time.Time) error {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	host.UpdatedAt = t

	for _, h := range orm.hosts {
		if h.ID == host.ID {
			h.UpdatedAt = t
			break
		}
	}
	return nil
}
<commit_msg>Fix NewHost bug introduced in #312 (#317)<commit_after>package datastore

import (
	"errors"
	"sort"
	"time"

	"github.com/kolide/kolide-ose/server/kolide"
)

func (orm *inmem) NewHost(host *kolide.Host) (*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	for _, h := range orm.hosts {
		if host.NodeKey == h.NodeKey || host.UUID == h.UUID {
			return nil, ErrExists
		}
	}

	host.ID = orm.nextID(host)
	orm.hosts[host.ID] = host

	return host, nil
}

func (orm *inmem) SaveHost(host *kolide.Host) error {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	if _, ok := orm.hosts[host.ID]; !ok {
		return ErrNotFound
	}

	orm.hosts[host.ID] = host
	return nil
}

func (orm *inmem) DeleteHost(host *kolide.Host) error {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	if _, ok := orm.hosts[host.ID]; !ok {
		return ErrNotFound
	}

	delete(orm.hosts, host.ID)
	return nil
}

func (orm *inmem) Host(id uint) (*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	host, ok := orm.hosts[id]
	if !ok {
		return nil, ErrNotFound
	}

	return host, nil
}

func (orm *inmem) ListHosts(opt kolide.ListOptions) ([]*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	// We need to sort by keys to provide reliable ordering
	keys := []int{}
	for k, _ := range orm.hosts {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)

	hosts := []*kolide.Host{}
	for _, k := range keys {
		hosts = append(hosts, orm.hosts[uint(k)])
	}

	// Apply limit/offset
	low, high := orm.getLimitOffsetSliceBounds(opt, len(hosts))
	hosts = hosts[low:high]

	return hosts, nil
}

func (orm *inmem) EnrollHost(uuid, hostname, ip, platform string, nodeKeySize int) (*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	if uuid == "" {
		return nil, errors.New("missing uuid for host enrollment")
	}

	host := kolide.Host{
		UUID:             uuid,
		HostName:         hostname,
		PrimaryIP:        ip,
		Platform:         platform,
		DetailUpdateTime: time.Unix(0, 0).Add(24 * time.Hour),
	}
	for _, h := range orm.hosts {
		if h.UUID == uuid {
			host = *h
			break
		}
	}

	var err error
	host.NodeKey, err = generateRandomText(nodeKeySize)
	if err != nil {
		return nil, err
	}

	if hostname != "" {
		host.HostName = hostname
	}
	if ip != "" {
		host.PrimaryIP = ip
	}
	if platform != "" {
		host.Platform = platform
	}

	if host.ID == 0 {
		host.ID = orm.nextID(host)
	}
	orm.hosts[host.ID] = &host

	return &host, nil
}

func (orm *inmem) AuthenticateHost(nodeKey string) (*kolide.Host, error) {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	for _, host := range orm.hosts {
		if host.NodeKey == nodeKey {
			return host, nil
		}
	}

	return nil, ErrNotFound
}

func (orm *inmem) MarkHostSeen(host *kolide.Host, t time.Time) error {
	orm.mtx.Lock()
	defer orm.mtx.Unlock()

	host.UpdatedAt = t

	for _, h := range orm.hosts {
		if h.ID == host.ID {
			h.UpdatedAt = t
			break
		}
	}
	return nil
}
<|endoftext|>


<commit_before><commit_msg>Fix moving to end of line on cursor down<commit_after><|endoftext|>


<commit_before><commit_msg>added NewConnection function and initDatabase()<commit_after><|endoftext|>


<commit_before>package prifi

/*
 * PRIFI SDA WRAPPER
 *
 * Caution : this is not the "PriFi protocol", which is really a "PriFi Library" which you need to import, and feed with some network methods.
 * This is the "PriFi-SDA-Wrapper" protocol, which imports the PriFi lib, gives it "SendToXXX()" methods and calls the "prifi_library.MessageReceived()"
 * methods (it build a map that converts the SDA tree into identities), and starts the PriFi Library.
 */

import (
	"errors"

	"github.com/dedis/cothority/log"
	"github.com/dedis/cothority/network"
	"github.com/dedis/cothority/sda"
	prifi_lib "github.com/lbarman/prifi_dev/prifi-lib"
)

// ProtocolName is the name used to register the SDA wrapper protocol with SDA.
const ProtocolName = "Prifi-SDA-Wrapper"

//the UDP channel we provide to PriFi. check udp.go for more details.
var udpChan UDPChannel = newRealUDPChannel()// Cannot use localhost channel anymore for real deployment

type PriFiRole int

const (
	Relay PriFiRole = iota
	Client
	Trustee
)

type PriFiIdentity struct {
	Role PriFiRole
	Id int
}

type PriFiSDAWrapperConfig struct {
	prifi_lib.ALL_ALL_PARAMETERS
	Identities map[network.Address]PriFiIdentity
	Role PriFiRole
}

//This is the PriFi-SDA-Wrapper protocol struct. It contains the SDA-tree, and a chanel that stops the simulation when it receives a "true"
type PriFiSDAWrapper struct {
	*sda.TreeNodeInstance
	configSet     bool
	config        PriFiSDAWrapperConfig
	role          PriFiRole
	ResultChannel chan interface{}

	//this is the actual "PriFi" (DC-net) protocol/library, defined in prifi-lib/prifi.go
	prifiProtocol *prifi_lib.PriFiProtocol
}

// Start implements the sda.Protocol interface.
func (p *PriFiSDAWrapper) Start() error {
	if !p.configSet {
		log.Fatal("Trying to start PriFi Library, but config not set !")
	}

	log.Lvl3("Starting PriFi-SDA-Wrapper Protocol")

	p.prifiProtocol.ConnectToTrustees()

	return nil
}

/**
 * On initialization of the PriFi-SDA-Wrapper protocol, it need to register the PriFi-Lib messages to be able to marshall them.
 * If we forget some messages there, it will crash when PriFi-Lib will call SendToXXX() with this message !
 */
func init() {

	//register the prifi_lib's message with the network lib here
	network.RegisterPacketType(prifi_lib.ALL_ALL_PARAMETERS{})
	network.RegisterPacketType(prifi_lib.CLI_REL_TELL_PK_AND_EPH_PK{})
	network.RegisterPacketType(prifi_lib.CLI_REL_UPSTREAM_DATA{})
	network.RegisterPacketType(prifi_lib.REL_CLI_DOWNSTREAM_DATA{})
	network.RegisterPacketType(prifi_lib.REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG{})
	network.RegisterPacketType(prifi_lib.REL_CLI_TELL_TRUSTEES_PK{})
	network.RegisterPacketType(prifi_lib.REL_TRU_TELL_CLIENTS_PKS_AND_EPH_PKS_AND_BASE{})
	network.RegisterPacketType(prifi_lib.REL_TRU_TELL_TRANSCRIPT{})
	network.RegisterPacketType(prifi_lib.TRU_REL_DC_CIPHER{})
	network.RegisterPacketType(prifi_lib.REL_TRU_TELL_RATE_CHANGE{})
	network.RegisterPacketType(prifi_lib.TRU_REL_SHUFFLE_SIG{})
	network.RegisterPacketType(prifi_lib.TRU_REL_TELL_NEW_BASE_AND_EPH_PKS{})
	network.RegisterPacketType(prifi_lib.TRU_REL_TELL_PK{})

	sda.GlobalProtocolRegister(ProtocolName, NewPriFiSDAWrapperProtocol)
}

// SetConfig configures the PriFi node.
// It **MUST** be called in service.newProtocol or before Start().
func (p *PriFiSDAWrapper) SetConfig(config *PriFiSDAWrapperConfig) {
	p.config = *config
	p.role = config.Role

	ms := p.buildMessageSender(config.Identities)

	// Prifi-lib parameters
	// TODO: read them from a config file (or let relay broadcast them ?)
	nClients := len(ms.clients)
	nTrustees := len(ms.trustees)
	upCellSize := 1000
	downCellSize := 10000
	relayWindowSize := 10
	relayUseDummyDataDown := false
	relayReportingLimit := -10
	useUDP := false
	doLatencyTests := false
	sendDataOutOfDCNet := false

	experimentResultChan := p.ResultChannel
	// Instantiate prifi-lib with the correct role
	switch config.Role {
	case Relay:
		relayState := prifi_lib.NewRelayState(
			nTrustees,
			nClients,
			upCellSize,
			downCellSize,
			relayWindowSize,
			relayUseDummyDataDown,
			relayReportingLimit,
			experimentResultChan,
			useUDP,
			sendDataOutOfDCNet)

		p.prifiProtocol = prifi_lib.NewPriFiRelayWithState(ms, relayState)

	case Trustee:
		id := config.Identities[p.ServerIdentity().Address].Id
		trusteeState := prifi_lib.NewTrusteeState(id, nTrustees, nClients, upCellSize)
		p.prifiProtocol = prifi_lib.NewPriFiTrusteeWithState(ms, trusteeState)

	case Client:
		id := config.Identities[p.ServerIdentity().Address].Id
		clientState := prifi_lib.NewClientState(id,
			nTrustees,
			nClients,
			upCellSize,
			doLatencyTests,
			useUDP,
			sendDataOutOfDCNet)
		p.prifiProtocol = prifi_lib.NewPriFiClientWithState(ms, clientState)
	}

	p.registerHandlers()

	p.configSet = true
}

// buildMessageSender creates a MessageSender struct
// given a mep between server identities and PriFi identities.
func (p *PriFiSDAWrapper) buildMessageSender(identities map[network.Address]PriFiIdentity) MessageSender {
	nodes := p.List() // Has type []*sda.TreeNode
	trustees := make(map[int]*sda.TreeNode)
	clients := make(map[int]*sda.TreeNode)
	var relay *sda.TreeNode = nil

	for i := 0; i < len(nodes); i++ {
		id, ok := identities[nodes[i].ServerIdentity.Address]
		if !ok {
			log.Fatal("Unknow node with address", nodes[i].ServerIdentity.Address)
		}
		switch id.Role {
		case Client: clients[id.Id] = nodes[i]
		case Trustee: trustees[id.Id] = nodes[i]
		case Relay:
			if relay == nil {
				relay = nodes[i]
			} else {
				log.Fatal("Multiple relays")
			}
		}
	}

	if relay == nil {
		log.Fatal("Relay is not reachable !")
	}

	if len(trustees) < 1 {
		log.Fatal("No trustee is reachable !")
	}

	if len(clients) < 2 {
		log.Info("Only one client is reachable, no anonymity is provided")
	}

	return MessageSender{p.TreeNodeInstance, relay, clients, trustees}
}

// registerHandlers contains the verbose code
// that registers handlers for all prifi messages.
func (p *PriFiSDAWrapper) registerHandlers() error {
	//register handlers
	err := p.RegisterHandler(p.Received_ALL_ALL_PARAMETERS)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_ALL_ALL_SHUTDOWN)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}

	//register client handlers
	err = p.RegisterHandler(p.Received_REL_CLI_DOWNSTREAM_DATA)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_REL_CLI_TELL_TRUSTEES_PK)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}

	//register relay handlers
	err = p.RegisterHandler(p.Received_CLI_REL_TELL_PK_AND_EPH_PK)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_CLI_REL_UPSTREAM_DATA)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_TRU_REL_DC_CIPHER)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_TRU_REL_SHUFFLE_SIG)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_TRU_REL_TELL_NEW_BASE_AND_EPH_PKS)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_TRU_REL_TELL_PK)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}

	//register trustees handlers
	err = p.RegisterHandler(p.Received_REL_TRU_TELL_CLIENTS_PKS_AND_EPH_PKS_AND_BASE)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_REL_TRU_TELL_TRANSCRIPT)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_REL_TRU_TELL_RATE_CHANGE)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}

	return nil
}

// NewPriFiSDAWrapperProtocol creates a bare PrifiSDAWrapper struct.
// SetConfig **MUST** be called on it before it can participate
// to the protocol.
func NewPriFiSDAWrapperProtocol(n *sda.TreeNodeInstance) (sda.ProtocolInstance, error) {
	p := &PriFiSDAWrapper{
		TreeNodeInstance: n,
		ResultChannel:    make(chan interface{}),
	}

	return p, nil
}
<commit_msg>Fixed bug in PriFiSDAWrapper.SetConfig<commit_after>package prifi

/*
 * PRIFI SDA WRAPPER
 *
 * Caution : this is not the "PriFi protocol", which is really a "PriFi Library" which you need to import, and feed with some network methods.
 * This is the "PriFi-SDA-Wrapper" protocol, which imports the PriFi lib, gives it "SendToXXX()" methods and calls the "prifi_library.MessageReceived()"
 * methods (it build a map that converts the SDA tree into identities), and starts the PriFi Library.
 */

import (
	"errors"

	"github.com/dedis/cothority/log"
	"github.com/dedis/cothority/network"
	"github.com/dedis/cothority/sda"
	prifi_lib "github.com/lbarman/prifi_dev/prifi-lib"
)

// ProtocolName is the name used to register the SDA wrapper protocol with SDA.
const ProtocolName = "Prifi-SDA-Wrapper"

//the UDP channel we provide to PriFi. check udp.go for more details.
var udpChan UDPChannel = newRealUDPChannel()// Cannot use localhost channel anymore for real deployment

type PriFiRole int

const (
	Relay PriFiRole = iota
	Client
	Trustee
)

type PriFiIdentity struct {
	Role PriFiRole
	Id int
}

type PriFiSDAWrapperConfig struct {
	prifi_lib.ALL_ALL_PARAMETERS
	Identities map[network.Address]PriFiIdentity
	Role PriFiRole
}

//This is the PriFi-SDA-Wrapper protocol struct. It contains the SDA-tree, and a chanel that stops the simulation when it receives a "true"
type PriFiSDAWrapper struct {
	*sda.TreeNodeInstance
	configSet     bool
	config        PriFiSDAWrapperConfig
	role          PriFiRole
	ResultChannel chan interface{}

	//this is the actual "PriFi" (DC-net) protocol/library, defined in prifi-lib/prifi.go
	prifiProtocol *prifi_lib.PriFiProtocol
}

// Start implements the sda.Protocol interface.
func (p *PriFiSDAWrapper) Start() error {
	if !p.configSet {
		log.Fatal("Trying to start PriFi Library, but config not set !")
	}

	log.Lvl3("Starting PriFi-SDA-Wrapper Protocol")

	p.prifiProtocol.ConnectToTrustees()

	return nil
}

/**
 * On initialization of the PriFi-SDA-Wrapper protocol, it need to register the PriFi-Lib messages to be able to marshall them.
 * If we forget some messages there, it will crash when PriFi-Lib will call SendToXXX() with this message !
 */
func init() {

	//register the prifi_lib's message with the network lib here
	network.RegisterPacketType(prifi_lib.ALL_ALL_PARAMETERS{})
	network.RegisterPacketType(prifi_lib.CLI_REL_TELL_PK_AND_EPH_PK{})
	network.RegisterPacketType(prifi_lib.CLI_REL_UPSTREAM_DATA{})
	network.RegisterPacketType(prifi_lib.REL_CLI_DOWNSTREAM_DATA{})
	network.RegisterPacketType(prifi_lib.REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG{})
	network.RegisterPacketType(prifi_lib.REL_CLI_TELL_TRUSTEES_PK{})
	network.RegisterPacketType(prifi_lib.REL_TRU_TELL_CLIENTS_PKS_AND_EPH_PKS_AND_BASE{})
	network.RegisterPacketType(prifi_lib.REL_TRU_TELL_TRANSCRIPT{})
	network.RegisterPacketType(prifi_lib.TRU_REL_DC_CIPHER{})
	network.RegisterPacketType(prifi_lib.REL_TRU_TELL_RATE_CHANGE{})
	network.RegisterPacketType(prifi_lib.TRU_REL_SHUFFLE_SIG{})
	network.RegisterPacketType(prifi_lib.TRU_REL_TELL_NEW_BASE_AND_EPH_PKS{})
	network.RegisterPacketType(prifi_lib.TRU_REL_TELL_PK{})

	sda.GlobalProtocolRegister(ProtocolName, NewPriFiSDAWrapperProtocol)
}

// SetConfig configures the PriFi node.
// It **MUST** be called in service.newProtocol or before Start().
func (p *PriFiSDAWrapper) SetConfig(config *PriFiSDAWrapperConfig) {
	p.config = *config
	p.role = config.Role

	ms := p.buildMessageSender(config.Identities)

	// Prifi-lib parameters
	// TODO: read them from a config file (or let relay broadcast them ?)
	nClients := len(ms.clients)
	nTrustees := len(ms.trustees)
	upCellSize := 1000
	downCellSize := 10000
	relayWindowSize := 10
	relayUseDummyDataDown := false
	relayReportingLimit := -10
	useUDP := false
	doLatencyTests := false
	sendDataOutOfDCNet := false

	experimentResultChan := p.ResultChannel
	// Instantiate prifi-lib with the correct role
	switch config.Role {
	case Relay:
		relayState := prifi_lib.NewRelayState(
			nTrustees,
			nClients,
			upCellSize,
			downCellSize,
			relayWindowSize,
			relayUseDummyDataDown,
			relayReportingLimit,
			experimentResultChan,
			useUDP,
			sendDataOutOfDCNet)

		p.prifiProtocol = prifi_lib.NewPriFiRelayWithState(ms, relayState)

	case Trustee:
		id := config.Identities[p.ServerIdentity().Address].Id
		trusteeState := prifi_lib.NewTrusteeState(id, nClients, nTrustees, upCellSize)
		p.prifiProtocol = prifi_lib.NewPriFiTrusteeWithState(ms, trusteeState)

	case Client:
		id := config.Identities[p.ServerIdentity().Address].Id
		clientState := prifi_lib.NewClientState(id,
			nTrustees,
			nClients,
			upCellSize,
			doLatencyTests,
			useUDP,
			sendDataOutOfDCNet)
		p.prifiProtocol = prifi_lib.NewPriFiClientWithState(ms, clientState)
	}

	p.registerHandlers()

	p.configSet = true
}

// buildMessageSender creates a MessageSender struct
// given a mep between server identities and PriFi identities.
func (p *PriFiSDAWrapper) buildMessageSender(identities map[network.Address]PriFiIdentity) MessageSender {
	nodes := p.List() // Has type []*sda.TreeNode
	trustees := make(map[int]*sda.TreeNode)
	clients := make(map[int]*sda.TreeNode)
	var relay *sda.TreeNode = nil

	for i := 0; i < len(nodes); i++ {
		id, ok := identities[nodes[i].ServerIdentity.Address]
		if !ok {
			log.Fatal("Unknow node with address", nodes[i].ServerIdentity.Address)
		}
		switch id.Role {
		case Client: clients[id.Id] = nodes[i]
		case Trustee: trustees[id.Id] = nodes[i]
		case Relay:
			if relay == nil {
				relay = nodes[i]
			} else {
				log.Fatal("Multiple relays")
			}
		}
	}

	if relay == nil {
		log.Fatal("Relay is not reachable !")
	}

	if len(trustees) < 1 {
		log.Fatal("No trustee is reachable !")
	}

	if len(clients) < 2 {
		log.Info("Only one client is reachable, no anonymity is provided")
	}

	return MessageSender{p.TreeNodeInstance, relay, clients, trustees}
}

// registerHandlers contains the verbose code
// that registers handlers for all prifi messages.
func (p *PriFiSDAWrapper) registerHandlers() error {
	//register handlers
	err := p.RegisterHandler(p.Received_ALL_ALL_PARAMETERS)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_ALL_ALL_SHUTDOWN)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}

	//register client handlers
	err = p.RegisterHandler(p.Received_REL_CLI_DOWNSTREAM_DATA)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_REL_CLI_TELL_TRUSTEES_PK)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}

	//register relay handlers
	err = p.RegisterHandler(p.Received_CLI_REL_TELL_PK_AND_EPH_PK)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_CLI_REL_UPSTREAM_DATA)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_TRU_REL_DC_CIPHER)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_TRU_REL_SHUFFLE_SIG)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_TRU_REL_TELL_NEW_BASE_AND_EPH_PKS)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_TRU_REL_TELL_PK)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}

	//register trustees handlers
	err = p.RegisterHandler(p.Received_REL_TRU_TELL_CLIENTS_PKS_AND_EPH_PKS_AND_BASE)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_REL_TRU_TELL_TRANSCRIPT)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}
	err = p.RegisterHandler(p.Received_REL_TRU_TELL_RATE_CHANGE)
	if err != nil {
		return errors.New("couldn't register handler: " + err.Error())
	}

	return nil
}

// NewPriFiSDAWrapperProtocol creates a bare PrifiSDAWrapper struct.
// SetConfig **MUST** be called on it before it can participate
// to the protocol.
func NewPriFiSDAWrapperProtocol(n *sda.TreeNodeInstance) (sda.ProtocolInstance, error) {
	p := &PriFiSDAWrapper{
		TreeNodeInstance: n,
		ResultChannel:    make(chan interface{}),
	}

	return p, nil
}
<|endoftext|>


<commit_before>package missinggo

import (
	"fmt"
	"io"
	"os"
)

type sectionReadSeeker struct {
	base      io.ReadSeeker
	off, size int64
}

// Returns a ReadSeeker on a section of another ReadSeeker.
func NewSectionReadSeeker(base io.ReadSeeker, off, size int64) (ret io.ReadSeeker) {
	ret = &sectionReadSeeker{
		base: base,
		off:  off,
		size: size,
	}
	seekOff, err := ret.Seek(0, os.SEEK_SET)
	if err != nil {
		panic(err)
	}
	if seekOff != 0 {
		panic(seekOff)
	}
	return
}

func (me *sectionReadSeeker) Seek(off int64, whence int) (ret int64, err error) {
	switch whence {
	case os.SEEK_SET:
		off += me.off
	case os.SEEK_CUR:
	case os.SEEK_END:
		off += me.off + me.size
		whence = os.SEEK_SET
	default:
		err = fmt.Errorf("unhandled whence: %d", whence)
		return
	}
	ret, err = me.base.Seek(off, whence)
	ret -= me.off
	return
}

func (me *sectionReadSeeker) Read(b []byte) (n int, err error) {
	off, err := me.Seek(0, os.SEEK_CUR)
	if err != nil {
		return
	}
	left := me.size - off
	if left <= 0 {
		err = io.EOF
		return
	}
	if int64(len(b)) > left {
		b = b[:left]
	}
	return me.base.Read(b)
}
<commit_msg>SectionReadSeeker: Switch to io whence constants<commit_after>package missinggo

import (
	"fmt"
	"io"
)

type sectionReadSeeker struct {
	base      io.ReadSeeker
	off, size int64
}

// Returns a ReadSeeker on a section of another ReadSeeker.
func NewSectionReadSeeker(base io.ReadSeeker, off, size int64) (ret io.ReadSeeker) {
	ret = &sectionReadSeeker{
		base: base,
		off:  off,
		size: size,
	}
	seekOff, err := ret.Seek(0, io.SeekStart)
	if err != nil {
		panic(err)
	}
	if seekOff != 0 {
		panic(seekOff)
	}
	return
}

func (me *sectionReadSeeker) Seek(off int64, whence int) (ret int64, err error) {
	switch whence {
	case io.SeekStart:
		off += me.off
	case io.SeekCurrent:
	case io.SeekEnd:
		off += me.off + me.size
		whence = io.SeekStart
	default:
		err = fmt.Errorf("unhandled whence: %d", whence)
		return
	}
	ret, err = me.base.Seek(off, whence)
	ret -= me.off
	return
}

func (me *sectionReadSeeker) Read(b []byte) (n int, err error) {
	off, err := me.Seek(0, io.SeekCurrent)
	if err != nil {
		return
	}
	left := me.size - off
	if left <= 0 {
		err = io.EOF
		return
	}
	if int64(len(b)) > left {
		b = b[:left]
	}
	return me.base.Read(b)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/rpc"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"
	"time"

	"golang.org/x/crypto/ssh/terminal"

	"github.com/jellevandenhooff/keytree/crypto"
	"github.com/jellevandenhooff/keytree/dkimproof"
	"github.com/jellevandenhooff/keytree/dns"
	"github.com/jellevandenhooff/keytree/trie"
	"github.com/jellevandenhooff/keytree/unixtime"
	"github.com/jellevandenhooff/keytree/updaterules"
	"github.com/jellevandenhooff/keytree/wire"
)

var server = flag.String("server", "localhost:8000", "URL of Keytree server")

func usage() {
	fmt.Printf("Usage: %s [flags] <name> [key=value]...\nFlags:\n", os.Args[0])
	flag.PrintDefaults()
}

func main() {
	publicKeys := []string{
		//"ed25519-pub(xmmqz7cvgdd9ewa79vw9cw9qvemyd4x3zsaftacc2jqqm4nfzw20)",
		"ed25519-pub(26wj522ncyprkc0t9yr1e1cz2szempbddkay02qqqxqkjnkbnygg)",
	}

	dnsClient := &dns.SimpleDNSClient{
		Server: "8.8.4.4:53",
	}

	flag.Usage = usage
	flag.Parse()

	if flag.NArg() < 1 {
		usage()
		os.Exit(1)
	}
	name := flag.Arg(0)
	if !strings.HasPrefix(name, "email:") && !strings.HasPrefix(name, "test:") {
		name = "email:" + name
	}

	client, err := rpc.DialHTTP("tcp", *server)
	if err != nil {
		log.Panicln(err)
	}
	defer client.Close()
	conn := wire.NewKeyTreeClient(client)

	newKeys := make(map[string]string)
	for _, arg := range flag.Args()[1:] {
		idx := strings.Index(arg, "=")
		if idx == -1 {
			usage()
			os.Exit(1)
		}
		if arg[:idx] == "keytree:recovery" {
			fmt.Println("This commandline tool does not let you manually manage your lock key. Managing your lock key is tricky business -- if you want to take care of your lock key by hand, modifying this tool should be a piece of cake!")
			os.Exit(1)
		}
		newKeys[arg[:idx]] = arg[idx+1:]
	}

	fmt.Printf("Updating Keytree record for '%s'.\n", name)

	var old *wire.Entry

	{
		reply, err := conn.Lookup(&wire.LookupRequest{
			Hash:       crypto.HashString(name),
			PublicKeys: publicKeys,
		})
		if err != nil {
			log.Panicln(err)
		}

		var checkedSignatures []string

		for _, publicKey := range publicKeys {
			signedTrieLookup, found := reply.SignedTrieLookups[publicKey]
			if !found {
				log.Panicln("lookup missing")
			}

			signedRoot := signedTrieLookup.SignedRoot

			if err := crypto.Verify(publicKey, signedRoot.Root, signedRoot.Signature); err != nil {
				log.Panicln(err)
			}

			if signedRoot.Root.Timestamp < unixtime.Now()-20 || signedRoot.Root.Timestamp > unixtime.Now()+20 {
				log.Panicln("signature time out of range!")
			}

			rootHash := trie.CompleteLookup(signedTrieLookup.TrieLookup, crypto.HashString(name), reply.Entry.Hash())

			if rootHash != signedRoot.Root.RootHash {
				log.Panicln("lookup does not match signed root")
			}

			checkedSignatures = append(checkedSignatures, publicKey)
		}

		old = reply.Entry
	}

	newEntry := &wire.Entry{
		Name:       name,
		Keys:       make(map[string]string),
		Timestamp:  unixtime.Now() - 10, // build in some slack if our clock is ahead
		InRecovery: false,
	}

	var oldPublic, oldPrivate string
	if old != nil && old.Keys["keytree:recovery"] != "" {
		fmt.Printf("This Keytree record is currently locked. Please enter the password used to lock this Keytree record to update it: ")
		pwbytes, _ := terminal.ReadPassword(syscall.Stdin)
		fmt.Println()
		password := string(pwbytes)
		oldPublic, oldPrivate = crypto.GenerateEd25519KeypairFromSecret(password, name)
		if oldPublic != old.Keys["keytree:recovery"] {
			fmt.Printf("Incorrect password.\n")
			os.Exit(1)
		}
	}

	var newPublic string
	fmt.Printf("Enter a password to lock your Keytree record, or leave empty for no lock: ")
	pwbytes, _ := terminal.ReadPassword(syscall.Stdin)
	fmt.Println()
	password := string(pwbytes)

	if password != "" {
		fmt.Printf("Please repeat the password: ")
		repeated, _ := terminal.ReadPassword(syscall.Stdin)
		fmt.Println()
		if password != string(repeated) {
			fmt.Printf("Passwords did not match!\n")
			os.Exit(1)
		}
		newPublic, _ = crypto.GenerateEd25519KeypairFromSecret(password, name)
	}

	if old != nil {
		for k, v := range old.Keys {
			newEntry.Keys[k] = v
		}
	}
	for k, v := range newKeys {
		if v == "" {
			delete(newEntry.Keys, k)
		} else {
			newEntry.Keys[k] = v
		}
	}

	if newPublic == "" {
		delete(newEntry.Keys, "keytree:recovery")
	} else {
		newEntry.Keys["keytree:recovery"] = newPublic
	}

	signatures := make(map[string]string)
	if oldPublic != "" {
		signatures[oldPublic], _ = crypto.Sign(oldPrivate, newEntry)
	}

	// todo: determine if we need a proof of ownership!
	if len(signatures) == 0 {
		token := updaterules.TokenForEntry(newEntry)
		if strings.HasPrefix(name, "email:") {
			statement := &wire.DKIMStatement{
				Sender: strings.TrimPrefix(name, "email:"),
				Token:  token,
			}

			dkimConn := wire.NewDKIMClient(client)

			fmt.Printf("Obtaining DKIM proof for new entry...\n")
			buffer := bytes.NewBuffer(nil)
			json.NewEncoder(buffer).Encode(&statement)

			reply, err := dkimConn.DKIMPrepare(&wire.DKIMPrepareRequest{
				Statement: statement,
			})
			if err != nil {
				log.Panicln(err)
			}

			email := reply.Email

			if runtime.GOOS == "darwin" {
				if err := exec.Command("/usr/bin/open", fmt.Sprintf("mailto:%s?subject=%s", email, statement.Token)).Run(); err != nil {
					log.Panicln(err)
				}
			} else {
				fmt.Printf("To verify e-mail ownership, send an e-mail to %s with subject %s.\n", email, statement.Token)
			}

			fmt.Printf("Waiting for e-mail...\n")

			idx := 0
			proof := ""
			for proof == "" {
				time.Sleep(1 * time.Second)

				reply, err := dkimConn.DKIMPoll(&wire.DKIMPollRequest{
					Email: email,
				})
				if err != nil {
					log.Panicln(err)
				}

				for ; idx < len(reply.Status); idx++ {
					fmt.Printf("%s\n", reply.Status[idx])
				}

				proof = reply.Proof
			}

			if err := dkimproof.CheckPlainEmail(proof, statement, dnsClient); err != nil {
				fmt.Printf("Got a DKIM proof from the server that we can't verify: %s\n", err)
				os.Exit(1)
			}

			signatures["dkim"] = proof
		}

		if strings.HasPrefix(name, "test:") {
			signatures["test"] = token
		}
	}

	{
		fmt.Printf("Submitting update to Keytree server...\n")
		_, err := conn.Update(&wire.UpdateRequest{
			SignedEntry: &wire.SignedEntry{
				Entry:      newEntry,
				Signatures: signatures,
			},
		})
		if err != nil {
			log.Panicln(err)
		}
	}

	/*
		buffer := bytes.NewBuffer(nil)
		json.NewEncoder(buffer).Encode(&update)
		var res interface{}
		resp, err = http.Post(*server+"/submit", "text/json; charset=utf8", buffer)
		parse(resp, err, "submitting update", &res)
	*/

	fmt.Printf("Successfully applied update.\n")

	if newPublic == "" {
		fmt.Printf("Your Keytree record is valid, but unlocked, so the owner of your domain can change your record at any time.\n")
	} else {
		fmt.Printf("Your Keytree record is valid. To ensure your Keytree record stays secure, make sure to update your record daily.\n")
	}
}
<commit_msg>with expiration logic, should inspect record every once in a while<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/rpc"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"
	"time"

	"golang.org/x/crypto/ssh/terminal"

	"github.com/jellevandenhooff/keytree/crypto"
	"github.com/jellevandenhooff/keytree/dkimproof"
	"github.com/jellevandenhooff/keytree/dns"
	"github.com/jellevandenhooff/keytree/trie"
	"github.com/jellevandenhooff/keytree/unixtime"
	"github.com/jellevandenhooff/keytree/updaterules"
	"github.com/jellevandenhooff/keytree/wire"
)

var server = flag.String("server", "localhost:8000", "URL of Keytree server")

func usage() {
	fmt.Printf("Usage: %s [flags] <name> [key=value]...\nFlags:\n", os.Args[0])
	flag.PrintDefaults()
}

func main() {
	publicKeys := []string{
		//"ed25519-pub(xmmqz7cvgdd9ewa79vw9cw9qvemyd4x3zsaftacc2jqqm4nfzw20)",
		"ed25519-pub(26wj522ncyprkc0t9yr1e1cz2szempbddkay02qqqxqkjnkbnygg)",
	}

	dnsClient := &dns.SimpleDNSClient{
		Server: "8.8.4.4:53",
	}

	flag.Usage = usage
	flag.Parse()

	if flag.NArg() < 1 {
		usage()
		os.Exit(1)
	}
	name := flag.Arg(0)
	if !strings.HasPrefix(name, "email:") && !strings.HasPrefix(name, "test:") {
		name = "email:" + name
	}

	client, err := rpc.DialHTTP("tcp", *server)
	if err != nil {
		log.Panicln(err)
	}
	defer client.Close()
	conn := wire.NewKeyTreeClient(client)

	newKeys := make(map[string]string)
	for _, arg := range flag.Args()[1:] {
		idx := strings.Index(arg, "=")
		if idx == -1 {
			usage()
			os.Exit(1)
		}
		if arg[:idx] == "keytree:recovery" {
			fmt.Println("This commandline tool does not let you manually manage your lock key. Managing your lock key is tricky business -- if you want to take care of your lock key by hand, modifying this tool should be a piece of cake!")
			os.Exit(1)
		}
		newKeys[arg[:idx]] = arg[idx+1:]
	}

	fmt.Printf("Updating Keytree record for '%s'.\n", name)

	var old *wire.Entry

	{
		reply, err := conn.Lookup(&wire.LookupRequest{
			Hash:       crypto.HashString(name),
			PublicKeys: publicKeys,
		})
		if err != nil {
			log.Panicln(err)
		}

		var checkedSignatures []string

		for _, publicKey := range publicKeys {
			signedTrieLookup, found := reply.SignedTrieLookups[publicKey]
			if !found {
				log.Panicln("lookup missing")
			}

			signedRoot := signedTrieLookup.SignedRoot

			if err := crypto.Verify(publicKey, signedRoot.Root, signedRoot.Signature); err != nil {
				log.Panicln(err)
			}

			if signedRoot.Root.Timestamp < unixtime.Now()-20 || signedRoot.Root.Timestamp > unixtime.Now()+20 {
				log.Panicln("signature time out of range!")
			}

			rootHash := trie.CompleteLookup(signedTrieLookup.TrieLookup, crypto.HashString(name), reply.Entry.Hash())

			if rootHash != signedRoot.Root.RootHash {
				log.Panicln("lookup does not match signed root")
			}

			checkedSignatures = append(checkedSignatures, publicKey)
		}

		old = reply.Entry
	}

	newEntry := &wire.Entry{
		Name:       name,
		Keys:       make(map[string]string),
		Timestamp:  unixtime.Now() - 10, // build in some slack if our clock is ahead
		InRecovery: false,
	}

	var oldPublic, oldPrivate string
	if old != nil && old.Keys["keytree:recovery"] != "" {
		fmt.Printf("This Keytree record is currently locked. Please enter the password used to lock this Keytree record to update it: ")
		pwbytes, _ := terminal.ReadPassword(syscall.Stdin)
		fmt.Println()
		password := string(pwbytes)
		oldPublic, oldPrivate = crypto.GenerateEd25519KeypairFromSecret(password, name)
		if oldPublic != old.Keys["keytree:recovery"] {
			fmt.Printf("Incorrect password.\n")
			os.Exit(1)
		}
	}

	var newPublic string
	fmt.Printf("Enter a password to lock your Keytree record, or leave empty for no lock: ")
	pwbytes, _ := terminal.ReadPassword(syscall.Stdin)
	fmt.Println()
	password := string(pwbytes)

	if password != "" {
		fmt.Printf("Please repeat the password: ")
		repeated, _ := terminal.ReadPassword(syscall.Stdin)
		fmt.Println()
		if password != string(repeated) {
			fmt.Printf("Passwords did not match!\n")
			os.Exit(1)
		}
		newPublic, _ = crypto.GenerateEd25519KeypairFromSecret(password, name)
	}

	if old != nil {
		for k, v := range old.Keys {
			newEntry.Keys[k] = v
		}
	}
	for k, v := range newKeys {
		if v == "" {
			delete(newEntry.Keys, k)
		} else {
			newEntry.Keys[k] = v
		}
	}

	if newPublic == "" {
		delete(newEntry.Keys, "keytree:recovery")
	} else {
		newEntry.Keys["keytree:recovery"] = newPublic
	}

	signatures := make(map[string]string)
	if oldPublic != "" {
		signatures[oldPublic], _ = crypto.Sign(oldPrivate, newEntry)
	}

	// todo: determine if we need a proof of ownership!
	if len(signatures) == 0 {
		token := updaterules.TokenForEntry(newEntry)
		if strings.HasPrefix(name, "email:") {
			statement := &wire.DKIMStatement{
				Sender: strings.TrimPrefix(name, "email:"),
				Token:  token,
			}

			dkimConn := wire.NewDKIMClient(client)

			fmt.Printf("Obtaining DKIM proof for new entry...\n")
			buffer := bytes.NewBuffer(nil)
			json.NewEncoder(buffer).Encode(&statement)

			reply, err := dkimConn.DKIMPrepare(&wire.DKIMPrepareRequest{
				Statement: statement,
			})
			if err != nil {
				log.Panicln(err)
			}

			email := reply.Email

			if runtime.GOOS == "darwin" {
				if err := exec.Command("/usr/bin/open", fmt.Sprintf("mailto:%s?subject=%s", email, statement.Token)).Run(); err != nil {
					log.Panicln(err)
				}
			} else {
				fmt.Printf("To verify e-mail ownership, send an e-mail to %s with subject %s.\n", email, statement.Token)
			}

			fmt.Printf("Waiting for e-mail...\n")

			idx := 0
			proof := ""
			for proof == "" {
				time.Sleep(1 * time.Second)

				reply, err := dkimConn.DKIMPoll(&wire.DKIMPollRequest{
					Email: email,
				})
				if err != nil {
					log.Panicln(err)
				}

				for ; idx < len(reply.Status); idx++ {
					fmt.Printf("%s\n", reply.Status[idx])
				}

				proof = reply.Proof
			}

			if err := dkimproof.CheckPlainEmail(proof, statement, dnsClient); err != nil {
				fmt.Printf("Got a DKIM proof from the server that we can't verify: %s\n", err)
				os.Exit(1)
			}

			signatures["dkim"] = proof
		}

		if strings.HasPrefix(name, "test:") {
			signatures["test"] = token
		}
	}

	{
		fmt.Printf("Submitting update to Keytree server...\n")
		_, err := conn.Update(&wire.UpdateRequest{
			SignedEntry: &wire.SignedEntry{
				Entry:      newEntry,
				Signatures: signatures,
			},
		})
		if err != nil {
			log.Panicln(err)
		}
	}

	/*
		buffer := bytes.NewBuffer(nil)
		json.NewEncoder(buffer).Encode(&update)
		var res interface{}
		resp, err = http.Post(*server+"/submit", "text/json; charset=utf8", buffer)
		parse(resp, err, "submitting update", &res)
	*/

	fmt.Printf("Successfully applied update.\n")

	if newPublic == "" {
		fmt.Printf("Your Keytree record is valid, but unlocked, so the owner of your domain can change your record at any time.\n")
	} else {
		fmt.Printf("Your Keytree record is valid. To ensure your Keytree record stays secure, make sure to check it regularly.\n")
	}
}
<|endoftext|>


<commit_before><commit_msg>Finalize changelog and release for version v3.95.0<commit_after><|endoftext|>


<commit_before>// Copyright 2019, OpenTelemetry 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 collectdreceiver

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"sync"
	"time"

	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/consumer"
	"go.opentelemetry.io/collector/translator/internaldata"
	"go.uber.org/zap"
)

var (
	errNilNextConsumer = errors.New("nil nextConsumer")
	errAlreadyStarted  = errors.New("already started")
	errAlreadyStopped  = errors.New("already stopped")
)

var _ component.MetricsReceiver = (*collectdReceiver)(nil)

// collectdReceiver implements the component.MetricsReceiver for CollectD protocol.
type collectdReceiver struct {
	sync.Mutex
	logger             *zap.Logger
	addr               string
	server             *http.Server
	defaultAttrsPrefix string
	nextConsumer       consumer.Metrics

	startOnce sync.Once
	stopOnce  sync.Once
}

// newCollectdReceiver creates the CollectD receiver with the given parameters.
func newCollectdReceiver(
	logger *zap.Logger,
	addr string,
	timeout time.Duration,
	defaultAttrsPrefix string,
	nextConsumer consumer.Metrics) (component.MetricsReceiver, error) {
	if nextConsumer == nil {
		return nil, errNilNextConsumer
	}

	r := &collectdReceiver{
		logger:             logger,
		addr:               addr,
		nextConsumer:       nextConsumer,
		defaultAttrsPrefix: defaultAttrsPrefix,
	}
	r.server = &http.Server{
		Addr:         addr,
		Handler:      r,
		ReadTimeout:  timeout,
		WriteTimeout: timeout,
	}
	return r, nil
}

// StartMetricsReception starts an HTTP server that can process CollectD JSON requests.
func (cdr *collectdReceiver) Start(_ context.Context, host component.Host) error {
	cdr.Lock()
	defer cdr.Unlock()

	err := errAlreadyStarted
	cdr.startOnce.Do(func() {
		err = nil
		go func() {
			err = cdr.server.ListenAndServe()
			if err != nil {
				host.ReportFatalError(fmt.Errorf("error starting collectd receiver: %v", err))
			}
		}()
	})

	return err
}

// StopMetricsReception stops the CollectD receiver.
func (cdr *collectdReceiver) Shutdown(context.Context) error {
	cdr.Lock()
	defer cdr.Unlock()

	var err = errAlreadyStopped
	cdr.stopOnce.Do(func() {
		err = cdr.server.Shutdown(context.Background())
	})
	return err
}

// ServeHTTP acts as the default and only HTTP handler for the CollectD receiver.
func (cdr *collectdReceiver) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	recordRequestReceived()

	if r.Method != "POST" {
		recordRequestErrors()
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		recordRequestErrors()
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	var records []collectDRecord
	err = json.Unmarshal(body, &records)
	if err != nil {
		cdr.handleHTTPErr(w, err, "unable to decode json")
		return
	}

	defaultAttrs := cdr.defaultAttributes(r)

	md := internaldata.MetricsData{}
	ctx := context.Background()
	for _, record := range records {
		md.Metrics, err = record.appendToMetrics(md.Metrics, defaultAttrs)
		if err != nil {
			cdr.handleHTTPErr(w, err, "unable to process metrics")
			return
		}
	}

	err = cdr.nextConsumer.ConsumeMetrics(ctx, internaldata.OCToMetrics(md))
	if err != nil {
		cdr.handleHTTPErr(w, err, "unable to process metrics")
		return
	}
	w.Write([]byte("OK"))
}

func (cdr *collectdReceiver) defaultAttributes(req *http.Request) map[string]string {
	if cdr.defaultAttrsPrefix == "" {
		return nil
	}
	params := req.URL.Query()
	attrs := make(map[string]string)
	for key := range params {
		if strings.HasPrefix(key, cdr.defaultAttrsPrefix) {
			value := params.Get(key)
			if len(value) == 0 {
				recordDefaultBlankAttrs()
				continue
			}
			key = key[len(cdr.defaultAttrsPrefix):]
			attrs[key] = value
		}
	}
	return attrs
}

func (cdr *collectdReceiver) handleHTTPErr(w http.ResponseWriter, err error, msg string) {
	recordRequestErrors()
	w.WriteHeader(http.StatusBadRequest)
	cdr.logger.Error(msg, zap.Error(err))
	_, err = w.Write([]byte(msg))
	if err != nil {
		cdr.logger.Error("error writing to response writer", zap.Error(err))
	}
}
<commit_msg>collectd receiver should not report ErrServerClosed (#3178)<commit_after>// Copyright 2019, OpenTelemetry 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 collectdreceiver

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"sync"
	"time"

	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/consumer"
	"go.opentelemetry.io/collector/translator/internaldata"
	"go.uber.org/zap"
)

var (
	errNilNextConsumer = errors.New("nil nextConsumer")
	errAlreadyStarted  = errors.New("already started")
	errAlreadyStopped  = errors.New("already stopped")
)

var _ component.MetricsReceiver = (*collectdReceiver)(nil)

// collectdReceiver implements the component.MetricsReceiver for CollectD protocol.
type collectdReceiver struct {
	sync.Mutex
	logger             *zap.Logger
	addr               string
	server             *http.Server
	defaultAttrsPrefix string
	nextConsumer       consumer.Metrics

	startOnce sync.Once
	stopOnce  sync.Once
}

// newCollectdReceiver creates the CollectD receiver with the given parameters.
func newCollectdReceiver(
	logger *zap.Logger,
	addr string,
	timeout time.Duration,
	defaultAttrsPrefix string,
	nextConsumer consumer.Metrics) (component.MetricsReceiver, error) {
	if nextConsumer == nil {
		return nil, errNilNextConsumer
	}

	r := &collectdReceiver{
		logger:             logger,
		addr:               addr,
		nextConsumer:       nextConsumer,
		defaultAttrsPrefix: defaultAttrsPrefix,
	}
	r.server = &http.Server{
		Addr:         addr,
		Handler:      r,
		ReadTimeout:  timeout,
		WriteTimeout: timeout,
	}
	return r, nil
}

// StartMetricsReception starts an HTTP server that can process CollectD JSON requests.
func (cdr *collectdReceiver) Start(_ context.Context, host component.Host) error {
	cdr.Lock()
	defer cdr.Unlock()

	err := errAlreadyStarted
	cdr.startOnce.Do(func() {
		err = nil
		go func() {
			err = cdr.server.ListenAndServe()
			if err != http.ErrServerClosed {
				host.ReportFatalError(fmt.Errorf("error starting collectd receiver: %v", err))
			}
		}()
	})

	return err
}

// StopMetricsReception stops the CollectD receiver.
func (cdr *collectdReceiver) Shutdown(context.Context) error {
	cdr.Lock()
	defer cdr.Unlock()

	var err = errAlreadyStopped
	cdr.stopOnce.Do(func() {
		err = cdr.server.Shutdown(context.Background())
	})
	return err
}

// ServeHTTP acts as the default and only HTTP handler for the CollectD receiver.
func (cdr *collectdReceiver) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	recordRequestReceived()

	if r.Method != "POST" {
		recordRequestErrors()
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		recordRequestErrors()
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	var records []collectDRecord
	err = json.Unmarshal(body, &records)
	if err != nil {
		cdr.handleHTTPErr(w, err, "unable to decode json")
		return
	}

	defaultAttrs := cdr.defaultAttributes(r)

	md := internaldata.MetricsData{}
	ctx := context.Background()
	for _, record := range records {
		md.Metrics, err = record.appendToMetrics(md.Metrics, defaultAttrs)
		if err != nil {
			cdr.handleHTTPErr(w, err, "unable to process metrics")
			return
		}
	}

	err = cdr.nextConsumer.ConsumeMetrics(ctx, internaldata.OCToMetrics(md))
	if err != nil {
		cdr.handleHTTPErr(w, err, "unable to process metrics")
		return
	}
	w.Write([]byte("OK"))
}

func (cdr *collectdReceiver) defaultAttributes(req *http.Request) map[string]string {
	if cdr.defaultAttrsPrefix == "" {
		return nil
	}
	params := req.URL.Query()
	attrs := make(map[string]string)
	for key := range params {
		if strings.HasPrefix(key, cdr.defaultAttrsPrefix) {
			value := params.Get(key)
			if len(value) == 0 {
				recordDefaultBlankAttrs()
				continue
			}
			key = key[len(cdr.defaultAttrsPrefix):]
			attrs[key] = value
		}
	}
	return attrs
}

func (cdr *collectdReceiver) handleHTTPErr(w http.ResponseWriter, err error, msg string) {
	recordRequestErrors()
	w.WriteHeader(http.StatusBadRequest)
	cdr.logger.Error(msg, zap.Error(err))
	_, err = w.Write([]byte(msg))
	if err != nil {
		cdr.logger.Error("error writing to response writer", zap.Error(err))
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Intel Corporation.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package packet

import (
	"fmt"
	"unsafe"

	. "github.com/intel-go/nff-go/types"
)

type MPLSHdr struct {
	mpls uint32 // Label, Exp, S, TTL
}

func (hdr *MPLSHdr) String() string {
	return fmt.Sprintf(`MPLS: Label: %d, EXP: %d, S: %d TTL: %d`,
		hdr.GetMPLSLabel(), hdr.GetMPLSTC(), hdr.GetMPLSS(), hdr.GetMPLSTTL())
}

// GetMPLSLabel returns Label (20 first bits of MPLS header).
func (hdr *MPLSHdr) GetMPLSLabel() uint32 {
	return SwapBytesUint32(hdr.mpls) >> 12
}

// SetMPLSLabel sets Label (20 first bits of MPLS header to specified value).
func (hdr *MPLSHdr) SetMPLSLabel(tag uint32) {
	hdr.mpls = SwapBytesUint32((SwapBytesUint32(hdr.mpls) & 0xfff) | (tag << 12))
}

// GetMPLSTC returns the Traffic Class (formerly known as EXP).
func (hdr *MPLSHdr) GetMPLSTC() uint32 {
	return (SwapBytesUint32(hdr.mpls) >> 9) & 0x00000007
}

// GetMPLSS returns the Bottom-Of-Stack value
func (hdr *MPLSHdr) GetMPLSS() uint32 {
	return (SwapBytesUint32(hdr.mpls) >> 8) & 1
}

// GetMPLSTTL returns the Time-to-Live value
func (hdr *MPLSHdr) GetMPLSTTL() uint32 {
	return SwapBytesUint32(hdr.mpls) & 0x000000ff
}

// GetMPLS returns MPLS header pointer if it is present in the packet.
func (packet *Packet) GetMPLS() *MPLSHdr {
	// MPLS shouldn't be used with VLAN tags, so we don't check any VLAN tags here
	if packet.Ether.EtherType == SwapBytesUint16(MPLSNumber) {
		return (*MPLSHdr)(unsafe.Pointer(packet.unparsed()))
	}
	return nil
}

// GetMPLSNoCheck casts pointer to memory right after Ethernet header
// to MPLSHdr type.
func (packet *Packet) GetMPLSNoCheck() *MPLSHdr {
	return (*MPLSHdr)(unsafe.Pointer(packet.unparsed()))
}

// ParseL3CheckMPLS set pointer to start of L3 header taking possible
// presence of MPLS header into account.
func (packet *Packet) ParseL3CheckMPLS() *MPLSHdr {
	ptr := packet.unparsed()
	// MPLS shouldn't be used with VLAN tags, so we don't check any VLAN tags here
	if packet.Ether.EtherType == SwapBytesUint16(MPLSNumber) {
		packet.L3 = unsafe.Pointer(uintptr(ptr) + MPLSLen)
		return (*MPLSHdr)(ptr)
	}
	packet.L3 = ptr
	return nil
}

// There are no "GetIPv4CheckMPLS, etc." functions here because
// mapping label to protocol ID is uniq for each label.

// AddMPLS increases size of packet on MPLSLen and adds MPLS header
// after Ether header, mpls is a whole MPLS header. Returns false if error.
func (packet *Packet) AddMPLS(mpls uint32) bool {
	if !packet.EncapsulateHead(EtherLen, MPLSLen) {
		return false
	}
	mhdr := (*MPLSHdr)(unsafe.Pointer(packet.unparsed()))
	// EncapsulateHead function has moved pointer to EtherType,
	// so the following line is correct. L3 stayed at the same place.
	packet.Ether.EtherType = SwapBytesUint16(MPLSNumber)
	mhdr.mpls = SwapBytesUint32(mpls)
	return true
}

// RemoveMPLS decreases size of packet on MPLSLen
// THIS FUNCTION DOESN'T SET ETHERTYPE!!! IT SHOULD BE SET ACCORDING TO LABEL!!!
// ETHERTYPE WILL REMAIN MPLS-LIKE = 0x8847
func (packet *Packet) RemoveMPLS() bool {
	if !packet.DecapsulateHead(EtherLen, MPLSLen) {
		return false
	}
	return true
}

// SetMPLSLabel sets Label (20 first bits of MPLS header to specified value).
func (hdr *MPLSHdr) DecreaseTTL() bool {
	newTime := SwapBytesUint32(hdr.mpls)&0x000000ff - 1
	if newTime == 0 {
		return false
	}
	hdr.mpls = SwapBytesUint32(SwapBytesUint32(hdr.mpls)&0xffffff00 | newTime)
	return true
}
<commit_msg>Addresses issues  #588 - Function description for DecreaseTTL<commit_after>// Copyright 2017 Intel Corporation.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package packet

import (
	"fmt"
	"unsafe"

	. "github.com/intel-go/nff-go/types"
)

type MPLSHdr struct {
	mpls uint32 // Label, Exp, S, TTL
}

func (hdr *MPLSHdr) String() string {
	return fmt.Sprintf(`MPLS: Label: %d, EXP: %d, S: %d TTL: %d`,
		hdr.GetMPLSLabel(), hdr.GetMPLSTC(), hdr.GetMPLSS(), hdr.GetMPLSTTL())
}

// GetMPLSLabel returns Label (20 first bits of MPLS header).
func (hdr *MPLSHdr) GetMPLSLabel() uint32 {
	return SwapBytesUint32(hdr.mpls) >> 12
}

// SetMPLSLabel sets Label (20 first bits of MPLS header to specified value).
func (hdr *MPLSHdr) SetMPLSLabel(tag uint32) {
	hdr.mpls = SwapBytesUint32((SwapBytesUint32(hdr.mpls) & 0xfff) | (tag << 12))
}

// GetMPLSTC returns the Traffic Class (formerly known as EXP).
func (hdr *MPLSHdr) GetMPLSTC() uint32 {
	return (SwapBytesUint32(hdr.mpls) >> 9) & 0x00000007
}

// GetMPLSS returns the Bottom-Of-Stack value
func (hdr *MPLSHdr) GetMPLSS() uint32 {
	return (SwapBytesUint32(hdr.mpls) >> 8) & 1
}

// GetMPLSTTL returns the Time-to-Live value
func (hdr *MPLSHdr) GetMPLSTTL() uint32 {
	return SwapBytesUint32(hdr.mpls) & 0x000000ff
}

// GetMPLS returns MPLS header pointer if it is present in the packet.
func (packet *Packet) GetMPLS() *MPLSHdr {
	// MPLS shouldn't be used with VLAN tags, so we don't check any VLAN tags here
	if packet.Ether.EtherType == SwapBytesUint16(MPLSNumber) {
		return (*MPLSHdr)(unsafe.Pointer(packet.unparsed()))
	}
	return nil
}

// GetMPLSNoCheck casts pointer to memory right after Ethernet header
// to MPLSHdr type.
func (packet *Packet) GetMPLSNoCheck() *MPLSHdr {
	return (*MPLSHdr)(unsafe.Pointer(packet.unparsed()))
}

// ParseL3CheckMPLS set pointer to start of L3 header taking possible
// presence of MPLS header into account.
func (packet *Packet) ParseL3CheckMPLS() *MPLSHdr {
	ptr := packet.unparsed()
	// MPLS shouldn't be used with VLAN tags, so we don't check any VLAN tags here
	if packet.Ether.EtherType == SwapBytesUint16(MPLSNumber) {
		packet.L3 = unsafe.Pointer(uintptr(ptr) + MPLSLen)
		return (*MPLSHdr)(ptr)
	}
	packet.L3 = ptr
	return nil
}

// There are no "GetIPv4CheckMPLS, etc." functions here because
// mapping label to protocol ID is uniq for each label.

// AddMPLS increases size of packet on MPLSLen and adds MPLS header
// after Ether header, mpls is a whole MPLS header. Returns false if error.
func (packet *Packet) AddMPLS(mpls uint32) bool {
	if !packet.EncapsulateHead(EtherLen, MPLSLen) {
		return false
	}
	mhdr := (*MPLSHdr)(unsafe.Pointer(packet.unparsed()))
	// EncapsulateHead function has moved pointer to EtherType,
	// so the following line is correct. L3 stayed at the same place.
	packet.Ether.EtherType = SwapBytesUint16(MPLSNumber)
	mhdr.mpls = SwapBytesUint32(mpls)
	return true
}

// RemoveMPLS decreases size of packet on MPLSLen
// THIS FUNCTION DOESN'T SET ETHERTYPE!!! IT SHOULD BE SET ACCORDING TO LABEL!!!
// ETHERTYPE WILL REMAIN MPLS-LIKE = 0x8847
func (packet *Packet) RemoveMPLS() bool {
	if !packet.DecapsulateHead(EtherLen, MPLSLen) {
		return false
	}
	return true
}

// DecreaseTTL decreases the MPLS header TTL by 1
func (hdr *MPLSHdr) DecreaseTTL() bool {
	newTime := SwapBytesUint32(hdr.mpls)&0x000000ff - 1
	if newTime == 0 {
		return false
	}
	hdr.mpls = SwapBytesUint32(SwapBytesUint32(hdr.mpls)&0xffffff00 | newTime)
	return true
}
<|endoftext|>


<commit_before><commit_msg>fixed the log prefix<commit_after><|endoftext|>


<commit_before>package frame_test

import (
	"bytes"
	"crypto/md5"
	"io"
	"testing"

	"gopkg.in/mewkiz/flac.v1"
)

var golden = []struct {
	name string
}{
	{name: "../testdata/love.flac"},   // i=0
	{name: "../testdata/19875.flac"},  // i=1
	{name: "../testdata/44127.flac"},  // i=2
	{name: "../testdata/59996.flac"},  // i=3
	{name: "../testdata/80574.flac"},  // i=4
	{name: "../testdata/172960.flac"}, // i=5
	{name: "../testdata/189983.flac"}, // i=6
	{name: "../testdata/191885.flac"}, // i=7
	{name: "../testdata/212768.flac"}, // i=8
	{name: "../testdata/220014.flac"}, // i=9
	{name: "../testdata/243749.flac"}, // i=10
	{name: "../testdata/256529.flac"}, // i=11
	{name: "../testdata/257344.flac"}, // i=12
}

func TestFrameHash(t *testing.T) {
	for i, g := range golden {
		stream, err := flac.ParseFile(g.name)
		if err != nil {
			t.Fatal(err)
		}
		defer stream.Close()

		md5sum := md5.New()
		for frameNum := 0; ; frameNum++ {
			frame, err := stream.ParseNext()
			if err != nil {
				if err == io.EOF {
					break
				}
				t.Errorf("i=%d, frameNum=%d: error while parsing frame; %v", i, frameNum, err)
				continue
			}
			frame.Hash(md5sum)
		}
		want := stream.Info.MD5sum[:]
		got := md5sum.Sum(nil)
		// Verify the decoded audio samples by comparing the MD5 checksum that is
		// stored in StreamInfo with the computed one.
		if !bytes.Equal(got, want) {
			t.Errorf("i=%d: MD5 checksum mismatch for decoded audio samples; expected %32x, got %32x", i, want, got)
		}
	}
}

func BenchmarkFrameParse(b *testing.B) {
	// The file 151185.flac is a 119.5 MB public domain FLAC file used to
	// benchmark the flac library. Because of its size, it has not been included
	// in the repository, but is available for download at
	//
	//    http://freesound.org/people/jarfil/sounds/151185/
	stream, err := flac.Open("../testdata/benchmark/151185.flac")
	if err != nil {
		b.Fatal(err)
	}
	for i := 0; i < b.N; i++ {
		_, err := stream.ParseNext()
		if err != nil {
			if err == io.EOF {
				break
			}
			b.Fatal(err)
		}
	}
}
<commit_msg>frame: Test frame decoding and metadata decoding independently of each other.<commit_after>package frame_test

import (
	"bytes"
	"crypto/md5"
	"io"
	"testing"

	"gopkg.in/mewkiz/flac.v1"
)

var golden = []struct {
	name string
}{
	{name: "../testdata/love.flac"},   // i=0
	{name: "../testdata/19875.flac"},  // i=1
	{name: "../testdata/44127.flac"},  // i=2
	{name: "../testdata/59996.flac"},  // i=3
	{name: "../testdata/80574.flac"},  // i=4
	{name: "../testdata/172960.flac"}, // i=5
	{name: "../testdata/189983.flac"}, // i=6
	{name: "../testdata/191885.flac"}, // i=7
	{name: "../testdata/212768.flac"}, // i=8
	{name: "../testdata/220014.flac"}, // i=9
	{name: "../testdata/243749.flac"}, // i=10
	{name: "../testdata/256529.flac"}, // i=11
	{name: "../testdata/257344.flac"}, // i=12
}

func TestFrameHash(t *testing.T) {
	for i, g := range golden {
		stream, err := flac.Open(g.name)
		if err != nil {
			t.Fatal(err)
		}
		defer stream.Close()

		md5sum := md5.New()
		for frameNum := 0; ; frameNum++ {
			frame, err := stream.ParseNext()
			if err != nil {
				if err == io.EOF {
					break
				}
				t.Errorf("i=%d, frameNum=%d: error while parsing frame; %v", i, frameNum, err)
				continue
			}
			frame.Hash(md5sum)
		}
		want := stream.Info.MD5sum[:]
		got := md5sum.Sum(nil)
		// Verify the decoded audio samples by comparing the MD5 checksum that is
		// stored in StreamInfo with the computed one.
		if !bytes.Equal(got, want) {
			t.Errorf("i=%d: MD5 checksum mismatch for decoded audio samples; expected %32x, got %32x", i, want, got)
		}
	}
}

func BenchmarkFrameParse(b *testing.B) {
	// The file 151185.flac is a 119.5 MB public domain FLAC file used to
	// benchmark the flac library. Because of its size, it has not been included
	// in the repository, but is available for download at
	//
	//    http://freesound.org/people/jarfil/sounds/151185/
	stream, err := flac.Open("../testdata/benchmark/151185.flac")
	if err != nil {
		b.Fatal(err)
	}
	for i := 0; i < b.N; i++ {
		_, err := stream.ParseNext()
		if err != nil {
			if err == io.EOF {
				break
			}
			b.Fatal(err)
		}
	}
}
<|endoftext|>