<commit_before>// +build linux windows

package libnetwork

import (
	"net"

	"github.com/docker/libnetwork/common"
	"github.com/sirupsen/logrus"
)

const maxSetStringLen = 350

func (c *controller) addEndpointNameResolution(svcName, svcID, nID, eID, containerName string, vip net.IP, serviceAliases, taskAliases []string, ip net.IP, addService bool, method string) error {
	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}

	logrus.Debugf("addEndpointNameResolution %s %s add_service:%t sAliases:%v tAliases:%v", eID, svcName, addService, serviceAliases, taskAliases)

	// Add container resolution mappings
	c.addContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)

	serviceID := svcID
	if serviceID == "" {
		// This is the case of a normal container not part of a service
		serviceID = eID
	}

	// Add endpoint IP to special "tasks.svc_name" so that the applications have access to DNS RR.
	n.(*network).addSvcRecords(eID, "tasks."+svcName, serviceID, ip, nil, false, method)
	for _, alias := range serviceAliases {
		n.(*network).addSvcRecords(eID, "tasks."+alias, serviceID, ip, nil, false, method)
	}

	// Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR
	if len(vip) == 0 {
		n.(*network).addSvcRecords(eID, svcName, serviceID, ip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).addSvcRecords(eID, alias, serviceID, ip, nil, false, method)
		}
	}

	if addService && len(vip) != 0 {
		n.(*network).addSvcRecords(eID, svcName, serviceID, vip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).addSvcRecords(eID, alias, serviceID, vip, nil, false, method)
		}
	}

	return nil
}

func (c *controller) addContainerNameResolution(nID, eID, containerName string, taskAliases []string, ip net.IP, method string) error {
	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}
	logrus.Debugf("addContainerNameResolution %s %s", eID, containerName)

	// Add resolution for container name
	n.(*network).addSvcRecords(eID, containerName, eID, ip, nil, true, method)

	// Add resolution for taskaliases
	for _, alias := range taskAliases {
		n.(*network).addSvcRecords(eID, alias, eID, ip, nil, true, method)
	}

	return nil
}

func (c *controller) deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName string, vip net.IP, serviceAliases, taskAliases []string, ip net.IP, rmService, multipleEntries bool, method string) error {
	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}

	logrus.Debugf("deleteEndpointNameResolution %s %s rm_service:%t suppress:%t sAliases:%v tAliases:%v", eID, svcName, rmService, multipleEntries, serviceAliases, taskAliases)

	// Delete container resolution mappings
	c.delContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)

	serviceID := svcID
	if serviceID == "" {
		// This is the case of a normal container not part of a service
		serviceID = eID
	}

	// Delete the special "tasks.svc_name" backend record.
	if !multipleEntries {
		n.(*network).deleteSvcRecords(eID, "tasks."+svcName, serviceID, ip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).deleteSvcRecords(eID, "tasks."+alias, serviceID, ip, nil, false, method)
		}
	}

	// If we are doing DNS RR delete the endpoint IP from DNS record right away.
	if !multipleEntries && len(vip) == 0 {
		n.(*network).deleteSvcRecords(eID, svcName, serviceID, ip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).deleteSvcRecords(eID, alias, serviceID, ip, nil, false, method)
		}
	}

	// Remove the DNS record for VIP only if we are removing the service
	if rmService && len(vip) != 0 && !multipleEntries {
		n.(*network).deleteSvcRecords(eID, svcName, serviceID, vip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).deleteSvcRecords(eID, alias, serviceID, vip, nil, false, method)
		}
	}

	return nil
}

func (c *controller) delContainerNameResolution(nID, eID, containerName string, taskAliases []string, ip net.IP, method string) error {
	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}
	logrus.Debugf("delContainerNameResolution %s %s", eID, containerName)

	// Delete resolution for container name
	n.(*network).deleteSvcRecords(eID, containerName, eID, ip, nil, true, method)

	// Delete resolution for taskaliases
	for _, alias := range taskAliases {
		n.(*network).deleteSvcRecords(eID, alias, eID, ip, nil, true, method)
	}

	return nil
}

func newService(name string, id string, ingressPorts []*PortConfig, serviceAliases []string) *service {
	return &service{
		name:          name,
		id:            id,
		ingressPorts:  ingressPorts,
		loadBalancers: make(map[string]*loadBalancer),
		aliases:       serviceAliases,
		ipToEndpoint:  common.NewSetMatrix(),
	}
}

func (c *controller) getLBIndex(sid, nid string, ingressPorts []*PortConfig) int {
	skey := serviceKey{
		id:    sid,
		ports: portConfigs(ingressPorts).String(),
	}
	c.Lock()
	s, ok := c.serviceBindings[skey]
	c.Unlock()

	if !ok {
		return 0
	}

	s.Lock()
	lb := s.loadBalancers[nid]
	s.Unlock()

	return int(lb.fwMark)
}

// cleanupServiceDiscovery when the network is being deleted, erase all the associated service discovery records
func (c *controller) cleanupServiceDiscovery(cleanupNID string) {
	c.Lock()
	defer c.Unlock()
	if cleanupNID == "" {
		logrus.Debugf("cleanupServiceDiscovery for all networks")
		c.svcRecords = make(map[string]svcInfo)
		return
	}
	logrus.Debugf("cleanupServiceDiscovery for network:%s", cleanupNID)
	delete(c.svcRecords, cleanupNID)
}

func (c *controller) cleanupServiceBindings(cleanupNID string) {
	var cleanupFuncs []func()

	logrus.Debugf("cleanupServiceBindings for %s", cleanupNID)
	c.Lock()
	services := make([]*service, 0, len(c.serviceBindings))
	for _, s := range c.serviceBindings {
		services = append(services, s)
	}
	c.Unlock()

	for _, s := range services {
		s.Lock()
		// Skip the serviceBindings that got deleted
		if s.deleted {
			s.Unlock()
			continue
		}
		for nid, lb := range s.loadBalancers {
			if cleanupNID != "" && nid != cleanupNID {
				continue
			}

			for eid, ip := range lb.backEnds {
				epID := eid
				epIP := ip
				service := s
				loadBalancer := lb
				networkID := nid
				cleanupFuncs = append(cleanupFuncs, func() {
					// ContainerName and taskAliases are not available here, this is still fine because the Service discovery
					// cleanup already happened before. The only thing that rmServiceBinding is still doing here a part from the Load
					// Balancer bookeeping, is to keep consistent the mapping of endpoint to IP.
					if err := c.rmServiceBinding(service.name, service.id, networkID, epID, "", loadBalancer.vip,
						service.ingressPorts, service.aliases, []string{}, epIP, "cleanupServiceBindings", false); err != nil {
						logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
							service.id, networkID, epID, err)
					}
				})
			}
		}
		s.Unlock()
	}

	for _, f := range cleanupFuncs {
		f()
	}

}

func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases, taskAliases []string, ip net.IP, method string) error {
	var addService bool

	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}

	skey := serviceKey{
		id:    svcID,
		ports: portConfigs(ingressPorts).String(),
	}

	var s *service
	for {
		c.Lock()
		var ok bool
		s, ok = c.serviceBindings[skey]
		if !ok {
			// Create a new service if we are seeing this service
			// for the first time.
			s = newService(svcName, svcID, ingressPorts, serviceAliases)
			c.serviceBindings[skey] = s
		}
		c.Unlock()
		s.Lock()
		if !s.deleted {
			// ok the object is good to be used
			break
		}
		s.Unlock()
	}
	logrus.Debugf("addServiceBinding from %s START for %s %s p:%p nid:%s skey:%v", method, svcName, eID, s, nID, skey)
	defer s.Unlock()

	lb, ok := s.loadBalancers[nID]
	if !ok {
		// Create a new load balancer if we are seeing this
		// network attachment on the service for the first
		// time.
		fwMarkCtrMu.Lock()

		lb = &loadBalancer{
			vip:      vip,
			fwMark:   fwMarkCtr,
			backEnds: make(map[string]net.IP),
			service:  s,
		}

		fwMarkCtr++
		fwMarkCtrMu.Unlock()

		s.loadBalancers[nID] = lb
		addService = true
	}

	lb.backEnds[eID] = ip

	ok, entries := s.assignIPToEndpoint(ip.String(), eID)
	if !ok || entries > 1 {
		setStr, b := s.printIPToEndpoint(ip.String())
		logrus.Warnf("addServiceBinding %s possible transient state ok:%t entries:%d set:%t %s", eID, ok, entries, b, setStr[:maxSetStringLen])
	}

	// Add loadbalancer service and backend in all sandboxes in
	// the network only if vip is valid.
	if len(vip) != 0 {
		n.(*network).addLBBackend(ip, vip, lb, ingressPorts)
	}

	// Add the appropriate name resolutions
	c.addEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, addService, "addServiceBinding")

	logrus.Debugf("addServiceBinding from %s END for %s %s", method, svcName, eID)

	return nil
}

func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases []string, taskAliases []string, ip net.IP, method string, deleteSvcRecords bool) error {

	var rmService bool

	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}

	skey := serviceKey{
		id:    svcID,
		ports: portConfigs(ingressPorts).String(),
	}

	c.Lock()
	s, ok := c.serviceBindings[skey]
	c.Unlock()
	if !ok {
		logrus.Warnf("rmServiceBinding %s %s %s aborted c.serviceBindings[skey] !ok", method, svcName, eID)
		return nil
	}

	s.Lock()
	defer s.Unlock()
	logrus.Debugf("rmServiceBinding from %s START for %s %s p:%p nid:%s sKey:%v deleteSvc:%t", method, svcName, eID, s, nID, skey, deleteSvcRecords)
	lb, ok := s.loadBalancers[nID]
	if !ok {
		logrus.Warnf("rmServiceBinding %s %s %s aborted s.loadBalancers[nid] !ok", method, svcName, eID)
		return nil
	}

	_, ok = lb.backEnds[eID]
	if !ok {
		logrus.Warnf("rmServiceBinding %s %s %s aborted lb.backEnds[eid] !ok", method, svcName, eID)
		return nil
	}

	delete(lb.backEnds, eID)
	if len(lb.backEnds) == 0 {
		// All the backends for this service have been
		// removed. Time to remove the load balancer and also
		// remove the service entry in IPVS.
		rmService = true

		delete(s.loadBalancers, nID)
		logrus.Debugf("rmServiceBinding %s delete %s, p:%p in loadbalancers len:%d", eID, nID, lb, len(s.loadBalancers))
	}

	ok, entries := s.removeIPToEndpoint(ip.String(), eID)
	if !ok || entries > 0 {
		setStr, b := s.printIPToEndpoint(ip.String())
		logrus.Warnf("rmServiceBinding %s possible transient state ok:%t entries:%d set:%t %s", eID, ok, entries, b, setStr[:maxSetStringLen])
	}

	// Remove loadbalancer service(if needed) and backend in all
	// sandboxes in the network only if the vip is valid.
	if len(vip) != 0 && entries == 0 {
		n.(*network).rmLBBackend(ip, vip, lb, ingressPorts, rmService)
	}

	// Delete the name resolutions
	if deleteSvcRecords {
		c.deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, rmService, entries > 0, "rmServiceBinding")
	}

	if len(s.loadBalancers) == 0 {
		// All loadbalancers for the service removed. Time to
		// remove the service itself.
		c.Lock()

		// Mark the object as deleted so that the add won't use it wrongly
		s.deleted = true
		// NOTE The delete from the serviceBindings map has to be the last operation else we are allowing a race between this service
		// that is getting deleted and a new service that will be created if the entry is not anymore there
		delete(c.serviceBindings, skey)
		c.Unlock()
	}

	logrus.Debugf("rmServiceBinding from %s END for %s %s", method, svcName, eID)
	return nil
}
<commit_msg>Fix crash if the len was < maxSetStringLen<commit_after>// +build linux windows

package libnetwork

import (
	"net"

	"github.com/docker/libnetwork/common"
	"github.com/sirupsen/logrus"
)

const maxSetStringLen = 350

func (c *controller) addEndpointNameResolution(svcName, svcID, nID, eID, containerName string, vip net.IP, serviceAliases, taskAliases []string, ip net.IP, addService bool, method string) error {
	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}

	logrus.Debugf("addEndpointNameResolution %s %s add_service:%t sAliases:%v tAliases:%v", eID, svcName, addService, serviceAliases, taskAliases)

	// Add container resolution mappings
	c.addContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)

	serviceID := svcID
	if serviceID == "" {
		// This is the case of a normal container not part of a service
		serviceID = eID
	}

	// Add endpoint IP to special "tasks.svc_name" so that the applications have access to DNS RR.
	n.(*network).addSvcRecords(eID, "tasks."+svcName, serviceID, ip, nil, false, method)
	for _, alias := range serviceAliases {
		n.(*network).addSvcRecords(eID, "tasks."+alias, serviceID, ip, nil, false, method)
	}

	// Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR
	if len(vip) == 0 {
		n.(*network).addSvcRecords(eID, svcName, serviceID, ip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).addSvcRecords(eID, alias, serviceID, ip, nil, false, method)
		}
	}

	if addService && len(vip) != 0 {
		n.(*network).addSvcRecords(eID, svcName, serviceID, vip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).addSvcRecords(eID, alias, serviceID, vip, nil, false, method)
		}
	}

	return nil
}

func (c *controller) addContainerNameResolution(nID, eID, containerName string, taskAliases []string, ip net.IP, method string) error {
	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}
	logrus.Debugf("addContainerNameResolution %s %s", eID, containerName)

	// Add resolution for container name
	n.(*network).addSvcRecords(eID, containerName, eID, ip, nil, true, method)

	// Add resolution for taskaliases
	for _, alias := range taskAliases {
		n.(*network).addSvcRecords(eID, alias, eID, ip, nil, true, method)
	}

	return nil
}

func (c *controller) deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName string, vip net.IP, serviceAliases, taskAliases []string, ip net.IP, rmService, multipleEntries bool, method string) error {
	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}

	logrus.Debugf("deleteEndpointNameResolution %s %s rm_service:%t suppress:%t sAliases:%v tAliases:%v", eID, svcName, rmService, multipleEntries, serviceAliases, taskAliases)

	// Delete container resolution mappings
	c.delContainerNameResolution(nID, eID, containerName, taskAliases, ip, method)

	serviceID := svcID
	if serviceID == "" {
		// This is the case of a normal container not part of a service
		serviceID = eID
	}

	// Delete the special "tasks.svc_name" backend record.
	if !multipleEntries {
		n.(*network).deleteSvcRecords(eID, "tasks."+svcName, serviceID, ip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).deleteSvcRecords(eID, "tasks."+alias, serviceID, ip, nil, false, method)
		}
	}

	// If we are doing DNS RR delete the endpoint IP from DNS record right away.
	if !multipleEntries && len(vip) == 0 {
		n.(*network).deleteSvcRecords(eID, svcName, serviceID, ip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).deleteSvcRecords(eID, alias, serviceID, ip, nil, false, method)
		}
	}

	// Remove the DNS record for VIP only if we are removing the service
	if rmService && len(vip) != 0 && !multipleEntries {
		n.(*network).deleteSvcRecords(eID, svcName, serviceID, vip, nil, false, method)
		for _, alias := range serviceAliases {
			n.(*network).deleteSvcRecords(eID, alias, serviceID, vip, nil, false, method)
		}
	}

	return nil
}

func (c *controller) delContainerNameResolution(nID, eID, containerName string, taskAliases []string, ip net.IP, method string) error {
	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}
	logrus.Debugf("delContainerNameResolution %s %s", eID, containerName)

	// Delete resolution for container name
	n.(*network).deleteSvcRecords(eID, containerName, eID, ip, nil, true, method)

	// Delete resolution for taskaliases
	for _, alias := range taskAliases {
		n.(*network).deleteSvcRecords(eID, alias, eID, ip, nil, true, method)
	}

	return nil
}

func newService(name string, id string, ingressPorts []*PortConfig, serviceAliases []string) *service {
	return &service{
		name:          name,
		id:            id,
		ingressPorts:  ingressPorts,
		loadBalancers: make(map[string]*loadBalancer),
		aliases:       serviceAliases,
		ipToEndpoint:  common.NewSetMatrix(),
	}
}

func (c *controller) getLBIndex(sid, nid string, ingressPorts []*PortConfig) int {
	skey := serviceKey{
		id:    sid,
		ports: portConfigs(ingressPorts).String(),
	}
	c.Lock()
	s, ok := c.serviceBindings[skey]
	c.Unlock()

	if !ok {
		return 0
	}

	s.Lock()
	lb := s.loadBalancers[nid]
	s.Unlock()

	return int(lb.fwMark)
}

// cleanupServiceDiscovery when the network is being deleted, erase all the associated service discovery records
func (c *controller) cleanupServiceDiscovery(cleanupNID string) {
	c.Lock()
	defer c.Unlock()
	if cleanupNID == "" {
		logrus.Debugf("cleanupServiceDiscovery for all networks")
		c.svcRecords = make(map[string]svcInfo)
		return
	}
	logrus.Debugf("cleanupServiceDiscovery for network:%s", cleanupNID)
	delete(c.svcRecords, cleanupNID)
}

func (c *controller) cleanupServiceBindings(cleanupNID string) {
	var cleanupFuncs []func()

	logrus.Debugf("cleanupServiceBindings for %s", cleanupNID)
	c.Lock()
	services := make([]*service, 0, len(c.serviceBindings))
	for _, s := range c.serviceBindings {
		services = append(services, s)
	}
	c.Unlock()

	for _, s := range services {
		s.Lock()
		// Skip the serviceBindings that got deleted
		if s.deleted {
			s.Unlock()
			continue
		}
		for nid, lb := range s.loadBalancers {
			if cleanupNID != "" && nid != cleanupNID {
				continue
			}

			for eid, ip := range lb.backEnds {
				epID := eid
				epIP := ip
				service := s
				loadBalancer := lb
				networkID := nid
				cleanupFuncs = append(cleanupFuncs, func() {
					// ContainerName and taskAliases are not available here, this is still fine because the Service discovery
					// cleanup already happened before. The only thing that rmServiceBinding is still doing here a part from the Load
					// Balancer bookeeping, is to keep consistent the mapping of endpoint to IP.
					if err := c.rmServiceBinding(service.name, service.id, networkID, epID, "", loadBalancer.vip,
						service.ingressPorts, service.aliases, []string{}, epIP, "cleanupServiceBindings", false); err != nil {
						logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
							service.id, networkID, epID, err)
					}
				})
			}
		}
		s.Unlock()
	}

	for _, f := range cleanupFuncs {
		f()
	}

}

func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases, taskAliases []string, ip net.IP, method string) error {
	var addService bool

	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}

	skey := serviceKey{
		id:    svcID,
		ports: portConfigs(ingressPorts).String(),
	}

	var s *service
	for {
		c.Lock()
		var ok bool
		s, ok = c.serviceBindings[skey]
		if !ok {
			// Create a new service if we are seeing this service
			// for the first time.
			s = newService(svcName, svcID, ingressPorts, serviceAliases)
			c.serviceBindings[skey] = s
		}
		c.Unlock()
		s.Lock()
		if !s.deleted {
			// ok the object is good to be used
			break
		}
		s.Unlock()
	}
	logrus.Debugf("addServiceBinding from %s START for %s %s p:%p nid:%s skey:%v", method, svcName, eID, s, nID, skey)
	defer s.Unlock()

	lb, ok := s.loadBalancers[nID]
	if !ok {
		// Create a new load balancer if we are seeing this
		// network attachment on the service for the first
		// time.
		fwMarkCtrMu.Lock()

		lb = &loadBalancer{
			vip:      vip,
			fwMark:   fwMarkCtr,
			backEnds: make(map[string]net.IP),
			service:  s,
		}

		fwMarkCtr++
		fwMarkCtrMu.Unlock()

		s.loadBalancers[nID] = lb
		addService = true
	}

	lb.backEnds[eID] = ip

	ok, entries := s.assignIPToEndpoint(ip.String(), eID)
	if !ok || entries > 1 {
		setStr, b := s.printIPToEndpoint(ip.String())
		if len(setStr) > maxSetStringLen {
			setStr = setStr[:maxSetStringLen]
		}
		logrus.Warnf("addServiceBinding %s possible transient state ok:%t entries:%d set:%t %s", eID, ok, entries, b, setStr)
	}

	// Add loadbalancer service and backend in all sandboxes in
	// the network only if vip is valid.
	if len(vip) != 0 {
		n.(*network).addLBBackend(ip, vip, lb, ingressPorts)
	}

	// Add the appropriate name resolutions
	c.addEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, addService, "addServiceBinding")

	logrus.Debugf("addServiceBinding from %s END for %s %s", method, svcName, eID)

	return nil
}

func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases []string, taskAliases []string, ip net.IP, method string, deleteSvcRecords bool) error {

	var rmService bool

	n, err := c.NetworkByID(nID)
	if err != nil {
		return err
	}

	skey := serviceKey{
		id:    svcID,
		ports: portConfigs(ingressPorts).String(),
	}

	c.Lock()
	s, ok := c.serviceBindings[skey]
	c.Unlock()
	if !ok {
		logrus.Warnf("rmServiceBinding %s %s %s aborted c.serviceBindings[skey] !ok", method, svcName, eID)
		return nil
	}

	s.Lock()
	defer s.Unlock()
	logrus.Debugf("rmServiceBinding from %s START for %s %s p:%p nid:%s sKey:%v deleteSvc:%t", method, svcName, eID, s, nID, skey, deleteSvcRecords)
	lb, ok := s.loadBalancers[nID]
	if !ok {
		logrus.Warnf("rmServiceBinding %s %s %s aborted s.loadBalancers[nid] !ok", method, svcName, eID)
		return nil
	}

	_, ok = lb.backEnds[eID]
	if !ok {
		logrus.Warnf("rmServiceBinding %s %s %s aborted lb.backEnds[eid] !ok", method, svcName, eID)
		return nil
	}

	delete(lb.backEnds, eID)
	if len(lb.backEnds) == 0 {
		// All the backends for this service have been
		// removed. Time to remove the load balancer and also
		// remove the service entry in IPVS.
		rmService = true

		delete(s.loadBalancers, nID)
		logrus.Debugf("rmServiceBinding %s delete %s, p:%p in loadbalancers len:%d", eID, nID, lb, len(s.loadBalancers))
	}

	ok, entries := s.removeIPToEndpoint(ip.String(), eID)
	if !ok || entries > 0 {
		setStr, b := s.printIPToEndpoint(ip.String())
		if len(setStr) > maxSetStringLen {
			setStr = setStr[:maxSetStringLen]
		}
		logrus.Warnf("rmServiceBinding %s possible transient state ok:%t entries:%d set:%t %s", eID, ok, entries, b, setStr)
	}

	// Remove loadbalancer service(if needed) and backend in all
	// sandboxes in the network only if the vip is valid.
	if len(vip) != 0 && entries == 0 {
		n.(*network).rmLBBackend(ip, vip, lb, ingressPorts, rmService)
	}

	// Delete the name resolutions
	if deleteSvcRecords {
		c.deleteEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, rmService, entries > 0, "rmServiceBinding")
	}

	if len(s.loadBalancers) == 0 {
		// All loadbalancers for the service removed. Time to
		// remove the service itself.
		c.Lock()

		// Mark the object as deleted so that the add won't use it wrongly
		s.deleted = true
		// NOTE The delete from the serviceBindings map has to be the last operation else we are allowing a race between this service
		// that is getting deleted and a new service that will be created if the entry is not anymore there
		delete(c.serviceBindings, skey)
		c.Unlock()
	}

	logrus.Debugf("rmServiceBinding from %s END for %s %s", method, svcName, eID)
	return nil
}
<|endoftext|>


<commit_before>package ircclient

import (
	"strings"

	"github.com/goshuirc/irc-go/ircmsg"
)

func loadServerCommands() {
	ServerCommands[RPL_WELCOME] = ServerCommand{
		minParams: 1,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			client.Lock()
			client.Nick = msg.Params[0]
			client.HasRegistered = true
			client.Unlock()

			return false
		},
	}

	ServerCommands[RPL_ISUPPORT] = ServerCommand{
		minParams: 1,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			client.Lock()
			defer client.Unlock()

			supported := msg.Params[1 : len(msg.Params)-1]
			for _, item := range supported {
				parts := strings.SplitN(item, "=", 2)
				if len(parts) == 1 {
					client.Supported[parts[0]] = ""
				} else {
					client.Supported[parts[0]] = parts[1]
				}
			}

			return false
		},
	}

	ServerCommands[ERR_NICKNAMEINUSE] = ServerCommand{
		minParams: 0,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			if client.HasRegistered {
				return true
			}

			// TODO: This should use the fallback nick set ont he client
			client.Lock()
			client.Nick = client.Nick + "_"
			client.Unlock()

			client.WriteLine("NICK %s", client.Nick)

			return true
		},
	}

	ServerCommands["NICK"] = ServerCommand{
		minParams: 1,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			client.Lock()
			client.Nick = msg.Params[0]
			client.Unlock()

			return false
		},
	}

	ServerCommands["PING"] = ServerCommand{
		minParams: 1,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			client.WriteLine("PONG :%s", msg.Params[0])
			return true
		},
	}

	ServerCommands["CAP"] = ServerCommand{
		minParams: 2,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			command := msg.Params[1]

			if command == "LS" && !client.HasRegistered {
				capsRaw := ""
				isLastCapsLine := true

				// Multiline list
				if getParam(msg, 2) == "*" {
					capsRaw = getParam(msg, 3)
					isLastCapsLine = false
				} else {
					capsRaw = getParam(msg, 2)
				}

				for _, cap := range strings.Split(capsRaw, " ") {
					parts := strings.Split(cap, "=")
					k := strings.ToLower(parts[0])
					v := ""
					if len(parts) > 1 {
						v = parts[1]
					}

					client.Lock()
					client.Caps.Available[k] = v
					client.Unlock()
				}

				if isLastCapsLine {
					common := client.Caps.CommonCaps()
					if len(common) > 0 {
						client.WriteLine("CAP REQ :%s", strings.Join(common, " "))
					} else {
						client.WriteLine("CAP END")
					}
				}
			}

			if command == "ACK" {
				// TODO: Do the ACK responses also use * to denote a multiline response?
				capsRaw := getParam(msg, 2)

				for _, cap := range strings.Split(capsRaw, " ") {
					parts := strings.Split(cap, "=")
					k := strings.ToLower(parts[0])
					v := ""
					if len(parts) > 1 {
						v = parts[1]
					}

					client.Lock()
					client.Caps.Enabled[k] = v
					client.Unlock()
				}

				client.WriteLine("CAP END")
			}

			if command == "NAK" {
				// TODO: This
			}

			return true
		},
	}
}

func getParam(msg *ircmsg.IrcMessage, idx int) string {
	if len(msg.Params)-1 < idx {
		return ""
	}

	return msg.Params[idx]
}
<commit_msg>Only update our nick if it's our own<commit_after>package ircclient

import (
	"strings"

	"github.com/goshuirc/irc-go/ircmsg"
)

func loadServerCommands() {
	ServerCommands[RPL_WELCOME] = ServerCommand{
		minParams: 1,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			client.Lock()
			client.Nick = msg.Params[0]
			client.HasRegistered = true
			client.Unlock()

			return false
		},
	}

	ServerCommands[RPL_ISUPPORT] = ServerCommand{
		minParams: 1,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			client.Lock()
			defer client.Unlock()

			supported := msg.Params[1 : len(msg.Params)-1]
			for _, item := range supported {
				parts := strings.SplitN(item, "=", 2)
				if len(parts) == 1 {
					client.Supported[parts[0]] = ""
				} else {
					client.Supported[parts[0]] = parts[1]
				}
			}

			return false
		},
	}

	ServerCommands[ERR_NICKNAMEINUSE] = ServerCommand{
		minParams: 0,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			if client.HasRegistered {
				return true
			}

			// TODO: This should use the fallback nick set ont he client
			client.Lock()
			client.Nick = client.Nick + "_"
			client.Unlock()

			client.WriteLine("NICK %s", client.Nick)

			return true
		},
	}

	ServerCommands["NICK"] = ServerCommand{
		minParams: 1,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			prefixNick, _, _ := SplitMask(msg.Prefix)

			// If our nick just changed, update ourselves
			if strings.ToLower(prefixNick) == strings.ToLower(client.Nick) {
				client.Lock()
				client.Nick = msg.Params[0]
				client.Unlock()
			}

			return false
		},
	}

	ServerCommands["PING"] = ServerCommand{
		minParams: 1,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			client.WriteLine("PONG :%s", msg.Params[0])
			return true
		},
	}

	ServerCommands["CAP"] = ServerCommand{
		minParams: 2,
		handler: func(client *Client, msg *ircmsg.IrcMessage) bool {
			command := msg.Params[1]

			if command == "LS" && !client.HasRegistered {
				capsRaw := ""
				isLastCapsLine := true

				// Multiline list
				if getParam(msg, 2) == "*" {
					capsRaw = getParam(msg, 3)
					isLastCapsLine = false
				} else {
					capsRaw = getParam(msg, 2)
				}

				for _, cap := range strings.Split(capsRaw, " ") {
					parts := strings.Split(cap, "=")
					k := strings.ToLower(parts[0])
					v := ""
					if len(parts) > 1 {
						v = parts[1]
					}

					client.Lock()
					client.Caps.Available[k] = v
					client.Unlock()
				}

				if isLastCapsLine {
					common := client.Caps.CommonCaps()
					if len(common) > 0 {
						client.WriteLine("CAP REQ :%s", strings.Join(common, " "))
					} else {
						client.WriteLine("CAP END")
					}
				}
			}

			if command == "ACK" {
				// TODO: Do the ACK responses also use * to denote a multiline response?
				capsRaw := getParam(msg, 2)

				for _, cap := range strings.Split(capsRaw, " ") {
					parts := strings.Split(cap, "=")
					k := strings.ToLower(parts[0])
					v := ""
					if len(parts) > 1 {
						v = parts[1]
					}

					client.Lock()
					client.Caps.Enabled[k] = v
					client.Unlock()
				}

				client.WriteLine("CAP END")
			}

			if command == "NAK" {
				// TODO: This
			}

			return true
		},
	}
}

func getParam(msg *ircmsg.IrcMessage, idx int) string {
	if len(msg.Params)-1 < idx {
		return ""
	}

	return msg.Params[idx]
}

func SplitMask(mask string) (string, string, string) {
	nick := ""
	username := ""
	host := ""

	pos := 0

	pos = strings.Index(mask, "!")
	if pos > -1 {
		nick = mask[0:pos]
		mask = mask[pos+1:]
	} else {
		nick = mask
		mask = ""
	}

	pos = strings.Index(mask, "@")
	if pos > -1 {
		username = mask[0:pos]
		mask = mask[pos+1:]
		host = mask
	} else {
		username = mask
		host = ""
	}

	return nick, username, host
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"fmt"
	"errors"
	"strings"
	"crypto/rsa"
	"crypto/x509"
	"encoding/hex"
	"encoding/asn1"
	"encoding/pem"
	"encoding/json"
	"github.com/urfave/cli"
	"github.com/howeyc/gopass"
	//"github.com/ebfe/go.pcsclite/scard"
	"github.com/ianmcmahon/encoding_ssh"
	//reflect"
    //"github.com/vaughan0/go-ini"
)

var commonFlags = []cli.Flag {
	cli.BoolFlag {
		Name: "verbose, v",
		Usage: "詳細出力",
	},
}

func checkCard(c *cli.Context) error {
	reader := NewReader(c)
	defer reader.Finalize()
	reader.CheckCard()
	return nil
}

func showCert(c *cli.Context, efid string, pin []byte) error {
	reader := NewReader(c)
	if reader == nil {
		os.Exit(1)
	}
	defer reader.Finalize()
	card := reader.WaitForCard()
	status, _ := card.Status()
	fmt.Printf("Card Status: %s\n", status)
	aid := "D3 92 f0 00 26 01 00 00 00 01"
	apdu := "00 A4 04 0C" + " 0A " + aid
	reader.Tx(apdu)

	if pin != nil {
        //tx(card, "00 a4 02 0C 02 00 18") // VERIFY EF for AUTH
		reader.Tx("00 a4 02 0C 02 00 1B") // VERIFY EF for SIGN
		reader.Tx("00 20 00 80")
		apdu = "00 20 00 80 " + fmt.Sprintf("%02X % X", len(pin), pin)
		reader.Tx(apdu)
    }

	reader.Tx("00 A4 02 0C 02 " + efid)
	data := reader.ReadBinary(4)
	if len(data) != 4 {
		fmt.Printf("エラー: Unkown\n")
		return errors.New("error")
	}
	data_size := uint16(data[2]) << 8 | uint16(data[3])
	data = reader.ReadBinary(4 + data_size)

	/*
	fp, _ := os.Create("cert.der")
	defer fp.Close()
	fp.Write(data)
    */

	form := c.String("form")
	if form == "ssh" {
		cert, _ := x509.ParseCertificate(data)
		rsaPubkey := cert.PublicKey.(*rsa.PublicKey)
		sshPubkey, _ := ssh.EncodePublicKey(*rsaPubkey, "")
		fmt.Println(sshPubkey)
	}else{
		var block pem.Block
		block.Type = "CERTIFICATE"
		block.Bytes = data
		pem.Encode(os.Stdout, &block)
	}

	return nil
}

func showAuthCert(c *cli.Context) error {
	showCert(c, "00 0A", nil)
	return nil
}

func showAuthCACert(c *cli.Context) error {
	showCert(c, "00 0B", nil)
	return nil
}

func changeAuthPIN(c *cli.Context) error {
	reader := NewReader(c)
	if reader == nil {
		os.Exit(1)
	}
	defer reader.Finalize()
	reader.WaitForCard()

	pin := c.String("pin")
	if len(pin) == 0 {
		fmt.Printf("認証用PIN(4桁): ")
		input, _ := gopass.GetPasswdMasked()
		pin = string(input)
	}

	newpin := c.String("newpin")
	if len(newpin) == 0 {
		fmt.Printf("新しい認証用PIN(4桁): ")
		input, _ := gopass.GetPasswdMasked()
		newpin = string(input)
	}

	reader.SelectAP("D3 92 f0 00 26 01 00 00 00 01")
	reader.SelectEF("00 18")
	apdu := "00 20 00 80"
	reader.Tx(apdu)
	apdu = "00 20 00 80 " + fmt.Sprintf("%02X % X", len(pin), pin)
	reader.Tx(apdu)
	apdu = "00 24 01 80 " + fmt.Sprintf("%02X % X", len(newpin), newpin)
	reader.Tx(apdu)
	return nil
}

func showSignCert(c *cli.Context) error {
	pin := c.String("pin")
	if len(pin) == 0 {
		fmt.Printf("署名用パスワード(6-16桁): ")
		input, _ := gopass.GetPasswdMasked()
		pin = string(input)
	}
	pass := []byte(strings.ToUpper(pin))

	if len(pin) < 6 || 16 < len(pin) {
		fmt.Printf("エラー: 署名用パスワード(6-16桁)を入力してください。\n")
		return nil
	}
	showCert(c, "00 01", pass)
	return nil
}

func showSignCACert(c *cli.Context) error {
	showCert(c, "00 02", nil)
	return nil
}

func ToHexString(b []byte) string {
	s := hex.EncodeToString(b)
	return s
}

func ToBytes(s string) []byte {
	b, _ := hex.DecodeString(strings.Replace(s, " ", "", -1))
	return b
}

func showMynumber(c *cli.Context) error {
	pin := []byte(c.String("pin"))
	if len(pin) == 0 {
		fmt.Printf("暗証番号(4桁): ")
		pin, _ = gopass.GetPasswd()
	}
	if len(pin) != 4 {
		fmt.Printf("エラー: 暗証番号(4桁)を入力してください。\n")
		return nil
	}
	reader := NewReader(c)
	if reader == nil {
		os.Exit(1)
	}
	defer reader.Finalize()
	card := reader.WaitForCard()
	if card == nil {
		os.Exit(1)
	}

	aid := "D3 92 10 00 31 00 01 01 04 08"
	apdu := "00 A4 04 0C" + " 0A " + aid
	reader.Tx(apdu)
	reader.Tx("00 a4 02 0C 02 00 11") // EF for VERIFY
	reader.Tx("00 20 00 80")
	apdu = "00 20 00 80 " + fmt.Sprintf("%02X % X", len(pin), pin)
	reader.Tx(apdu)
	reader.Tx("00 A4 02 0C 02 00 01")
	data := reader.ReadBinary(16)
	var mynum asn1.RawValue
	asn1.Unmarshal(data, &mynum)

	reader.Tx("00 A4 02 0C 02 00 02")
	data = reader.ReadBinary(5)
	if len(data) != 5 {
		fmt.Printf("エラー: Unkown\n")
		return errors.New("error")
	}
	data_size := uint16(data[3]) << 8 | uint16(data[4])
	data = reader.ReadBinary(5 + data_size)
	var attr[5] asn1.RawValue
	pos := 5
	for i := 0; i < 5; i++ {
		asn1.Unmarshal(data[pos:], &attr[i])
		pos += len(attr[i].FullBytes)
	}
	if c.String("form") == "json" {
		j, _ := json.MarshalIndent(map[string]string{
			"mynumber": string(mynum.Bytes),
			"header": fmt.Sprintf("% X", attr[0].Bytes),
			"name": string(attr[1].Bytes),
			"addr": string(attr[2].Bytes),
			"birthday": string(attr[3].Bytes),
			"sex": string(attr[4].Bytes),
		}, "", "  ")
		fmt.Printf("%s", j)
	}else{
		fmt.Printf("個人番号: %s\n", mynum.Bytes)
		fmt.Printf("謎ヘッダ: % X\n", attr[0].Bytes)
		fmt.Printf("氏名:     %s\n", attr[1].Bytes)
		fmt.Printf("住所:     %s\n", attr[2].Bytes)
		fmt.Printf("生年月日: %s\n", attr[3].Bytes)
		fmt.Printf("性別:     %s\n", attr[4].Bytes)
	}
	return nil
}

func main() {
	cli.VersionFlag = cli.BoolFlag{
		Name: "version, V",
		Usage: "print version",
	}
	app := cli.NewApp()
	app.Name = "jinc"
	app.Usage = "個人番号カードユーティリティ"
	app.Author = "HAMANO Tsukasa"
	app.Email = "hamano@osstech.co.jp"
	app.Version = Version
	app.Commands = []cli.Command {
		{
			Name: "sign_cert",
			Usage: "署名用証明書を表示",
			Action: showSignCert,
			Flags: append(commonFlags, []cli.Flag {
				cli.StringFlag {
					Name: "pin",
					Usage: "署名用パスワード(6-16桁)",
				},
				cli.StringFlag {
					Name: "form",
					Usage: "出力形式(pem,ssh)",
				},
			}...),
		},
		{
			Name: "sign_ca_cert",
			Usage: "署名用CA証明書を表示",
			Action: showSignCACert,
			Flags: commonFlags,
		},
		{
			Name: "auth_cert",
			Usage: "利用者認証用証明書を表示",
			Action: showAuthCert,
			Flags: append(commonFlags, []cli.Flag {
				cli.StringFlag {
					Name: "form",
					Usage: "出力形式(pem,ssh)",
				},
			}...),
		},
		{
			Name: "auth_ca_cert",
			Usage: "利用者認証用CA証明書を表示",
			Action: showAuthCACert,
			Flags: commonFlags,
		},
		{
			Name: "auth_change_pin",
			Usage: "利用者認証用PINを変更",
			Flags: append(commonFlags, []cli.Flag {
				cli.StringFlag {
					Name: "pin",
					Usage: "暗証番号(4桁)",
				},
				cli.StringFlag {
					Name: "newpin",
					Usage: "新しい暗証番号(4桁)",
				},
			}...),
			Action: changeAuthPIN,
		},
		{
			Name: "mynumber",
			Usage: "券面事項入力補助AP",
			Action: showMynumber,
			Before: checkCard,
			Flags: append(commonFlags, []cli.Flag {
				cli.StringFlag {
					Name: "pin",
					Usage: "暗証番号(4桁)",
				},
				cli.StringFlag {
					Name: "form",
					Usage: "出力形式(txt,json)",
				},
			}...),
		},
		{
			Name: "cms",
			Usage: "署名関連",
			Subcommands: cmsCommands,
		},
		{
			Name: "tool",
			Usage: "種々様々なツール",
			Subcommands: toolCommands,
		},
	}
	app.Run(os.Args)
}
<commit_msg>mask passwd<commit_after>package main

import (
	"os"
	"fmt"
	"errors"
	"strings"
	"crypto/rsa"
	"crypto/x509"
	"encoding/hex"
	"encoding/asn1"
	"encoding/pem"
	"encoding/json"
	"github.com/urfave/cli"
	"github.com/howeyc/gopass"
	//"github.com/ebfe/go.pcsclite/scard"
	"github.com/ianmcmahon/encoding_ssh"
	//reflect"
    //"github.com/vaughan0/go-ini"
)

var commonFlags = []cli.Flag {
	cli.BoolFlag {
		Name: "verbose, v",
		Usage: "詳細出力",
	},
}

func checkCard(c *cli.Context) error {
	reader := NewReader(c)
	defer reader.Finalize()
	reader.CheckCard()
	return nil
}

func showCert(c *cli.Context, efid string, pin []byte) error {
	reader := NewReader(c)
	if reader == nil {
		os.Exit(1)
	}
	defer reader.Finalize()
	card := reader.WaitForCard()
	status, _ := card.Status()
	fmt.Printf("Card Status: %s\n", status)
	aid := "D3 92 f0 00 26 01 00 00 00 01"
	apdu := "00 A4 04 0C" + " 0A " + aid
	reader.Tx(apdu)

	if pin != nil {
        //tx(card, "00 a4 02 0C 02 00 18") // VERIFY EF for AUTH
		reader.Tx("00 a4 02 0C 02 00 1B") // VERIFY EF for SIGN
		reader.Tx("00 20 00 80")
		apdu = "00 20 00 80 " + fmt.Sprintf("%02X % X", len(pin), pin)
		reader.Tx(apdu)
    }

	reader.Tx("00 A4 02 0C 02 " + efid)
	data := reader.ReadBinary(4)
	if len(data) != 4 {
		fmt.Printf("エラー: Unkown\n")
		return errors.New("error")
	}
	data_size := uint16(data[2]) << 8 | uint16(data[3])
	data = reader.ReadBinary(4 + data_size)

	/*
	fp, _ := os.Create("cert.der")
	defer fp.Close()
	fp.Write(data)
    */

	form := c.String("form")
	if form == "ssh" {
		cert, _ := x509.ParseCertificate(data)
		rsaPubkey := cert.PublicKey.(*rsa.PublicKey)
		sshPubkey, _ := ssh.EncodePublicKey(*rsaPubkey, "")
		fmt.Println(sshPubkey)
	}else{
		var block pem.Block
		block.Type = "CERTIFICATE"
		block.Bytes = data
		pem.Encode(os.Stdout, &block)
	}

	return nil
}

func showAuthCert(c *cli.Context) error {
	showCert(c, "00 0A", nil)
	return nil
}

func showAuthCACert(c *cli.Context) error {
	showCert(c, "00 0B", nil)
	return nil
}

func changeAuthPIN(c *cli.Context) error {
	reader := NewReader(c)
	if reader == nil {
		os.Exit(1)
	}
	defer reader.Finalize()
	reader.WaitForCard()

	pin := c.String("pin")
	if len(pin) == 0 {
		fmt.Printf("認証用PIN(4桁): ")
		input, _ := gopass.GetPasswdMasked()
		pin = string(input)
	}

	newpin := c.String("newpin")
	if len(newpin) == 0 {
		fmt.Printf("新しい認証用PIN(4桁): ")
		input, _ := gopass.GetPasswdMasked()
		newpin = string(input)
	}

	reader.SelectAP("D3 92 f0 00 26 01 00 00 00 01")
	reader.SelectEF("00 18")
	apdu := "00 20 00 80"
	reader.Tx(apdu)
	apdu = "00 20 00 80 " + fmt.Sprintf("%02X % X", len(pin), pin)
	reader.Tx(apdu)
	apdu = "00 24 01 80 " + fmt.Sprintf("%02X % X", len(newpin), newpin)
	reader.Tx(apdu)
	return nil
}

func showSignCert(c *cli.Context) error {
	pin := c.String("pin")
	if len(pin) == 0 {
		fmt.Printf("署名用パスワード(6-16桁): ")
		input, _ := gopass.GetPasswdMasked()
		pin = string(input)
	}
	pass := []byte(strings.ToUpper(pin))

	if len(pin) < 6 || 16 < len(pin) {
		fmt.Printf("エラー: 署名用パスワード(6-16桁)を入力してください。\n")
		return nil
	}
	showCert(c, "00 01", pass)
	return nil
}

func showSignCACert(c *cli.Context) error {
	showCert(c, "00 02", nil)
	return nil
}

func ToHexString(b []byte) string {
	s := hex.EncodeToString(b)
	return s
}

func ToBytes(s string) []byte {
	b, _ := hex.DecodeString(strings.Replace(s, " ", "", -1))
	return b
}

func showMynumber(c *cli.Context) error {
	pin := []byte(c.String("pin"))
	if len(pin) == 0 {
		fmt.Printf("暗証番号(4桁): ")
		pin, _ = gopass.GetPasswdMasked()
	}
	if len(pin) != 4 {
		fmt.Printf("エラー: 暗証番号(4桁)を入力してください。\n")
		return nil
	}
	reader := NewReader(c)
	if reader == nil {
		os.Exit(1)
	}
	defer reader.Finalize()
	card := reader.WaitForCard()
	if card == nil {
		os.Exit(1)
	}

	aid := "D3 92 10 00 31 00 01 01 04 08"
	apdu := "00 A4 04 0C" + " 0A " + aid
	reader.Tx(apdu)
	reader.Tx("00 a4 02 0C 02 00 11") // EF for VERIFY
	reader.Tx("00 20 00 80")
	apdu = "00 20 00 80 " + fmt.Sprintf("%02X % X", len(pin), pin)
	reader.Tx(apdu)
	reader.Tx("00 A4 02 0C 02 00 01")
	data := reader.ReadBinary(16)
	var mynum asn1.RawValue
	asn1.Unmarshal(data, &mynum)

	reader.Tx("00 A4 02 0C 02 00 02")
	data = reader.ReadBinary(5)
	if len(data) != 5 {
		fmt.Printf("エラー: Unkown\n")
		return errors.New("error")
	}
	data_size := uint16(data[3]) << 8 | uint16(data[4])
	data = reader.ReadBinary(5 + data_size)
	var attr[5] asn1.RawValue
	pos := 5
	for i := 0; i < 5; i++ {
		asn1.Unmarshal(data[pos:], &attr[i])
		pos += len(attr[i].FullBytes)
	}
	if c.String("form") == "json" {
		j, _ := json.MarshalIndent(map[string]string{
			"mynumber": string(mynum.Bytes),
			"header": fmt.Sprintf("% X", attr[0].Bytes),
			"name": string(attr[1].Bytes),
			"addr": string(attr[2].Bytes),
			"birthday": string(attr[3].Bytes),
			"sex": string(attr[4].Bytes),
		}, "", "  ")
		fmt.Printf("%s", j)
	}else{
		fmt.Printf("個人番号: %s\n", mynum.Bytes)
		fmt.Printf("謎ヘッダ: % X\n", attr[0].Bytes)
		fmt.Printf("氏名:     %s\n", attr[1].Bytes)
		fmt.Printf("住所:     %s\n", attr[2].Bytes)
		fmt.Printf("生年月日: %s\n", attr[3].Bytes)
		fmt.Printf("性別:     %s\n", attr[4].Bytes)
	}
	return nil
}

func main() {
	cli.VersionFlag = cli.BoolFlag{
		Name: "version, V",
		Usage: "print version",
	}
	app := cli.NewApp()
	app.Name = "jinc"
	app.Usage = "個人番号カードユーティリティ"
	app.Author = "HAMANO Tsukasa"
	app.Email = "hamano@osstech.co.jp"
	app.Version = Version
	app.Commands = []cli.Command {
		{
			Name: "sign_cert",
			Usage: "署名用証明書を表示",
			Action: showSignCert,
			Flags: append(commonFlags, []cli.Flag {
				cli.StringFlag {
					Name: "pin",
					Usage: "署名用パスワード(6-16桁)",
				},
				cli.StringFlag {
					Name: "form",
					Usage: "出力形式(pem,ssh)",
				},
			}...),
		},
		{
			Name: "sign_ca_cert",
			Usage: "署名用CA証明書を表示",
			Action: showSignCACert,
			Flags: commonFlags,
		},
		{
			Name: "auth_cert",
			Usage: "利用者認証用証明書を表示",
			Action: showAuthCert,
			Flags: append(commonFlags, []cli.Flag {
				cli.StringFlag {
					Name: "form",
					Usage: "出力形式(pem,ssh)",
				},
			}...),
		},
		{
			Name: "auth_ca_cert",
			Usage: "利用者認証用CA証明書を表示",
			Action: showAuthCACert,
			Flags: commonFlags,
		},
		{
			Name: "auth_change_pin",
			Usage: "利用者認証用PINを変更",
			Flags: append(commonFlags, []cli.Flag {
				cli.StringFlag {
					Name: "pin",
					Usage: "暗証番号(4桁)",
				},
				cli.StringFlag {
					Name: "newpin",
					Usage: "新しい暗証番号(4桁)",
				},
			}...),
			Action: changeAuthPIN,
		},
		{
			Name: "mynumber",
			Usage: "券面事項入力補助AP",
			Action: showMynumber,
			Before: checkCard,
			Flags: append(commonFlags, []cli.Flag {
				cli.StringFlag {
					Name: "pin",
					Usage: "暗証番号(4桁)",
				},
				cli.StringFlag {
					Name: "form",
					Usage: "出力形式(txt,json)",
				},
			}...),
		},
		{
			Name: "cms",
			Usage: "署名関連",
			Subcommands: cmsCommands,
		},
		{
			Name: "tool",
			Usage: "種々様々なツール",
			Subcommands: toolCommands,
		},
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/wkharold/jobd/deps/code.google.com/p/go9p/p"
	"github.com/wkharold/jobd/deps/code.google.com/p/go9p/p/srv"
)

type jobsdir struct {
	srv.File
}
<commit_msg>More skeleton code to get a clean compile<commit_after>package main

import (
	"github.com/wkharold/jobd/deps/code.google.com/p/go9p/p"
	"github.com/wkharold/jobd/deps/code.google.com/p/go9p/p/srv"
)

type jobsdir struct {
	srv.File
}

func (jd jobsdir) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
	return 0, nil
}

func (jd *jobsdir) Wstat(fid *srv.FFid, dir *p.Dir) error {
	return nil
}
<|endoftext|>


<commit_before>package testfixtures

import (
	"database/sql/driver"
	"encoding/json"
)

var (
	_ driver.Valuer = jsonArray{}
	_ driver.Valuer = jsonMap{}
)

type jsonArray []interface{}

func (a jsonArray) Value() (driver.Value, error) {
	return json.Marshal(a)
}

type jsonMap map[string]interface{}

func (m jsonMap) Value() (driver.Value, error) {
	return json.Marshal(m)
}

// Go refuses to convert map[interface{}]interface{} to JSON because JSON only support string keys
// So it's necessary to recursively convert all map[interface]interface{} to map[string]interface{}
func recursiveToJSON(v interface{}) (r interface{}) {
	switch v := v.(type) {
	case []interface{}:
		for i, e := range v {
			v[i] = recursiveToJSON(e)
		}
		r = jsonArray(v)
	case map[interface{}]interface{}:
		newMap := make(map[string]interface{}, len(v))
		for k, e := range v {
			newMap[k.(string)] = recursiveToJSON(e)
		}
		r = jsonMap(newMap)
	default:
		r = v
	}
	return r
}
<commit_msg>Unecessary value on return<commit_after>package testfixtures

import (
	"database/sql/driver"
	"encoding/json"
)

var (
	_ driver.Valuer = jsonArray{}
	_ driver.Valuer = jsonMap{}
)

type jsonArray []interface{}

func (a jsonArray) Value() (driver.Value, error) {
	return json.Marshal(a)
}

type jsonMap map[string]interface{}

func (m jsonMap) Value() (driver.Value, error) {
	return json.Marshal(m)
}

// Go refuses to convert map[interface{}]interface{} to JSON because JSON only support string keys
// So it's necessary to recursively convert all map[interface]interface{} to map[string]interface{}
func recursiveToJSON(v interface{}) (r interface{}) {
	switch v := v.(type) {
	case []interface{}:
		for i, e := range v {
			v[i] = recursiveToJSON(e)
		}
		r = jsonArray(v)
	case map[interface{}]interface{}:
		newMap := make(map[string]interface{}, len(v))
		for k, e := range v {
			newMap[k.(string)] = recursiveToJSON(e)
		}
		r = jsonMap(newMap)
	default:
		r = v
	}
	return
}
<|endoftext|>


<commit_before>package json

import (
	"encoding/json"
	"errors"
	"strconv"

	"github.com/yuin/gopher-lua"
)

// Preload adds json to the given Lua state's package.preload table. After it
// has been preloaded, it can be loaded using require:
//
//  local json = require("json")
func Preload(L *lua.LState) {
	L.PreloadModule("json", Loader)
}

// Loader is the module loader function.
func Loader(L *lua.LState) int {
	t := L.NewTable()
	L.SetFuncs(t, api)
	L.Push(t)
	return 1
}

var api = map[string]lua.LGFunction{
	"decode": apiDecode,
	"encode": apiEncode,
}

func apiDecode(L *lua.LState) int {
	str := L.CheckString(1)

	value, err := Decode(L, []byte(str))
	if err != nil {
		L.Push(lua.LNil)
		L.Push(lua.LString(err.Error()))
		return 2
	}
	L.Push(value)
	return 1
}

func apiEncode(L *lua.LState) int {
	value := L.CheckAny(1)

	data, err := Encode(value)
	if err != nil {
		L.Push(lua.LNil)
		L.Push(lua.LString(err.Error()))
		return 2
	}
	L.Push(lua.LString(string(data)))
	return 1
}

var (
	errFunction = errors.New("cannot encode function to JSON")
	errChannel  = errors.New("cannot encode channel to JSON")
	errState    = errors.New("cannot encode state to JSON")
	errUserData = errors.New("cannot encode userdata to JSON")
	errNested   = errors.New("cannot encode recursively nested tables to JSON")
)

type jsonValue struct {
	lua.LValue
	visited map[*lua.LTable]bool
}

func (j jsonValue) MarshalJSON() ([]byte, error) {
	return encode(j.LValue, j.visited)
}

// Encode returns the JSON encoding of value.
func Encode(value lua.LValue) ([]byte, error) {
	return encode(value, make(map[*lua.LTable]bool))
}

func encode(value lua.LValue, visited map[*lua.LTable]bool) (data []byte, err error) {
	switch converted := value.(type) {
	case lua.LBool:
		data, err = json.Marshal(converted)
	case lua.LChannel:
		err = errChannel
	case lua.LNumber:
		data, err = json.Marshal(converted)
	case *lua.LFunction:
		err = errFunction
	case *lua.LNilType:
		data, err = json.Marshal(converted)
	case *lua.LState:
		err = errState
	case lua.LString:
		data, err = json.Marshal(converted)
	case *lua.LTable:
		var arr []jsonValue
		var obj map[string]jsonValue

		if visited[converted] {
			panic(errNested)
		}
		visited[converted] = true

		converted.ForEach(func(k lua.LValue, v lua.LValue) {
			i, numberKey := k.(lua.LNumber)
			if numberKey && obj == nil {
				index := int(i) - 1
				if index != len(arr) {
					// map out of order; convert to map
					obj = make(map[string]jsonValue)
					for i, value := range arr {
						obj[strconv.Itoa(i+1)] = value
					}
					obj[strconv.Itoa(index+1)] = jsonValue{v, visited}
					return
				}
				arr = append(arr, jsonValue{v, visited})
				return
			}
			if obj == nil {
				obj = make(map[string]jsonValue)
				for i, value := range arr {
					obj[strconv.Itoa(i+1)] = value
				}
			}
			obj[k.String()] = jsonValue{v, visited}
		})
		if obj != nil {
			data, err = json.Marshal(obj)
		} else {
			data, err = json.Marshal(arr)
		}
	case *lua.LUserData:
		// TODO: call metatable __tostring?
		err = errUserData
	}
	return
}

// Decode converts the JSON encoded data to Lua values.
func Decode(L *lua.LState, data []byte) (lua.LValue, error) {
	var value interface{}
	err := json.Unmarshal(data, &value)
	if err != nil {
		return nil, err
	}
	return decode(L, value), nil
}

func decode(L *lua.LState, value interface{}) lua.LValue {
	switch converted := value.(type) {
	case bool:
		return lua.LBool(converted)
	case float64:
		return lua.LNumber(converted)
	case string:
		return lua.LString(converted)
	case []interface{}:
		arr := L.CreateTable(len(converted), 0)
		for _, item := range converted {
			arr.Append(decode(L, item))
		}
		return arr
	case map[string]interface{}:
		tbl := L.CreateTable(0, len(converted))
		for key, item := range converted {
			tbl.RawSetH(lua.LString(key), decode(L, item))
		}
		return tbl
	}
	return lua.LNil
}
<commit_msg>simplify encoding functions<commit_after>package json

import (
	"encoding/json"
	"errors"
	"strconv"

	"github.com/yuin/gopher-lua"
)

// Preload adds json to the given Lua state's package.preload table. After it
// has been preloaded, it can be loaded using require:
//
//  local json = require("json")
func Preload(L *lua.LState) {
	L.PreloadModule("json", Loader)
}

// Loader is the module loader function.
func Loader(L *lua.LState) int {
	t := L.NewTable()
	L.SetFuncs(t, api)
	L.Push(t)
	return 1
}

var api = map[string]lua.LGFunction{
	"decode": apiDecode,
	"encode": apiEncode,
}

func apiDecode(L *lua.LState) int {
	str := L.CheckString(1)

	value, err := Decode(L, []byte(str))
	if err != nil {
		L.Push(lua.LNil)
		L.Push(lua.LString(err.Error()))
		return 2
	}
	L.Push(value)
	return 1
}

func apiEncode(L *lua.LState) int {
	value := L.CheckAny(1)

	data, err := Encode(value)
	if err != nil {
		L.Push(lua.LNil)
		L.Push(lua.LString(err.Error()))
		return 2
	}
	L.Push(lua.LString(string(data)))
	return 1
}

var (
	errFunction = errors.New("cannot encode function to JSON")
	errChannel  = errors.New("cannot encode channel to JSON")
	errState    = errors.New("cannot encode state to JSON")
	errUserData = errors.New("cannot encode userdata to JSON")
	errNested   = errors.New("cannot encode recursively nested tables to JSON")
)

// Encode returns the JSON encoding of value.
func Encode(value lua.LValue) ([]byte, error) {
	return json.Marshal(jsonValue{
		LValue:  value,
		visited: make(map[*lua.LTable]bool),
	})
}

type jsonValue struct {
	lua.LValue
	visited map[*lua.LTable]bool
}

func (j jsonValue) MarshalJSON() (data []byte, err error) {
	switch converted := j.LValue.(type) {
	case lua.LBool:
		data, err = json.Marshal(converted)
	case lua.LChannel:
		err = errChannel
	case lua.LNumber:
		data, err = json.Marshal(converted)
	case *lua.LFunction:
		err = errFunction
	case *lua.LNilType:
		data, err = json.Marshal(converted)
	case *lua.LState:
		err = errState
	case lua.LString:
		data, err = json.Marshal(converted)
	case *lua.LTable:
		var arr []jsonValue
		var obj map[string]jsonValue

		if j.visited[converted] {
			panic(errNested)
		}
		j.visited[converted] = true

		converted.ForEach(func(k lua.LValue, v lua.LValue) {
			i, numberKey := k.(lua.LNumber)
			if numberKey && obj == nil {
				index := int(i) - 1
				if index != len(arr) {
					// map out of order; convert to map
					obj = make(map[string]jsonValue)
					for i, value := range arr {
						obj[strconv.Itoa(i+1)] = value
					}
					obj[strconv.Itoa(index+1)] = jsonValue{v, j.visited}
					return
				}
				arr = append(arr, jsonValue{v, j.visited})
				return
			}
			if obj == nil {
				obj = make(map[string]jsonValue)
				for i, value := range arr {
					obj[strconv.Itoa(i+1)] = value
				}
			}
			obj[k.String()] = jsonValue{v, j.visited}
		})
		if obj != nil {
			data, err = json.Marshal(obj)
		} else {
			data, err = json.Marshal(arr)
		}
	case *lua.LUserData:
		// TODO: call metatable __tostring?
		err = errUserData
	}
	return
}

// Decode converts the JSON encoded data to Lua values.
func Decode(L *lua.LState, data []byte) (lua.LValue, error) {
	var value interface{}
	err := json.Unmarshal(data, &value)
	if err != nil {
		return nil, err
	}
	return decode(L, value), nil
}

func decode(L *lua.LState, value interface{}) lua.LValue {
	switch converted := value.(type) {
	case bool:
		return lua.LBool(converted)
	case float64:
		return lua.LNumber(converted)
	case string:
		return lua.LString(converted)
	case []interface{}:
		arr := L.CreateTable(len(converted), 0)
		for _, item := range converted {
			arr.Append(decode(L, item))
		}
		return arr
	case map[string]interface{}:
		tbl := L.CreateTable(0, len(converted))
		for key, item := range converted {
			tbl.RawSetH(lua.LString(key), decode(L, item))
		}
		return tbl
	}
	return lua.LNil
}
<|endoftext|>


<commit_before>/*  lMDQ is a MDQ server that caches metadata locally so it's local clients can lookup
    pre-checked metadata and not depend on a working connection to a remote MDQ server.

    It uses SQLite as it's datastore and allows lookup by either entityID or Location.
    The latter is used by WAYF for it's mass hosting services BIRK and KRIB.

    It can also be used as a library for just looking up metadata inside a go program.

    Or a client can use the SQLite database directly using the following query:

		"select e.md, e.hash from entity e, lookup l where l.hash = $1 and l.entity_id_fk = e.id and e.validuntil >= $2"

    where $1 is the lowercase hex sha1 of the entityID or location without the {sha1} prefix
    $2 is the current epoch.

    to-do:
        √ caching interface
          invalidate cache ???
*/

package lMDQ

import (
	"crypto/sha1"
	"database/sql"
	"encoding/hex"
	_ "github.com/mattn/go-sqlite3"
	"github.com/wayf-dk/gosaml"
	"github.com/wayf-dk/goxml"
	"github.com/y0ssar1an/q"
	"sort"
	"strings"
	"sync"
	"time"
)

type (
	EntityRec struct {
		id       int64
		entityid string
		hash     string
	}

	MDQ struct {
		db    *sql.DB
		stmt  *sql.Stmt
		Path  string
		Cache map[string]*MdXp
		Lock  sync.Mutex
		Table string
	}

	MdXp struct {
		*goxml.Xp
		created time.Time
	}
)

var (
	cacheduration = time.Minute * 60
	_             = q.Q
)

func (xp *MdXp) Valid(duration time.Duration) bool {
	since := time.Since(xp.created)
	//log.Println(since, duration, since  < duration)
	return since < duration
}

func (mdq *MDQ) Open() (err error) {
	mdq.Lock.Lock()
	defer mdq.Lock.Unlock()
	mdq.Cache = make(map[string]*MdXp)
	mdq.db, err = sql.Open("sqlite3", mdq.Path)
	if err != nil {
		return
	}
	mdq.stmt, err = mdq.db.Prepare("select e.md md from entity_" + mdq.Table + " e, lookup_" + mdq.Table + " l where l.hash = ? and l.entity_id_fk = e.id")
	if err != nil {
		return
	}
	return
}

// MDQ looks up an entity using the supplied feed and key.
// The key can be an entityID or a location, optionally in {sha1} format
// It returns a non nil err if the entity is not found
// and the metadata and a hash/etag over the content if it is.
// The hash can be used to decide if a cached dom object is still valid,
// This might be an optimization as the database lookup is much faster that the parsing.
func (mdq *MDQ) MDQ(key string) (xp *goxml.Xp, err error) {
	return mdq.dbget(key, true)
}

func (mdq *MDQ) dbget(key string, cache bool) (xp *goxml.Xp, err error) {
	mdq.Lock.Lock()
	defer mdq.Lock.Unlock()

	k := key
	if strings.HasPrefix(key, "{sha1}") {
		key = key[6:]
	} else {
		hash := sha1.Sum([]byte(key))
		key = hex.EncodeToString(append(hash[:]))
	}
	cachedxp := mdq.Cache[key]
	if cachedxp != nil && cachedxp.Valid(cacheduration) {
		xp = cachedxp.Xp.CpXp()
		return
	}

	var xml []byte
	err = mdq.stmt.QueryRow(key).Scan(&xml)
	switch {
	case err == sql.ErrNoRows:
		err = goxml.Wrap(err, "err:Metadata not found", "key:"+k, "table:"+mdq.Table)
		return
	case err != nil:
		return
	default:
		md := gosaml.Inflate(xml)
		xp = goxml.NewXp(md)
	}
	if cache {
		mdxp := new(MdXp)
		mdxp.Xp = xp
		mdxp.created = time.Now()
		mdq.Cache[key] = mdxp
	}
	return
}

/**
  One at a time - not that fast - only use for testing
  Filtered by xpath for testing purposes
*/
func (mdq *MDQ) MDQFilter(xpathfilter string) (xp *goxml.Xp, numberOfEntities int, err error) {
	recs, err := mdq.getEntityList()
	if err != nil {
		return
	}

	// get the entities into an ordered slice
	index := make([]string, len(recs))
	i := 0
	for k, _ := range recs {
		index[i] = k
		i++
	}
	sort.Strings(index)

	//log.Println(xpathfilter)
	xp = goxml.NewXpFromString(`<md:EntitiesDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" />`)

	root, _ := xp.Doc.DocumentElement()
	for _, entityID := range index {
		ent, _ := mdq.dbget(entityID, false)

		if xpathfilter == "" || len(ent.Query(nil, xpathfilter)) > 0 {
			entity, _ := ent.Doc.DocumentElement()
			root.AddChild(xp.CopyNode(entity, 1))
			numberOfEntities++
		}
	}
	return
}

// getEntityList returns a map keyed by entityIDs for the
// current entities in the database
func (mdq *MDQ) getEntityList() (entities map[string]EntityRec, err error) {

	entities = make(map[string]EntityRec)
	var rows *sql.Rows
	rows, err = mdq.db.Query("select id, entityid, hash from entity_" + mdq.Table)
	if err != nil {
		return
	}
	defer rows.Close()
	for rows.Next() {
		var rec EntityRec
		if err = rows.Scan(&rec.id, &rec.entityid, &rec.hash); err != nil {
			return
		}
		entities[rec.entityid] = rec
	}
	if err = rows.Err(); err != nil { // no reason to actually check err, but if we later forget ...
		return
	}
	return
}
<commit_msg>Make it possible to prefix searching in sha1 hashes. For now always use a 10 char prefix.<commit_after>/*  lMDQ is a MDQ server that caches metadata locally so it's local clients can lookup
    pre-checked metadata and not depend on a working connection to a remote MDQ server.

    It uses SQLite as it's datastore and allows lookup by either entityID or Location.
    The latter is used by WAYF for it's mass hosting services BIRK and KRIB.

    It can also be used as a library for just looking up metadata inside a go program.

    Or a client can use the SQLite database directly using the following query:

		"select e.md, e.hash from entity e, lookup l where l.hash = $1 and l.entity_id_fk = e.id and e.validuntil >= $2"

    where $1 is the lowercase hex sha1 of the entityID or location without the {sha1} prefix
    $2 is the current epoch.

    to-do:
        √ caching interface
          invalidate cache ???
*/

package lMDQ

import (
	"crypto/sha1"
	"database/sql"
	"encoding/hex"
	_ "github.com/mattn/go-sqlite3"
	"github.com/wayf-dk/gosaml"
	"github.com/wayf-dk/goxml"
	"github.com/y0ssar1an/q"
	"sort"
	"strings"
	"sync"
	"time"
)

type (
	EntityRec struct {
		id       int64
		entityid string
		hash     string
	}

	MDQ struct {
		db    *sql.DB
		stmt  *sql.Stmt
		Path  string
		Cache map[string]*MdXp
		Lock  sync.Mutex
		Table string
	}

	MdXp struct {
		*goxml.Xp
		created time.Time
	}
)

var (
	cacheduration = time.Minute * 60
	_             = q.Q
)

func (xp *MdXp) Valid(duration time.Duration) bool {
	since := time.Since(xp.created)
	//log.Println(since, duration, since  < duration)
	return since < duration
}

func (mdq *MDQ) Open() (err error) {
	mdq.Lock.Lock()
	defer mdq.Lock.Unlock()
	mdq.Cache = make(map[string]*MdXp)
	mdq.db, err = sql.Open("sqlite3", mdq.Path)
	if err != nil {
		return
	}
	// This is supposed to be a very smart wayf do to prefix search - keep an eye on wheather a 10 char prefix ie. using 40 bits is enough
	mdq.stmt, err = mdq.db.Prepare("select e.md md from entity_" + mdq.Table + " e, lookup_" + mdq.Table + " l where ? < l.hash||'z' and l.hash||'z' <= ? and l.entity_id_fk = e.id")
	if err != nil {
		return
	}
	return
}

// MDQ looks up an entity using the supplied feed and key.
// The key can be an entityID or a location, optionally in {sha1} format
// It returns a non nil err if the entity is not found
// and the metadata and a hash/etag over the content if it is.
// The hash can be used to decide if a cached dom object is still valid,
// This might be an optimization as the database lookup is much faster that the parsing.
func (mdq *MDQ) MDQ(key string) (xp *goxml.Xp, err error) {
	return mdq.dbget(key, true)
}

func (mdq *MDQ) dbget(key string, cache bool) (xp *goxml.Xp, err error) {
	mdq.Lock.Lock()
	defer mdq.Lock.Unlock()

	k := key
	if strings.HasPrefix(key, "{sha1}") {
		key = key[6:]
	} else {
		hash := sha1.Sum([]byte(key))
		key = hex.EncodeToString(append(hash[:]))
	}
	key = key[:10] // only use the first 10 chars for key
	cachedxp := mdq.Cache[key]
	if cachedxp != nil && cachedxp.Valid(cacheduration) {
		xp = cachedxp.Xp.CpXp()
		return
	}

	var xml []byte
	err = mdq.stmt.QueryRow(key, key+"z").Scan(&xml)
	switch {
	case err == sql.ErrNoRows:
		err = goxml.Wrap(err, "err:Metadata not found", "key:"+k, "table:"+mdq.Table)
		return
	case err != nil:
		return
	default:
		md := gosaml.Inflate(xml)
		xp = goxml.NewXp(md)
	}
	if cache {
		mdxp := new(MdXp)
		mdxp.Xp = xp
		mdxp.created = time.Now()
		mdq.Cache[key] = mdxp
	}
	return
}

/**
  One at a time - not that fast - only use for testing
  Filtered by xpath for testing purposes
*/
func (mdq *MDQ) MDQFilter(xpathfilter string) (xp *goxml.Xp, numberOfEntities int, err error) {
	recs, err := mdq.getEntityList()
	if err != nil {
		return
	}

	// get the entities into an ordered slice
	index := make([]string, len(recs))
	i := 0
	for k, _ := range recs {
		index[i] = k
		i++
	}
	sort.Strings(index)

	//log.Println(xpathfilter)
	xp = goxml.NewXpFromString(`<md:EntitiesDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" />`)

	root, _ := xp.Doc.DocumentElement()
	for _, entityID := range index {
		ent, _ := mdq.dbget(entityID, false)

		if xpathfilter == "" || len(ent.Query(nil, xpathfilter)) > 0 {
			entity, _ := ent.Doc.DocumentElement()
			root.AddChild(xp.CopyNode(entity, 1))
			numberOfEntities++
		}
	}
	return
}

// getEntityList returns a map keyed by entityIDs for the
// current entities in the database
func (mdq *MDQ) getEntityList() (entities map[string]EntityRec, err error) {

	entities = make(map[string]EntityRec)
	var rows *sql.Rows
	rows, err = mdq.db.Query("select id, entityid, hash from entity_" + mdq.Table)
	if err != nil {
		return
	}
	defer rows.Close()
	for rows.Next() {
		var rec EntityRec
		if err = rows.Scan(&rec.id, &rec.entityid, &rec.hash); err != nil {
			return
		}
		entities[rec.entityid] = rec
	}
	if err = rows.Err(); err != nil { // no reason to actually check err, but if we later forget ...
		return
	}
	return
}
<|endoftext|>


<commit_before>package thermal

import (
	"crypto/rand"
	"fmt"
)

type lineHalf struct {
	id     [16]byte
	at     int
	secret [32]byte
}

type lineSession struct {
	local         lineHalf
	remote        lineHalf
	encryptionKey [32]byte
	decryptionKey [32]byte
}

type lineMap map[string]lineSession

// Generate a random 16 char hex encoded string to be used as a line id
func generateLineId() string {
	var idBin [8]byte
	rand.Reader.Read(idBin[:])
	idHex := fmt.Sprintf("%x", idBin)
	return idHex
}
<commit_msg>add name to doc string<commit_after>package thermal

import (
	"crypto/rand"
	"fmt"
)

type lineHalf struct {
	id     [16]byte
	at     int
	secret [32]byte
}

type lineSession struct {
	local         lineHalf
	remote        lineHalf
	encryptionKey [32]byte
	decryptionKey [32]byte
}

type lineMap map[string]lineSession

// generateLineId returns a random 16 char hex encoded string
func generateLineId() string {
	var idBin [8]byte
	rand.Reader.Read(idBin[:])
	idHex := fmt.Sprintf("%x", idBin)
	return idHex
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"syscall"
	"text/tabwriter"
	"time"

	"github.com/opencontainers/runc/libcontainer"
	"github.com/opencontainers/runc/libcontainer/user"
	"github.com/opencontainers/runc/libcontainer/utils"
	"github.com/urfave/cli"
)

const formatOptions = `table or json`

// containerState represents the platform agnostic pieces relating to a
// running container's status and state
type containerState struct {
	// Version is the OCI version for the container
	Version string `json:"ociVersion"`
	// ID is the container ID
	ID string `json:"id"`
	// InitProcessPid is the init process id in the parent namespace
	InitProcessPid int `json:"pid"`
	// Status is the current status of the container, running, paused, ...
	Status string `json:"status"`
	// Bundle is the path on the filesystem to the bundle
	Bundle string `json:"bundle"`
	// Rootfs is a path to a directory containing the container's root filesystem.
	Rootfs string `json:"rootfs"`
	// Created is the unix timestamp for the creation time of the container in UTC
	Created time.Time `json:"created"`
	// Annotations is the user defined annotations added to the config.
	Annotations map[string]string `json:"annotations,omitempty"`
	// The owner of the state directory (the owner of the container).
	Owner string `json:"owner"`
}

var listCommand = cli.Command{
	Name:  "list",
	Usage: "lists containers started by runc with the given root",
	ArgsUsage: `

Where the given root is specified via the global option "--root"
(default: "/run/runc").

EXAMPLE 1:
To list containers created via the default "--root":
       # runc list

EXAMPLE 2:
To list containers created using a non-default value for "--root":
       # runc --root value list`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "format, f",
			Value: "table",
			Usage: `select one of: ` + formatOptions,
		},
		cli.BoolFlag{
			Name:  "quiet, q",
			Usage: "display only container IDs",
		},
	},
	Action: func(context *cli.Context) error {
		if err := checkArgs(context, 0, exactArgs); err != nil {
			return err
		}
		s, err := getContainers(context)
		if err != nil {
			return err
		}

		if context.Bool("quiet") {
			for _, item := range s {
				fmt.Println(item.ID)
			}
			return nil
		}

		switch context.String("format") {
		case "table":
			w := tabwriter.NewWriter(os.Stdout, 12, 1, 3, ' ', 0)
			fmt.Fprint(w, "ID\tPID\tSTATUS\tBUNDLE\tCREATED\tOWNER\n")
			for _, item := range s {
				fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\n",
					item.ID,
					item.InitProcessPid,
					item.Status,
					item.Bundle,
					item.Created.Format(time.RFC3339Nano),
					item.Owner)
			}
			if err := w.Flush(); err != nil {
				return err
			}
		case "json":
			if err := json.NewEncoder(os.Stdout).Encode(s); err != nil {
				return err
			}
		default:
			return errors.New("invalid format option")
		}
		return nil
	},
}

func getContainers(context *cli.Context) ([]containerState, error) {
	factory, err := loadFactory(context)
	if err != nil {
		return nil, err
	}
	root := context.GlobalString("root")
	absRoot, err := filepath.Abs(root)
	if err != nil {
		return nil, err
	}
	list, err := os.ReadDir(absRoot)
	if err != nil {
		fatal(err)
	}

	var s []containerState
	for _, item := range list {
		if !item.IsDir() {
			continue
		}
		st, err := os.Stat(filepath.Join(absRoot, item.Name()))
		if err != nil {
			fatal(err)
		}
		// This cast is safe on Linux.
		uid := st.Sys().(*syscall.Stat_t).Uid
		owner, err := user.LookupUid(int(uid))
		if err != nil {
			owner.Name = fmt.Sprintf("#%d", uid)
		}

		container, err := factory.Load(item.Name())
		if err != nil {
			fmt.Fprintf(os.Stderr, "load container %s: %v\n", item.Name(), err)
			continue
		}
		containerStatus, err := container.Status()
		if err != nil {
			fmt.Fprintf(os.Stderr, "status for %s: %v\n", item.Name(), err)
			continue
		}
		state, err := container.State()
		if err != nil {
			fmt.Fprintf(os.Stderr, "state for %s: %v\n", item.Name(), err)
			continue
		}
		pid := state.BaseState.InitProcessPid
		if containerStatus == libcontainer.Stopped {
			pid = 0
		}
		bundle, annotations := utils.Annotations(state.Config.Labels)
		s = append(s, containerState{
			Version:        state.BaseState.Config.Version,
			ID:             state.BaseState.ID,
			InitProcessPid: pid,
			Status:         containerStatus.String(),
			Bundle:         bundle,
			Rootfs:         state.BaseState.Config.Rootfs,
			Created:        state.BaseState.Created,
			Annotations:    annotations,
			Owner:          owner.Name,
		})
	}
	return s, nil
}
<commit_msg>list: use Info(), fix race with delete<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"syscall"
	"text/tabwriter"
	"time"

	"github.com/opencontainers/runc/libcontainer"
	"github.com/opencontainers/runc/libcontainer/user"
	"github.com/opencontainers/runc/libcontainer/utils"
	"github.com/urfave/cli"
)

const formatOptions = `table or json`

// containerState represents the platform agnostic pieces relating to a
// running container's status and state
type containerState struct {
	// Version is the OCI version for the container
	Version string `json:"ociVersion"`
	// ID is the container ID
	ID string `json:"id"`
	// InitProcessPid is the init process id in the parent namespace
	InitProcessPid int `json:"pid"`
	// Status is the current status of the container, running, paused, ...
	Status string `json:"status"`
	// Bundle is the path on the filesystem to the bundle
	Bundle string `json:"bundle"`
	// Rootfs is a path to a directory containing the container's root filesystem.
	Rootfs string `json:"rootfs"`
	// Created is the unix timestamp for the creation time of the container in UTC
	Created time.Time `json:"created"`
	// Annotations is the user defined annotations added to the config.
	Annotations map[string]string `json:"annotations,omitempty"`
	// The owner of the state directory (the owner of the container).
	Owner string `json:"owner"`
}

var listCommand = cli.Command{
	Name:  "list",
	Usage: "lists containers started by runc with the given root",
	ArgsUsage: `

Where the given root is specified via the global option "--root"
(default: "/run/runc").

EXAMPLE 1:
To list containers created via the default "--root":
       # runc list

EXAMPLE 2:
To list containers created using a non-default value for "--root":
       # runc --root value list`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "format, f",
			Value: "table",
			Usage: `select one of: ` + formatOptions,
		},
		cli.BoolFlag{
			Name:  "quiet, q",
			Usage: "display only container IDs",
		},
	},
	Action: func(context *cli.Context) error {
		if err := checkArgs(context, 0, exactArgs); err != nil {
			return err
		}
		s, err := getContainers(context)
		if err != nil {
			return err
		}

		if context.Bool("quiet") {
			for _, item := range s {
				fmt.Println(item.ID)
			}
			return nil
		}

		switch context.String("format") {
		case "table":
			w := tabwriter.NewWriter(os.Stdout, 12, 1, 3, ' ', 0)
			fmt.Fprint(w, "ID\tPID\tSTATUS\tBUNDLE\tCREATED\tOWNER\n")
			for _, item := range s {
				fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\n",
					item.ID,
					item.InitProcessPid,
					item.Status,
					item.Bundle,
					item.Created.Format(time.RFC3339Nano),
					item.Owner)
			}
			if err := w.Flush(); err != nil {
				return err
			}
		case "json":
			if err := json.NewEncoder(os.Stdout).Encode(s); err != nil {
				return err
			}
		default:
			return errors.New("invalid format option")
		}
		return nil
	},
}

func getContainers(context *cli.Context) ([]containerState, error) {
	factory, err := loadFactory(context)
	if err != nil {
		return nil, err
	}
	root := context.GlobalString("root")
	absRoot, err := filepath.Abs(root)
	if err != nil {
		return nil, err
	}
	list, err := os.ReadDir(absRoot)
	if err != nil {
		fatal(err)
	}

	var s []containerState
	for _, item := range list {
		if !item.IsDir() {
			continue
		}
		st, err := item.Info()
		if err != nil {
			if errors.Is(err, os.ErrNotExist) {
				// Possible race with runc delete.
				continue
			}
			fatal(err)
		}
		// This cast is safe on Linux.
		uid := st.Sys().(*syscall.Stat_t).Uid
		owner, err := user.LookupUid(int(uid))
		if err != nil {
			owner.Name = fmt.Sprintf("#%d", uid)
		}

		container, err := factory.Load(item.Name())
		if err != nil {
			fmt.Fprintf(os.Stderr, "load container %s: %v\n", item.Name(), err)
			continue
		}
		containerStatus, err := container.Status()
		if err != nil {
			fmt.Fprintf(os.Stderr, "status for %s: %v\n", item.Name(), err)
			continue
		}
		state, err := container.State()
		if err != nil {
			fmt.Fprintf(os.Stderr, "state for %s: %v\n", item.Name(), err)
			continue
		}
		pid := state.BaseState.InitProcessPid
		if containerStatus == libcontainer.Stopped {
			pid = 0
		}
		bundle, annotations := utils.Annotations(state.Config.Labels)
		s = append(s, containerState{
			Version:        state.BaseState.Config.Version,
			ID:             state.BaseState.ID,
			InitProcessPid: pid,
			Status:         containerStatus.String(),
			Bundle:         bundle,
			Rootfs:         state.BaseState.Config.Rootfs,
			Created:        state.BaseState.Created,
			Annotations:    annotations,
			Owner:          owner.Name,
		})
	}
	return s, nil
}
<|endoftext|>


<commit_before>package integration

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"time"

	"veyron.io/veyron/veyron/lib/expect"
	"veyron.io/veyron/veyron/lib/modules"
	"veyron.io/veyron/veyron/lib/modules/core"
)

// BuildPkgs returns a path to a directory that contains the built
// binaries for the given set of packages and a function that should
// be invoked to clean up the build artifacts. Note that the clients
// of this function should not modify the contents of this directory
// directly and instead defer to the cleanup function.
func BuildPkgs(pkgs []string) (string, func(), error) {
	// The VEYRON_INTEGRATION_BIN_DIR environment variable can be
	// used to identify a directory that multiple integration
	// tests can use to share binaries. Whoever sets this
	// environment variable is responsible for cleaning up the
	// directory it points to.
	binDir, cleanupFn := os.Getenv("VEYRON_INTEGRATION_BIN_DIR"), func() {}
	if binDir == "" {
		// If the aforementioned environment variable is not
		// set, the given packages are built in a temporary
		// directory, which the cleanup function removes.
		tmpDir, err := ioutil.TempDir("", "")
		if err != nil {
			return "", nil, fmt.Errorf("TempDir() failed: %v", err)
		}
		binDir, cleanupFn = tmpDir, func() { os.RemoveAll(tmpDir) }
	}
	for _, pkg := range pkgs {
		binFile := filepath.Join(binDir, path.Base(pkg))
		if _, err := os.Stat(binFile); err != nil {
			if !os.IsNotExist(err) {
				return "", nil, err
			}
			cmd := exec.Command("veyron", "go", "build", "-o", filepath.Join(binDir, path.Base(pkg)), pkg)
			if err := cmd.Run(); err != nil {
				return "", nil, err
			}
		}
	}
	return binDir, cleanupFn, nil
}

// StartRootMT uses the given shell to start a root mount table and
// returns a handle for the started command along with the object name
// of the mount table.
func StartRootMT(shell *modules.Shell) (modules.Handle, string, error) {
	handle, err := shell.Start(core.RootMTCommand, nil, "--", "--veyron.tcp.address=127.0.0.1:0")
	if err != nil {
		return nil, "", err
	}
	s := expect.NewSession(nil, handle.Stdout(), time.Second)
	name := s.ExpectVar("MT_NAME")
	if err := s.Error(); err != nil {
		return nil, "", err
	}
	s.ExpectVar("MT_ADDR")
	if err := s.Error(); err != nil {
		return nil, "", err
	}
	s.ExpectVar("PID")
	if err := s.Error(); err != nil {
		return nil, "", err
	}
	return handle, name, nil
}

// StartServer starts a veyron server using the given binary and
// arguments, waiting for the server to successfully mount itself in
// the mount table.
//
// TODO(jsimsa,sadovsky): Use an instance of modules.Shell to start
// and manage the server process to prevent leaking processes when
// its parent terminates unexpectedly.
func StartServer(bin string, args []string) (*os.Process, error) {
	args = append(args, "-logtostderr", "-vmodule=publisher=2")
	cmd := exec.Command(bin, args...)
	outPipe, err := cmd.StderrPipe()
	if err != nil {
		return nil, err
	}
	// TODO(jsimsa): Consider using the veyron exec library to
	// facilitate coordination and communication between the
	// parent and the child process.
	if err := cmd.Start(); err != nil {
		return nil, fmt.Errorf("%q failed: %v", strings.Join(cmd.Args, " "), err)
	}
	// Wait for the server to mount both its tcp and ws endpoint.
	ready := make(chan struct{}, 1)
	go func() {
		defer outPipe.Close()
		scanner := bufio.NewScanner(outPipe)
		nmounts := 0
		for scanner.Scan() {
			line := scanner.Text()
			if strings.Index(line, "ipc pub: mount") != -1 {
				nmounts++
				if nmounts == 2 {
					close(ready)
				}
			}
		}
		if err := scanner.Err(); err != nil {
			fmt.Fprintf(os.Stderr, "Scan() failed: %v\n", err)
		}
	}()
	select {
	case <-ready:
		return cmd.Process, nil
	case <-time.After(time.Second):
		cmd.Process.Kill()
		return nil, fmt.Errorf("timed out waiting for %q to mount itself", strings.Join(cmd.Args, " "))
	}
}
<commit_msg>veyron/lib/testutil/integration: increase timeout.<commit_after>package integration

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"time"

	"veyron.io/veyron/veyron/lib/expect"
	"veyron.io/veyron/veyron/lib/modules"
	"veyron.io/veyron/veyron/lib/modules/core"
)

// BuildPkgs returns a path to a directory that contains the built
// binaries for the given set of packages and a function that should
// be invoked to clean up the build artifacts. Note that the clients
// of this function should not modify the contents of this directory
// directly and instead defer to the cleanup function.
func BuildPkgs(pkgs []string) (string, func(), error) {
	// The VEYRON_INTEGRATION_BIN_DIR environment variable can be
	// used to identify a directory that multiple integration
	// tests can use to share binaries. Whoever sets this
	// environment variable is responsible for cleaning up the
	// directory it points to.
	binDir, cleanupFn := os.Getenv("VEYRON_INTEGRATION_BIN_DIR"), func() {}
	if binDir == "" {
		// If the aforementioned environment variable is not
		// set, the given packages are built in a temporary
		// directory, which the cleanup function removes.
		tmpDir, err := ioutil.TempDir("", "")
		if err != nil {
			return "", nil, fmt.Errorf("TempDir() failed: %v", err)
		}
		binDir, cleanupFn = tmpDir, func() { os.RemoveAll(tmpDir) }
	}
	for _, pkg := range pkgs {
		binFile := filepath.Join(binDir, path.Base(pkg))
		if _, err := os.Stat(binFile); err != nil {
			if !os.IsNotExist(err) {
				return "", nil, err
			}
			cmd := exec.Command("veyron", "go", "build", "-o", filepath.Join(binDir, path.Base(pkg)), pkg)
			if err := cmd.Run(); err != nil {
				return "", nil, err
			}
		}
	}
	return binDir, cleanupFn, nil
}

// StartRootMT uses the given shell to start a root mount table and
// returns a handle for the started command along with the object name
// of the mount table.
func StartRootMT(shell *modules.Shell) (modules.Handle, string, error) {
	handle, err := shell.Start(core.RootMTCommand, nil, "--", "--veyron.tcp.address=127.0.0.1:0")
	if err != nil {
		return nil, "", err
	}
	s := expect.NewSession(nil, handle.Stdout(), time.Second)
	name := s.ExpectVar("MT_NAME")
	if err := s.Error(); err != nil {
		return nil, "", err
	}
	s.ExpectVar("MT_ADDR")
	if err := s.Error(); err != nil {
		return nil, "", err
	}
	s.ExpectVar("PID")
	if err := s.Error(); err != nil {
		return nil, "", err
	}
	return handle, name, nil
}

// StartServer starts a veyron server using the given binary and
// arguments, waiting for the server to successfully mount itself in
// the mount table.
//
// TODO(jsimsa,sadovsky): Use an instance of modules.Shell to start
// and manage the server process to prevent leaking processes when
// its parent terminates unexpectedly.
func StartServer(bin string, args []string) (*os.Process, error) {
	args = append(args, "-logtostderr", "-vmodule=publisher=2")
	cmd := exec.Command(bin, args...)
	outPipe, err := cmd.StderrPipe()
	if err != nil {
		return nil, err
	}
	// TODO(jsimsa): Consider using the veyron exec library to
	// facilitate coordination and communication between the
	// parent and the child process.
	if err := cmd.Start(); err != nil {
		return nil, fmt.Errorf("%q failed: %v", strings.Join(cmd.Args, " "), err)
	}
	// Wait for the server to mount both its tcp and ws endpoint.
	ready := make(chan struct{}, 1)
	go func() {
		defer outPipe.Close()
		scanner := bufio.NewScanner(outPipe)
		nmounts := 0
		for scanner.Scan() {
			line := scanner.Text()
			if strings.Index(line, "ipc pub: mount") != -1 {
				nmounts++
				if nmounts == 2 {
					close(ready)
				}
			}
		}
		if err := scanner.Err(); err != nil {
			fmt.Fprintf(os.Stderr, "Scan() failed: %v\n", err)
		}
	}()
	select {
	case <-ready:
		return cmd.Process, nil
	case <-time.After(time.Minute):
		cmd.Process.Kill()
		return nil, fmt.Errorf("timed out waiting for %q to mount itself", strings.Join(cmd.Args, " "))
	}
}
<|endoftext|>


<commit_before>package loop

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

type Loop struct {
	Data    []byte
	pointer int
	length  int
}

func New(data []byte) *Loop {
	return &Loop{
		Data:    data,
		pointer: 0,
		length:  len(data),
	}
}

func (l *Loop) Reset() { l.pointer = 0 }

// return bytes as long as you are asked for it
func (l *Loop) Read(p []byte) (n int, err error) {
	for i := 0; i < len(p); i++ {
		dataPos := (l.pointer + i) % l.length
		p[i] = l.Data[dataPos]
	}
	l.pointer = (l.pointer + len(p)) % l.length
	return len(p), nil
}

type Spinner struct {
	io.Writer
	l *Loop
}

func NewSpinner(w io.Writer) *Spinner {
	return &Spinner{w, New([]byte("-\\|/"))}
}

func (s *Spinner) Spin() (err error) {
	b := make([]byte, 1)
	s.l.Read(b)

	_, err = fmt.Fprint(s.Writer, string(b))
	return
}

func (s *Spinner) SpinEvery(d time.Duration) {
	for {
		s.Spin()
		time.Sleep(d)
	}
}

func NewStdoutSpinner() *Spinner {
	return NewSpinner(os.Stdout)
}
<commit_msg>remove char before printing<commit_after>package loop

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

type Loop struct {
	Data    []byte
	pointer int
	length  int
}

func New(data []byte) *Loop {
	return &Loop{
		Data:    data,
		pointer: 0,
		length:  len(data),
	}
}

func (l *Loop) Reset() { l.pointer = 0 }

// return bytes as long as you are asked for it
func (l *Loop) Read(p []byte) (n int, err error) {
	for i := 0; i < len(p); i++ {
		dataPos := (l.pointer + i) % l.length
		p[i] = l.Data[dataPos]
	}
	l.pointer = (l.pointer + len(p)) % l.length
	return len(p), nil
}

type Spinner struct {
	io.Writer
	l *Loop
}

func NewSpinner(w io.Writer) *Spinner {
	return &Spinner{w, New([]byte("-\\|/"))}
}

func (s *Spinner) Spin() (err error) {
	b := make([]byte, 1)
	s.l.Read(b)

	_, err = fmt.Fprint(s.Writer, "\b"+string(b))
	return
}

func (s *Spinner) SpinEvery(d time.Duration) {
	for {
		s.Spin()
		time.Sleep(d)
	}
}

func NewStdoutSpinner() *Spinner {
	return NewSpinner(os.Stdout)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/howeyc/fsnotify"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func md2conf(c *cli.Context) {
	arg := c.Args().First()
	cmd := exec.Command("markdown2confluence", arg)
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()

	if err != nil {
		log.Fatal(err)
	}

	ioutil.WriteFile(strings.TrimSuffix(arg, filepath.Ext(arg))+".wiki", out.Bytes(), 0644)
}

func main() {
	app := cli.NewApp()
	app.Name = "m2cw"
	app.Usage = "Convert markdown file to confluence style when save md file."
	app.Author = "Layzie <HIRAKI Satoru>"
	app.Email = "saruko313@gmail.com"
	app.Version = "0.0.1"
	app.Action = func(c *cli.Context) {
		arg := c.Args().First()

		fmt.Println("Start watching md file. <C-c> makes stop the command.")

		watcher, err := fsnotify.NewWatcher()
		if err != nil {
			log.Fatal(err)
		}

		err = watcher.Watch("./")
		if err != nil {
			log.Fatal(err)
		}

		defer watcher.Close()

		for {
			select {
			case ev := <-watcher.Event:
				if ev.Name == c.Args().First() {
					md2conf(c)
					log.Println("convert md to wiki ", ev.Name+" -> "+strings.TrimSuffix(arg, filepath.Ext(arg))+".wiki")
				}
			case err := <-watcher.Error:
				log.Println("error:", err)
			}
		}
	}

	app.Run(os.Args)
}
<commit_msg>refactoring to read easily<commit_after>package main

import (
	"bytes"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/howeyc/fsnotify"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func md2conf(c *cli.Context) {
	arg := c.Args().First()
	cmd := exec.Command("markdown2confluence", arg)
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()

	if err != nil {
		log.Fatal(err)
	}

	ioutil.WriteFile(
		strings.TrimSuffix(arg, filepath.Ext(arg))+".wiki",
		out.Bytes(),
		0644,
	)
}

func main() {
	app := cli.NewApp()
	app.Name = "m2cw"
	app.Usage = "Convert markdown file to confluence style when save md file."
	app.Author = "Layzie <HIRAKI Satoru>"
	app.Email = "saruko313@gmail.com"
	app.Version = "0.0.1"
	app.Action = func(c *cli.Context) {
		arg := c.Args().First()

		fmt.Println("Start watching " + arg + ". <C-c> makes stop the command.")

		watcher, err := fsnotify.NewWatcher()
		if err != nil {
			log.Fatal(err)
		}

		err = watcher.Watch("./")
		if err != nil {
			log.Fatal(err)
		}

		defer watcher.Close()

		for {
			select {
			case ev := <-watcher.Event:
				if ev.Name == c.Args().First() {
					md2conf(c)
					log.Println(
						"convert md to wiki ",
						ev.Name+" -> "+strings.TrimSuffix(arg, filepath.Ext(arg))+".wiki",
					)
				}
			case err := <-watcher.Error:
				log.Println("error:", err)
			}
		}
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	// "fmt"
	"os"

	"strings"

	"github.com/cucumber/godog"
	"github.com/cucumber/godog/colors"
	pb "github.com/ii/xds-test-harness/api/adapter"
	"github.com/ii/xds-test-harness/internal/runner"
	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
	"github.com/spf13/pflag"
)

var (
	debug          = pflag.BoolP("debug", "D", false, "sets log level to debug")
	adapterAddress = pflag.StringP("adapter", "A", ":17000", "port of adapter on target")
	targetAddress  = pflag.StringP("target", "T", ":18000", "port of xds target to test")
	nodeID         = pflag.StringP("nodeID", "N", "test-id", "node id of target")
	variants       = pflag.StringP("variants", "V", "1111", "Set which xDS transport variants your server supports.\n These are, in order: sotw non-aggregated\n, sotw aggregated\n, incremental non-aggregated\n, incremental aggregated\n. 1 if your server supports that variant, 0 if not\n. eg: --variants 1010 supports sotw non-aggregated and incremental non-aggregated.")
	aggregated     = false
	incremental    = false

	godogOpts = godog.Options{
		ShowStepDefinitions: false,
		Randomize:           0,
		StopOnFailure:       false,
		Strict:              false,
		NoColors:            false,
		Tags:                "",
		Format:              "",
		Concurrency:         0,
		Paths:               []string{},
		Output:              colors.Colored(os.Stdout),
	}

	r *runner.Runner
)

func init() {
	godog.BindCommandLineFlags("godog.", &godogOpts)
	zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
	log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
	zerolog.SetGlobalLevel(zerolog.InfoLevel)
}

func InitializeTestSuite(sc *godog.TestSuiteContext) {

	sc.BeforeSuite(func() {
		r = runner.FreshRunner()
		if err := r.ConnectClient("target", *targetAddress); err != nil {
			log.Fatal().
				Msgf("error connecting to target: %v", err)
		}
		if err := r.ConnectClient("adapter", *adapterAddress); err != nil {
			log.Fatal().
				Msgf("error connecting to adapter: %v", err)
		}
		r.NodeID = *nodeID
		r.Aggregated = aggregated
		log.Info().
			Msgf("Connected to target at %s and adapter at %s\n", *targetAddress, *adapterAddress)
		if r.Aggregated {
			log.Info().
				Msgf("Tests will be run via ADS")
		} else {
			log.Info().
				Msgf("Tests will be run non-aggregated, via separate streams")
		}
	})
}

func InitializeScenario(ctx *godog.ScenarioContext) {
	ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
		log.Debug().Msg("Fresh Runner!")
		r = runner.FreshRunner(r)
		return ctx, nil
	})
	ctx.After(func(ctx context.Context, sc *godog.Scenario, err error) (context.Context, error) {
		c := pb.NewAdapterClient(r.Adapter.Conn)
		clearRequest := &pb.ClearRequest{
			Node: r.NodeID,
		}
		clear, err := c.ClearState(context.Background(), clearRequest)
		if err != nil {
			log.Err(err).
				Msg("Couldn't clear state")
		}
		log.Debug().
			Msgf("Clearing state...%v", clear.Response)
		return ctx, nil
	})
	r.LoadSteps(ctx)
}

func supportedVariants(combo string) (err error, supportedVariants []bool) {
	flags := strings.Split(combo, "")
	if len(flags) < 4 {
		err := fmt.Errorf("Expected four digits, each a 1 or 0 (e.g. 1001). Given \"%v\"", combo)
		return err, []bool{}
	}
	for i := 0; i < 4; i++ {
		if flags[i] == "1" {
			supportedVariants = append(supportedVariants, true)
		} else if flags[i] == "0" {
			supportedVariants = append(supportedVariants, false)
		} else {
			err := fmt.Errorf("Expected four digits, each a 1 or 0 (e.g. 1001). Given \"%v\"", combo)
			return err, []bool{}
		}
	}
	return nil, supportedVariants
}

func main() {
	pflag.Parse()
	godogOpts.Paths = pflag.Args()
	if *debug {
		zerolog.SetGlobalLevel(zerolog.DebugLevel)
	}

	suite := godog.TestSuite{
		Name:                 "xDS Test Suite",
		ScenarioInitializer:  InitializeScenario,
		TestSuiteInitializer: InitializeTestSuite,
		Options:              &godogOpts,
	}

	// we have four variants, either set to T or F
	err, supportedVariants := supportedVariants(*variants)
	if err != nil {
		log.Info().Msgf("Error parsing variants config: %v\n", err)
		os.Exit(0)
	}

	//SOTW, Separate
	if supportedVariants[0] {
		incremental = false
		aggregated = false
		godogOpts.Tags = "@sotw && @separate"
		suite.Run();
	}

	//SOTW, Aggregated
	if supportedVariants[1] {
		incremental = false
		aggregated = true
		godogOpts.Tags = "@sotw && @aggregated"
		suite.Run();
	}

	//Incremental, Separate
	if supportedVariants[2] {
		incremental = true
		aggregated = false
		godogOpts.Tags = "@incremental && @separate"
		suite.Run();
	}

	//Incremental, Aggregated
	if supportedVariants[3] {
		incremental = true
		aggregated = true
		godogOpts.Tags = "@incremental && @aggregated"
		suite.Run();
	}
	os.Exit(0)
}
<commit_msg>ensure you can pass godog tags to runner<commit_after>package main

import (
	"context"
	"fmt"
	// "fmt"
	"os"

	"strings"

	"github.com/cucumber/godog"
	"github.com/cucumber/godog/colors"
	pb "github.com/ii/xds-test-harness/api/adapter"
	"github.com/ii/xds-test-harness/internal/runner"
	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
	"github.com/spf13/pflag"
)

var (
	debug          = pflag.BoolP("debug", "D", false, "sets log level to debug")
	adapterAddress = pflag.StringP("adapter", "A", ":17000", "port of adapter on target")
	targetAddress  = pflag.StringP("target", "T", ":18000", "port of xds target to test")
	nodeID         = pflag.StringP("nodeID", "N", "test-id", "node id of target")
	variants       = pflag.StringP("variants", "V", "1111", "Set which xDS transport variants your server supports.\n These are, in order: sotw non-aggregated\n, sotw aggregated\n, incremental non-aggregated\n, incremental aggregated\n. 1 if your server supports that variant, 0 if not\n. eg: --variants 1010 supports sotw non-aggregated and incremental non-aggregated.")
	aggregated     = false
	incremental    = false

	godogOpts = godog.Options{
		ShowStepDefinitions: false,
		Randomize:           0,
		StopOnFailure:       false,
		Strict:              false,
		NoColors:            false,
		Tags:                "",
		Format:              "",
		Concurrency:         0,
		Paths:               []string{},
		Output:              colors.Colored(os.Stdout),
	}

	r *runner.Runner
)

func init() {
	godog.BindCommandLineFlags("godog.", &godogOpts)
	zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
	log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
	zerolog.SetGlobalLevel(zerolog.InfoLevel)
}

func InitializeTestSuite(sc *godog.TestSuiteContext) {

	sc.BeforeSuite(func() {
		r = runner.FreshRunner()
		if err := r.ConnectClient("target", *targetAddress); err != nil {
			log.Fatal().
				Msgf("error connecting to target: %v", err)
		}
		if err := r.ConnectClient("adapter", *adapterAddress); err != nil {
			log.Fatal().
				Msgf("error connecting to adapter: %v", err)
		}
		r.NodeID = *nodeID
		r.Aggregated = aggregated
		log.Info().
			Msgf("Connected to target at %s and adapter at %s\n", *targetAddress, *adapterAddress)
		if r.Aggregated {
			log.Info().
				Msgf("Tests will be run via ADS")
		} else {
			log.Info().
				Msgf("Tests will be run non-aggregated, via separate streams")
		}
	})
}

func InitializeScenario(ctx *godog.ScenarioContext) {
	ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
		log.Debug().Msg("Fresh Runner!")
		r = runner.FreshRunner(r)
		return ctx, nil
	})
	ctx.After(func(ctx context.Context, sc *godog.Scenario, err error) (context.Context, error) {
		c := pb.NewAdapterClient(r.Adapter.Conn)
		clearRequest := &pb.ClearRequest{
			Node: r.NodeID,
		}
		clear, err := c.ClearState(context.Background(), clearRequest)
		if err != nil {
			log.Err(err).
				Msg("Couldn't clear state")
		}
		log.Debug().
			Msgf("Clearing state...%v", clear.Response)
		return ctx, nil
	})
	r.LoadSteps(ctx)
}

func supportedVariants(combo string) (err error, supportedVariants []bool) {
	flags := strings.Split(combo, "")
	if len(flags) < 4 {
		err := fmt.Errorf("Expected four digits, each a 1 or 0 (e.g. 1001). Given \"%v\"", combo)
		return err, []bool{}
	}
	for i := 0; i < 4; i++ {
		if flags[i] == "1" {
			supportedVariants = append(supportedVariants, true)
		} else if flags[i] == "0" {
			supportedVariants = append(supportedVariants, false)
		} else {
			err := fmt.Errorf("Expected four digits, each a 1 or 0 (e.g. 1001). Given \"%v\"", combo)
			return err, []bool{}
		}
	}
	return nil, supportedVariants
}

func main() {
	pflag.Parse()
	godogOpts.Paths = pflag.Args()
	if *debug {
		zerolog.SetGlobalLevel(zerolog.DebugLevel)
	}

	suite := godog.TestSuite{
		Name:                 "xDS Test Suite",
		ScenarioInitializer:  InitializeScenario,
		TestSuiteInitializer: InitializeTestSuite,
		Options:              &godogOpts,
	}

	// we have four variants, either set to T or F
	err, supportedVariants := supportedVariants(*variants)
	if err != nil {
		log.Info().Msgf("Error parsing variants config: %v\n", err)
		os.Exit(0)
	}

	//SOTW, Separate
	if supportedVariants[0] {
		incremental = false
		aggregated = false
		godogOpts.Tags = strings.Join([]string{godogOpts.Tags, "@sotw","@separate"}, " && ")
		suite.Run();
	}

	//SOTW, Aggregated
	if supportedVariants[1] {
		incremental = false
		aggregated = true
		godogOpts.Tags = strings.Join([]string{godogOpts.Tags, "@sotw","@aggregated"}, " && ")
		suite.Run();
	}

	//Incremental, Separate
	if supportedVariants[2] {
		incremental = true
		aggregated = false
		godogOpts.Tags = strings.Join([]string{godogOpts.Tags, "@incremental","@separate"}, " && ")
		suite.Run();
	}

	//Incremental, Aggregated
	if supportedVariants[3] {
		incremental = true
		aggregated = true
		godogOpts.Tags = strings.Join([]string{godogOpts.Tags, "@incremental","@aggregated"}, " && ")
		suite.Run();
	}
	os.Exit(0)
}
<|endoftext|>