<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 2020 Red Hat, Inc.
 *
 */

package network

import (
	"context"
	"fmt"
	"strconv"
	"time"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"

	batchv1 "k8s.io/api/batch/v1"
	k8sv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	v1 "kubevirt.io/client-go/api/v1"
	"kubevirt.io/client-go/kubecli"
	"kubevirt.io/kubevirt/tests"
	"kubevirt.io/kubevirt/tests/console"
	"kubevirt.io/kubevirt/tests/libnet"
	"kubevirt.io/kubevirt/tests/libvmi"
)

var _ = SIGDescribe("[Serial]Services", func() {
	var virtClient kubecli.KubevirtClient

	runTCPClientExpectingHelloWorldFromServer := func(host, port, namespace string, isIPv6 bool) *batchv1.Job {
		var pingCmd string
		if isIPv6 {
			pingCmd = fmt.Sprintf("ping -c1 %s;", host)
		}
		job, err := virtClient.BatchV1().Jobs(namespace).Create(context.Background(), tests.NewHelloWorldJob(host, port, pingCmd), k8smetav1.CreateOptions{})
		ExpectWithOffset(1, err).ToNot(HaveOccurred())
		return job
	}

	exposeExistingVMISpec := func(vmi *v1.VirtualMachineInstance, subdomain string, hostname string, selectorLabelKey string, selectorLabelValue string) *v1.VirtualMachineInstance {
		vmi.Labels = map[string]string{selectorLabelKey: selectorLabelValue}
		vmi.Spec.Subdomain = subdomain
		vmi.Spec.Hostname = hostname

		return vmi
	}

	readyVMI := func(vmi *v1.VirtualMachineInstance) *v1.VirtualMachineInstance {
		createdVMI, err := virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
		Expect(err).ToNot(HaveOccurred())

		return tests.WaitUntilVMIReady(createdVMI, libnet.WithIPv6(console.LoginToCirros))
	}

	cleanupVMI := func(virtClient kubecli.KubevirtClient, vmi *v1.VirtualMachineInstance) {
		By("Deleting the VMI")
		Expect(virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Delete(vmi.GetName(), &k8smetav1.DeleteOptions{})).To(Succeed())

		By("Waiting for the VMI to be gone")
		Eventually(func() error {
			_, err := virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmi.GetName(), &k8smetav1.GetOptions{})
			return err
		}, 2*time.Minute, time.Second).Should(SatisfyAll(HaveOccurred(), WithTransform(errors.IsNotFound, BeTrue())), "The VMI should be gone within the given timeout")
	}

	cleanupService := func(namespace string, serviceName string) error {
		return virtClient.CoreV1().Services(namespace).Delete(context.Background(), serviceName, k8smetav1.DeleteOptions{})
	}

	assertConnectivityToService := func(serviceName, namespace string, servicePort int, isIPv6 bool) (func() error, error) {
		serviceFQDN := fmt.Sprintf("%s.%s", serviceName, namespace)

		By(fmt.Sprintf("starting a job which tries to reach the vmi via service %s", serviceFQDN))
		job := runTCPClientExpectingHelloWorldFromServer(serviceFQDN, strconv.Itoa(servicePort), namespace, isIPv6)

		By(fmt.Sprintf("waiting for the job to report a SUCCESSFUL connection attempt to service %s on port %d", serviceFQDN, servicePort))
		err := tests.WaitForJobToSucceed(job, 90*time.Second)
		return func() error {
			return virtClient.BatchV1().Jobs(tests.NamespaceTestDefault).Delete(context.Background(), job.Name, k8smetav1.DeleteOptions{})
		}, err
	}

	assertNoConnectivityToService := func(serviceName, namespace string, servicePort int, isIPv6 bool) (func() error, error) {
		serviceFQDN := fmt.Sprintf("%s.%s", serviceName, namespace)

		By(fmt.Sprintf("starting a job which tries to reach the vmi via service %s", serviceFQDN))
		job := runTCPClientExpectingHelloWorldFromServer(serviceFQDN, strconv.Itoa(servicePort), namespace, isIPv6)

		By(fmt.Sprintf("waiting for the job to report a FAILED connection attempt to service %s on port %d", serviceFQDN, servicePort))
		err := tests.WaitForJobToFail(job, 90*time.Second)
		return func() error {
			return virtClient.BatchV1().Jobs(tests.NamespaceTestDefault).Delete(context.Background(), job.Name, k8smetav1.DeleteOptions{})
		}, err
	}

	BeforeEach(func() {
		var err error
		virtClient, err = kubecli.GetKubevirtClient()
		Expect(err).NotTo(HaveOccurred(), "Should successfully initialize an API client")
	})

	Context("bridge interface binding", func() {
		var inboundVMI *v1.VirtualMachineInstance
		var serviceName string

		const (
			selectorLabelKey   = "expose"
			selectorLabelValue = "me"
			servicePort        = 1500
		)

		createVMISpecWithBridgeInterface := func() *v1.VirtualMachineInstance {
			return libvmi.NewCirros(
				libvmi.WithInterface(libvmi.InterfaceDeviceWithBridgeBinding()),
				libvmi.WithNetwork(v1.DefaultPodNetwork()))
		}

		createReadyVMIWithBridgeBindingAndExposedService := func(hostname string, subdomain string) *v1.VirtualMachineInstance {
			return readyVMI(
				exposeExistingVMISpec(
					createVMISpecWithBridgeInterface(), subdomain, hostname, selectorLabelKey, selectorLabelValue))
		}

		BeforeEach(func() {
			subdomain := "vmi"
			hostname := "inbound"

			inboundVMI = createReadyVMIWithBridgeBindingAndExposedService(hostname, subdomain)
			tests.StartTCPServer(inboundVMI, servicePort)
		})

		AfterEach(func() {
			Expect(inboundVMI).NotTo(BeNil(), "the VMI object must exist in order to be deleted.")
			cleanupVMI(virtClient, inboundVMI)
		})

		Context("with a service matching the vmi exposed", func() {
			var jobCleanup func() error

			BeforeEach(func() {
				serviceName = "myservice"

				service := buildServiceSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
				_, err := virtClient.CoreV1().Services(inboundVMI.Namespace).Create(context.Background(), service, k8smetav1.CreateOptions{})
				Expect(err).ToNot(HaveOccurred())
			})

			AfterEach(func() {
				Expect(cleanupService(inboundVMI.GetNamespace(), serviceName)).To(Succeed(), "cleaning up the k8sv1.Service entity should have succeeded.")
			})

			AfterEach(func() {
				Expect(jobCleanup).NotTo(BeNil(), "a k8sv1.Job cleaning up function should exist")
				Expect(jobCleanup()).To(Succeed(), "cleaning up the k8sv1.Job entity should have succeeded.")
				jobCleanup = nil
			})

			It("[test_id:1547] should be able to reach the vmi based on labels specified on the vmi", func() {
				var err error

				jobCleanup, err = assertConnectivityToService(serviceName, inboundVMI.Namespace, servicePort, false)
				Expect(err).NotTo(HaveOccurred(), "connectivity is expected to the exposed service")
			})

			It("[test_id:1548] should fail to reach the vmi if an invalid servicename is used", func() {
				var err error

				jobCleanup, err = assertNoConnectivityToService("wrongservice", inboundVMI.Namespace, servicePort, false)
				Expect(err).NotTo(HaveOccurred(), "connectivity is *not* expected, since there isn't an exposed service")
			})
		})

		Context("with a subdomain and a headless service given", func() {
			var jobCleanup func() error

			BeforeEach(func() {
				serviceName = inboundVMI.Spec.Subdomain

				service := buildHeadlessServiceSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
				_, err := virtClient.CoreV1().Services(inboundVMI.Namespace).Create(context.Background(), service, k8smetav1.CreateOptions{})
				Expect(err).ToNot(HaveOccurred())
			})

			AfterEach(func() {
				Expect(virtClient.CoreV1().Services(inboundVMI.Namespace).Delete(context.Background(), serviceName, k8smetav1.DeleteOptions{})).To(Succeed())
			})

			AfterEach(func() {
				Expect(jobCleanup()).To(Succeed(), "cleaning up the k8sv1.Service entity should have succeeded.")
			})

			It("[test_id:1549]should be able to reach the vmi via its unique fully qualified domain name", func() {
				var err error
				serviceHostnameWithSubdomain := fmt.Sprintf("%s.%s", inboundVMI.Spec.Hostname, inboundVMI.Spec.Subdomain)

				jobCleanup, err = assertConnectivityToService(serviceHostnameWithSubdomain, inboundVMI.Namespace, servicePort, false)
				Expect(err).NotTo(HaveOccurred(), "connectivity is expected to the exposed service")
			})
		})
	})

	Context("Masquerade interface binding", func() {
		var inboundVMI *v1.VirtualMachineInstance

		const (
			selectorLabelKey   = "expose"
			selectorLabelValue = "me"
			servicePort        = 1500
		)

		createReadyVMIWithMasqueradeBindingAndExposedService := func(hostname string, subdomain string) *v1.VirtualMachineInstance {
			vmi := libvmi.NewCirros(
				libvmi.WithInterface(libvmi.InterfaceDeviceWithMasqueradeBinding()),
				libvmi.WithNetwork(v1.DefaultPodNetwork()))
			return readyVMI(
				exposeExistingVMISpec(vmi, subdomain, hostname, selectorLabelKey, selectorLabelValue))
		}

		BeforeEach(func() {
			subdomain := "vmi"
			hostname := "inbound"

			inboundVMI = createReadyVMIWithMasqueradeBindingAndExposedService(hostname, subdomain)
			tests.StartTCPServer(inboundVMI, servicePort)
		})

		AfterEach(func() {
			Expect(inboundVMI).NotTo(BeNil(), "the VMI object must exist in order to be deleted.")
			cleanupVMI(virtClient, inboundVMI)
		})

		Context("with a service matching the vmi exposed", func() {
			var jobCleanup func() error
			var service *k8sv1.Service

			AfterEach(func() {
				Expect(jobCleanup).NotTo(BeNil(), "a k8sv1.Job cleaning up function should exist")
				Expect(jobCleanup()).To(Succeed(), "cleaning up the k8sv1.Job entity should have succeeded.")
				jobCleanup = nil
			})

			AfterEach(func() {
				Expect(cleanupService(inboundVMI.GetNamespace(), service.Name)).To(Succeed(), "cleaning up the k8sv1.Service entity should have succeeded.")
			})

			table.DescribeTable("[Conformance] should be able to reach the vmi based on labels specified on the vmi", func(ipFamily k8sv1.IPFamily) {
				serviceName := "myservice"
				By("setting up resources to expose the VMI via a service", func() {
					if ipFamily == k8sv1.IPv6Protocol {
						libnet.SkipWhenNotDualStackCluster(virtClient)

						serviceName = serviceName + "v6"
						service = buildIPv6ServiceSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
					} else {
						service = buildServiceSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
					}

					_, err := virtClient.CoreV1().Services(inboundVMI.Namespace).Create(context.Background(), service, k8smetav1.CreateOptions{})
					Expect(err).NotTo(HaveOccurred(), "the k8sv1.Service entity should have been created.")
				})

				By("checking connectivity the the exposed service")
				var err error

				jobCleanup, err = assertConnectivityToService(serviceName, inboundVMI.Namespace, servicePort, ipFamily == k8sv1.IPv6Protocol)
				Expect(err).NotTo(HaveOccurred(), "connectivity is expected to the exposed service")
			},
				table.Entry("when the service is exposed by an IPv4 address.", k8sv1.IPv4Protocol),
				table.Entry("when the service is exposed by an IPv6 address.", k8sv1.IPv6Protocol),
			)
		})

		Context("*without* a service matching the vmi exposed", func() {
			var jobCleanup func() error
			var serviceName string

			AfterEach(func() {
				Expect(jobCleanup).NotTo(BeNil(), "a k8sv1.Job cleaning up function should exist")
				Expect(jobCleanup()).To(Succeed(), "cleaning up the k8sv1.Job entity should have succeeded.")
				jobCleanup = nil
			})

			It("should fail to reach the vmi", func() {
				var err error
				serviceName = "missingservice"

				jobCleanup, err = assertNoConnectivityToService(serviceName, inboundVMI.Namespace, servicePort, false)
				Expect(err).NotTo(HaveOccurred(), "connectivity is *not* expected, since there isn't an exposed service")
			})
		})
	})
})

func buildHeadlessServiceSpec(serviceName string, exposedPort int, portToExpose int, selectorKey string, selectorValue string) *k8sv1.Service {
	service := buildServiceSpec(serviceName, exposedPort, portToExpose, selectorKey, selectorValue)
	service.Spec.ClusterIP = k8sv1.ClusterIPNone
	return service
}

func buildIPv6ServiceSpec(serviceName string, exposedPort int, portToExpose int, selectorKey string, selectorValue string) *k8sv1.Service {
	service := buildServiceSpec(serviceName, exposedPort, portToExpose, selectorKey, selectorValue)
	ipv6Family := k8sv1.IPv6Protocol
	service.Spec.IPFamilies = []k8sv1.IPFamily{ipv6Family}

	return service
}

func buildServiceSpec(serviceName string, exposedPort int, portToExpose int, selectorKey string, selectorValue string) *k8sv1.Service {
	return &k8sv1.Service{
		ObjectMeta: k8smetav1.ObjectMeta{
			Name: serviceName,
		},
		Spec: k8sv1.ServiceSpec{
			Selector: map[string]string{
				selectorKey: selectorValue,
			},
			Ports: []k8sv1.ServicePort{
				{Protocol: k8sv1.ProtocolTCP, Port: int32(portToExpose), TargetPort: intstr.FromInt(exposedPort)},
			},
		},
	}
}
<commit_msg>Don't retry jobs that are expected to fail<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 2020 Red Hat, Inc.
 *
 */

package network

import (
	"context"
	"fmt"
	"strconv"
	"time"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"

	batchv1 "k8s.io/api/batch/v1"
	k8sv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	v1 "kubevirt.io/client-go/api/v1"
	"kubevirt.io/client-go/kubecli"
	"kubevirt.io/kubevirt/tests"
	"kubevirt.io/kubevirt/tests/console"
	"kubevirt.io/kubevirt/tests/libnet"
	"kubevirt.io/kubevirt/tests/libvmi"
)

var _ = SIGDescribe("[Serial]Services", func() {
	var virtClient kubecli.KubevirtClient

	runTCPClientExpectingHelloWorldFromServer := func(host, port, namespace string, isIPv6 bool, retries int32) *batchv1.Job {
		var pingCmd string
		if isIPv6 {
			pingCmd = fmt.Sprintf("ping -c1 %s;", host)
		}
		job := tests.NewHelloWorldJob(host, port, pingCmd)
		job.Spec.BackoffLimit = &retries
		var err error
		job, err = virtClient.BatchV1().Jobs(namespace).Create(context.Background(), job, k8smetav1.CreateOptions{})
		ExpectWithOffset(1, err).ToNot(HaveOccurred())
		return job
	}

	exposeExistingVMISpec := func(vmi *v1.VirtualMachineInstance, subdomain string, hostname string, selectorLabelKey string, selectorLabelValue string) *v1.VirtualMachineInstance {
		vmi.Labels = map[string]string{selectorLabelKey: selectorLabelValue}
		vmi.Spec.Subdomain = subdomain
		vmi.Spec.Hostname = hostname

		return vmi
	}

	readyVMI := func(vmi *v1.VirtualMachineInstance) *v1.VirtualMachineInstance {
		createdVMI, err := virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
		Expect(err).ToNot(HaveOccurred())

		return tests.WaitUntilVMIReady(createdVMI, libnet.WithIPv6(console.LoginToCirros))
	}

	cleanupVMI := func(virtClient kubecli.KubevirtClient, vmi *v1.VirtualMachineInstance) {
		By("Deleting the VMI")
		Expect(virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Delete(vmi.GetName(), &k8smetav1.DeleteOptions{})).To(Succeed())

		By("Waiting for the VMI to be gone")
		Eventually(func() error {
			_, err := virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmi.GetName(), &k8smetav1.GetOptions{})
			return err
		}, 2*time.Minute, time.Second).Should(SatisfyAll(HaveOccurred(), WithTransform(errors.IsNotFound, BeTrue())), "The VMI should be gone within the given timeout")
	}

	cleanupService := func(namespace string, serviceName string) error {
		return virtClient.CoreV1().Services(namespace).Delete(context.Background(), serviceName, k8smetav1.DeleteOptions{})
	}

	assertConnectivityToService := func(serviceName, namespace string, servicePort int, isIPv6 bool) (func() error, error) {
		serviceFQDN := fmt.Sprintf("%s.%s", serviceName, namespace)

		By(fmt.Sprintf("starting a job which tries to reach the vmi via service %s", serviceFQDN))
		job := runTCPClientExpectingHelloWorldFromServer(serviceFQDN, strconv.Itoa(servicePort), namespace, isIPv6, 3)

		By(fmt.Sprintf("waiting for the job to report a SUCCESSFUL connection attempt to service %s on port %d", serviceFQDN, servicePort))
		err := tests.WaitForJobToSucceed(job, 90*time.Second)
		return func() error {
			return virtClient.BatchV1().Jobs(tests.NamespaceTestDefault).Delete(context.Background(), job.Name, k8smetav1.DeleteOptions{})
		}, err
	}

	assertNoConnectivityToService := func(serviceName, namespace string, servicePort int, isIPv6 bool) (func() error, error) {
		serviceFQDN := fmt.Sprintf("%s.%s", serviceName, namespace)

		By(fmt.Sprintf("starting a job which tries to reach the vmi via service %s", serviceFQDN))
		job := runTCPClientExpectingHelloWorldFromServer(serviceFQDN, strconv.Itoa(servicePort), namespace, isIPv6, 0)

		By(fmt.Sprintf("waiting for the job to report a FAILED connection attempt to service %s on port %d", serviceFQDN, servicePort))
		err := tests.WaitForJobToFail(job, 90*time.Second)
		return func() error {
			return virtClient.BatchV1().Jobs(tests.NamespaceTestDefault).Delete(context.Background(), job.Name, k8smetav1.DeleteOptions{})
		}, err
	}

	BeforeEach(func() {
		var err error
		virtClient, err = kubecli.GetKubevirtClient()
		Expect(err).NotTo(HaveOccurred(), "Should successfully initialize an API client")
	})

	Context("bridge interface binding", func() {
		var inboundVMI *v1.VirtualMachineInstance
		var serviceName string

		const (
			selectorLabelKey   = "expose"
			selectorLabelValue = "me"
			servicePort        = 1500
		)

		createVMISpecWithBridgeInterface := func() *v1.VirtualMachineInstance {
			return libvmi.NewCirros(
				libvmi.WithInterface(libvmi.InterfaceDeviceWithBridgeBinding()),
				libvmi.WithNetwork(v1.DefaultPodNetwork()))
		}

		createReadyVMIWithBridgeBindingAndExposedService := func(hostname string, subdomain string) *v1.VirtualMachineInstance {
			return readyVMI(
				exposeExistingVMISpec(
					createVMISpecWithBridgeInterface(), subdomain, hostname, selectorLabelKey, selectorLabelValue))
		}

		BeforeEach(func() {
			subdomain := "vmi"
			hostname := "inbound"

			inboundVMI = createReadyVMIWithBridgeBindingAndExposedService(hostname, subdomain)
			tests.StartTCPServer(inboundVMI, servicePort)
		})

		AfterEach(func() {
			Expect(inboundVMI).NotTo(BeNil(), "the VMI object must exist in order to be deleted.")
			cleanupVMI(virtClient, inboundVMI)
		})

		Context("with a service matching the vmi exposed", func() {
			var jobCleanup func() error

			BeforeEach(func() {
				serviceName = "myservice"

				service := buildServiceSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
				_, err := virtClient.CoreV1().Services(inboundVMI.Namespace).Create(context.Background(), service, k8smetav1.CreateOptions{})
				Expect(err).ToNot(HaveOccurred())
			})

			AfterEach(func() {
				Expect(cleanupService(inboundVMI.GetNamespace(), serviceName)).To(Succeed(), "cleaning up the k8sv1.Service entity should have succeeded.")
			})

			AfterEach(func() {
				Expect(jobCleanup).NotTo(BeNil(), "a k8sv1.Job cleaning up function should exist")
				Expect(jobCleanup()).To(Succeed(), "cleaning up the k8sv1.Job entity should have succeeded.")
				jobCleanup = nil
			})

			It("[test_id:1547] should be able to reach the vmi based on labels specified on the vmi", func() {
				var err error

				jobCleanup, err = assertConnectivityToService(serviceName, inboundVMI.Namespace, servicePort, false)
				Expect(err).NotTo(HaveOccurred(), "connectivity is expected to the exposed service")
			})

			It("[test_id:1548] should fail to reach the vmi if an invalid servicename is used", func() {
				var err error

				jobCleanup, err = assertNoConnectivityToService("wrongservice", inboundVMI.Namespace, servicePort, false)
				Expect(err).NotTo(HaveOccurred(), "connectivity is *not* expected, since there isn't an exposed service")
			})
		})

		Context("with a subdomain and a headless service given", func() {
			var jobCleanup func() error

			BeforeEach(func() {
				serviceName = inboundVMI.Spec.Subdomain

				service := buildHeadlessServiceSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
				_, err := virtClient.CoreV1().Services(inboundVMI.Namespace).Create(context.Background(), service, k8smetav1.CreateOptions{})
				Expect(err).ToNot(HaveOccurred())
			})

			AfterEach(func() {
				Expect(virtClient.CoreV1().Services(inboundVMI.Namespace).Delete(context.Background(), serviceName, k8smetav1.DeleteOptions{})).To(Succeed())
			})

			AfterEach(func() {
				Expect(jobCleanup()).To(Succeed(), "cleaning up the k8sv1.Service entity should have succeeded.")
			})

			It("[test_id:1549]should be able to reach the vmi via its unique fully qualified domain name", func() {
				var err error
				serviceHostnameWithSubdomain := fmt.Sprintf("%s.%s", inboundVMI.Spec.Hostname, inboundVMI.Spec.Subdomain)

				jobCleanup, err = assertConnectivityToService(serviceHostnameWithSubdomain, inboundVMI.Namespace, servicePort, false)
				Expect(err).NotTo(HaveOccurred(), "connectivity is expected to the exposed service")
			})
		})
	})

	Context("Masquerade interface binding", func() {
		var inboundVMI *v1.VirtualMachineInstance

		const (
			selectorLabelKey   = "expose"
			selectorLabelValue = "me"
			servicePort        = 1500
		)

		createReadyVMIWithMasqueradeBindingAndExposedService := func(hostname string, subdomain string) *v1.VirtualMachineInstance {
			vmi := libvmi.NewCirros(
				libvmi.WithInterface(libvmi.InterfaceDeviceWithMasqueradeBinding()),
				libvmi.WithNetwork(v1.DefaultPodNetwork()))
			return readyVMI(
				exposeExistingVMISpec(vmi, subdomain, hostname, selectorLabelKey, selectorLabelValue))
		}

		BeforeEach(func() {
			subdomain := "vmi"
			hostname := "inbound"

			inboundVMI = createReadyVMIWithMasqueradeBindingAndExposedService(hostname, subdomain)
			tests.StartTCPServer(inboundVMI, servicePort)
		})

		AfterEach(func() {
			Expect(inboundVMI).NotTo(BeNil(), "the VMI object must exist in order to be deleted.")
			cleanupVMI(virtClient, inboundVMI)
		})

		Context("with a service matching the vmi exposed", func() {
			var jobCleanup func() error
			var service *k8sv1.Service

			AfterEach(func() {
				Expect(jobCleanup).NotTo(BeNil(), "a k8sv1.Job cleaning up function should exist")
				Expect(jobCleanup()).To(Succeed(), "cleaning up the k8sv1.Job entity should have succeeded.")
				jobCleanup = nil
			})

			AfterEach(func() {
				Expect(cleanupService(inboundVMI.GetNamespace(), service.Name)).To(Succeed(), "cleaning up the k8sv1.Service entity should have succeeded.")
			})

			table.DescribeTable("[Conformance] should be able to reach the vmi based on labels specified on the vmi", func(ipFamily k8sv1.IPFamily) {
				serviceName := "myservice"
				By("setting up resources to expose the VMI via a service", func() {
					if ipFamily == k8sv1.IPv6Protocol {
						libnet.SkipWhenNotDualStackCluster(virtClient)

						serviceName = serviceName + "v6"
						service = buildIPv6ServiceSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
					} else {
						service = buildServiceSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
					}

					_, err := virtClient.CoreV1().Services(inboundVMI.Namespace).Create(context.Background(), service, k8smetav1.CreateOptions{})
					Expect(err).NotTo(HaveOccurred(), "the k8sv1.Service entity should have been created.")
				})

				By("checking connectivity the the exposed service")
				var err error

				jobCleanup, err = assertConnectivityToService(serviceName, inboundVMI.Namespace, servicePort, ipFamily == k8sv1.IPv6Protocol)
				Expect(err).NotTo(HaveOccurred(), "connectivity is expected to the exposed service")
			},
				table.Entry("when the service is exposed by an IPv4 address.", k8sv1.IPv4Protocol),
				table.Entry("when the service is exposed by an IPv6 address.", k8sv1.IPv6Protocol),
			)
		})

		Context("*without* a service matching the vmi exposed", func() {
			var jobCleanup func() error
			var serviceName string

			AfterEach(func() {
				Expect(jobCleanup).NotTo(BeNil(), "a k8sv1.Job cleaning up function should exist")
				Expect(jobCleanup()).To(Succeed(), "cleaning up the k8sv1.Job entity should have succeeded.")
				jobCleanup = nil
			})

			It("should fail to reach the vmi", func() {
				var err error
				serviceName = "missingservice"

				jobCleanup, err = assertNoConnectivityToService(serviceName, inboundVMI.Namespace, servicePort, false)
				Expect(err).NotTo(HaveOccurred(), "connectivity is *not* expected, since there isn't an exposed service")
			})
		})
	})
})

func buildHeadlessServiceSpec(serviceName string, exposedPort int, portToExpose int, selectorKey string, selectorValue string) *k8sv1.Service {
	service := buildServiceSpec(serviceName, exposedPort, portToExpose, selectorKey, selectorValue)
	service.Spec.ClusterIP = k8sv1.ClusterIPNone
	return service
}

func buildIPv6ServiceSpec(serviceName string, exposedPort int, portToExpose int, selectorKey string, selectorValue string) *k8sv1.Service {
	service := buildServiceSpec(serviceName, exposedPort, portToExpose, selectorKey, selectorValue)
	ipv6Family := k8sv1.IPv6Protocol
	service.Spec.IPFamilies = []k8sv1.IPFamily{ipv6Family}

	return service
}

func buildServiceSpec(serviceName string, exposedPort int, portToExpose int, selectorKey string, selectorValue string) *k8sv1.Service {
	return &k8sv1.Service{
		ObjectMeta: k8smetav1.ObjectMeta{
			Name: serviceName,
		},
		Spec: k8sv1.ServiceSpec{
			Selector: map[string]string{
				selectorKey: selectorValue,
			},
			Ports: []k8sv1.ServicePort{
				{Protocol: k8sv1.ProtocolTCP, Port: int32(portToExpose), TargetPort: intstr.FromInt(exposedPort)},
			},
		},
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"net"
	"strconv"
)

func startServer(listenPort int, backends *Backends) {
	port := strconv.Itoa(listenPort)
	fmt.Println("Starting server on port ", port)

	addr, _ := net.ResolveTCPAddr("tcp", ":"+port)

	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		fmt.Println("Could not listen on port because:", err.Error())
		return
	}

	for {
		con, err := listener.Accept()
		if err != nil {
			fmt.Println("Error occured accepting a connection", err.Error())
		}

		go handleConnection(con, backends.NextAddress())
	}

}

func handleConnection(cli_conn net.Conn, srv_addr string) {
	srv_conn, err := net.Dial("tcp", srv_addr)
	if err != nil {
		fmt.Printf("Could not connect to server (%s), connection dropping\n", srv_addr)
		return
	}

	go io.Copy(cli_conn, srv_conn)
	io.Copy(srv_conn, cli_conn)
	srv_conn.Close()
	cli_conn.Close()
}
<commit_msg>Print format fix<commit_after>package main

import (
	"fmt"
	"io"
	"net"
	"strconv"
)

func startServer(listenPort int, backends *Backends) {
	port := strconv.Itoa(listenPort)
	fmt.Println("Starting server on port ", port)

	addr, _ := net.ResolveTCPAddr("tcp", ":"+port)

	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		fmt.Println("Could not listen on port because:", err.Error())
		return
	}

	for {
		con, err := listener.Accept()
		if err != nil {
			fmt.Println("Error occured accepting a connection", err.Error())
		}

		go handleConnection(con, backends.NextAddress())
	}

}

func handleConnection(cli_conn net.Conn, srv_addr string) {
	srv_conn, err := net.Dial("tcp", srv_addr)
	if err != nil {
		fmt.Sprintf("Could not connect to server (%q), connection dropping\n", srv_addr)
		return
	}

	go io.Copy(cli_conn, srv_conn)
	io.Copy(srv_conn, cli_conn)
	srv_conn.Close()
	cli_conn.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"regexp"

	"github.com/cep21/xdgbasedir"
	"gopkg.in/yaml.v1"
)

func main() {
	lf := NewLocalFiles("")
	Main(os.Args, os.Stdout, os.Stderr, &lf)
}

// The programs usage help.
var Usage = `dwi.

Usage:
	dwi <file>
`

// FileIndex provides methods for manipulating a list of files.
type FileIndex interface {
	Exists(filename string) bool
	Open(filename string) (*os.File, error)
}

// LocalFiles is a FileIndex for files in the local filesystem.
type LocalFiles struct {
	Root string
}

// Exists returns true if a file given by path exists.
func (lf *LocalFiles) Exists(filename string) bool {
	if _, err := os.Stat(lf.getFullPath(filename)); err != nil {
		return false
	}
	return true
}

// Open opens a file or returns an error.
func (lf *LocalFiles) Open(filename string) (*os.File, error) {
	return os.Open(filename)
}

// GetFullPath returns the full path.
func (lf *LocalFiles) getFullPath(filename string) string {
	return path.Join(lf.Root, filename)
}

// NewLocalFiles creates and initializes a new LocalFiles with a given path root.
func NewLocalFiles(root string) LocalFiles {
	return LocalFiles{root}
}

// Main function.
func Main(args []string, out io.Writer, eout io.Writer, fi FileIndex) {
	if len(args) < 2 {
		fmt.Fprintln(out, Usage)
		return
	}

	files := ParseArgs(args)
	if AnyFilesDontExist(eout, fi, files) {
		return
	}

	configDir, err := xdgbasedir.ConfigHomeDirectory()
	if err != nil {
		return
	}

	rules := LoadRules(path.Join(configDir, "/dealwithit/rules.yaml"), fi, eout)

	ForEachMatchingFile(files, rules, eout, fi)
}

// AnyFilesDontExist will look for each of the given files in the given FileIndex,
// output an error to eout for any file that doesn't exist and return true if where any missing.
func AnyFilesDontExist(eout io.Writer, fi FileIndex, files []string) bool {
	err := false
	for _, f := range files {
		if !fi.Exists(f) {
			fmt.Fprintln(eout, "Error: File not found:", f)
			err = true
		}
	}
	return err
}

// ParseArgs takes a list of args and returns the list of files.
// The first arg must be the executable name.
func ParseArgs(args []string) []string {
	return args[1:]
}

type Rule map[string]string
type Rules []Rule

// LoadRules loads the rules file given by filename from the given FileIndex.
func LoadRules(filename string, fi FileIndex, eout io.Writer) Rules {
	var rules Rules

	file, err := fi.Open(filename)
	if err != nil {
		fmt.Fprintln(eout, "Error: Could not open rules file", filename, err)
		return rules
	}

	data, err := ioutil.ReadAll(file)
	if err != nil {
		fmt.Fprintln(eout, "Error: Could not read rules file", filename, err)
		return rules
	}

	rules = ParseRules(data, eout)
	return rules
}

// ParseRules parses the YAML.
func ParseRules(data []byte, eout io.Writer) Rules {
	var rules Rules
	err := yaml.Unmarshal(data, &rules)
	if err != nil {
		fmt.Fprintln(eout, "Error: Could not parse rules file", err)
		return rules
	}

	return rules
}

// ForEachMatchingFile executes a function on each file if the function match returns true.
func ForEachMatchingFile(files []string, rules Rules, eout io.Writer, fi FileIndex) {
	for _, f := range files {
		matches, rule := FileMatchesRules(f, rules, eout, fi)

		if !matches {
			continue
		}

		ExecuteRule(f, rule, fi)

	}
}

// FileMatchesRules if filename matches a rule given in rules returns true and the rule.
func FileMatchesRules(filename string, rules Rules, eout io.Writer, fi FileIndex) (bool, Rule) {
	for _, rule := range rules {
		if FileMatchesRule(filename, rule, eout) {
			return true, rule
		}
	}
	return false, nil
}

// FileMatchesRule return true if filename matches the rule given.
func FileMatchesRule(filename string, rule Rule, eout io.Writer) bool {
	re, err := regexp.Compile(rule["file"])
	if err != nil {
		fmt.Fprintln(eout, "Error: Could not compile regexp", err)
		return false
	}
	return re.MatchString(filename)
}

// ExecuteRule executes the given rules on file.
func ExecuteRule(filename string, rule Rule, fi FileIndex) {
	fmt.Println("DEBUG: ", filename, "matches", rule)
}
<commit_msg>Output mv command.<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"regexp"

	"github.com/cep21/xdgbasedir"
	"gopkg.in/yaml.v1"
)

func main() {
	lf := NewLocalFiles("")
	Main(os.Args, os.Stdout, os.Stderr, &lf)
}

// The programs usage help.
var Usage = `dwi.

Usage:
	dwi <file>
`

// FileIndex provides methods for manipulating a list of files.
type FileIndex interface {
	Exists(filename string) bool
	Open(filename string) (*os.File, error)
}

// LocalFiles is a FileIndex for files in the local filesystem.
type LocalFiles struct {
	Root string
}

// Exists returns true if a file given by path exists.
func (lf *LocalFiles) Exists(filename string) bool {
	if _, err := os.Stat(lf.getFullPath(filename)); err != nil {
		return false
	}
	return true
}

// Open opens a file or returns an error.
func (lf *LocalFiles) Open(filename string) (*os.File, error) {
	return os.Open(filename)
}

// GetFullPath returns the full path.
func (lf *LocalFiles) getFullPath(filename string) string {
	return path.Join(lf.Root, filename)
}

// NewLocalFiles creates and initializes a new LocalFiles with a given path root.
func NewLocalFiles(root string) LocalFiles {
	return LocalFiles{root}
}

// Main function.
func Main(args []string, out io.Writer, eout io.Writer, fi FileIndex) {
	if len(args) < 2 {
		fmt.Fprintln(out, Usage)
		return
	}

	files := ParseArgs(args)
	if AnyFilesDontExist(eout, fi, files) {
		return
	}

	configDir, err := xdgbasedir.ConfigHomeDirectory()
	if err != nil {
		return
	}

	rules := LoadRules(path.Join(configDir, "/dealwithit/rules.yaml"), fi, eout)

	ForEachMatchingFile(files, rules, out, eout, fi)
}

// AnyFilesDontExist will look for each of the given files in the given FileIndex,
// output an error to eout for any file that doesn't exist and return true if where any missing.
func AnyFilesDontExist(eout io.Writer, fi FileIndex, files []string) bool {
	err := false
	for _, f := range files {
		if !fi.Exists(f) {
			fmt.Fprintln(eout, "Error: File not found:", f)
			err = true
		}
	}
	return err
}

// ParseArgs takes a list of args and returns the list of files.
// The first arg must be the executable name.
func ParseArgs(args []string) []string {
	return args[1:]
}

type Rule map[string]string
type Rules []Rule

// LoadRules loads the rules file given by filename from the given FileIndex.
func LoadRules(filename string, fi FileIndex, eout io.Writer) Rules {
	var rules Rules

	file, err := fi.Open(filename)
	if err != nil {
		fmt.Fprintln(eout, "Error: Could not open rules file", filename, err)
		return rules
	}

	data, err := ioutil.ReadAll(file)
	if err != nil {
		fmt.Fprintln(eout, "Error: Could not read rules file", filename, err)
		return rules
	}

	rules = ParseRules(data, eout)
	return rules
}

// ParseRules parses the YAML.
func ParseRules(data []byte, eout io.Writer) Rules {
	var rules Rules
	err := yaml.Unmarshal(data, &rules)
	if err != nil {
		fmt.Fprintln(eout, "Error: Could not parse rules file", err)
		return rules
	}

	return rules
}

// ForEachMatchingFile executes a function on each file if the function match returns true.
func ForEachMatchingFile(files []string, rules Rules, out io.Writer, eout io.Writer, fi FileIndex) {
	for _, f := range files {
		matches, rule := FileMatchesRules(f, rules, eout, fi)

		if !matches {
			continue
		}

		ExecuteRule(f, rule, out, fi)

	}
}

// FileMatchesRules if filename matches a rule given in rules returns true and the rule.
func FileMatchesRules(filename string, rules Rules, eout io.Writer, fi FileIndex) (bool, Rule) {
	for _, rule := range rules {
		if FileMatchesRule(filename, rule, eout) {
			return true, rule
		}
	}
	return false, nil
}

// FileMatchesRule return true if filename matches the rule given.
func FileMatchesRule(filename string, rule Rule, eout io.Writer) bool {
	re, err := regexp.Compile(rule["file"])
	if err != nil {
		fmt.Fprintln(eout, "Error: Could not compile regexp", err)
		return false
	}
	return re.MatchString(filename)
}

// ExecuteRule executes the given rules on file.
func ExecuteRule(filename string, rule Rule, out io.Writer, fi FileIndex) {
	// [TODO]: Check destination exists and is a directory. - 2014-12-21 12:09pm
	fmt.Fprintf(out, "mv -v \"%s\" \"%s\"\n", filename, rule["move"])
}
<|endoftext|>


<commit_before>package filter

import (
	"github.com/200sc/klangsynthese/audio"
	"github.com/200sc/klangsynthese/audio/filter/supports"
)

// Encoding filters are functions on any combination of the values
// in an audio.Encoding
type Encoding func(supports.Encoding)

// Apply checks that the given audio supports Encoding, filters if it
// can, then returns
func (enc Encoding) Apply(a audio.Audio) (audio.Audio, error) {
	if senc, ok := a.(supports.Encoding); ok {
		enc(senc)
		return a, nil
	}
	return a, supports.NewUnsupported([]string{"Encoding"})
}

// LeftPan filters audio to only play on the left speaker
func LeftPan() Encoding {
	return func(enc supports.Encoding) {
		data := enc.GetData()
		// Right/Left only makes sense for 2 channel
		if *enc.GetChannels() != 2 {
			return
		}
		// Zero out one channel
		swtch := int((*enc.GetBitDepth()) / 8)
		d := *data
		for i := 0; i < len(d); i += (2 * swtch) {
			for j := 0; j < swtch; j++ {
				d[i+j] = byte((int(d[i+j]) + int(d[i+j+swtch])) / 2)
				d[i+j+swtch] = 0
			}
		}
		*data = d
	}
}

// RightPan filters audio to only play on the right speaker
func RightPan() Encoding {
	return func(enc supports.Encoding) {
		data := enc.GetData()
		// Right/Left only makes sense for 2 channel
		if *enc.GetChannels() != 2 {
			return
		}
		// Zero out one channel
		swtch := int((*enc.GetBitDepth()) / 8)
		d := *data
		for i := 0; i < len(d); i += (2 * swtch) {
			for j := 0; j < swtch; j++ {
				d[i+j+swtch] = byte((int(d[i+j]) + int(d[i+j+swtch])) / 2)
				d[i+j] = 0
			}
		}
		*data = d
	}
}

// Pan takes -1 <= f <= 1.
// An f of -1 represents a full pan to the left, a pan of 1 represents
// a full pan to the right.
func Pan(f float64) Encoding {
	// Todo: test this is accurate
	if f > 0 {
		return VolumeBalance(1-f, 1)
	} else if f < 0 {
		return VolumeBalance(1, 1-(-1*f))
	} else {
		return func(enc supports.Encoding) {
			data := enc.GetData()
			// Right/Left only makes sense for 2 channel
			if *enc.GetChannels() != 2 {
				return
			}
			// Zero out one channel
			swtch := int((*enc.GetBitDepth()) / 8)
			d := *data
			for i := 0; i < len(d); i += (2 * swtch) {
				for j := 0; j < swtch; j++ {
					v := byte((int(d[i+j]) + int(d[i+j+swtch])) / 2)
					d[i+j+swtch] = v
					d[i+j] = v
				}
			}
			*data = d
		}
	}
}

// Volume will magnify the data by mult, increasing or reducing the volume
// of the output sound. For mult <= 1 this should have no unexpected behavior,
// although for mult ~= 1 it might not have any effect. More importantly for
// mult > 1, values may result in the output data clipping over integer overflows,
// which is presumably not desired behavior.
func Volume(mult float64) Encoding {
	return func(enc supports.Encoding) {
		data := enc.GetData()
		d := *data
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := 0; i < len(d); i += byteDepth {
				var v int16
				var shift uint16
				for j := 0; j < byteDepth; j++ {
					v += int16(d[i+j]) << shift
					shift += 8
				}
				v3 := round(float64(v) * mult)
				for j := 0; j < byteDepth; j++ {
					d[i+j] = byte(v3 & 255)
					v3 >>= 8
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = d
	}
}

// VolumeBalance will filter audio on two channels such that the left channel
// is (l+r)/2 * lMult, and the right channel is (l+r)/2 * rMult
func VolumeBalance(lMult, rMult float64) Encoding {
	return func(enc supports.Encoding) {
		if *enc.GetChannels() != 2 {
			return
		}
		data := enc.GetData()
		d := *data
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := 0; i < len(d); i += (byteDepth * 2) {
				var v int16
				var shift uint16
				for j := 0; j < byteDepth; j++ {
					v += int16(int(d[i+j])+int(d[i+j+byteDepth])) / 2 << shift
					shift += 8
				}
				l := round(float64(v) * lMult)
				r := round(float64(v) * rMult)
				for j := 0; j < byteDepth; j++ {
					d[i+j] = byte(l & 255)
					d[i+j+byteDepth] = byte(r & 255)
					l >>= 8
					r >>= 8
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = d
	}
}

// VolumeLeft acts like volume but reduces left channel volume only
func VolumeLeft(mult float64) Encoding {
	return func(enc supports.Encoding) {
		// Right/Left only makes sense for 2 channel
		if *enc.GetChannels() != 2 {
			return
		}
		data := enc.GetData()
		d := *data
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := 0; i < len(d); i += (byteDepth * 2) {
				var v int16
				var shift uint16
				for j := 0; j < byteDepth; j++ {
					v += int16(d[i+j]) << shift
					shift += 8
				}
				v3 := round(float64(v) * mult)
				for j := 0; j < byteDepth; j++ {
					d[i+j] = byte(v3 & 255)
					v3 >>= 8
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = d
	}
}

// VolumeRight acts like volume but reduces left channel volume only
func VolumeRight(mult float64) Encoding {
	return func(enc supports.Encoding) {
		// Right/Left only makes sense for 2 channel
		if *enc.GetChannels() != 2 {
			return
		}
		data := enc.GetData()
		d := *data
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := byteDepth; i < len(d); i += (byteDepth * 2) {

				var v int16
				var shift uint16
				for j := 0; j < byteDepth; j++ {
					v += int16(d[i+j]) << shift
					shift += 8
				}
				v3 := round(float64(v) * mult)
				for j := 0; j < byteDepth; j++ {
					d[i+j] = byte(v3 & 255)
					v3 >>= 8
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = d
	}
}

// AssertStereo does nothing to audio that has two channels, but will convert
// mono audio to two-channeled audio with the same data on both channels
func AssertStereo() Encoding {
	return func(enc supports.Encoding) {
		chs := enc.GetChannels()
		if *chs > 1 {
			// We can't really do this for non-mono audio
			return
		}
		*chs = 2
		data := enc.GetData()
		d := *data
		newData := make([]byte, len(d)*2)
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := 0; i < len(d); i += 2 {
				for j := 0; j < byteDepth; j++ {
					newData[i*2+j] = d[i+j]
					newData[i*2+j+byteDepth] = d[i+j]
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = newData
	}
}

func round(f float64) int64 {
	if f < 0 {
		return int64(f - .5)
	}
	return int64(f + .5)
}
<commit_msg>Stereo does not care about byte depth<commit_after>package filter

import (
	"github.com/200sc/klangsynthese/audio"
	"github.com/200sc/klangsynthese/audio/filter/supports"
)

// Encoding filters are functions on any combination of the values
// in an audio.Encoding
type Encoding func(supports.Encoding)

// Apply checks that the given audio supports Encoding, filters if it
// can, then returns
func (enc Encoding) Apply(a audio.Audio) (audio.Audio, error) {
	if senc, ok := a.(supports.Encoding); ok {
		enc(senc)
		return a, nil
	}
	return a, supports.NewUnsupported([]string{"Encoding"})
}

// LeftPan filters audio to only play on the left speaker
func LeftPan() Encoding {
	return func(enc supports.Encoding) {
		data := enc.GetData()
		// Right/Left only makes sense for 2 channel
		if *enc.GetChannels() != 2 {
			return
		}
		// Zero out one channel
		swtch := int((*enc.GetBitDepth()) / 8)
		d := *data
		for i := 0; i < len(d); i += (2 * swtch) {
			for j := 0; j < swtch; j++ {
				d[i+j] = byte((int(d[i+j]) + int(d[i+j+swtch])) / 2)
				d[i+j+swtch] = 0
			}
		}
		*data = d
	}
}

// RightPan filters audio to only play on the right speaker
func RightPan() Encoding {
	return func(enc supports.Encoding) {
		data := enc.GetData()
		// Right/Left only makes sense for 2 channel
		if *enc.GetChannels() != 2 {
			return
		}
		// Zero out one channel
		swtch := int((*enc.GetBitDepth()) / 8)
		d := *data
		for i := 0; i < len(d); i += (2 * swtch) {
			for j := 0; j < swtch; j++ {
				d[i+j+swtch] = byte((int(d[i+j]) + int(d[i+j+swtch])) / 2)
				d[i+j] = 0
			}
		}
		*data = d
	}
}

// Pan takes -1 <= f <= 1.
// An f of -1 represents a full pan to the left, a pan of 1 represents
// a full pan to the right.
func Pan(f float64) Encoding {
	// Todo: test this is accurate
	if f > 0 {
		return VolumeBalance(1-f, 1)
	} else if f < 0 {
		return VolumeBalance(1, 1-(-1*f))
	} else {
		return func(enc supports.Encoding) {
			data := enc.GetData()
			// Right/Left only makes sense for 2 channel
			if *enc.GetChannels() != 2 {
				return
			}
			// Zero out one channel
			swtch := int((*enc.GetBitDepth()) / 8)
			d := *data
			for i := 0; i < len(d); i += (2 * swtch) {
				for j := 0; j < swtch; j++ {
					v := byte((int(d[i+j]) + int(d[i+j+swtch])) / 2)
					d[i+j+swtch] = v
					d[i+j] = v
				}
			}
			*data = d
		}
	}
}

// Volume will magnify the data by mult, increasing or reducing the volume
// of the output sound. For mult <= 1 this should have no unexpected behavior,
// although for mult ~= 1 it might not have any effect. More importantly for
// mult > 1, values may result in the output data clipping over integer overflows,
// which is presumably not desired behavior.
func Volume(mult float64) Encoding {
	return func(enc supports.Encoding) {
		data := enc.GetData()
		d := *data
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := 0; i < len(d); i += byteDepth {
				var v int16
				var shift uint16
				for j := 0; j < byteDepth; j++ {
					v += int16(d[i+j]) << shift
					shift += 8
				}
				v3 := round(float64(v) * mult)
				for j := 0; j < byteDepth; j++ {
					d[i+j] = byte(v3 & 255)
					v3 >>= 8
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = d
	}
}

// VolumeBalance will filter audio on two channels such that the left channel
// is (l+r)/2 * lMult, and the right channel is (l+r)/2 * rMult
func VolumeBalance(lMult, rMult float64) Encoding {
	return func(enc supports.Encoding) {
		if *enc.GetChannels() != 2 {
			return
		}
		data := enc.GetData()
		d := *data
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := 0; i < len(d); i += (byteDepth * 2) {
				var v int16
				var shift uint16
				for j := 0; j < byteDepth; j++ {
					v += int16(int(d[i+j])+int(d[i+j+byteDepth])) / 2 << shift
					shift += 8
				}
				l := round(float64(v) * lMult)
				r := round(float64(v) * rMult)
				for j := 0; j < byteDepth; j++ {
					d[i+j] = byte(l & 255)
					d[i+j+byteDepth] = byte(r & 255)
					l >>= 8
					r >>= 8
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = d
	}
}

// VolumeLeft acts like volume but reduces left channel volume only
func VolumeLeft(mult float64) Encoding {
	return func(enc supports.Encoding) {
		// Right/Left only makes sense for 2 channel
		if *enc.GetChannels() != 2 {
			return
		}
		data := enc.GetData()
		d := *data
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := 0; i < len(d); i += (byteDepth * 2) {
				var v int16
				var shift uint16
				for j := 0; j < byteDepth; j++ {
					v += int16(d[i+j]) << shift
					shift += 8
				}
				v3 := round(float64(v) * mult)
				for j := 0; j < byteDepth; j++ {
					d[i+j] = byte(v3 & 255)
					v3 >>= 8
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = d
	}
}

// VolumeRight acts like volume but reduces left channel volume only
func VolumeRight(mult float64) Encoding {
	return func(enc supports.Encoding) {
		// Right/Left only makes sense for 2 channel
		if *enc.GetChannels() != 2 {
			return
		}
		data := enc.GetData()
		d := *data
		byteDepth := int(*enc.GetBitDepth() / 8)
		switch byteDepth {
		case 2:
			for i := byteDepth; i < len(d); i += (byteDepth * 2) {

				var v int16
				var shift uint16
				for j := 0; j < byteDepth; j++ {
					v += int16(d[i+j]) << shift
					shift += 8
				}
				v3 := round(float64(v) * mult)
				for j := 0; j < byteDepth; j++ {
					d[i+j] = byte(v3 & 255)
					v3 >>= 8
				}
			}
		default:
			// log unsupported bit depth
			// 2 4 and 8 should also be supported, as int8 int32 and int64
		}
		*data = d
	}
}

// AssertStereo does nothing to audio that has two channels, but will convert
// mono audio to two-channeled audio with the same data on both channels
func AssertStereo() Encoding {
	return func(enc supports.Encoding) {
		chs := enc.GetChannels()
		if *chs > 1 {
			// We can't really do this for non-mono audio
			return
		}
		*chs = 2
		data := enc.GetData()
		d := *data
		newData := make([]byte, len(d)*2)
		byteDepth := int(*enc.GetBitDepth() / 8)
		for i := 0; i < len(d); i += 2 {
			for j := 0; j < byteDepth; j++ {
				newData[i*2+j] = d[i+j]
				newData[i*2+j+byteDepth] = d[i+j]
			}
		}
		*data = newData
	}
}

func round(f float64) int64 {
	if f < 0 {
		return int64(f - .5)
	}
	return int64(f + .5)
}
<|endoftext|>


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

package mdns

import "bytes"
import "fmt"
import "log"
import "math"
import "math/rand"
import "net"
import "time"

import "code.google.com/p/go.net/ipv4"

func NewServer(addr string, maddr string) (*net.UDPAddr, *ipv4.PacketConn, error) {
	saddr, err := net.ResolveUDPAddr("udp", addr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not resolve address '%s': %s", addr, err);
	}

	smaddr, err := net.ResolveUDPAddr("udp", maddr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not resolve address '%s': %s", maddr, err);
	}

	udp, err := net.ListenUDP("udp", saddr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not listen: %s", err);
	}

	p := ipv4.NewPacketConn(udp);
	if err := p.JoinGroup(nil, smaddr); err != nil {
		return nil, nil, fmt.Errorf("Could not join group: %s", err);
	}

	err = p.SetTTL(1);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set TTL: %s", err);
	}

	err = p.SetMulticastLoopback(false);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set loop: %s", err);
	}

	err = p.SetControlMessage(ipv4.FlagInterface, true);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set ctrlmsg: %s", err);
	}

	return smaddr, p, nil;
}

func NewClient(addr string, maddr string) (*net.UDPAddr, *ipv4.PacketConn, error) {
	saddr, err := net.ResolveUDPAddr("udp", addr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not resolve address '%s': %s", addr, err);
	}

	smaddr, err := net.ResolveUDPAddr("udp", maddr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not resolve address '%s': %s", maddr, err);
	}

	udp, err := net.ListenUDP("udp", saddr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not listen: %s", err);
	}

	p := ipv4.NewPacketConn(udp);

	err = p.SetMulticastLoopback(false);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set loop: %s", err);
	}

	err = p.SetControlMessage(ipv4.FlagInterface, true);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set ctrlmsg: %s", err);
	}

	return smaddr, p, nil;
}

func MakeResponse(client *net.UDPAddr, req *Message) (*Message) {
	rsp := new(Message);

	rsp.Header.Flags |= FlagQR;
	rsp.Header.Flags |= FlagAA;

	if req.Header.Flags & FlagRD != 0 {
		rsp.Header.Flags |= FlagRD;
		rsp.Header.Flags |= FlagRA;
	}

	if client.Port != 5353 {
		rsp.Header.Id = req.Header.Id;
	}

	return rsp;
}

func Read(p *ipv4.PacketConn) (*Message, *net.IPNet, *net.IPNet, *net.UDPAddr, error) {
	var local4 *net.IPNet;
	var local6 *net.IPNet;

	pkt := make([]byte, 65536);

	n, cm, from, err := p.ReadFrom(pkt);
	if err != nil {
		return nil, nil, nil, nil,
		  fmt.Errorf("Could not read: %s", err);
	}

	ifi, err := net.InterfaceByIndex(cm.IfIndex);
	if err != nil {
		return nil, nil, nil, nil,
		    fmt.Errorf("Could not find if: %s", err);
	}

	addrs, err := ifi.Addrs();
	if err != nil {
		return nil, nil, nil, nil,
		  fmt.Errorf("Could not find addrs: %s", err);
	}

	for _, a := range addrs {
		if a.(*net.IPNet).IP.To4() != nil {
			local4 = a.(*net.IPNet);
		} else {
			local6 = a.(*net.IPNet);
		}
	}

	req, err := Unpack(pkt[:n]);
	if err != nil {
		return nil, nil, nil, nil,
		  fmt.Errorf("Could not unpack request: %s", err);
	}

	return req, local4, local6, from.(*net.UDPAddr), err;
}

func Write(p *ipv4.PacketConn, addr *net.UDPAddr, msg *Message) (error) {
	pkt, err := Pack(msg);
	if err != nil {
		return fmt.Errorf("Could not pack response: %s", err);
	}

	_, err = p.WriteTo(pkt, nil, addr);
	if err != nil {
		return fmt.Errorf("Could not write to network: %s", err);
	}

	return nil;
}

func SendRequest(req *Message) (*Message, error) {
	maddr, client, err := NewClient("0.0.0.0:0", "224.0.0.251:5353");
	if err != nil {
		return nil, fmt.Errorf("Could not create client: %s", err);
	}
	defer client.Close();

	seconds := 3 * time.Second;
	timeout := time.Now().Add(seconds);

	err = Write(client, maddr, req);
	if err != nil {
		return nil, fmt.Errorf("Could not send request: %s", err);
	}

	client.SetReadDeadline(timeout);

	rsp, _, _, _, err := Read(client);
	if err != nil {
		return nil, fmt.Errorf("Could not read response: %s", err);
	}

	if rsp.Header.Id != req.Header.Id {
		return nil, fmt.Errorf("Wrong id: %d", rsp.Header.Id);
	}

	return rsp, nil;
}

func Serve(p *ipv4.PacketConn, maddr *net.UDPAddr, localname string, silent, forward bool) {
	var sent_id uint16;

	for {
		req, local4, local6, client, err := Read(p);
		if err != nil {
			if silent != true {
				log.Println("Error reading request: ", err);
				continue;
			}
		}

		if req.Header.Flags & FlagQR != 0 {
			continue;
		}

		if sent_id > 0 && req.Header.Id == sent_id {
			continue;
		}

		rsp := MakeResponse(client, req);

		for _, q := range req.Question {
			if client.Port != 5353 {
				rsp.Question = append(rsp.Question, q);
				rsp.Header.QDCount++;
			}

			if string(q.Name) != localname {
				if forward != false {
					sent_id, _ = MakeRecursive(q, rsp);
				}

				continue;
			}

			switch (q.Type) {
				case TypeA:
					an := NewA(local4.IP);
					rsp.AppendAN(q, an);

				case TypeAAAA:
					an := NewAAAA(local6.IP);
					rsp.AppendAN(q, an);

				default:
					continue;
			}
		}

		if rsp.Header.ANCount == 0 &&
		   rsp.Header.Flags.RCode() == RCodeOK {
			continue;
		}

		if client.Port == 5353 {
			client = maddr;
		}

		err = Write(p, client, rsp);
		if err != nil {
			if silent != true {
				log.Println("Error sending response: ", err);
				continue;
			}
		}
	}
}

func MakeRecursive(qd *Question, out *Message) (uint16, error) {
	if bytes.HasSuffix(qd.Name, []byte("local.")) != true {
		out.Header.Flags |= RCodeFmtErr;
		return 0, nil;
	}

	rand.Seed(time.Now().UTC().UnixNano());
	id := uint16(rand.Intn(math.MaxUint16));

	req := new(Message);
	req.Header.Id = id;
	req.AppendQD(qd);

	rsp, err := SendRequest(req);
	if err != nil {
		return 0, fmt.Errorf("Could not send request: %s", err);
	}

	for _, an := range rsp.Answer {
		out.Answer = append(out.Answer, an);
		out.Header.ANCount++;
	}

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

package mdns

import "bytes"
import "fmt"
import "log"
import "math"
import "math/rand"
import "net"
import "time"

import "code.google.com/p/go.net/ipv4"

func NewServer(addr string, maddr string) (*net.UDPAddr, *ipv4.PacketConn, error) {
	saddr, err := net.ResolveUDPAddr("udp", addr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not resolve address '%s': %s", addr, err);
	}

	smaddr, err := net.ResolveUDPAddr("udp", maddr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not resolve address '%s': %s", maddr, err);
	}

	udp, err := net.ListenUDP("udp", saddr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not listen: %s", err);
	}

	p := ipv4.NewPacketConn(udp);
	if err := p.JoinGroup(nil, smaddr); err != nil {
		return nil, nil, fmt.Errorf("Could not join group: %s", err);
	}

	err = p.SetTTL(1);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set TTL: %s", err);
	}

	err = p.SetMulticastLoopback(false);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set loop: %s", err);
	}

	err = p.SetControlMessage(ipv4.FlagInterface | ipv4.FlagDst, true);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set ctrlmsg: %s", err);
	}

	return smaddr, p, nil;
}

func NewClient(addr string, maddr string) (*net.UDPAddr, *ipv4.PacketConn, error) {
	saddr, err := net.ResolveUDPAddr("udp", addr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not resolve address '%s': %s", addr, err);
	}

	smaddr, err := net.ResolveUDPAddr("udp", maddr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not resolve address '%s': %s", maddr, err);
	}

	udp, err := net.ListenUDP("udp", saddr);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not listen: %s", err);
	}

	p := ipv4.NewPacketConn(udp);

	err = p.SetMulticastLoopback(false);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set loop: %s", err);
	}

	err = p.SetControlMessage(ipv4.FlagInterface | ipv4.FlagDst, true);
	if err != nil {
		return nil, nil, fmt.Errorf("Could not set ctrlmsg: %s", err);
	}

	return smaddr, p, nil;
}

func MakeResponse(client *net.UDPAddr, req *Message) (*Message) {
	rsp := new(Message);

	rsp.Header.Flags |= FlagQR;
	rsp.Header.Flags |= FlagAA;

	if req.Header.Flags & FlagRD != 0 {
		rsp.Header.Flags |= FlagRD;
		rsp.Header.Flags |= FlagRA;
	}

	if client.Port != 5353 {
		rsp.Header.Id = req.Header.Id;
	}

	return rsp;
}

func Read(p *ipv4.PacketConn) (*Message, net.IP, *net.IPNet, *net.IPNet, *net.UDPAddr, error) {
	var local4 *net.IPNet;
	var local6 *net.IPNet;

	pkt := make([]byte, 65536);

	n, cm, from, err := p.ReadFrom(pkt);
	if err != nil {
		return nil, nil, nil, nil, nil,
		  fmt.Errorf("Could not read: %s", err);
	}

	ifi, err := net.InterfaceByIndex(cm.IfIndex);
	if err != nil {
		return nil, nil, nil, nil, nil,
		    fmt.Errorf("Could not find if: %s", err);
	}

	addrs, err := ifi.Addrs();
	if err != nil {
		return nil, nil, nil, nil, nil,
		  fmt.Errorf("Could not find addrs: %s", err);
	}

	for _, a := range addrs {
		if a.(*net.IPNet).IP.To4() != nil {
			local4 = a.(*net.IPNet);
		} else {
			local6 = a.(*net.IPNet);
		}
	}

	req, err := Unpack(pkt[:n]);
	if err != nil {
		return nil, nil, nil, nil, nil,
		  fmt.Errorf("Could not unpack request: %s", err);
	}

	return req, cm.Dst, local4, local6, from.(*net.UDPAddr), err;
}

func Write(p *ipv4.PacketConn, addr *net.UDPAddr, msg *Message) (error) {
	pkt, err := Pack(msg);
	if err != nil {
		return fmt.Errorf("Could not pack response: %s", err);
	}

	_, err = p.WriteTo(pkt, nil, addr);
	if err != nil {
		return fmt.Errorf("Could not write to network: %s", err);
	}

	return nil;
}

func SendRequest(req *Message) (*Message, error) {
	maddr, client, err := NewClient("0.0.0.0:0", "224.0.0.251:5353");
	if err != nil {
		return nil, fmt.Errorf("Could not create client: %s", err);
	}
	defer client.Close();

	seconds := 3 * time.Second;
	timeout := time.Now().Add(seconds);

	err = Write(client, maddr, req);
	if err != nil {
		return nil, fmt.Errorf("Could not send request: %s", err);
	}

	client.SetReadDeadline(timeout);

	rsp, _, _, _, _, err := Read(client);
	if err != nil {
		return nil, fmt.Errorf("Could not read response: %s", err);
	}

	if rsp.Header.Id != req.Header.Id {
		return nil, fmt.Errorf("Wrong id: %d", rsp.Header.Id);
	}

	return rsp, nil;
}

func Serve(p *ipv4.PacketConn, maddr *net.UDPAddr, localname string, silent, forward bool) {
	var sent_id uint16;

	for {
		req, dest, local4, local6, client, err := Read(p);
		if err != nil {
			if silent != true {
				log.Println("Error reading request: ", err);
				continue;
			}
		}

		if req.Header.Flags & FlagQR != 0 {
			continue;
		}

		if sent_id > 0 && req.Header.Id == sent_id {
			continue;
		}

		rsp := MakeResponse(client, req);

		for _, q := range req.Question {
			if client.Port != 5353 {
				rsp.Question = append(rsp.Question, q);
				rsp.Header.QDCount++;
			}

			if string(q.Name) != localname {
				if dest.IsLoopback() && forward != false {
					sent_id, _ = MakeRecursive(q, rsp);
				}

				continue;
			}

			switch (q.Type) {
				case TypeA:
					an := NewA(local4.IP);
					rsp.AppendAN(q, an);

				case TypeAAAA:
					an := NewAAAA(local6.IP);
					rsp.AppendAN(q, an);

				default:
					continue;
			}
		}

		if rsp.Header.ANCount == 0 &&
		   rsp.Header.Flags.RCode() == RCodeOK {
			continue;
		}

		if client.Port == 5353 {
			client = maddr;
		}

		err = Write(p, client, rsp);
		if err != nil {
			if silent != true {
				log.Println("Error sending response: ", err);
				continue;
			}
		}
	}
}

func MakeRecursive(qd *Question, out *Message) (uint16, error) {
	if bytes.HasSuffix(qd.Name, []byte("local.")) != true {
		out.Header.Flags |= RCodeFmtErr;
		return 0, nil;
	}

	rand.Seed(time.Now().UTC().UnixNano());
	id := uint16(rand.Intn(math.MaxUint16));

	req := new(Message);
	req.Header.Id = id;
	req.AppendQD(qd);

	rsp, err := SendRequest(req);
	if err != nil {
		return 0, fmt.Errorf("Could not send request: %s", err);
	}

	for _, an := range rsp.Answer {
		out.Answer = append(out.Answer, an);
		out.Header.ANCount++;
	}

	return id, nil;
}
<|endoftext|>


<commit_before>package multiconfig

import (
	"fmt"
	"os"
	"sort"
	"strings"

	"github.com/fatih/camelcase"
	"github.com/fatih/structs"
)

// EnvironmentLoader satisifies the loader interface. It loads the
// configuration from the environment variables in the form of
// STRUCTNAME_FIELDNAME.
type EnvironmentLoader struct {
	// Prefix prepends given string to every environment variable
	// {STRUCTNAME}_FIELDNAME will be {PREFIX}_FIELDNAME
	Prefix string

	// CamelCase adds a separator for field names in camelcase form. A
	// fieldname of "AccessKey" would generate a environment name of
	// "STRUCTNAME_ACCESSKEY". If CamelCase is enabled, the environment name
	// will be generated in the form of "STRUCTNAME_ACCESS_KEY"
	CamelCase bool
}

func (e *EnvironmentLoader) getPrefix(s *structs.Struct) string {
	if e.Prefix != "" {
		return e.Prefix
	}

	return s.Name()
}

// Load loads the source into the config defined by struct s
func (e *EnvironmentLoader) Load(s interface{}) error {
	strct := structs.New(s)
	strctMap := strct.Map()
	prefix := e.getPrefix(strct)

	for key, val := range strctMap {
		field := strct.Field(key)

		if err := e.processField(prefix, field, key, val); err != nil {
			return err
		}
	}

	return nil
}

// processField gets leading name for the env variable and combines the current
// field's name and generates environemnt variable names recursively
func (e *EnvironmentLoader) processField(prefix string, field *structs.Field, name string, strctMap interface{}) error {
	fieldName := e.generateFieldName(prefix, name)

	switch strctMap.(type) {
	case map[string]interface{}:
		for key, val := range strctMap.(map[string]interface{}) {
			field := field.Field(key)

			if err := e.processField(fieldName, field, key, val); err != nil {
				return err
			}
		}
	default:
		v := os.Getenv(fieldName)
		if v == "" {
			return nil
		}

		if err := fieldSet(field, v); err != nil {
			return err
		}
	}

	return nil
}

// PrintEnvs prints the generated environment variables to the std out.
func (e *EnvironmentLoader) PrintEnvs(s interface{}) {
	strct := structs.New(s)
	strctMap := strct.Map()
	prefix := e.getPrefix(strct)

	keys := make([]string, 0, len(strctMap))
	for key, _ := range strctMap {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	for _, key := range keys {
		field := strct.Field(key)

		e.printField(prefix, field, key, strctMap[key])
	}
}

// printField prints the field of the config struct for the flag.Usage
func (e *EnvironmentLoader) printField(prefix string, field *structs.Field, name string, strctMap interface{}) {
	fieldName := e.generateFieldName(prefix, name)

	switch strctMap.(type) {
	case map[string]interface{}:
		for key, val := range strctMap.(map[string]interface{}) {
			field := field.Field(key)

			e.printField(fieldName, field, key, val)
		}
	default:
		fmt.Println("  ", fieldName)
	}
}

// generateFieldName generates the field name combined with the prefix and the
// struct's field name
func (e *EnvironmentLoader) generateFieldName(prefix string, name string) string {
	fieldName := strings.ToUpper(name)
	if e.CamelCase {
		fieldName = strings.ToUpper(strings.Join(camelcase.Split(name), "_"))
	}

	return strings.ToUpper(prefix) + "_" + fieldName
}
<commit_msg>sort sub-struct environment keys<commit_after>package multiconfig

import (
	"fmt"
	"os"
	"sort"
	"strings"

	"github.com/fatih/camelcase"
	"github.com/fatih/structs"
)

// EnvironmentLoader satisifies the loader interface. It loads the
// configuration from the environment variables in the form of
// STRUCTNAME_FIELDNAME.
type EnvironmentLoader struct {
	// Prefix prepends given string to every environment variable
	// {STRUCTNAME}_FIELDNAME will be {PREFIX}_FIELDNAME
	Prefix string

	// CamelCase adds a separator for field names in camelcase form. A
	// fieldname of "AccessKey" would generate a environment name of
	// "STRUCTNAME_ACCESSKEY". If CamelCase is enabled, the environment name
	// will be generated in the form of "STRUCTNAME_ACCESS_KEY"
	CamelCase bool
}

func (e *EnvironmentLoader) getPrefix(s *structs.Struct) string {
	if e.Prefix != "" {
		return e.Prefix
	}

	return s.Name()
}

// Load loads the source into the config defined by struct s
func (e *EnvironmentLoader) Load(s interface{}) error {
	strct := structs.New(s)
	strctMap := strct.Map()
	prefix := e.getPrefix(strct)

	for key, val := range strctMap {
		field := strct.Field(key)

		if err := e.processField(prefix, field, key, val); err != nil {
			return err
		}
	}

	return nil
}

// processField gets leading name for the env variable and combines the current
// field's name and generates environemnt variable names recursively
func (e *EnvironmentLoader) processField(prefix string, field *structs.Field, name string, strctMap interface{}) error {
	fieldName := e.generateFieldName(prefix, name)

	switch strctMap.(type) {
	case map[string]interface{}:
		for key, val := range strctMap.(map[string]interface{}) {
			field := field.Field(key)

			if err := e.processField(fieldName, field, key, val); err != nil {
				return err
			}
		}
	default:
		v := os.Getenv(fieldName)
		if v == "" {
			return nil
		}

		if err := fieldSet(field, v); err != nil {
			return err
		}
	}

	return nil
}

// PrintEnvs prints the generated environment variables to the std out.
func (e *EnvironmentLoader) PrintEnvs(s interface{}) {
	strct := structs.New(s)
	strctMap := strct.Map()
	prefix := e.getPrefix(strct)

	keys := make([]string, 0, len(strctMap))
	for key, _ := range strctMap {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	for _, key := range keys {
		field := strct.Field(key)
		e.printField(prefix, field, key, strctMap[key])
	}
}

// printField prints the field of the config struct for the flag.Usage
func (e *EnvironmentLoader) printField(prefix string, field *structs.Field, name string, strctMap interface{}) {
	fieldName := e.generateFieldName(prefix, name)

	switch strctMap.(type) {
	case map[string]interface{}:
		smap := strctMap.(map[string]interface{})
		keys := make([]string, 0, len(smap))
		for key, _ := range smap {
			keys = append(keys, key)
		}
		sort.Strings(keys)
		for _, key := range keys {
			field := field.Field(key)
			e.printField(fieldName, field, key, smap[key])
		}
	default:
		fmt.Println("  ", fieldName)
	}
}

// generateFieldName generates the field name combined with the prefix and the
// struct's field name
func (e *EnvironmentLoader) generateFieldName(prefix string, name string) string {
	fieldName := strings.ToUpper(name)
	if e.CamelCase {
		fieldName = strings.ToUpper(strings.Join(camelcase.Split(name), "_"))
	}

	return strings.ToUpper(prefix) + "_" + fieldName
}
<|endoftext|>


<commit_before>package tests

import (
	"testing"

	"github.com/talbor49/HoneyBee/grammar"
)

func TestParseGetRequest(t *testing.T) {
	requestType, parsedTokens, err := grammar.ParseQuery("GET foo")

	if err != nil {
		t.Error("Error parsing legit query")
	}
	if requestType != "GET" {
		t.Error("Query parsing did not recognize the right request type")
	}
	if parsedTokens[0] != "foo" {
		t.Error("Tokens parsed wrongly")
	}

	_, _, err = grammar.ParseQuery("GET")

	if err == nil {
		t.Error("Succeed in parsing an invalid query")
	}

	// requestType, parsedTokens, err = grammar.ParseQuery("GET ASMDQWE2309123 123====SAC A-S---- ;LQAWE,ZWD;LAZOW,E1PO;243KE0P2O1-3EOI90135I1123   12333333333123123\"\" --- ;")

}

func TestParseSetRequest(t *testing.T) {
	requestType, parsedTokens, err := grammar.ParseQuery("SET foo bar")

	if err != nil {
		t.Error("Error parsing legit query")
	}
	if requestType != "SET" {
		t.Error("Query parsing did not recognize the right request type")
	}
	if len(parsedTokens) != 2 || parsedTokens[0] != "foo" || parsedTokens[1] != "bar" {
		t.Error("Tokens parsed wrongly")
	}

	_, _, err = grammar.ParseQuery("SET")

	if err == nil {
		t.Error("Succeed in parsing an invalid query")
	}
}

func TestParseAuthRequest(t *testing.T) {
	requestType, parsedTokens, err := grammar.ParseQuery("AUTH username password bucket")

	if err != nil {
		t.Error("Error parsing legit query")
	}
	if requestType != "AUTH" {
		t.Error("Query parsing did not recognize the right request type")
	}
	if len(parsedTokens) != 3 || parsedTokens[0] != "username" || parsedTokens[1] != "password" || parsedTokens[2] != "bucket" {
		t.Error("Tokens parsed wrongly")
	}

	_, _, err = grammar.ParseQuery("AUTH ASMDQWE2309123 123====SAC A-S---- ;LQAWE,ZWD;LAZOW,E1PO;243KE0P2O1-3EOI90135I1123   12333333333123123\"\" --- ;")
	if err == nil {
		t.Error("Succeed in parsing an invalid query")
	}
}

func TestParseDeleteRequest(t *testing.T) {
	requestType, parsedTokens, err := grammar.ParseQuery("DELETE KEY foo")

	if err != nil {
		t.Error("Error parsing legit query")
	}
	if requestType != "DELETE" {
		t.Error("Query parsing did not recognize the right request type")
	}
	if len(parsedTokens) != 2 || parsedTokens[0] != "KEY" || parsedTokens[1] != "foo" {
		t.Error("Tokens parsed wrongly")
	}
}

func TestEmptyRequest(t *testing.T) {
	requestType, _, err := grammar.ParseQuery("")
	if err == nil || requestType != "" {
		t.Error("Succeed in parsing an invalid query")
	}
}

func TestNonsenseRequest(t *testing.T) {
	requestType, _, err := grammar.ParseQuery("1OP2M34IO1P2M3AWMDL;KA,SC;LZXS,C AOWMSXCOIAL MC0123945 I2103965I24-6")
	if err == nil || requestType != "" {
		t.Error("Succeed in parsing an invalid query")
	}
}
<commit_msg>Fixed AUTH request tests that fail because of changing of it's structure<commit_after>package tests

import (
	"testing"

	"github.com/talbor49/HoneyBee/grammar"
)

func TestParseGetRequest(t *testing.T) {
	requestType, parsedTokens, err := grammar.ParseQuery("GET foo")

	if err != nil {
		t.Error("Error parsing legit query")
	}
	if requestType != "GET" {
		t.Error("Query parsing did not recognize the right request type")
	}
	if parsedTokens[0] != "foo" {
		t.Error("Tokens parsed wrongly")
	}

	_, _, err = grammar.ParseQuery("GET")

	if err == nil {
		t.Error("Succeed in parsing an invalid query")
	}

	// requestType, parsedTokens, err = grammar.ParseQuery("GET ASMDQWE2309123 123====SAC A-S---- ;LQAWE,ZWD;LAZOW,E1PO;243KE0P2O1-3EOI90135I1123   12333333333123123\"\" --- ;")

}

func TestParseSetRequest(t *testing.T) {
	requestType, parsedTokens, err := grammar.ParseQuery("SET foo bar")

	if err != nil {
		t.Error("Error parsing legit query")
	}
	if requestType != "SET" {
		t.Error("Query parsing did not recognize the right request type")
	}
	if len(parsedTokens) != 2 || parsedTokens[0] != "foo" || parsedTokens[1] != "bar" {
		t.Error("Tokens parsed wrongly")
	}

	_, _, err = grammar.ParseQuery("SET")

	if err == nil {
		t.Error("Succeed in parsing an invalid query")
	}
}

func TestParseAuthRequest(t *testing.T) {
	requestType, parsedTokens, err := grammar.ParseQuery("AUTH username password")

	if err != nil {
		t.Error("Error parsing legit query")
	}
	if requestType != "AUTH" {
		t.Error("Query parsing did not recognize the right request type")
	}
	if len(parsedTokens) != 2 || parsedTokens[0] != "username" || parsedTokens[1] != "password" {
		t.Error("Tokens parsed wrongly")
	}

	_, _, err = grammar.ParseQuery("AUTH ASMDQWE2309123 123====SAC A-S---- ;LQAWE,ZWD;LAZOW,E1PO;243KE0P2O1-3EOI90135I1123   12333333333123123\"\" --- ;")
	if err == nil {
		t.Error("Succeed in parsing an invalid query")
	}
}

func TestParseDeleteRequest(t *testing.T) {
	requestType, parsedTokens, err := grammar.ParseQuery("DELETE KEY foo")

	if err != nil {
		t.Error("Error parsing legit query")
	}
	if requestType != "DELETE" {
		t.Error("Query parsing did not recognize the right request type")
	}
	if len(parsedTokens) != 2 || parsedTokens[0] != "KEY" || parsedTokens[1] != "foo" {
		t.Error("Tokens parsed wrongly")
	}
}

func TestEmptyRequest(t *testing.T) {
	requestType, _, err := grammar.ParseQuery("")
	if err == nil || requestType != "" {
		t.Error("Succeed in parsing an invalid query")
	}
}

func TestNonsenseRequest(t *testing.T) {
	requestType, _, err := grammar.ParseQuery("1OP2M34IO1P2M3AWMDL;KA,SC;LZXS,C AOWMSXCOIAL MC0123945 I2103965I24-6")
	if err == nil || requestType != "" {
		t.Error("Succeed in parsing an invalid query")
	}
}
<|endoftext|>


<commit_before>package errors

import (
	"fmt"
	"runtime"
)

type (
	ErrFields  map[string]interface{}
	ErrFmtFunc func(err *Err) string
	ErrType    uint
)

const (
	Generic ErrType = iota
	NotFound
	Unauthorized
	NotImplemented
	AlreadyExists
	NotSupported
	NotValid
	NotProvisioned
	NotAssigned
	BadRequest
	MethodNotAllowed
)

type Err struct {
	cause   error
	message string
	fields  ErrFields
	errType ErrType

	line    int
	file    string
	fmtFunc ErrFmtFunc
}

func NewErr(cause error, fields ErrFields, fmtFunc ErrFmtFunc,
	format string, args ...interface{}) *Err {
	return newErr(cause, fields, defaultFmtFunc, format, args...)
}

func newErr(cause error, fields ErrFields, fmtFunc ErrFmtFunc,
	format string, args ...interface{}) *Err {
	if fmtFunc == nil {
		fmtFunc = defaultFmtFunc
	}

	err := &Err{
		cause:   cause,
		message: fmt.Sprintf(format, args...),
		fields:  fields,
		fmtFunc: fmtFunc,
	}

	err.SetLocation(2)
	return err
}

func (e *Err) Error() string {
	return e.fmtFunc(e)
}

func (e *Err) Message() string {
	return e.message
}

func (e *Err) Cause() error {
	return e.cause
}

func (e *Err) Fields() ErrFields {
	return e.fields
}

func (e *Err) Type() ErrType {
	return e.errType
}

func (e *Err) Location() (string, int) {
	return e.file, e.line
}

func (e *Err) WithMessage(format string, args ...interface{}) *Err {
	e.message = fmt.Sprintf(format, args...)
	return e
}

func (e *Err) WithCause(err error) *Err {
	e.cause = err
	return e
}

func (e *Err) WithFields(fields ErrFields) *Err {
	e.fields = fields
	return e
}

func (e *Err) WithType(errType ErrType) *Err {
	e.errType = errType
	return e
}

func (e *Err) WithFormat(fmtFunc ErrFmtFunc) *Err {
	e.fmtFunc = fmtFunc
	return e
}

func (e *Err) SetLocation(depth int) {
	_, e.file, e.line, _ = runtime.Caller(depth + 1)
}
<commit_msg>Add Forbidden error type<commit_after>package errors

import (
	"fmt"
	"runtime"
)

type (
	ErrFields  map[string]interface{}
	ErrFmtFunc func(err *Err) string
	ErrType    uint
)

const (
	Generic ErrType = iota
	NotFound
	Unauthorized
	Forbidden
	NotImplemented
	AlreadyExists
	NotSupported
	NotValid
	NotProvisioned
	NotAssigned
	BadRequest
	MethodNotAllowed
)

type Err struct {
	cause   error
	message string
	fields  ErrFields
	errType ErrType

	line    int
	file    string
	fmtFunc ErrFmtFunc
}

func NewErr(cause error, fields ErrFields, fmtFunc ErrFmtFunc,
	format string, args ...interface{}) *Err {
	return newErr(cause, fields, defaultFmtFunc, format, args...)
}

func newErr(cause error, fields ErrFields, fmtFunc ErrFmtFunc,
	format string, args ...interface{}) *Err {
	if fmtFunc == nil {
		fmtFunc = defaultFmtFunc
	}

	err := &Err{
		cause:   cause,
		message: fmt.Sprintf(format, args...),
		fields:  fields,
		fmtFunc: fmtFunc,
	}

	err.SetLocation(2)
	return err
}

func (e *Err) Error() string {
	return e.fmtFunc(e)
}

func (e *Err) Message() string {
	return e.message
}

func (e *Err) Cause() error {
	return e.cause
}

func (e *Err) Fields() ErrFields {
	return e.fields
}

func (e *Err) Type() ErrType {
	return e.errType
}

func (e *Err) Location() (string, int) {
	return e.file, e.line
}

func (e *Err) WithMessage(format string, args ...interface{}) *Err {
	e.message = fmt.Sprintf(format, args...)
	return e
}

func (e *Err) WithCause(err error) *Err {
	e.cause = err
	return e
}

func (e *Err) WithFields(fields ErrFields) *Err {
	e.fields = fields
	return e
}

func (e *Err) WithType(errType ErrType) *Err {
	e.errType = errType
	return e
}

func (e *Err) WithFormat(fmtFunc ErrFmtFunc) *Err {
	e.fmtFunc = fmtFunc
	return e
}

func (e *Err) SetLocation(depth int) {
	_, e.file, e.line, _ = runtime.Caller(depth + 1)
}
<|endoftext|>


<commit_before>package jsonrpc

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"time"
)

type Client struct {
	Url string
	id  int
	c   *http.Client
}

type Response struct {
	Id     int            `json:"id"`
	Result interface{}    `json:"result"`
	Error  *ResponseError `json:"error"`
}

type ResponseError struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

func NewClient(url string) *Client {
	client := new(Client)
	client.Url = url
	client.c = &http.Client{}
	return client
}

func (c *Client) Call(method string, params interface{}) (*Response, error) {
	return c.CallTimeout(method, params, 0)
}

func (c *Client) CallTimeout(method string, params interface{}, timeout time.Duration) (*Response, error) {
	var payload = map[string]interface{}{
		"jsonrpc": "2.0",
		"method":  method,
		"params":  params,
		"id":      c.id,
	}

	c.id += 1
	data, err := json.Marshal(payload)
	if err != nil {
		return nil, err
	}
	buf := bytes.NewBuffer(data)
	c.c.Timeout = timeout
	resp, err := c.c.Post(c.Url, "application/json", buf)

	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	decoder := json.NewDecoder(resp.Body)
	var respPayload *Response
	err = decoder.Decode(&respPayload)

	if err != nil {
		return nil, errors.New(fmt.Sprintf("Invalid response from server. Status: %s. %s", resp.Status, err.Error()))
	}

	return respPayload, nil
}
<commit_msg>update<commit_after>package jsonrpc

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"time"
)

type Client struct {
	Url string
	id  int
	c   *http.Client
}

type Response struct {
	Id     int            `json:"id"`
	Result interface{}    `json:"result"`
	Error  *ResponseError `json:"error"`
}

type ResponseError struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

func (this *ResponseError) Error() string {
	b, err := json.Marshal(this)
	if err != nil {
		return err.Error()
	}
	return string(b)
}

func NewClient(url string) *Client {
	client := new(Client)
	client.Url = url
	client.c = &http.Client{}
	return client
}

func (c *Client) Call(method string, params interface{}) (*Response, error) {
	return c.CallTimeout(method, params, 0)
}

func (c *Client) CallTimeout(method string, params interface{}, timeout time.Duration) (*Response, error) {
	var payload = map[string]interface{}{
		"jsonrpc": "2.0",
		"method":  method,
		"params":  params,
		"id":      c.id,
	}

	c.id += 1
	data, err := json.Marshal(payload)
	if err != nil {
		return nil, err
	}
	buf := bytes.NewBuffer(data)
	c.c.Timeout = timeout
	resp, err := c.c.Post(c.Url, "application/json", buf)

	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	decoder := json.NewDecoder(resp.Body)
	var respPayload *Response
	err = decoder.Decode(&respPayload)

	if err != nil {
		return nil, errors.New(fmt.Sprintf("Invalid response from server. Status: %s. %s", resp.Status, err.Error()))
	}

	return respPayload, nil
}
<|endoftext|>


<commit_before>// fmt.go, like render.go, contains stuff concerning output formatting in the stdoutt/terminal,
// but fmt.go is for more bash-specific/lower level stuff
package main

import (
	"fmt"
	"strings"
	"unicode/utf8"

	c "github.com/mitchellh/colorstring"
)

const (dashesNumber = 2)

func printCentered(o string) {
	length := utf8.RuneCount([]byte(o))
	var sideburns int = (6 + 2*columnSize - length) / 2- dashesNumber
	fmt.Printf(strings.Repeat(" ", sideburns))
  fmt.Printf(c.Color("[red]"+strings.Repeat("-", dashesNumber)))
	fmt.Printf(c.Color("[red]"+o+"[white]"))
  fmt.Printf(c.Color("[red]"+strings.Repeat("-", dashesNumber))+"\n")
}
<commit_msg>get terminal symbol width to center text all nicely<commit_after>// fmt.go, like render.go, contains stuff concerning output formatting in the stdoutt/terminal,
// but fmt.go is for more bash-specific/lower level stuff
package main

import (
	"fmt"
	"strings"
	"syscall"
	"unicode/utf8"
	"unsafe"

	c "github.com/mitchellh/colorstring"
)

const (
	dashesNumber = 2
)

var (
	terminalWidth   = 80
	columnSize      = 39 // characters in the filename column
	maxFileNameSize = columnSize - 7
)

func printCentered(o string) {
	length := utf8.RuneCount([]byte(o))
	sideburns := (6+2*columnSize-length)/2 - dashesNumber
	fmt.Printf(strings.Repeat(" ", sideburns))
	fmt.Printf(c.Color("[red]" + strings.Repeat("-", dashesNumber)))
	fmt.Printf(c.Color("[red]" + o + "[white]"))
	fmt.Printf(c.Color("[red]"+strings.Repeat("-", dashesNumber)) + "\n")
}

// SetTerminalSize returns the dimensions of the given terminal.
func SetColumnSize() {
	const stdoutFD = 1
	var dimensions [4]uint16

	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(stdoutFD), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
		return
	}
	terminalWidth = int(dimensions[1])
	if terminalWidth < 3 {
		return
	}
	columnSize = (terminalWidth - 2) / 2
}

func printHR() {
	fmt.Printf(c.Color("\n[cyan]" + strings.Repeat("-", terminalWidth) + "\n"))
}
<|endoftext|>


<commit_before>// Copyright 2018 The Go 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 xerrors

import (
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"

	"golang.org/x/xerrors/internal"
)

const percentBangString = "%!"

// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error.
//
// The returned error includes the file and line number of the caller when
// formatted with additional detail enabled. If the last argument is an error
// the returned error's Format method will return it if the format string ends
// with ": %s", ": %v", or ": %w". If the last argument is an error and the
// format string ends with ": %w", the returned error implements an Unwrap
// method returning it.
//
// If the format specifier includes a %w verb with an error operand in a
// position other than at the end, the returned error will still implement an
// Unwrap method returning the operand, but the error's Format method will not
// return the wrapped error.
//
// It is invalid to include more than one %w verb or to supply it with an
// operand that does not implement the error interface. The %w verb is otherwise
// a synonym for %v.
//
// Deprecated: As of Go 1.13, use fmt.Errorf instead.
func Errorf(format string, a ...interface{}) error {
	format = formatPlusW(format)
	// Support a ": %[wsv]" suffix, which works well with xerrors.Formatter.
	wrap := strings.HasSuffix(format, ": %w")
	idx, format2, ok := parsePercentW(format)
	percentWElsewhere := !wrap && idx >= 0
	if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) {
		err := errorAt(a, len(a)-1)
		if err == nil {
			return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
		}
		// TODO: this is not entirely correct. The error value could be
		// printed elsewhere in format if it mixes numbered with unnumbered
		// substitutions. With relatively small changes to doPrintf we can
		// have it optionally ignore extra arguments and pass the argument
		// list in its entirety.
		msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
		frame := Frame{}
		if internal.EnableTrace {
			frame = Caller(1)
		}
		if wrap {
			return &wrapError{msg, err, frame}
		}
		return &noWrapError{msg, err, frame}
	}
	// Support %w anywhere.
	// TODO: don't repeat the wrapped error's message when %w occurs in the middle.
	msg := fmt.Sprintf(format2, a...)
	if idx < 0 {
		return &noWrapError{msg, nil, Caller(1)}
	}
	err := errorAt(a, idx)
	if !ok || err == nil {
		// Too many %ws or argument of %w is not an error. Approximate the Go
		// 1.13 fmt.Errorf message.
		return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)}
	}
	frame := Frame{}
	if internal.EnableTrace {
		frame = Caller(1)
	}
	return &wrapError{msg, err, frame}
}

func errorAt(args []interface{}, i int) error {
	if i < 0 || i >= len(args) {
		return nil
	}
	err, ok := args[i].(error)
	if !ok {
		return nil
	}
	return err
}

// formatPlusW is used to avoid the vet check that will barf at %w.
func formatPlusW(s string) string {
	return s
}

// Return the index of the only %w in format, or -1 if none.
// Also return a rewritten format string with %w replaced by %v, and
// false if there is more than one %w.
// TODO: handle "%[N]w".
func parsePercentW(format string) (idx int, newFormat string, ok bool) {
	// Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go.
	idx = -1
	ok = true
	n := 0
	sz := 0
	var isW bool
	for i := 0; i < len(format); i += sz {
		if format[i] != '%' {
			sz = 1
			continue
		}
		// "%%" is not a format directive.
		if i+1 < len(format) && format[i+1] == '%' {
			sz = 2
			continue
		}
		sz, isW = parsePrintfVerb(format[i:])
		if isW {
			if idx >= 0 {
				ok = false
			} else {
				idx = n
			}
			// "Replace" the last character, the 'w', with a 'v'.
			p := i + sz - 1
			format = format[:p] + "v" + format[p+1:]
		}
		n++
	}
	return idx, format, ok
}

// Parse the printf verb starting with a % at s[0].
// Return how many bytes it occupies and whether the verb is 'w'.
func parsePrintfVerb(s string) (int, bool) {
	// Assume only that the directive is a sequence of non-letters followed by a single letter.
	sz := 0
	var r rune
	for i := 1; i < len(s); i += sz {
		r, sz = utf8.DecodeRuneInString(s[i:])
		if unicode.IsLetter(r) {
			return i + sz, r == 'w'
		}
	}
	return len(s), false
}

type noWrapError struct {
	msg   string
	err   error
	frame Frame
}

func (e *noWrapError) Error() string {
	return fmt.Sprint(e)
}

func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }

func (e *noWrapError) FormatError(p Printer) (next error) {
	p.Print(e.msg)
	e.frame.Format(p)
	return e.err
}

type wrapError struct {
	msg   string
	err   error
	frame Frame
}

func (e *wrapError) Error() string {
	return fmt.Sprint(e)
}

func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }

func (e *wrapError) FormatError(p Printer) (next error) {
	p.Print(e.msg)
	e.frame.Format(p)
	return e.err
}

func (e *wrapError) Unwrap() error {
	return e.err
}
<commit_msg>xerrors: undeprecate Errorf<commit_after>// Copyright 2018 The Go 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 xerrors

import (
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"

	"golang.org/x/xerrors/internal"
)

const percentBangString = "%!"

// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error.
//
// The returned error includes the file and line number of the caller when
// formatted with additional detail enabled. If the last argument is an error
// the returned error's Format method will return it if the format string ends
// with ": %s", ": %v", or ": %w". If the last argument is an error and the
// format string ends with ": %w", the returned error implements an Unwrap
// method returning it.
//
// If the format specifier includes a %w verb with an error operand in a
// position other than at the end, the returned error will still implement an
// Unwrap method returning the operand, but the error's Format method will not
// return the wrapped error.
//
// It is invalid to include more than one %w verb or to supply it with an
// operand that does not implement the error interface. The %w verb is otherwise
// a synonym for %v.
//
// Note that as of Go 1.13, the fmt.Errorf function will do error formatting,
// but it will not capture a stack backtrace.
func Errorf(format string, a ...interface{}) error {
	format = formatPlusW(format)
	// Support a ": %[wsv]" suffix, which works well with xerrors.Formatter.
	wrap := strings.HasSuffix(format, ": %w")
	idx, format2, ok := parsePercentW(format)
	percentWElsewhere := !wrap && idx >= 0
	if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) {
		err := errorAt(a, len(a)-1)
		if err == nil {
			return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
		}
		// TODO: this is not entirely correct. The error value could be
		// printed elsewhere in format if it mixes numbered with unnumbered
		// substitutions. With relatively small changes to doPrintf we can
		// have it optionally ignore extra arguments and pass the argument
		// list in its entirety.
		msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
		frame := Frame{}
		if internal.EnableTrace {
			frame = Caller(1)
		}
		if wrap {
			return &wrapError{msg, err, frame}
		}
		return &noWrapError{msg, err, frame}
	}
	// Support %w anywhere.
	// TODO: don't repeat the wrapped error's message when %w occurs in the middle.
	msg := fmt.Sprintf(format2, a...)
	if idx < 0 {
		return &noWrapError{msg, nil, Caller(1)}
	}
	err := errorAt(a, idx)
	if !ok || err == nil {
		// Too many %ws or argument of %w is not an error. Approximate the Go
		// 1.13 fmt.Errorf message.
		return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)}
	}
	frame := Frame{}
	if internal.EnableTrace {
		frame = Caller(1)
	}
	return &wrapError{msg, err, frame}
}

func errorAt(args []interface{}, i int) error {
	if i < 0 || i >= len(args) {
		return nil
	}
	err, ok := args[i].(error)
	if !ok {
		return nil
	}
	return err
}

// formatPlusW is used to avoid the vet check that will barf at %w.
func formatPlusW(s string) string {
	return s
}

// Return the index of the only %w in format, or -1 if none.
// Also return a rewritten format string with %w replaced by %v, and
// false if there is more than one %w.
// TODO: handle "%[N]w".
func parsePercentW(format string) (idx int, newFormat string, ok bool) {
	// Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go.
	idx = -1
	ok = true
	n := 0
	sz := 0
	var isW bool
	for i := 0; i < len(format); i += sz {
		if format[i] != '%' {
			sz = 1
			continue
		}
		// "%%" is not a format directive.
		if i+1 < len(format) && format[i+1] == '%' {
			sz = 2
			continue
		}
		sz, isW = parsePrintfVerb(format[i:])
		if isW {
			if idx >= 0 {
				ok = false
			} else {
				idx = n
			}
			// "Replace" the last character, the 'w', with a 'v'.
			p := i + sz - 1
			format = format[:p] + "v" + format[p+1:]
		}
		n++
	}
	return idx, format, ok
}

// Parse the printf verb starting with a % at s[0].
// Return how many bytes it occupies and whether the verb is 'w'.
func parsePrintfVerb(s string) (int, bool) {
	// Assume only that the directive is a sequence of non-letters followed by a single letter.
	sz := 0
	var r rune
	for i := 1; i < len(s); i += sz {
		r, sz = utf8.DecodeRuneInString(s[i:])
		if unicode.IsLetter(r) {
			return i + sz, r == 'w'
		}
	}
	return len(s), false
}

type noWrapError struct {
	msg   string
	err   error
	frame Frame
}

func (e *noWrapError) Error() string {
	return fmt.Sprint(e)
}

func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }

func (e *noWrapError) FormatError(p Printer) (next error) {
	p.Print(e.msg)
	e.frame.Format(p)
	return e.err
}

type wrapError struct {
	msg   string
	err   error
	frame Frame
}

func (e *wrapError) Error() string {
	return fmt.Sprint(e)
}

func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }

func (e *wrapError) FormatError(p Printer) (next error) {
	p.Print(e.msg)
	e.frame.Format(p)
	return e.err
}

func (e *wrapError) Unwrap() error {
	return e.err
}
<|endoftext|>