<commit_before>package container

import (
	"errors"
	"fmt"
	"net"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"

	clustertypes "github.com/docker/docker/daemon/cluster/provider"
	"github.com/docker/docker/reference"
	"github.com/docker/engine-api/types"
	enginecontainer "github.com/docker/engine-api/types/container"
	"github.com/docker/engine-api/types/network"
	"github.com/docker/swarmkit/agent/exec"
	"github.com/docker/swarmkit/api"
)

const (
	// Explicitly use the kernel's default setting for CPU quota of 100ms.
	// https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
	cpuQuotaPeriod = 100 * time.Millisecond

	// systemLabelPrefix represents the reserved namespace for system labels.
	systemLabelPrefix = "com.docker.swarm"
)

// containerConfig converts task properties into docker container compatible
// components.
type containerConfig struct {
	task                *api.Task
	networksAttachments map[string]*api.NetworkAttachment
}

// newContainerConfig returns a validated container config. No methods should
// return an error if this function returns without error.
func newContainerConfig(t *api.Task) (*containerConfig, error) {
	var c containerConfig
	return &c, c.setTask(t)
}

func (c *containerConfig) setTask(t *api.Task) error {
	container := t.Spec.GetContainer()
	if container == nil {
		return exec.ErrRuntimeUnsupported
	}

	if container.Image == "" {
		return ErrImageRequired
	}

	// index the networks by name
	c.networksAttachments = make(map[string]*api.NetworkAttachment, len(t.Networks))
	for _, attachment := range t.Networks {
		c.networksAttachments[attachment.Network.Spec.Annotations.Name] = attachment
	}

	c.task = t
	return nil
}

func (c *containerConfig) endpoint() *api.Endpoint {
	return c.task.Endpoint
}

func (c *containerConfig) spec() *api.ContainerSpec {
	return c.task.Spec.GetContainer()
}

func (c *containerConfig) name() string {
	if c.task.Annotations.Name != "" {
		// if set, use the container Annotations.Name field, set in the orchestrator.
		return c.task.Annotations.Name
	}

	// fallback to service.slot.id.
	return strings.Join([]string{c.task.ServiceAnnotations.Name, fmt.Sprint(c.task.Slot), c.task.ID}, ".")
}

func (c *containerConfig) image() string {
	raw := c.spec().Image
	ref, err := reference.ParseNamed(raw)
	if err != nil {
		return raw
	}
	return reference.WithDefaultTag(ref).String()
}

func (c *containerConfig) volumes() map[string]struct{} {
	r := make(map[string]struct{})

	for _, mount := range c.spec().Mounts {
		// pick off all the volume mounts.
		if mount.Type != api.MountTypeVolume {
			continue
		}

		r[fmt.Sprintf("%s:%s", mount.Target, getMountMask(&mount))] = struct{}{}
	}

	return r
}

func (c *containerConfig) config() *enginecontainer.Config {
	config := &enginecontainer.Config{
		Labels:     c.labels(),
		User:       c.spec().User,
		Env:        c.spec().Env,
		WorkingDir: c.spec().Dir,
		Image:      c.image(),
		Volumes:    c.volumes(),
	}

	if len(c.spec().Command) > 0 {
		// If Command is provided, we replace the whole invocation with Command
		// by replacing Entrypoint and specifying Cmd. Args is ignored in this
		// case.
		config.Entrypoint = append(config.Entrypoint, c.spec().Command[0])
		config.Cmd = append(config.Cmd, c.spec().Command[1:]...)
	} else if len(c.spec().Args) > 0 {
		// In this case, we assume the image has an Entrypoint and Args
		// specifies the arguments for that entrypoint.
		config.Cmd = c.spec().Args
	}

	return config
}

func (c *containerConfig) labels() map[string]string {
	var (
		system = map[string]string{
			"task":         "", // mark as cluster task
			"task.id":      c.task.ID,
			"task.name":    fmt.Sprintf("%v.%v", c.task.ServiceAnnotations.Name, c.task.Slot),
			"node.id":      c.task.NodeID,
			"service.id":   c.task.ServiceID,
			"service.name": c.task.ServiceAnnotations.Name,
		}
		labels = make(map[string]string)
	)

	// base labels are those defined in the spec.
	for k, v := range c.spec().Labels {
		labels[k] = v
	}

	// we then apply the overrides from the task, which may be set via the
	// orchestrator.
	for k, v := range c.task.Annotations.Labels {
		labels[k] = v
	}

	// finally, we apply the system labels, which override all labels.
	for k, v := range system {
		labels[strings.Join([]string{systemLabelPrefix, k}, ".")] = v
	}

	return labels
}

func (c *containerConfig) bindMounts() []string {
	var r []string

	for _, val := range c.spec().Mounts {
		mask := getMountMask(&val)
		if val.Type == api.MountTypeBind {
			r = append(r, fmt.Sprintf("%s:%s:%s", val.Source, val.Target, mask))
		}
	}

	return r
}

func getMountMask(m *api.Mount) string {
	maskOpts := []string{"ro"}
	if m.Writable {
		maskOpts[0] = "rw"
	}

	if m.BindOptions != nil {
		switch m.BindOptions.Propagation {
		case api.MountPropagationPrivate:
			maskOpts = append(maskOpts, "private")
		case api.MountPropagationRPrivate:
			maskOpts = append(maskOpts, "rprivate")
		case api.MountPropagationShared:
			maskOpts = append(maskOpts, "shared")
		case api.MountPropagationRShared:
			maskOpts = append(maskOpts, "rshared")
		case api.MountPropagationSlave:
			maskOpts = append(maskOpts, "slave")
		case api.MountPropagationRSlave:
			maskOpts = append(maskOpts, "rslave")
		}
	}

	if m.VolumeOptions != nil {
		if !m.VolumeOptions.Populate {
			maskOpts = append(maskOpts, "nocopy")
		}
	}
	return strings.Join(maskOpts, ",")
}

func (c *containerConfig) hostConfig() *enginecontainer.HostConfig {
	return &enginecontainer.HostConfig{
		Resources: c.resources(),
		Binds:     c.bindMounts(),
	}
}

// This handles the case of volumes that are defined inside a service Mount
func (c *containerConfig) volumeCreateRequest(mount *api.Mount) *types.VolumeCreateRequest {
	var (
		driverName string
		driverOpts map[string]string
		labels     map[string]string
	)

	if mount.VolumeOptions != nil && mount.VolumeOptions.DriverConfig != nil {
		driverName = mount.VolumeOptions.DriverConfig.Name
		driverOpts = mount.VolumeOptions.DriverConfig.Options
		labels = mount.VolumeOptions.Labels
	}

	if mount.VolumeOptions != nil {
		return &types.VolumeCreateRequest{
			Name:       mount.Source,
			Driver:     driverName,
			DriverOpts: driverOpts,
			Labels:     labels,
		}
	}
	return nil
}

func (c *containerConfig) resources() enginecontainer.Resources {
	resources := enginecontainer.Resources{}

	// If no limits are specified let the engine use its defaults.
	//
	// TODO(aluzzardi): We might want to set some limits anyway otherwise
	// "unlimited" tasks will step over the reservation of other tasks.
	r := c.task.Spec.Resources
	if r == nil || r.Limits == nil {
		return resources
	}

	if r.Limits.MemoryBytes > 0 {
		resources.Memory = r.Limits.MemoryBytes
	}

	if r.Limits.NanoCPUs > 0 {
		// CPU Period must be set in microseconds.
		resources.CPUPeriod = int64(cpuQuotaPeriod / time.Microsecond)
		resources.CPUQuota = r.Limits.NanoCPUs * resources.CPUPeriod / 1e9
	}

	return resources
}

// Docker daemon supports just 1 network during container create.
func (c *containerConfig) createNetworkingConfig() *network.NetworkingConfig {
	var networks []*api.NetworkAttachment
	if c.task.Spec.GetContainer() != nil {
		networks = c.task.Networks
	}

	epConfig := make(map[string]*network.EndpointSettings)
	if len(networks) > 0 {
		epConfig[networks[0].Network.Spec.Annotations.Name] = getEndpointConfig(networks[0])
	}

	return &network.NetworkingConfig{EndpointsConfig: epConfig}
}

// TODO: Merge this function with createNetworkingConfig after daemon supports multiple networks in container create
func (c *containerConfig) connectNetworkingConfig() *network.NetworkingConfig {
	var networks []*api.NetworkAttachment
	if c.task.Spec.GetContainer() != nil {
		networks = c.task.Networks
	}

	// First network is used during container create. Other networks are used in "docker network connect"
	if len(networks) < 2 {
		return nil
	}

	epConfig := make(map[string]*network.EndpointSettings)
	for _, na := range networks[1:] {
		epConfig[na.Network.Spec.Annotations.Name] = getEndpointConfig(na)
	}
	return &network.NetworkingConfig{EndpointsConfig: epConfig}
}

func getEndpointConfig(na *api.NetworkAttachment) *network.EndpointSettings {
	var ipv4, ipv6 string
	for _, addr := range na.Addresses {
		ip, _, err := net.ParseCIDR(addr)
		if err != nil {
			continue
		}

		if ip.To4() != nil {
			ipv4 = ip.String()
			continue
		}

		if ip.To16() != nil {
			ipv6 = ip.String()
		}
	}

	return &network.EndpointSettings{
		IPAMConfig: &network.EndpointIPAMConfig{
			IPv4Address: ipv4,
			IPv6Address: ipv6,
		},
	}
}

func (c *containerConfig) virtualIP(networkID string) string {
	if c.task.Endpoint == nil {
		return ""
	}

	for _, eVip := range c.task.Endpoint.VirtualIPs {
		// We only support IPv4 VIPs for now.
		if eVip.NetworkID == networkID {
			vip, _, err := net.ParseCIDR(eVip.Addr)
			if err != nil {
				return ""
			}

			return vip.String()
		}
	}

	return ""
}

func (c *containerConfig) serviceConfig() *clustertypes.ServiceConfig {
	if len(c.task.Networks) == 0 {
		return nil
	}

	logrus.Debugf("Creating service config in agent for t = %+v", c.task)
	svcCfg := &clustertypes.ServiceConfig{
		Name:             c.task.ServiceAnnotations.Name,
		Aliases:          make(map[string][]string),
		ID:               c.task.ServiceID,
		VirtualAddresses: make(map[string]*clustertypes.VirtualAddress),
	}

	for _, na := range c.task.Networks {
		svcCfg.VirtualAddresses[na.Network.ID] = &clustertypes.VirtualAddress{
			// We support only IPv4 virtual IP for now.
			IPv4: c.virtualIP(na.Network.ID),
		}
		if len(na.Aliases) > 0 {
			svcCfg.Aliases[na.Network.ID] = na.Aliases
		}
	}

	if c.task.Endpoint != nil {
		for _, ePort := range c.task.Endpoint.Ports {
			svcCfg.ExposedPorts = append(svcCfg.ExposedPorts, &clustertypes.PortConfig{
				Name:          ePort.Name,
				Protocol:      int32(ePort.Protocol),
				TargetPort:    ePort.TargetPort,
				PublishedPort: ePort.PublishedPort,
			})
		}
	}

	return svcCfg
}

// networks returns a list of network names attached to the container. The
// returned name can be used to lookup the corresponding network create
// options.
func (c *containerConfig) networks() []string {
	var networks []string

	for name := range c.networksAttachments {
		networks = append(networks, name)
	}

	return networks
}

func (c *containerConfig) networkCreateRequest(name string) (clustertypes.NetworkCreateRequest, error) {
	na, ok := c.networksAttachments[name]
	if !ok {
		return clustertypes.NetworkCreateRequest{}, errors.New("container: unknown network referenced")
	}

	options := types.NetworkCreate{
		// ID:     na.Network.ID,
		Driver: na.Network.DriverState.Name,
		IPAM: network.IPAM{
			Driver: na.Network.IPAM.Driver.Name,
		},
		Options:        na.Network.DriverState.Options,
		CheckDuplicate: true,
	}

	for _, ic := range na.Network.IPAM.Configs {
		c := network.IPAMConfig{
			Subnet:  ic.Subnet,
			IPRange: ic.Range,
			Gateway: ic.Gateway,
		}
		options.IPAM.Config = append(options.IPAM.Config, c)
	}

	return clustertypes.NetworkCreateRequest{na.Network.ID, types.NetworkCreateRequest{Name: name, NetworkCreate: options}}, nil
}
<commit_msg>Added missing flags for swarm-mode networks<commit_after>package container

import (
	"errors"
	"fmt"
	"net"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"

	clustertypes "github.com/docker/docker/daemon/cluster/provider"
	"github.com/docker/docker/reference"
	"github.com/docker/engine-api/types"
	enginecontainer "github.com/docker/engine-api/types/container"
	"github.com/docker/engine-api/types/network"
	"github.com/docker/swarmkit/agent/exec"
	"github.com/docker/swarmkit/api"
)

const (
	// Explicitly use the kernel's default setting for CPU quota of 100ms.
	// https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
	cpuQuotaPeriod = 100 * time.Millisecond

	// systemLabelPrefix represents the reserved namespace for system labels.
	systemLabelPrefix = "com.docker.swarm"
)

// containerConfig converts task properties into docker container compatible
// components.
type containerConfig struct {
	task                *api.Task
	networksAttachments map[string]*api.NetworkAttachment
}

// newContainerConfig returns a validated container config. No methods should
// return an error if this function returns without error.
func newContainerConfig(t *api.Task) (*containerConfig, error) {
	var c containerConfig
	return &c, c.setTask(t)
}

func (c *containerConfig) setTask(t *api.Task) error {
	container := t.Spec.GetContainer()
	if container == nil {
		return exec.ErrRuntimeUnsupported
	}

	if container.Image == "" {
		return ErrImageRequired
	}

	// index the networks by name
	c.networksAttachments = make(map[string]*api.NetworkAttachment, len(t.Networks))
	for _, attachment := range t.Networks {
		c.networksAttachments[attachment.Network.Spec.Annotations.Name] = attachment
	}

	c.task = t
	return nil
}

func (c *containerConfig) endpoint() *api.Endpoint {
	return c.task.Endpoint
}

func (c *containerConfig) spec() *api.ContainerSpec {
	return c.task.Spec.GetContainer()
}

func (c *containerConfig) name() string {
	if c.task.Annotations.Name != "" {
		// if set, use the container Annotations.Name field, set in the orchestrator.
		return c.task.Annotations.Name
	}

	// fallback to service.slot.id.
	return strings.Join([]string{c.task.ServiceAnnotations.Name, fmt.Sprint(c.task.Slot), c.task.ID}, ".")
}

func (c *containerConfig) image() string {
	raw := c.spec().Image
	ref, err := reference.ParseNamed(raw)
	if err != nil {
		return raw
	}
	return reference.WithDefaultTag(ref).String()
}

func (c *containerConfig) volumes() map[string]struct{} {
	r := make(map[string]struct{})

	for _, mount := range c.spec().Mounts {
		// pick off all the volume mounts.
		if mount.Type != api.MountTypeVolume {
			continue
		}

		r[fmt.Sprintf("%s:%s", mount.Target, getMountMask(&mount))] = struct{}{}
	}

	return r
}

func (c *containerConfig) config() *enginecontainer.Config {
	config := &enginecontainer.Config{
		Labels:     c.labels(),
		User:       c.spec().User,
		Env:        c.spec().Env,
		WorkingDir: c.spec().Dir,
		Image:      c.image(),
		Volumes:    c.volumes(),
	}

	if len(c.spec().Command) > 0 {
		// If Command is provided, we replace the whole invocation with Command
		// by replacing Entrypoint and specifying Cmd. Args is ignored in this
		// case.
		config.Entrypoint = append(config.Entrypoint, c.spec().Command[0])
		config.Cmd = append(config.Cmd, c.spec().Command[1:]...)
	} else if len(c.spec().Args) > 0 {
		// In this case, we assume the image has an Entrypoint and Args
		// specifies the arguments for that entrypoint.
		config.Cmd = c.spec().Args
	}

	return config
}

func (c *containerConfig) labels() map[string]string {
	var (
		system = map[string]string{
			"task":         "", // mark as cluster task
			"task.id":      c.task.ID,
			"task.name":    fmt.Sprintf("%v.%v", c.task.ServiceAnnotations.Name, c.task.Slot),
			"node.id":      c.task.NodeID,
			"service.id":   c.task.ServiceID,
			"service.name": c.task.ServiceAnnotations.Name,
		}
		labels = make(map[string]string)
	)

	// base labels are those defined in the spec.
	for k, v := range c.spec().Labels {
		labels[k] = v
	}

	// we then apply the overrides from the task, which may be set via the
	// orchestrator.
	for k, v := range c.task.Annotations.Labels {
		labels[k] = v
	}

	// finally, we apply the system labels, which override all labels.
	for k, v := range system {
		labels[strings.Join([]string{systemLabelPrefix, k}, ".")] = v
	}

	return labels
}

func (c *containerConfig) bindMounts() []string {
	var r []string

	for _, val := range c.spec().Mounts {
		mask := getMountMask(&val)
		if val.Type == api.MountTypeBind {
			r = append(r, fmt.Sprintf("%s:%s:%s", val.Source, val.Target, mask))
		}
	}

	return r
}

func getMountMask(m *api.Mount) string {
	maskOpts := []string{"ro"}
	if m.Writable {
		maskOpts[0] = "rw"
	}

	if m.BindOptions != nil {
		switch m.BindOptions.Propagation {
		case api.MountPropagationPrivate:
			maskOpts = append(maskOpts, "private")
		case api.MountPropagationRPrivate:
			maskOpts = append(maskOpts, "rprivate")
		case api.MountPropagationShared:
			maskOpts = append(maskOpts, "shared")
		case api.MountPropagationRShared:
			maskOpts = append(maskOpts, "rshared")
		case api.MountPropagationSlave:
			maskOpts = append(maskOpts, "slave")
		case api.MountPropagationRSlave:
			maskOpts = append(maskOpts, "rslave")
		}
	}

	if m.VolumeOptions != nil {
		if !m.VolumeOptions.Populate {
			maskOpts = append(maskOpts, "nocopy")
		}
	}
	return strings.Join(maskOpts, ",")
}

func (c *containerConfig) hostConfig() *enginecontainer.HostConfig {
	return &enginecontainer.HostConfig{
		Resources: c.resources(),
		Binds:     c.bindMounts(),
	}
}

// This handles the case of volumes that are defined inside a service Mount
func (c *containerConfig) volumeCreateRequest(mount *api.Mount) *types.VolumeCreateRequest {
	var (
		driverName string
		driverOpts map[string]string
		labels     map[string]string
	)

	if mount.VolumeOptions != nil && mount.VolumeOptions.DriverConfig != nil {
		driverName = mount.VolumeOptions.DriverConfig.Name
		driverOpts = mount.VolumeOptions.DriverConfig.Options
		labels = mount.VolumeOptions.Labels
	}

	if mount.VolumeOptions != nil {
		return &types.VolumeCreateRequest{
			Name:       mount.Source,
			Driver:     driverName,
			DriverOpts: driverOpts,
			Labels:     labels,
		}
	}
	return nil
}

func (c *containerConfig) resources() enginecontainer.Resources {
	resources := enginecontainer.Resources{}

	// If no limits are specified let the engine use its defaults.
	//
	// TODO(aluzzardi): We might want to set some limits anyway otherwise
	// "unlimited" tasks will step over the reservation of other tasks.
	r := c.task.Spec.Resources
	if r == nil || r.Limits == nil {
		return resources
	}

	if r.Limits.MemoryBytes > 0 {
		resources.Memory = r.Limits.MemoryBytes
	}

	if r.Limits.NanoCPUs > 0 {
		// CPU Period must be set in microseconds.
		resources.CPUPeriod = int64(cpuQuotaPeriod / time.Microsecond)
		resources.CPUQuota = r.Limits.NanoCPUs * resources.CPUPeriod / 1e9
	}

	return resources
}

// Docker daemon supports just 1 network during container create.
func (c *containerConfig) createNetworkingConfig() *network.NetworkingConfig {
	var networks []*api.NetworkAttachment
	if c.task.Spec.GetContainer() != nil {
		networks = c.task.Networks
	}

	epConfig := make(map[string]*network.EndpointSettings)
	if len(networks) > 0 {
		epConfig[networks[0].Network.Spec.Annotations.Name] = getEndpointConfig(networks[0])
	}

	return &network.NetworkingConfig{EndpointsConfig: epConfig}
}

// TODO: Merge this function with createNetworkingConfig after daemon supports multiple networks in container create
func (c *containerConfig) connectNetworkingConfig() *network.NetworkingConfig {
	var networks []*api.NetworkAttachment
	if c.task.Spec.GetContainer() != nil {
		networks = c.task.Networks
	}

	// First network is used during container create. Other networks are used in "docker network connect"
	if len(networks) < 2 {
		return nil
	}

	epConfig := make(map[string]*network.EndpointSettings)
	for _, na := range networks[1:] {
		epConfig[na.Network.Spec.Annotations.Name] = getEndpointConfig(na)
	}
	return &network.NetworkingConfig{EndpointsConfig: epConfig}
}

func getEndpointConfig(na *api.NetworkAttachment) *network.EndpointSettings {
	var ipv4, ipv6 string
	for _, addr := range na.Addresses {
		ip, _, err := net.ParseCIDR(addr)
		if err != nil {
			continue
		}

		if ip.To4() != nil {
			ipv4 = ip.String()
			continue
		}

		if ip.To16() != nil {
			ipv6 = ip.String()
		}
	}

	return &network.EndpointSettings{
		IPAMConfig: &network.EndpointIPAMConfig{
			IPv4Address: ipv4,
			IPv6Address: ipv6,
		},
	}
}

func (c *containerConfig) virtualIP(networkID string) string {
	if c.task.Endpoint == nil {
		return ""
	}

	for _, eVip := range c.task.Endpoint.VirtualIPs {
		// We only support IPv4 VIPs for now.
		if eVip.NetworkID == networkID {
			vip, _, err := net.ParseCIDR(eVip.Addr)
			if err != nil {
				return ""
			}

			return vip.String()
		}
	}

	return ""
}

func (c *containerConfig) serviceConfig() *clustertypes.ServiceConfig {
	if len(c.task.Networks) == 0 {
		return nil
	}

	logrus.Debugf("Creating service config in agent for t = %+v", c.task)
	svcCfg := &clustertypes.ServiceConfig{
		Name:             c.task.ServiceAnnotations.Name,
		Aliases:          make(map[string][]string),
		ID:               c.task.ServiceID,
		VirtualAddresses: make(map[string]*clustertypes.VirtualAddress),
	}

	for _, na := range c.task.Networks {
		svcCfg.VirtualAddresses[na.Network.ID] = &clustertypes.VirtualAddress{
			// We support only IPv4 virtual IP for now.
			IPv4: c.virtualIP(na.Network.ID),
		}
		if len(na.Aliases) > 0 {
			svcCfg.Aliases[na.Network.ID] = na.Aliases
		}
	}

	if c.task.Endpoint != nil {
		for _, ePort := range c.task.Endpoint.Ports {
			svcCfg.ExposedPorts = append(svcCfg.ExposedPorts, &clustertypes.PortConfig{
				Name:          ePort.Name,
				Protocol:      int32(ePort.Protocol),
				TargetPort:    ePort.TargetPort,
				PublishedPort: ePort.PublishedPort,
			})
		}
	}

	return svcCfg
}

// networks returns a list of network names attached to the container. The
// returned name can be used to lookup the corresponding network create
// options.
func (c *containerConfig) networks() []string {
	var networks []string

	for name := range c.networksAttachments {
		networks = append(networks, name)
	}

	return networks
}

func (c *containerConfig) networkCreateRequest(name string) (clustertypes.NetworkCreateRequest, error) {
	na, ok := c.networksAttachments[name]
	if !ok {
		return clustertypes.NetworkCreateRequest{}, errors.New("container: unknown network referenced")
	}

	options := types.NetworkCreate{
		// ID:     na.Network.ID,
		Driver: na.Network.DriverState.Name,
		IPAM: network.IPAM{
			Driver: na.Network.IPAM.Driver.Name,
		},
		Options:        na.Network.DriverState.Options,
		Labels:         na.Network.Spec.Annotations.Labels,
		Internal:       na.Network.Spec.Internal,
		EnableIPv6:     na.Network.Spec.Ipv6Enabled,
		CheckDuplicate: true,
	}

	for _, ic := range na.Network.IPAM.Configs {
		c := network.IPAMConfig{
			Subnet:  ic.Subnet,
			IPRange: ic.Range,
			Gateway: ic.Gateway,
		}
		options.IPAM.Config = append(options.IPAM.Config, c)
	}

	return clustertypes.NetworkCreateRequest{na.Network.ID, types.NetworkCreateRequest{Name: name, NetworkCreate: options}}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

var cmdLogout = &Command{
	Usage: "logout",
	Short: "Log out from force.com",
	Long: `
  force logout -u=username

  Example:

    force logout -u=user@example.org
`,
}

func init() {
	cmdLogout.Run = runLogout
}

var (
	userName1 = cmdLogout.Flag.String("u", "", "Username for Soap Login")
)

func runLogout(cmd *Command, args []string) {
	if *userName1 == "" {
		fmt.Println("Missing required argument...")
		cmd.Flag.Usage()
	}
	Config.Delete("accounts", *userName1)
	if active, _ := Config.Load("current", "account"); active == *userName1 {
		Config.Delete("current", "account")
		SetActiveLoginDefault()
	}
}
<commit_msg>fix terminal title for logout<commit_after>package main

import (
	"fmt"
	"runtime"
	"os/exec"
)

var cmdLogout = &Command{
	Usage: "logout",
	Short: "Log out from force.com",
	Long: `
  force logout -u=username

  Example:

    force logout -u=user@example.org
`,
}

func init() {
	cmdLogout.Run = runLogout
}

var (
	userName1 = cmdLogout.Flag.String("u", "", "Username for Soap Login")
)

func runLogout(cmd *Command, args []string) {
	if *userName1 == "" {
		fmt.Println("Missing required argument...")
		cmd.Flag.Usage()
	}
	Config.Delete("accounts", *userName1)
	if active, _ := Config.Load("current", "account"); active == *userName1 {
		Config.Delete("current", "account")
		SetActiveLoginDefault()
	}
	if runtime.GOOS == "windows" {
		cmd := exec.Command("title", account)
		cmd.Run()
	} else {
		title := fmt.Sprintf("\033];%s\007", "")
		fmt.Printf(title)
	}
}
<|endoftext|>


<commit_before>package lua

var lua_type = luaDLL.NewProc("lua_type")

func (this *Lua) GetType(index int) int {
	rv, _, _ := lua_type.Call(this.State(), uintptr(index))
	return int(rv)
}

// 'lua_isfunction' is implemented as C-macro in the header file.
func (this *Lua) IsFunction(index int) bool {
	return this.GetType(index) == LUA_TFUNCTION
}

var lua_isstring = luaDLL.NewProc("lua_isstring")

func (this *Lua) IsString(index int) bool {
	rc, _, _ := lua_isstring.Call(this.State(), uintptr(index))
	return rc != 0
}
<commit_msg>Add lua.IsTable()<commit_after>package lua

var lua_type = luaDLL.NewProc("lua_type")

func (this *Lua) GetType(index int) int {
	rv, _, _ := lua_type.Call(this.State(), uintptr(index))
	return int(rv)
}

// 'lua_isfunction' is implemented as C-macro in the header file.
func (this *Lua) IsFunction(index int) bool {
	return this.GetType(index) == LUA_TFUNCTION
}

// 'lua_istable' is implemented as C-macro in the header file.
func (this *Lua) IsTable(index int) bool {
	return this.GetType(index) == LUA_TTABLE
}

var lua_isstring = luaDLL.NewProc("lua_isstring")

func (this *Lua) IsString(index int) bool {
	rc, _, _ := lua_isstring.Call(this.State(), uintptr(index))
	return rc != 0
}
<|endoftext|>


<commit_before>package smpp34

import (
	"bufio"
	"crypto/tls"
	"encoding/hex"
	"fmt"
	"net"
	"strconv"
	"sync"
)

var Debug bool

type NewSeqNumFunc func() uint32

type Smpp struct {
	Mu            sync.Mutex
	conn          net.Conn
	reader        *bufio.Reader
	writer        *bufio.Writer
	Sequence      uint32
	Bound         bool
	NewSeqNumFunc NewSeqNumFunc
}

type SmppErr string
type SmppBindAuthErr string

type Params map[string]interface{}

const (
	SmppBindRespErr SmppErr = "BIND Resp not received"
	SmppPduErr      SmppErr = "PDU out of spec for this connection type"
	SmppPduSizeErr  SmppErr = "PDU Len larger than MAX_PDU_SIZE"
	SmppPduLenErr   SmppErr = "PDU Len different than read bytes"
	SmppELWriteErr  SmppErr = "Error writing ELR PDU"
	SmppELRespErr   SmppErr = "No enquire link response"
)

func (p SmppErr) Error() string {
	return string(p)
}

func (p SmppBindAuthErr) Error() string {
	return string(p)
}

func NewSmppConnect(host string, port int) (*Smpp, error) {
	s := &Smpp{}

	err := s.Connect(host, port)

	return s, err
}

func (s *Smpp) Connect(host string, port int) (err error) {
	s.conn, err = net.Dial("tcp", host+":"+strconv.Itoa(port))

	return err
}

func NewSmppConnectTLS(host string, port int, config *tls.Config) (*Smpp, error) {
	s := &Smpp{}

	err := s.ConnectTLS(host, port, config)

	return s, err
}

func (s *Smpp) ConnectTLS(host string, port int, config *tls.Config) error {
	conn, err := net.Dial("tcp", host+":"+strconv.Itoa(port))
	if err != nil {
		return err
	}
	if config == nil {
		config = &tls.Config{}
	}
	s.conn = tls.Client(conn, config)
	return err
}

func (s *Smpp) NewSeqNum() uint32 {
	if s.NewSeqNumFunc != nil {
		return s.NewSeqNumFunc()
	}

	defer s.Mu.Unlock()

	s.Mu.Lock()
	s.Sequence++
	return s.Sequence
}

func (s *Smpp) Bind(cmdId CMDId, system_id string, password string, params *Params) (Pdu, error) {
	b, _ := NewBind(
		&Header{Id: cmdId},
		[]byte{},
	)

	b.SetField(INTERFACE_VERSION, 0x34)
	b.SetField(SYSTEM_ID, system_id)
	b.SetField(PASSWORD, password)
	b.SetSeqNum(s.NewSeqNum())

	for f, v := range *params {
		err := b.SetField(f, v)

		if err != nil {
			return nil, err
		}
	}

	return Pdu(b), nil
}

func (s *Smpp) BindResp(cmdId CMDId, seq uint32, status CMDStatus, sysId string) (Pdu, error) {
	p, _ := NewBindResp(
		&Header{
			Id:       cmdId,
			Status:   status,
			Sequence: seq,
		},
		[]byte{},
	)

	p.SetField(SYSTEM_ID, sysId)
	p.SetTLVField(0x0210, 1, []byte{0x34}) // sc_interface_version TLV

	return Pdu(p), nil
}

func (s *Smpp) EnquireLink() (Pdu, error) {
	p, _ := NewEnquireLink(
		&Header{
			Id:       ENQUIRE_LINK,
			Sequence: s.NewSeqNum(),
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) EnquireLinkResp(seq uint32) (Pdu, error) {
	p, _ := NewEnquireLinkResp(
		&Header{
			Id:       ENQUIRE_LINK_RESP,
			Status:   ESME_ROK,
			Sequence: seq,
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) SubmitSm(source_addr, destination_addr, short_message string, params *Params) (Pdu, error) {

	p, _ := NewSubmitSm(
		&Header{
			Id:       SUBMIT_SM,
			Sequence: s.NewSeqNum(),
		},
		[]byte{},
	)

	p.SetField(SOURCE_ADDR, source_addr)
	p.SetField(DESTINATION_ADDR, destination_addr)
	p.SetField(SHORT_MESSAGE, short_message)

	for f, v := range *params {
		err := p.SetField(f, v)

		if err != nil {
			return nil, err
		}
	}

	return p, nil
}

func (s *Smpp) SubmitSmResp(seq uint32, status CMDStatus, messageId string) (Pdu, error) {
	p, _ := NewSubmitSmResp(
		&Header{
			Id:       SUBMIT_SM_RESP,
			Status:   status,
			Sequence: seq,
		},
		[]byte{},
	)

	p.SetField(MESSAGE_ID, messageId)

	return Pdu(p), nil
}

func (s *Smpp) QuerySm(message_id, source_addr string, params *Params) (Pdu, error) {

	p, _ := NewQuerySm(
		&Header{
			Id:       QUERY_SM,
			Sequence: s.NewSeqNum(),
		},
		[]byte{},
	)

	p.SetField(MESSAGE_ID, message_id)
	p.SetField(SOURCE_ADDR, source_addr)

	for f, v := range *params {
		err := p.SetField(f, v)

		if err != nil {
			return nil, err
		}
	}

	return p, nil
}

func (s *Smpp) Unbind() (Pdu, error) {
	p, _ := NewUnbind(
		&Header{
			Id:       UNBIND,
			Sequence: s.NewSeqNum(),
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) UnbindResp(seq uint32) (Pdu, error) {
	p, _ := NewUnbindResp(
		&Header{
			Id:       UNBIND_RESP,
			Sequence: seq,
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) DeliverSmResp(seq uint32, status CMDStatus) (Pdu, error) {
	p, _ := NewDeliverSmResp(
		&Header{
			Id:       DELIVER_SM_RESP,
			Status:   status,
			Sequence: seq,
		},
		[]byte{},
	)

	return Pdu(p), nil
}

func (s *Smpp) GenericNack(seq uint32, status CMDStatus) (Pdu, error) {
	p, _ := NewGenericNack(
		&Header{
			Id:       GENERIC_NACK,
			Status:   status,
			Sequence: seq,
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) Read() (Pdu, error) {
	l := make([]byte, 4)
	_, err := s.conn.Read(l)
	if err != nil {
		return nil, err
	}

	pduLength := unpackUi32(l) - 4
	if pduLength > MAX_PDU_SIZE {
		return nil, SmppPduSizeErr
	}

	data := make([]byte, pduLength)

	i, err := s.conn.Read(data)
	if err != nil {
		return nil, err
	}

	if i != int(pduLength) {
		return nil, SmppPduLenErr
	}

	pkt := append(l, data...)
	if Debug {
		fmt.Println(hex.Dump(pkt))
	}

	pdu, err := ParsePdu(pkt)
	if err != nil {
		return nil, err
	}

	return pdu, nil
}

func (s *Smpp) Write(p Pdu) error {
	_, err := s.conn.Write(p.Writer())

	if Debug {
		fmt.Println(hex.Dump(p.Writer()))
	}

	return err
}

func (s *Smpp) Close() {
	s.conn.Close()
}
<commit_msg>move Smpp.Read to SmppReadFrom in order to parse PDU from plain net.Conn; e.g. in test SMPP server (based on plain TCP server);<commit_after>package smpp34

import (
	"bufio"
	"crypto/tls"
	"encoding/hex"
	"fmt"
	"net"
	"strconv"
	"sync"
)

var Debug bool

type NewSeqNumFunc func() uint32

type Smpp struct {
	Mu            sync.Mutex
	conn          net.Conn
	reader        *bufio.Reader
	writer        *bufio.Writer
	Sequence      uint32
	Bound         bool
	NewSeqNumFunc NewSeqNumFunc
}

type SmppErr string
type SmppBindAuthErr string

type Params map[string]interface{}

const (
	SmppBindRespErr SmppErr = "BIND Resp not received"
	SmppPduErr      SmppErr = "PDU out of spec for this connection type"
	SmppPduSizeErr  SmppErr = "PDU Len larger than MAX_PDU_SIZE"
	SmppPduLenErr   SmppErr = "PDU Len different than read bytes"
	SmppELWriteErr  SmppErr = "Error writing ELR PDU"
	SmppELRespErr   SmppErr = "No enquire link response"
)

func (p SmppErr) Error() string {
	return string(p)
}

func (p SmppBindAuthErr) Error() string {
	return string(p)
}

func NewSmppConnect(host string, port int) (*Smpp, error) {
	s := &Smpp{}

	err := s.Connect(host, port)

	return s, err
}

func (s *Smpp) Connect(host string, port int) (err error) {
	s.conn, err = net.Dial("tcp", host+":"+strconv.Itoa(port))

	return err
}

func NewSmppConnectTLS(host string, port int, config *tls.Config) (*Smpp, error) {
	s := &Smpp{}

	err := s.ConnectTLS(host, port, config)

	return s, err
}

func (s *Smpp) ConnectTLS(host string, port int, config *tls.Config) error {
	conn, err := net.Dial("tcp", host+":"+strconv.Itoa(port))
	if err != nil {
		return err
	}
	if config == nil {
		config = &tls.Config{}
	}
	s.conn = tls.Client(conn, config)
	return err
}

func (s *Smpp) NewSeqNum() uint32 {
	if s.NewSeqNumFunc != nil {
		return s.NewSeqNumFunc()
	}

	defer s.Mu.Unlock()

	s.Mu.Lock()
	s.Sequence++
	return s.Sequence
}

func (s *Smpp) Bind(cmdId CMDId, system_id string, password string, params *Params) (Pdu, error) {
	b, _ := NewBind(
		&Header{Id: cmdId},
		[]byte{},
	)

	b.SetField(INTERFACE_VERSION, 0x34)
	b.SetField(SYSTEM_ID, system_id)
	b.SetField(PASSWORD, password)
	b.SetSeqNum(s.NewSeqNum())

	for f, v := range *params {
		err := b.SetField(f, v)

		if err != nil {
			return nil, err
		}
	}

	return Pdu(b), nil
}

func (s *Smpp) BindResp(cmdId CMDId, seq uint32, status CMDStatus, sysId string) (Pdu, error) {
	p, _ := NewBindResp(
		&Header{
			Id:       cmdId,
			Status:   status,
			Sequence: seq,
		},
		[]byte{},
	)

	p.SetField(SYSTEM_ID, sysId)
	p.SetTLVField(0x0210, 1, []byte{0x34}) // sc_interface_version TLV

	return Pdu(p), nil
}

func (s *Smpp) EnquireLink() (Pdu, error) {
	p, _ := NewEnquireLink(
		&Header{
			Id:       ENQUIRE_LINK,
			Sequence: s.NewSeqNum(),
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) EnquireLinkResp(seq uint32) (Pdu, error) {
	p, _ := NewEnquireLinkResp(
		&Header{
			Id:       ENQUIRE_LINK_RESP,
			Status:   ESME_ROK,
			Sequence: seq,
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) SubmitSm(source_addr, destination_addr, short_message string, params *Params) (Pdu, error) {

	p, _ := NewSubmitSm(
		&Header{
			Id:       SUBMIT_SM,
			Sequence: s.NewSeqNum(),
		},
		[]byte{},
	)

	p.SetField(SOURCE_ADDR, source_addr)
	p.SetField(DESTINATION_ADDR, destination_addr)
	p.SetField(SHORT_MESSAGE, short_message)

	for f, v := range *params {
		err := p.SetField(f, v)

		if err != nil {
			return nil, err
		}
	}

	return p, nil
}

func (s *Smpp) SubmitSmResp(seq uint32, status CMDStatus, messageId string) (Pdu, error) {
	p, _ := NewSubmitSmResp(
		&Header{
			Id:       SUBMIT_SM_RESP,
			Status:   status,
			Sequence: seq,
		},
		[]byte{},
	)

	p.SetField(MESSAGE_ID, messageId)

	return Pdu(p), nil
}

func (s *Smpp) QuerySm(message_id, source_addr string, params *Params) (Pdu, error) {

	p, _ := NewQuerySm(
		&Header{
			Id:       QUERY_SM,
			Sequence: s.NewSeqNum(),
		},
		[]byte{},
	)

	p.SetField(MESSAGE_ID, message_id)
	p.SetField(SOURCE_ADDR, source_addr)

	for f, v := range *params {
		err := p.SetField(f, v)

		if err != nil {
			return nil, err
		}
	}

	return p, nil
}

func (s *Smpp) Unbind() (Pdu, error) {
	p, _ := NewUnbind(
		&Header{
			Id:       UNBIND,
			Sequence: s.NewSeqNum(),
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) UnbindResp(seq uint32) (Pdu, error) {
	p, _ := NewUnbindResp(
		&Header{
			Id:       UNBIND_RESP,
			Sequence: seq,
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) DeliverSmResp(seq uint32, status CMDStatus) (Pdu, error) {
	p, _ := NewDeliverSmResp(
		&Header{
			Id:       DELIVER_SM_RESP,
			Status:   status,
			Sequence: seq,
		},
		[]byte{},
	)

	return Pdu(p), nil
}

func (s *Smpp) GenericNack(seq uint32, status CMDStatus) (Pdu, error) {
	p, _ := NewGenericNack(
		&Header{
			Id:       GENERIC_NACK,
			Status:   status,
			Sequence: seq,
		},
	)

	return Pdu(p), nil
}

func (s *Smpp) Read() (Pdu, error) { return SmppReadFrom(s.conn) }

func (s *Smpp) Write(p Pdu) error {
	_, err := s.conn.Write(p.Writer())

	if Debug {
		fmt.Println(hex.Dump(p.Writer()))
	}

	return err
}

func (s *Smpp) Close() {
	s.conn.Close()
}

func SmppReadFrom(conn net.Conn) (Pdu, error) {
	l := make([]byte, 4)
	_, err := conn.Read(l)
	if err != nil {
		return nil, err
	}

	pduLength := unpackUi32(l) - 4
	if pduLength > MAX_PDU_SIZE {
		return nil, SmppPduSizeErr
	}

	data := make([]byte, pduLength)

	i, err := conn.Read(data)
	if err != nil {
		return nil, err
	}

	if i != int(pduLength) {
		return nil, SmppPduLenErr
	}

	pkt := append(l, data...)
	if Debug {
		fmt.Println(hex.Dump(pkt))
	}

	pdu, err := ParsePdu(pkt)
	if err != nil {
		return nil, err
	}

	return pdu, nil
}
<|endoftext|>


<commit_before>package main

import (
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
)

type EtcdClusterList struct {
	unversioned.TypeMeta `json:",inline"`
	// Standard list metadata
	// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
	unversioned.ListMeta `json:"metadata,omitempty"`
	// Items is a list of third party objects
	Items []EtcdCluster `json:"items"`
}

type EtcdCluster struct {
	unversioned.TypeMeta `json:",inline"`
	api.ObjectMeta       `json:"metadata,omitempty"`
	Spec                 Spec `json: "spec"`
}

type Spec struct {
	// Size is the expected size of the etcd cluster.
	// The controller will eventually make the size of the running
	// cluster equal to the expected size.
	// The vaild range of the size is from 1 to 7.
	Size int `json:"size"`
	// AntiAffinity determines if the controller tries to avoid putting
	// the etcd members in the same cluster onto the same node.
	AntiAffinity bool `json:"antiAffinity"`
	// Version is the expected version of the etcd cluster.
	// The controller will eventually make the etcd cluster version
	// equal to the expected version.
	Version string `json:"version"`
}
<commit_msg>add backup into spec<commit_after>package main

import (
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
)

type EtcdClusterList struct {
	unversioned.TypeMeta `json:",inline"`
	// Standard list metadata
	// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
	unversioned.ListMeta `json:"metadata,omitempty"`
	// Items is a list of third party objects
	Items []EtcdCluster `json:"items"`
}

type EtcdCluster struct {
	unversioned.TypeMeta `json:",inline"`
	api.ObjectMeta       `json:"metadata,omitempty"`
	Spec                 Spec `json: "spec"`
}

type Spec struct {
	// Size is the expected size of the etcd cluster.
	// The controller will eventually make the size of the running
	// cluster equal to the expected size.
	// The vaild range of the size is from 1 to 7.
	Size int `json:"size"`
	// AntiAffinity determines if the controller tries to avoid putting
	// the etcd members in the same cluster onto the same node.
	AntiAffinity bool `json:"antiAffinity"`
	// Version is the expected version of the etcd cluster.
	// The controller will eventually make the etcd cluster version
	// equal to the expected version.
	Version string `json:"version"`
	// Backup is the backup strategy for the etcd cluster.
	// There is no backup by default.
	Backup Backup `json:"backup"`
}

type Backup struct {
	// MaxSnapshot is the maximum number of snapshot files to retain. 0 is disable backup.
	// If backup is disabled, the etcd cluster cannot recover from a
	// disaster failure (lose more than half of its members at the same
	// time).
	MaxSnapshot int
	// RequiredVolumeSizeInMB specifies the required volume size to perform backups.
	// Controller will claim the required size before creating the etcd cluster for backup
	// purpose.
	// If the snapshot size is larger than the size specified, backup fails.
	RequiredVolumeSizeInMB int
}
<|endoftext|>


<commit_before>package layout

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	"github.com/pkg/errors"

	"github.com/containers/image/manifest"
	"github.com/containers/image/types"
	"github.com/opencontainers/go-digest"
	imgspec "github.com/opencontainers/image-spec/specs-go"
	imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
)

type ociImageDestination struct {
	ref   ociReference
	index imgspecv1.Index
}

// newImageDestination returns an ImageDestination for writing to an existing directory.
func newImageDestination(ref ociReference) (types.ImageDestination, error) {
	if ref.image == "" {
		return nil, errors.Errorf("cannot save image with empty image.ref.name")
	}
	index := imgspecv1.Index{
		Versioned: imgspec.Versioned{
			SchemaVersion: 2,
		},
	}
	return &ociImageDestination{ref: ref, index: index}, nil
}

// Reference returns the reference used to set up this destination.  Note that this should directly correspond to user's intent,
// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects.
func (d *ociImageDestination) Reference() types.ImageReference {
	return d.ref
}

// Close removes resources associated with an initialized ImageDestination, if any.
func (d *ociImageDestination) Close() error {
	return nil
}

func (d *ociImageDestination) SupportedManifestMIMETypes() []string {
	return []string{
		imgspecv1.MediaTypeImageManifest,
	}
}

// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures.
// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil.
func (d *ociImageDestination) SupportsSignatures() error {
	return errors.Errorf("Pushing signatures for OCI images is not supported")
}

// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination.
func (d *ociImageDestination) ShouldCompressLayers() bool {
	return true
}

// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually
// uploaded to the image destination, true otherwise.
func (d *ociImageDestination) AcceptsForeignLayerURLs() bool {
	return false
}

// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise.
func (d *ociImageDestination) MustMatchRuntimeOS() bool {
	return false
}

// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
// WARNING: The contents of stream are being verified on the fly.  Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
// to any other readers for download using the supplied digest.
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
func (d *ociImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) {
	if err := ensureDirectoryExists(d.ref.dir); err != nil {
		return types.BlobInfo{}, err
	}
	blobFile, err := ioutil.TempFile(d.ref.dir, "oci-put-blob")
	if err != nil {
		return types.BlobInfo{}, err
	}
	succeeded := false
	defer func() {
		blobFile.Close()
		if !succeeded {
			os.Remove(blobFile.Name())
		}
	}()

	digester := digest.Canonical.Digester()
	tee := io.TeeReader(stream, digester.Hash())

	size, err := io.Copy(blobFile, tee)
	if err != nil {
		return types.BlobInfo{}, err
	}
	computedDigest := digester.Digest()
	if inputInfo.Size != -1 && size != inputInfo.Size {
		return types.BlobInfo{}, errors.Errorf("Size mismatch when copying %s, expected %d, got %d", computedDigest, inputInfo.Size, size)
	}
	if err := blobFile.Sync(); err != nil {
		return types.BlobInfo{}, err
	}
	if err := blobFile.Chmod(0644); err != nil {
		return types.BlobInfo{}, err
	}

	blobPath, err := d.ref.blobPath(computedDigest)
	if err != nil {
		return types.BlobInfo{}, err
	}
	if err := ensureParentDirectoryExists(blobPath); err != nil {
		return types.BlobInfo{}, err
	}
	if err := os.Rename(blobFile.Name(), blobPath); err != nil {
		return types.BlobInfo{}, err
	}
	succeeded = true
	return types.BlobInfo{Digest: computedDigest, Size: size}, nil
}

// HasBlob returns true iff the image destination already contains a blob with the matching digest which can be reapplied using ReapplyBlob.
// Unlike PutBlob, the digest can not be empty.  If HasBlob returns true, the size of the blob must also be returned.
// If the destination does not contain the blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil);
// it returns a non-nil error only on an unexpected failure.
func (d *ociImageDestination) HasBlob(info types.BlobInfo) (bool, int64, error) {
	if info.Digest == "" {
		return false, -1, errors.Errorf(`"Can not check for a blob with unknown digest`)
	}
	blobPath, err := d.ref.blobPath(info.Digest)
	if err != nil {
		return false, -1, err
	}
	finfo, err := os.Stat(blobPath)
	if err != nil && os.IsNotExist(err) {
		return false, -1, nil
	}
	if err != nil {
		return false, -1, err
	}
	return true, finfo.Size(), nil
}

func (d *ociImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) {
	return info, nil
}

// PutManifest writes manifest to the destination.
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
func (d *ociImageDestination) PutManifest(m []byte) error {
	digest, err := manifest.Digest(m)
	if err != nil {
		return err
	}
	desc := imgspecv1.Descriptor{}
	desc.Digest = digest
	// TODO(runcom): beaware and add support for OCI manifest list
	desc.MediaType = imgspecv1.MediaTypeImageManifest
	desc.Size = int64(len(m))

	blobPath, err := d.ref.blobPath(digest)
	if err != nil {
		return err
	}
	if err := ensureParentDirectoryExists(blobPath); err != nil {
		return err
	}
	if err := ioutil.WriteFile(blobPath, m, 0644); err != nil {
		return err
	}

	annotations := make(map[string]string)
	annotations["org.opencontainers.image.ref.name"] = d.ref.image
	desc.Annotations = annotations
	desc.Platform = &imgspecv1.Platform{
		Architecture: runtime.GOARCH,
		OS:           runtime.GOOS,
	}
	d.index.Manifests = append(d.index.Manifests, desc)

	return nil
}

func ensureDirectoryExists(path string) error {
	if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(path, 0755); err != nil {
			return err
		}
	}
	return nil
}

// ensureParentDirectoryExists ensures the parent of the supplied path exists.
func ensureParentDirectoryExists(path string) error {
	return ensureDirectoryExists(filepath.Dir(path))
}

func (d *ociImageDestination) PutSignatures(signatures [][]byte) error {
	if len(signatures) != 0 {
		return errors.Errorf("Pushing signatures for OCI images is not supported")
	}
	return nil
}

// Commit marks the process of storing the image as successful and asks for the image to be persisted.
// WARNING: This does not have any transactional semantics:
// - Uploaded data MAY be visible to others before Commit() is called
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
func (d *ociImageDestination) Commit() error {
	if err := ioutil.WriteFile(d.ref.ociLayoutPath(), []byte(`{"imageLayoutVersion": "1.0.0"}`), 0644); err != nil {
		return err
	}
	indexJSON, err := json.Marshal(d.index)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(d.ref.indexPath(), indexJSON, 0644)
}
<commit_msg>Fix oci to save the full image name<commit_after>package layout

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	"github.com/pkg/errors"

	"github.com/containers/image/manifest"
	"github.com/containers/image/types"
	"github.com/opencontainers/go-digest"
	imgspec "github.com/opencontainers/image-spec/specs-go"
	imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
)

type ociImageDestination struct {
	ref   ociReference
	index imgspecv1.Index
}

// newImageDestination returns an ImageDestination for writing to an existing directory.
func newImageDestination(ref ociReference) (types.ImageDestination, error) {
	if ref.image == "" {
		return nil, errors.Errorf("cannot save image with empty image.ref.name")
	}
	index := imgspecv1.Index{
		Versioned: imgspec.Versioned{
			SchemaVersion: 2,
		},
	}
	return &ociImageDestination{ref: ref, index: index}, nil
}

// Reference returns the reference used to set up this destination.  Note that this should directly correspond to user's intent,
// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects.
func (d *ociImageDestination) Reference() types.ImageReference {
	return d.ref
}

// Close removes resources associated with an initialized ImageDestination, if any.
func (d *ociImageDestination) Close() error {
	return nil
}

func (d *ociImageDestination) SupportedManifestMIMETypes() []string {
	return []string{
		imgspecv1.MediaTypeImageManifest,
	}
}

// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures.
// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil.
func (d *ociImageDestination) SupportsSignatures() error {
	return errors.Errorf("Pushing signatures for OCI images is not supported")
}

// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination.
func (d *ociImageDestination) ShouldCompressLayers() bool {
	return true
}

// AcceptsForeignLayerURLs returns false iff foreign layers in manifest should be actually
// uploaded to the image destination, true otherwise.
func (d *ociImageDestination) AcceptsForeignLayerURLs() bool {
	return false
}

// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise.
func (d *ociImageDestination) MustMatchRuntimeOS() bool {
	return false
}

// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
// WARNING: The contents of stream are being verified on the fly.  Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
// to any other readers for download using the supplied digest.
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
func (d *ociImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) {
	if err := ensureDirectoryExists(d.ref.dir); err != nil {
		return types.BlobInfo{}, err
	}
	blobFile, err := ioutil.TempFile(d.ref.dir, "oci-put-blob")
	if err != nil {
		return types.BlobInfo{}, err
	}
	succeeded := false
	defer func() {
		blobFile.Close()
		if !succeeded {
			os.Remove(blobFile.Name())
		}
	}()

	digester := digest.Canonical.Digester()
	tee := io.TeeReader(stream, digester.Hash())

	size, err := io.Copy(blobFile, tee)
	if err != nil {
		return types.BlobInfo{}, err
	}
	computedDigest := digester.Digest()
	if inputInfo.Size != -1 && size != inputInfo.Size {
		return types.BlobInfo{}, errors.Errorf("Size mismatch when copying %s, expected %d, got %d", computedDigest, inputInfo.Size, size)
	}
	if err := blobFile.Sync(); err != nil {
		return types.BlobInfo{}, err
	}
	if err := blobFile.Chmod(0644); err != nil {
		return types.BlobInfo{}, err
	}

	blobPath, err := d.ref.blobPath(computedDigest)
	if err != nil {
		return types.BlobInfo{}, err
	}
	if err := ensureParentDirectoryExists(blobPath); err != nil {
		return types.BlobInfo{}, err
	}
	if err := os.Rename(blobFile.Name(), blobPath); err != nil {
		return types.BlobInfo{}, err
	}
	succeeded = true
	return types.BlobInfo{Digest: computedDigest, Size: size}, nil
}

// HasBlob returns true iff the image destination already contains a blob with the matching digest which can be reapplied using ReapplyBlob.
// Unlike PutBlob, the digest can not be empty.  If HasBlob returns true, the size of the blob must also be returned.
// If the destination does not contain the blob, or it is unknown, HasBlob ordinarily returns (false, -1, nil);
// it returns a non-nil error only on an unexpected failure.
func (d *ociImageDestination) HasBlob(info types.BlobInfo) (bool, int64, error) {
	if info.Digest == "" {
		return false, -1, errors.Errorf(`"Can not check for a blob with unknown digest`)
	}
	blobPath, err := d.ref.blobPath(info.Digest)
	if err != nil {
		return false, -1, err
	}
	finfo, err := os.Stat(blobPath)
	if err != nil && os.IsNotExist(err) {
		return false, -1, nil
	}
	if err != nil {
		return false, -1, err
	}
	return true, finfo.Size(), nil
}

func (d *ociImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo, error) {
	return info, nil
}

// PutManifest writes manifest to the destination.
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
func (d *ociImageDestination) PutManifest(m []byte) error {
	digest, err := manifest.Digest(m)
	if err != nil {
		return err
	}
	desc := imgspecv1.Descriptor{}
	desc.Digest = digest
	// TODO(runcom): beaware and add support for OCI manifest list
	desc.MediaType = imgspecv1.MediaTypeImageManifest
	desc.Size = int64(len(m))

	blobPath, err := d.ref.blobPath(digest)
	if err != nil {
		return err
	}
	if err := ensureParentDirectoryExists(blobPath); err != nil {
		return err
	}
	if err := ioutil.WriteFile(blobPath, m, 0644); err != nil {
		return err
	}

	if d.ref.image == "" {
		return errors.Errorf("cannot save image with empyt image.ref.name")
	}

	annotations := make(map[string]string)
	annotations["org.opencontainers.image.ref.name"] = d.ref.image
	desc.Annotations = annotations
	desc.Platform = &imgspecv1.Platform{
		Architecture: runtime.GOARCH,
		OS:           runtime.GOOS,
	}
	d.index.Manifests = append(d.index.Manifests, desc)

	return nil
}

func ensureDirectoryExists(path string) error {
	if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(path, 0755); err != nil {
			return err
		}
	}
	return nil
}

// ensureParentDirectoryExists ensures the parent of the supplied path exists.
func ensureParentDirectoryExists(path string) error {
	return ensureDirectoryExists(filepath.Dir(path))
}

func (d *ociImageDestination) PutSignatures(signatures [][]byte) error {
	if len(signatures) != 0 {
		return errors.Errorf("Pushing signatures for OCI images is not supported")
	}
	return nil
}

// Commit marks the process of storing the image as successful and asks for the image to be persisted.
// WARNING: This does not have any transactional semantics:
// - Uploaded data MAY be visible to others before Commit() is called
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
func (d *ociImageDestination) Commit() error {
	if err := ioutil.WriteFile(d.ref.ociLayoutPath(), []byte(`{"imageLayoutVersion": "1.0.0"}`), 0644); err != nil {
		return err
	}
	indexJSON, err := json.Marshal(d.index)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(d.ref.indexPath(), indexJSON, 0644)
}
<|endoftext|>


<commit_before>package gomail

import (
	"crypto/tls"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/mail"
	"net/smtp"
	"strings"
)

// A Mailer represents an SMTP server.
type Mailer struct {
	addr   string
	host   string
	config *tls.Config
	auth   smtp.Auth
	send   SendMailFunc
}

// A MailerSetting can be used in a mailer constructor to configure it.
type MailerSetting func(m *Mailer)

// SetSendMail allows to set the email-sending function of a mailer.
//
// Example:
//
//	myFunc := func(addr string, a smtp.Auth, from string, to []string, msg []byte) error {
//		// Implement your email-sending function similar to smtp.SendMail
//	}
//	mailer := gomail.NewMailer("host", "user", "pwd", 465, SetSendMail(myFunc))
func SetSendMail(s SendMailFunc) MailerSetting {
	return func(m *Mailer) {
		m.send = s
	}
}

// SetTLSConfig allows to set the TLS configuration used to connect the SMTP
// server.
func SetTLSConfig(c *tls.Config) MailerSetting {
	return func(m *Mailer) {
		m.config = c
	}
}

// A SendMailFunc is a function to send emails with the same signature than
// smtp.SendMail.
type SendMailFunc func(addr string, a smtp.Auth, from string, to []string, msg []byte) error

// NewMailer returns a mailer. The given parameters are used to connect to the
// SMTP server via a PLAIN authentication mechanism.
func NewMailer(host string, username string, password string, port int, settings ...MailerSetting) *Mailer {
	return NewCustomMailer(
		fmt.Sprintf("%s:%d", host, port),
		smtp.PlainAuth("", username, password, host),
		settings...,
	)
}

// NewCustomMailer creates a mailer with the given authentication mechanism.
//
// Example:
//
//	gomail.NewCustomMailer("host:587", smtp.CRAMMD5Auth("username", "secret"))
func NewCustomMailer(addr string, auth smtp.Auth, settings ...MailerSetting) *Mailer {
	// Error is not handled here to preserve backward compatibility
	host, port, _ := net.SplitHostPort(addr)

	m := &Mailer{
		addr: addr,
		host: host,
		auth: auth,
	}

	for _, s := range settings {
		s(m)
	}

	if m.config == nil {
		m.config = &tls.Config{ServerName: host}
	}
	if m.send == nil {
		m.send = m.getSendMailFunc(port == "465")
	}

	return m
}

// Send sends the emails to all the recipients of the message.
func (m *Mailer) Send(msg *Message) error {
	message := msg.Export()

	from, err := getFrom(message)
	if err != nil {
		return err
	}
	recipients, bcc, err := getRecipients(message)
	if err != nil {
		return err
	}

	h := flattenHeader(message, "")
	body, err := ioutil.ReadAll(message.Body)
	if err != nil {
		return err
	}

	mail := append(h, body...)
	if err := m.send(m.addr, m.auth, from, recipients, mail); err != nil {
		return err
	}

	for _, to := range bcc {
		h = flattenHeader(message, to)
		mail = append(h, body...)
		if err := m.send(m.addr, m.auth, from, []string{to}, mail); err != nil {
			return err
		}
	}

	return nil
}

func flattenHeader(msg *mail.Message, bcc string) []byte {
	buf := getBuffer()
	defer putBuffer(buf)

	for field, value := range msg.Header {
		if field != "Bcc" {
			buf.WriteString(field + ": " + strings.Join(value, ", ") + "\r\n")
		} else if bcc != "" {
			for _, to := range value {
				if strings.Contains(to, bcc) {
					buf.WriteString(field + ": " + to + "\r\n")
				}
			}
		}
	}
	buf.WriteString("\r\n")

	return buf.Bytes()
}

func getFrom(msg *mail.Message) (string, error) {
	from := msg.Header.Get("Sender")
	if from == "" {
		from = msg.Header.Get("From")
		if from == "" {
			return "", errors.New("mailer: invalid message, \"From\" field is absent")
		}
	}

	return parseAddress(from)
}

func getRecipients(msg *mail.Message) (recipients, bcc []string, err error) {
	for _, field := range []string{"Bcc", "To", "Cc"} {
		if addresses, ok := msg.Header[field]; ok {
			for _, addr := range addresses {
				switch field {
				case "Bcc":
					bcc, err = addAdress(bcc, addr)
				default:
					recipients, err = addAdress(recipients, addr)
				}
				if err != nil {
					return recipients, bcc, err
				}
			}
		}
	}

	return recipients, bcc, nil
}

func addAdress(list []string, addr string) ([]string, error) {
	addr, err := parseAddress(addr)
	if err != nil {
		return list, err
	}
	for _, a := range list {
		if addr == a {
			return list, nil
		}
	}

	return append(list, addr), nil
}

func parseAddress(field string) (string, error) {
	a, err := mail.ParseAddress(field)
	if a == nil {
		return "", err
	}

	return a.Address, err
}
<commit_msg>Improved memory consumption<commit_after>package gomail

import (
	"crypto/tls"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/mail"
	"net/smtp"
	"strings"
)

// A Mailer represents an SMTP server.
type Mailer struct {
	addr   string
	host   string
	config *tls.Config
	auth   smtp.Auth
	send   SendMailFunc
}

// A MailerSetting can be used in a mailer constructor to configure it.
type MailerSetting func(m *Mailer)

// SetSendMail allows to set the email-sending function of a mailer.
//
// Example:
//
//	myFunc := func(addr string, a smtp.Auth, from string, to []string, msg []byte) error {
//		// Implement your email-sending function similar to smtp.SendMail
//	}
//	mailer := gomail.NewMailer("host", "user", "pwd", 465, SetSendMail(myFunc))
func SetSendMail(s SendMailFunc) MailerSetting {
	return func(m *Mailer) {
		m.send = s
	}
}

// SetTLSConfig allows to set the TLS configuration used to connect the SMTP
// server.
func SetTLSConfig(c *tls.Config) MailerSetting {
	return func(m *Mailer) {
		m.config = c
	}
}

// A SendMailFunc is a function to send emails with the same signature than
// smtp.SendMail.
type SendMailFunc func(addr string, a smtp.Auth, from string, to []string, msg []byte) error

// NewMailer returns a mailer. The given parameters are used to connect to the
// SMTP server via a PLAIN authentication mechanism.
func NewMailer(host string, username string, password string, port int, settings ...MailerSetting) *Mailer {
	return NewCustomMailer(
		fmt.Sprintf("%s:%d", host, port),
		smtp.PlainAuth("", username, password, host),
		settings...,
	)
}

// NewCustomMailer creates a mailer with the given authentication mechanism.
//
// Example:
//
//	gomail.NewCustomMailer("host:587", smtp.CRAMMD5Auth("username", "secret"))
func NewCustomMailer(addr string, auth smtp.Auth, settings ...MailerSetting) *Mailer {
	// Error is not handled here to preserve backward compatibility
	host, port, _ := net.SplitHostPort(addr)

	m := &Mailer{
		addr: addr,
		host: host,
		auth: auth,
	}

	for _, s := range settings {
		s(m)
	}

	if m.config == nil {
		m.config = &tls.Config{ServerName: host}
	}
	if m.send == nil {
		m.send = m.getSendMailFunc(port == "465")
	}

	return m
}

// Send sends the emails to all the recipients of the message.
func (m *Mailer) Send(msg *Message) error {
	message := msg.Export()

	from, err := getFrom(message)
	if err != nil {
		return err
	}
	recipients, bcc, err := getRecipients(message)
	if err != nil {
		return err
	}

	h := flattenHeader(message, "")
	body, err := ioutil.ReadAll(message.Body)
	if err != nil {
		return err
	}

	mail := append(h, body...)
	if err := m.send(m.addr, m.auth, from, recipients, mail); err != nil {
		return err
	}

	for _, to := range bcc {
		h = flattenHeader(message, to)
		mail = append(h, body...)
		if err := m.send(m.addr, m.auth, from, []string{to}, mail); err != nil {
			return err
		}
	}

	return nil
}

func flattenHeader(msg *mail.Message, bcc string) []byte {
	buf := getBuffer()
	defer putBuffer(buf)

	for field, value := range msg.Header {
		if field != "Bcc" {
			buf.WriteString(field)
			buf.WriteString(": ")
			buf.WriteString(strings.Join(value, ", "))
			buf.WriteString("\r\n")
		} else if bcc != "" {
			for _, to := range value {
				if strings.Contains(to, bcc) {
					buf.WriteString(field)
					buf.WriteString(": ")
					buf.WriteString(to)
					buf.WriteString("\r\n")
				}
			}
		}
	}
	buf.WriteString("\r\n")

	return buf.Bytes()
}

func getFrom(msg *mail.Message) (string, error) {
	from := msg.Header.Get("Sender")
	if from == "" {
		from = msg.Header.Get("From")
		if from == "" {
			return "", errors.New("mailer: invalid message, \"From\" field is absent")
		}
	}

	return parseAddress(from)
}

func getRecipients(msg *mail.Message) (recipients, bcc []string, err error) {
	for _, field := range []string{"Bcc", "To", "Cc"} {
		if addresses, ok := msg.Header[field]; ok {
			for _, addr := range addresses {
				switch field {
				case "Bcc":
					bcc, err = addAdress(bcc, addr)
				default:
					recipients, err = addAdress(recipients, addr)
				}
				if err != nil {
					return recipients, bcc, err
				}
			}
		}
	}

	return recipients, bcc, nil
}

func addAdress(list []string, addr string) ([]string, error) {
	addr, err := parseAddress(addr)
	if err != nil {
		return list, err
	}
	for _, a := range list {
		if addr == a {
			return list, nil
		}
	}

	return append(list, addr), nil
}

func parseAddress(field string) (string, error) {
	a, err := mail.ParseAddress(field)
	if a == nil {
		return "", err
	}

	return a.Address, err
}
<|endoftext|>


<commit_before>// $G $F.go && $L $F.$A && ./$A.out

// Copyright 2010 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 main

import (
	"fmt"
	"math"
	"strings"
	"syscall"
)

type Error interface {
	String() string
}

type ErrorTest struct {
	name	string
	fn	func()
	err	string
}

var (
	i, j, k int = 0, 0, 1
	i8, j8, k8 int8 = 0, 0, 1
	i16, j16, k16 int16 = 0, 0, 1
	i32, j32, k32 int32 = 0, 0, 1
	i64, j64, k64 int64 = 0, 0, 1

	u, v, w uint = 0, 0, 1
	u8, v8, w8 uint8 = 0, 0, 1
	u16, v16, w16 uint16 = 0, 0, 1
	u32, v32, w32 uint32 = 0, 0, 1
	u64, v64, w64 uint64 = 0, 0, 1
	up, vp, wp uintptr = 0, 0, 1

	f, g, h float = 0, 0, 1
	f32, g32, h32 float32 = 0, 0, 1
	f64, g64, h64, inf, negInf, nan float64 = 0, 0, 1, math.Inf(1), math.Inf(-1), math.NaN()

	c, d, e complex = 0+0i, 0+0i, 1+1i
	c64, d64, e64 complex64 = 0+0i, 0+0i, 1+1i
	c128, d128, e128 complex128 = 0+0i, 0+0i, 1+1i
)

var tmp interface{}

// We could assign to _ but the compiler optimizes it too easily.
func use(v interface{}) {
	tmp = v
}

// Verify error/no error for all types.
var errorTests = []ErrorTest{
	// All integer divide by zero should error.
	ErrorTest{ "int 0/0", func() { use(i/j) }, "divide", },
	ErrorTest{ "int8 0/0", func() { use(i8/j8) }, "divide", },
	ErrorTest{ "int16 0/0", func() { use(i16/j16) }, "divide", },
	ErrorTest{ "int32 0/0", func() { use(i32/j32) }, "divide", },
	ErrorTest{ "int64 0/0", func() { use(i64/j64) }, "divide", },

	ErrorTest{ "int 1/0", func() { use(k/j) }, "divide", },
	ErrorTest{ "int8 1/0", func() { use(k8/j8) }, "divide", },
	ErrorTest{ "int16 1/0", func() { use(k16/j16) }, "divide", },
	ErrorTest{ "int32 1/0", func() { use(k32/j32) }, "divide", },
	ErrorTest{ "int64 1/0", func() { use(k64/j64) }, "divide", },

	ErrorTest{ "uint 0/0", func() { use(u/v) }, "divide", },
	ErrorTest{ "uint8 0/0", func() { use(u8/v8) }, "divide", },
	ErrorTest{ "uint16 0/0", func() { use(u16/v16) }, "divide", },
	ErrorTest{ "uint32 0/0", func() { use(u32/v32) }, "divide", },
	ErrorTest{ "uint64 0/0", func() { use(u64/v64) }, "divide", },
	ErrorTest{ "uintptr 0/0", func() { use(up/vp) }, "divide", },

	ErrorTest{ "uint 1/0", func() { use(w/v) }, "divide", },
	ErrorTest{ "uint8 1/0", func() { use(w8/v8) }, "divide", },
	ErrorTest{ "uint16 1/0", func() { use(w16/v16) }, "divide", },
	ErrorTest{ "uint32 1/0", func() { use(w32/v32) }, "divide", },
	ErrorTest{ "uint64 1/0", func() { use(w64/v64) }, "divide", },
	ErrorTest{ "uintptr 1/0", func() { use(wp/vp) }, "divide", },

	// All floating divide by zero should not error.
	ErrorTest{ "float 0/0", func() { use(f/g) }, "", },
	ErrorTest{ "float32 0/0", func() { use(f32/g32) }, "", },
	ErrorTest{ "float64 0/0", func() { use(f64/g64) }, "", },

	ErrorTest{ "float 1/0", func() { use(h/g) }, "", },
	ErrorTest{ "float32 1/0", func() { use(h32/g32) }, "", },
	ErrorTest{ "float64 1/0", func() { use(h64/g64) }, "", },
	ErrorTest{ "float64 inf/0", func() { use(inf/g64) }, "", },
	ErrorTest{ "float64 -inf/0", func() { use(negInf/g64) }, "", },
	ErrorTest{ "float64 nan/0", func() { use(nan/g64) }, "", },

	// All complex divide by zero should not error.
	ErrorTest{ "complex 0/0", func() { use(c/d) }, "", },
	ErrorTest{ "complex64 0/0", func() { use(c64/d64) }, "", },
	ErrorTest{ "complex128 0/0", func() { use(c128/d128) }, "", },

	ErrorTest{ "complex 1/0", func() { use(e/d) }, "", },
	ErrorTest{ "complex64 1/0", func() { use(e64/d64) }, "", },
	ErrorTest{ "complex128 1/0", func() { use(e128/d128) }, "", },
}

func error(fn func()) (error string) {
	defer func() {
		if e := recover(); e != nil {
			error = e.(Error).String()
		}
	}()
	fn()
	return ""
}

type FloatTest struct{
	f, g	float64
	out	float64
}

var floatTests = []FloatTest{
	FloatTest{0, 0, nan},
	FloatTest{nan, 0, nan},
	FloatTest{inf, 0, inf},
	FloatTest{negInf, 0, negInf},
}

func alike(a, b float64) bool {
	switch {
	case math.IsNaN(a) && math.IsNaN(b):
		return true
	case a == b:
		return math.Signbit(a) == math.Signbit(b)
	}
	return false
}

func main() {
	bad := false
	for _, t := range errorTests {
		if t.err != "" && syscall.OS == "nacl" {
			continue
		}
		err := error(t.fn)
		switch {
		case t.err == "" && err == "":
			// fine
		case t.err != "" && err == "":
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%s: expected %q; got no error\n", t.name, t.err)
		case t.err == "" && err != "":
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%s: expected no error; got %q\n", t.name, err)
		case t.err != "" && err != "":
			if strings.Index(err, t.err) < 0 {
				if !bad {
					bad = true
					fmt.Printf("BUG\n")
				}
				fmt.Printf("%s: expected %q; got %q\n", t.name, t.err, err)
				continue
			}
		}
	}

	// At this point we know we don't error on the values we're testing
	for _, t := range floatTests {
		x := t.f/t.g
		if !alike(x, t.out) {
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%v/%v: expected %g error; got %g\n", t.f, t.g, t.out, x)
		}
	}
}
<commit_msg>test: Make gccgo believe that the variables can change.<commit_after>// $G $F.go && $L $F.$A && ./$A.out

// Copyright 2010 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 main

import (
	"fmt"
	"math"
	"strings"
	"syscall"
)

type Error interface {
	String() string
}

type ErrorTest struct {
	name	string
	fn	func()
	err	string
}

var (
	i, j, k int = 0, 0, 1
	i8, j8, k8 int8 = 0, 0, 1
	i16, j16, k16 int16 = 0, 0, 1
	i32, j32, k32 int32 = 0, 0, 1
	i64, j64, k64 int64 = 0, 0, 1

	u, v, w uint = 0, 0, 1
	u8, v8, w8 uint8 = 0, 0, 1
	u16, v16, w16 uint16 = 0, 0, 1
	u32, v32, w32 uint32 = 0, 0, 1
	u64, v64, w64 uint64 = 0, 0, 1
	up, vp, wp uintptr = 0, 0, 1

	f, g, h float = 0, 0, 1
	f32, g32, h32 float32 = 0, 0, 1
	f64, g64, h64, inf, negInf, nan float64 = 0, 0, 1, math.Inf(1), math.Inf(-1), math.NaN()

	c, d, e complex = 0+0i, 0+0i, 1+1i
	c64, d64, e64 complex64 = 0+0i, 0+0i, 1+1i
	c128, d128, e128 complex128 = 0+0i, 0+0i, 1+1i
)

// Fool gccgo into thinking that these variables can change.
func NotCalled() {
	i++; j++; k++
	i8++; j8++; k8++
	i16++; j16++; k16++
	i32++; j32++; k32++
	i64++; j64++; k64++

	u++; v++; w++
	u8++; v8++; w8++
	u16++; v16++; w16++
	u32++; v32++; w32++
	u64++; v64++; w64++
	up++; vp++; wp++

	f += 1; g += 1; h += 1
	f32 += 1; g32 += 1; h32 += 1
	f64 += 1; g64 += 1; h64 += 1

	c += 1+1i; d += 1+1i; e += 1+1i
	c64 += 1+1i; d64 += 1+1i; e64 += 1+1i
	c128 += 1+1i; d128 += 1+1i; e128 += 1+1i
}

var tmp interface{}

// We could assign to _ but the compiler optimizes it too easily.
func use(v interface{}) {
	tmp = v
}

// Verify error/no error for all types.
var errorTests = []ErrorTest{
	// All integer divide by zero should error.
	ErrorTest{ "int 0/0", func() { use(i/j) }, "divide", },
	ErrorTest{ "int8 0/0", func() { use(i8/j8) }, "divide", },
	ErrorTest{ "int16 0/0", func() { use(i16/j16) }, "divide", },
	ErrorTest{ "int32 0/0", func() { use(i32/j32) }, "divide", },
	ErrorTest{ "int64 0/0", func() { use(i64/j64) }, "divide", },

	ErrorTest{ "int 1/0", func() { use(k/j) }, "divide", },
	ErrorTest{ "int8 1/0", func() { use(k8/j8) }, "divide", },
	ErrorTest{ "int16 1/0", func() { use(k16/j16) }, "divide", },
	ErrorTest{ "int32 1/0", func() { use(k32/j32) }, "divide", },
	ErrorTest{ "int64 1/0", func() { use(k64/j64) }, "divide", },

	ErrorTest{ "uint 0/0", func() { use(u/v) }, "divide", },
	ErrorTest{ "uint8 0/0", func() { use(u8/v8) }, "divide", },
	ErrorTest{ "uint16 0/0", func() { use(u16/v16) }, "divide", },
	ErrorTest{ "uint32 0/0", func() { use(u32/v32) }, "divide", },
	ErrorTest{ "uint64 0/0", func() { use(u64/v64) }, "divide", },
	ErrorTest{ "uintptr 0/0", func() { use(up/vp) }, "divide", },

	ErrorTest{ "uint 1/0", func() { use(w/v) }, "divide", },
	ErrorTest{ "uint8 1/0", func() { use(w8/v8) }, "divide", },
	ErrorTest{ "uint16 1/0", func() { use(w16/v16) }, "divide", },
	ErrorTest{ "uint32 1/0", func() { use(w32/v32) }, "divide", },
	ErrorTest{ "uint64 1/0", func() { use(w64/v64) }, "divide", },
	ErrorTest{ "uintptr 1/0", func() { use(wp/vp) }, "divide", },

	// All floating divide by zero should not error.
	ErrorTest{ "float 0/0", func() { use(f/g) }, "", },
	ErrorTest{ "float32 0/0", func() { use(f32/g32) }, "", },
	ErrorTest{ "float64 0/0", func() { use(f64/g64) }, "", },

	ErrorTest{ "float 1/0", func() { use(h/g) }, "", },
	ErrorTest{ "float32 1/0", func() { use(h32/g32) }, "", },
	ErrorTest{ "float64 1/0", func() { use(h64/g64) }, "", },
	ErrorTest{ "float64 inf/0", func() { use(inf/g64) }, "", },
	ErrorTest{ "float64 -inf/0", func() { use(negInf/g64) }, "", },
	ErrorTest{ "float64 nan/0", func() { use(nan/g64) }, "", },

	// All complex divide by zero should not error.
	ErrorTest{ "complex 0/0", func() { use(c/d) }, "", },
	ErrorTest{ "complex64 0/0", func() { use(c64/d64) }, "", },
	ErrorTest{ "complex128 0/0", func() { use(c128/d128) }, "", },

	ErrorTest{ "complex 1/0", func() { use(e/d) }, "", },
	ErrorTest{ "complex64 1/0", func() { use(e64/d64) }, "", },
	ErrorTest{ "complex128 1/0", func() { use(e128/d128) }, "", },
}

func error(fn func()) (error string) {
	defer func() {
		if e := recover(); e != nil {
			error = e.(Error).String()
		}
	}()
	fn()
	return ""
}

type FloatTest struct{
	f, g	float64
	out	float64
}

var floatTests = []FloatTest{
	FloatTest{0, 0, nan},
	FloatTest{nan, 0, nan},
	FloatTest{inf, 0, inf},
	FloatTest{negInf, 0, negInf},
}

func alike(a, b float64) bool {
	switch {
	case math.IsNaN(a) && math.IsNaN(b):
		return true
	case a == b:
		return math.Signbit(a) == math.Signbit(b)
	}
	return false
}

func main() {
	bad := false
	for _, t := range errorTests {
		if t.err != "" && syscall.OS == "nacl" {
			continue
		}
		err := error(t.fn)
		switch {
		case t.err == "" && err == "":
			// fine
		case t.err != "" && err == "":
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%s: expected %q; got no error\n", t.name, t.err)
		case t.err == "" && err != "":
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%s: expected no error; got %q\n", t.name, err)
		case t.err != "" && err != "":
			if strings.Index(err, t.err) < 0 {
				if !bad {
					bad = true
					fmt.Printf("BUG\n")
				}
				fmt.Printf("%s: expected %q; got %q\n", t.name, t.err, err)
				continue
			}
		}
	}

	// At this point we know we don't error on the values we're testing
	for _, t := range floatTests {
		x := t.f/t.g
		if !alike(x, t.out) {
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%v/%v: expected %g error; got %g\n", t.f, t.g, t.out, x)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"math"
	"math/cmplx"
)

// TrigGenerator implements a trigonometric generator using a recursively updated complex
// phasor
type TrigGenerator struct {
	t          Timecode
	phasor     complex128
	sampleRate Frequency
}

// NewTrigGenerator creates a new TrigGenerator
func NewTrigGenerator(f Frequency) *TrigGenerator {
	gen := new(TrigGenerator)
	gen.t = 0
	gen.sampleRate = f
	gen.phasor = complex(1, 0)
	return gen
}

// Sine emits a sine wave for a given frequency and timecode
// http://dsp.stackexchange.com/a/1087
func (gen *TrigGenerator) Sine(tʹ Timecode, f Frequency) Amplitude {
	// determine how many samples we have to advance
	// typically this is one - more than one implies time dialation
	Δt := tʹ - gen.t

	// compute the angular frequency of the oscilator in radians
	ω := 2 * math.Pi * f / sampleRate

	// compute the complex angular coeficient
	Ω := cmplx.Exp(complex(0, ω))

	// advance the phasor Δt units
	for ; Δt > 0; Δt-- {
		gen.phasor = gen.phasor * Ω
	}
	gen.t = tʹ

	// return the 'sine' component of the phasor
	return Amplitude(imag(gen.phasor))
}
<commit_msg>Phasor unity correction<commit_after>package main

import (
	"math"
	"math/cmplx"
)

// number of elapsed samples before stabilization occurs
const stabilizationPeriod = 500

// TrigGenerator implements a trigonometric generator using a recursively updated complex
// phasor
type TrigGenerator struct {
	// The last known generator timecode
	t Timecode
	// Time of last stabilization
	s Timecode
	// A phasor holding the current state of the trig generator
	z complex128
	// The sample rate for generation
	sampleRate Frequency
}

// NewTrigGenerator creates a new TrigGenerator
func NewTrigGenerator(f Frequency) *TrigGenerator {
	gen := new(TrigGenerator)
	gen.t = 0
	gen.s = 0
	gen.sampleRate = f
	gen.z = complex(1, 0)
	return gen
}

// Sine emits a sine wave for a given frequency and timecode
// http://dsp.stackexchange.com/a/1087
func (gen *TrigGenerator) Sine(tʹ Timecode, f Frequency) Amplitude {
	// determine how many samples we have to advance
	// typically this is one - more than one implies time dialation
	Δt := tʹ - gen.t

	// compute the angular frequency of the oscilator in radians
	ω := 2 * math.Pi * f / sampleRate

	// compute the complex angular coeficient
	Ω := cmplx.Exp(complex(0, ω))

	// advance the phasor Δt units
	for i := Δt; i > 0; i-- {
		gen.z = gen.z * Ω
	}

	// stabilize the phasor's amplitude every once in a while
	// the amplitude can drift due to rounding errors
	// since z is a unity phasor, adjust its amplitude back towards unity
	if gen.s > stabilizationPeriod {
		a := real(gen.z)
		b := imag(gen.z)
		c := (3 - math.Pow(a, 2) - math.Pow(b, 2)) / 2
		gen.z = gen.z * complex(c, 0)
		gen.s = 0
	}

	// advance time
	gen.t += Δt
	gen.s += Δt
	// return the 'sine' component of the phasor
	return Amplitude(imag(gen.z))
}
<|endoftext|>


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

// +build windows

package sspi

import (
	"syscall"
	"time"
	"unsafe"
)

// TODO: add documentation

type PackageInfo struct {
	Capabilities uint32
	Version      uint16
	RPCID        uint16
	MaxToken     uint32
	Name         string
	Comment      string
}

func QueryPackageInfo(pkgname string) (*PackageInfo, error) {
	name, err := syscall.UTF16PtrFromString(pkgname)
	if err != nil {
		return nil, err
	}
	var pi *SecPkgInfo
	ret := QuerySecurityPackageInfo(name, &pi)
	if ret != SEC_E_OK {
		return nil, ret
	}
	defer FreeContextBuffer((*byte)(unsafe.Pointer(pi)))

	return &PackageInfo{
		Capabilities: pi.Capabilities,
		Version:      pi.Version,
		RPCID:        pi.RPCID,
		MaxToken:     pi.MaxToken,
		Name:         syscall.UTF16ToString((*[2 << 12]uint16)(unsafe.Pointer(pi.Name))[:]),
		Comment:      syscall.UTF16ToString((*[2 << 12]uint16)(unsafe.Pointer(pi.Comment))[:]),
	}, nil
}

type Credentials struct {
	Handle CredHandle
	expiry syscall.Filetime
}

func AcquireCredentials(principal string, pkgname string, creduse uint32, authdata *byte) (*Credentials, error) {
	var principalName *uint16
	if principal != "" {
		var err error
		principalName, err = syscall.UTF16PtrFromString(principal)
		if err != nil {
			return nil, err
		}
	}
	name, err := syscall.UTF16PtrFromString(pkgname)
	if err != nil {
		return nil, err
	}
	var c Credentials
	ret := AcquireCredentialsHandle(principalName, name, creduse, nil, authdata, 0, 0, &c.Handle, &c.expiry)
	if ret != SEC_E_OK {
		return nil, ret
	}
	return &c, nil
}

func (c *Credentials) Release() error {
	ret := FreeCredentialsHandle(&c.Handle)
	if ret != SEC_E_OK {
		return ret
	}
	return nil
}

func (c *Credentials) Expiry() time.Time {
	return time.Unix(0, c.expiry.Nanoseconds())
}

// TODO: add functions to display and manage RequestedFlags and EstablishedFlags fields.
// TODO: maybe get rid of RequestedFlags and EstablishedFlags fields, and replace them with input parameter for New...Context and return value of Update (instead of current bool parameter).

type updateFunc func(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno

type Context struct {
	Cred             *Credentials
	Handle           *CtxtHandle
	handle           CtxtHandle
	updFn            updateFunc
	expiry           syscall.Filetime
	RequestedFlags   uint32
	EstablishedFlags uint32
}

func NewClientContext(cred *Credentials, flags uint32) *Context {
	return &Context{
		Cred:           cred,
		updFn:          initialize,
		RequestedFlags: flags,
	}
}

func NewServerContext(cred *Credentials, flags uint32) *Context {
	return &Context{
		Cred:           cred,
		updFn:          accept,
		RequestedFlags: flags,
	}
}

func initialize(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno {
	return InitializeSecurityContext(&c.Cred.Handle, h, targname, c.RequestedFlags,
		0, SECURITY_NATIVE_DREP, in, 0, newh, out, &c.EstablishedFlags, &c.expiry)
}

func accept(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno {
	return AcceptSecurityContext(&c.Cred.Handle, h, in, c.RequestedFlags,
		SECURITY_NATIVE_DREP, newh, out, &c.EstablishedFlags, &c.expiry)
}

func (c *Context) Update(targname *uint16, out, in *SecBufferDesc) syscall.Errno {
	h := c.Handle
	if c.Handle == nil {
		c.Handle = &c.handle
	}
	return c.updFn(c, targname, h, c.Handle, out, in)
}

func (c *Context) Release() error {
	ret := DeleteSecurityContext(c.Handle)
	if ret != SEC_E_OK {
		return ret
	}
	return nil
}

func (c *Context) Expiry() time.Time {
	return time.Unix(0, c.expiry.Nanoseconds())
}

// TODO: add comment to function doco that this "impersonation" is applied to current OS thread.
func (c *Context) ImpersonateUser() error {
	ret := ImpersonateSecurityContext(c.Handle)
	if ret != SEC_E_OK {
		return ret
	}
	return nil
}

func (c *Context) RevertToSelf() error {
	ret := RevertSecurityContext(c.Handle)
	if ret != SEC_E_OK {
		return ret
	}
	return nil
}

// Sizes queries the context for the sizes used in per-message functions.
// It returns the maximum token size used in authentication exchanges, the
// maximum signature size, the preferred integral size of messages, the
// size of any security trailer, and any error.
func (c *Context) Sizes() (uint32, uint32, uint32, uint32, error) {
	var s _SecPkgContext_Sizes
	ret := QueryContextAttributes(c.Handle, _SECPKG_ATTR_SIZES, (*byte)(unsafe.Pointer(&s)))
	if ret != SEC_E_OK {
		return 0, 0, 0, 0, ret
	}
	return s.MaxToken, s.MaxSignature, s.BlockSize, s.SecurityTrailer, nil
}

// NewSecBufferDesc returns an initialized SecBufferDesc describing the
// provided SecBuffer.
func NewSecBufferDesc(b []SecBuffer) *SecBufferDesc {
	return &SecBufferDesc{
		Version:      SECBUFFER_VERSION,
		BuffersCount: uint32(len(b)),
		Buffers:      &b[0],
	}
}
<commit_msg>sspi: add comments to AcquireCredentials<commit_after>// Copyright 2015 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.

// +build windows

package sspi

import (
	"syscall"
	"time"
	"unsafe"
)

// TODO: add documentation

type PackageInfo struct {
	Capabilities uint32
	Version      uint16
	RPCID        uint16
	MaxToken     uint32
	Name         string
	Comment      string
}

func QueryPackageInfo(pkgname string) (*PackageInfo, error) {
	name, err := syscall.UTF16PtrFromString(pkgname)
	if err != nil {
		return nil, err
	}
	var pi *SecPkgInfo
	ret := QuerySecurityPackageInfo(name, &pi)
	if ret != SEC_E_OK {
		return nil, ret
	}
	defer FreeContextBuffer((*byte)(unsafe.Pointer(pi)))

	return &PackageInfo{
		Capabilities: pi.Capabilities,
		Version:      pi.Version,
		RPCID:        pi.RPCID,
		MaxToken:     pi.MaxToken,
		Name:         syscall.UTF16ToString((*[2 << 12]uint16)(unsafe.Pointer(pi.Name))[:]),
		Comment:      syscall.UTF16ToString((*[2 << 12]uint16)(unsafe.Pointer(pi.Comment))[:]),
	}, nil
}

type Credentials struct {
	Handle CredHandle
	expiry syscall.Filetime
}

// AcquireCredentials calls the windows AcquireCredentialsHandle function and
// returns Credentials containing a security handle that can be used for
// InitializeSecurityContext or AcceptSecurityContext operations.
// As a special case, passing an empty string as the principal parameter will
// pass a null string to the underlying function.
func AcquireCredentials(principal string, pkgname string, creduse uint32, authdata *byte) (*Credentials, error) {
	var principalName *uint16
	if principal != "" {
		var err error
		principalName, err = syscall.UTF16PtrFromString(principal)
		if err != nil {
			return nil, err
		}
	}
	name, err := syscall.UTF16PtrFromString(pkgname)
	if err != nil {
		return nil, err
	}
	var c Credentials
	ret := AcquireCredentialsHandle(principalName, name, creduse, nil, authdata, 0, 0, &c.Handle, &c.expiry)
	if ret != SEC_E_OK {
		return nil, ret
	}
	return &c, nil
}

func (c *Credentials) Release() error {
	ret := FreeCredentialsHandle(&c.Handle)
	if ret != SEC_E_OK {
		return ret
	}
	return nil
}

func (c *Credentials) Expiry() time.Time {
	return time.Unix(0, c.expiry.Nanoseconds())
}

// TODO: add functions to display and manage RequestedFlags and EstablishedFlags fields.
// TODO: maybe get rid of RequestedFlags and EstablishedFlags fields, and replace them with input parameter for New...Context and return value of Update (instead of current bool parameter).

type updateFunc func(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno

type Context struct {
	Cred             *Credentials
	Handle           *CtxtHandle
	handle           CtxtHandle
	updFn            updateFunc
	expiry           syscall.Filetime
	RequestedFlags   uint32
	EstablishedFlags uint32
}

func NewClientContext(cred *Credentials, flags uint32) *Context {
	return &Context{
		Cred:           cred,
		updFn:          initialize,
		RequestedFlags: flags,
	}
}

func NewServerContext(cred *Credentials, flags uint32) *Context {
	return &Context{
		Cred:           cred,
		updFn:          accept,
		RequestedFlags: flags,
	}
}

func initialize(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno {
	return InitializeSecurityContext(&c.Cred.Handle, h, targname, c.RequestedFlags,
		0, SECURITY_NATIVE_DREP, in, 0, newh, out, &c.EstablishedFlags, &c.expiry)
}

func accept(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno {
	return AcceptSecurityContext(&c.Cred.Handle, h, in, c.RequestedFlags,
		SECURITY_NATIVE_DREP, newh, out, &c.EstablishedFlags, &c.expiry)
}

func (c *Context) Update(targname *uint16, out, in *SecBufferDesc) syscall.Errno {
	h := c.Handle
	if c.Handle == nil {
		c.Handle = &c.handle
	}
	return c.updFn(c, targname, h, c.Handle, out, in)
}

func (c *Context) Release() error {
	ret := DeleteSecurityContext(c.Handle)
	if ret != SEC_E_OK {
		return ret
	}
	return nil
}

func (c *Context) Expiry() time.Time {
	return time.Unix(0, c.expiry.Nanoseconds())
}

// TODO: add comment to function doco that this "impersonation" is applied to current OS thread.
func (c *Context) ImpersonateUser() error {
	ret := ImpersonateSecurityContext(c.Handle)
	if ret != SEC_E_OK {
		return ret
	}
	return nil
}

func (c *Context) RevertToSelf() error {
	ret := RevertSecurityContext(c.Handle)
	if ret != SEC_E_OK {
		return ret
	}
	return nil
}

// Sizes queries the context for the sizes used in per-message functions.
// It returns the maximum token size used in authentication exchanges, the
// maximum signature size, the preferred integral size of messages, the
// size of any security trailer, and any error.
func (c *Context) Sizes() (uint32, uint32, uint32, uint32, error) {
	var s _SecPkgContext_Sizes
	ret := QueryContextAttributes(c.Handle, _SECPKG_ATTR_SIZES, (*byte)(unsafe.Pointer(&s)))
	if ret != SEC_E_OK {
		return 0, 0, 0, 0, ret
	}
	return s.MaxToken, s.MaxSignature, s.BlockSize, s.SecurityTrailer, nil
}

// NewSecBufferDesc returns an initialized SecBufferDesc describing the
// provided SecBuffer.
func NewSecBufferDesc(b []SecBuffer) *SecBufferDesc {
	return &SecBufferDesc{
		Version:      SECBUFFER_VERSION,
		BuffersCount: uint32(len(b)),
		Buffers:      &b[0],
	}
}
<|endoftext|>