<commit_before>package zog

import "fmt"

func Decode(inCh chan byte) (chan instruction, chan error) {
	errCh := make(chan error)
	iCh := make(chan instruction)
	go decode(inCh, iCh, errCh)
	return iCh, errCh
}

func DecodeBytes(buf []byte) ([]instruction, error) {

	ch := make(chan byte)

	go func() {
		for _, n := range buf {
			ch <- n
		}
		close(ch)
	}()

	var insts []instruction
	var err error
	var ok bool

	instCh, errCh := Decode(ch)
	looping := true
	for looping {
		select {
		case inst, ok := <-instCh:
			if !ok {
				looping = false
				break
			}
			insts = append(insts, inst)
		case err, ok = <-errCh:
			if !ok {
				looping = false
				break
			}
			break
		}
	}

	return insts, err
}

func decode(inCh chan byte, iCh chan instruction, errCh chan error) {

	// Set to 0 if no prefix in effect
	var prefix byte
	var inst instruction

	for n := range inCh {
		// Prefix bytes
		switch n {
		case 0xDD:
		case 0xFD:
			if prefix != 0 {
				errCh <- fmt.Errorf("Double prefix: %02% %02X", prefix, n)
			}
			prefix = n
			continue

		}

		x, y, z, _, _ := decomposeByte(n)
		fmt.Printf("D: N %02X, x %d y %d z %d\n", n, x, y, z)
		switch x {
		case 1:
			if x == 6 && y == 6 {
				inst = HALT
			} else {
				inst = &LD8{tableR[y], tableR[z]}
			}
		default:
			panic("TODO - impl")
		}

		iCh <- inst

		prefix = 0
	}
	//	close(iCh)
	close(errCh)
}

var tableR []Loc8 = []Loc8{B, C, D, E, H, L, Contents{HL}, A}

func decomposeByte(n byte) (byte, byte, byte, byte, byte) {
	// We follow terminology from http://www.z80.info/decoding.htm
	// x = the opcode's 1st octal digit (i.e. bits 7-6)
	// y = the opcode's 2nd octal digit (i.e. bits 5-3)
	// z = the opcode's 3rd octal digit (i.e. bits 2-0)
	// p = y rightshifted one position (i.e. bits 5-4)
	// q = y modulo 2 (i.e. bit 3)
	z := n & 0x07
	y := (n >> 3) & 0x07
	x := (n >> 6) & 0x07
	p := y >> 1
	q := y & 0x01

	return x, y, z, p, q
}
<commit_msg>use error handling flow for unimplemented, not panic<commit_after>package zog

import "fmt"

func Decode(inCh chan byte) (chan instruction, chan error) {
	errCh := make(chan error)
	iCh := make(chan instruction)
	go decode(inCh, iCh, errCh)
	return iCh, errCh
}

func DecodeBytes(buf []byte) ([]instruction, error) {

	ch := make(chan byte)

	go func() {
		for _, n := range buf {
			ch <- n
		}
		close(ch)
	}()

	var insts []instruction
	var err error
	var ok bool

	instCh, errCh := Decode(ch)
	looping := true
	for looping {
		select {
		case inst, ok := <-instCh:
			if !ok {
				looping = false
				break
			}
			insts = append(insts, inst)
		case err, ok = <-errCh:
			if !ok {
				looping = false
				break
			}
			break
		}
	}

	return insts, err
}

func decode(inCh chan byte, iCh chan instruction, errCh chan error) {

	// Set to 0 if no prefix in effect
	var prefix byte
	var inst instruction

	for n := range inCh {
		// Prefix bytes
		switch n {
		case 0xDD:
		case 0xFD:
			if prefix != 0 {
				errCh <- fmt.Errorf("Double prefix: %02% %02X", prefix, n)
			}
			prefix = n
			continue

		}

		x, y, z, _, _ := decomposeByte(n)
		fmt.Printf("D: N %02X, x %d y %d z %d\n", n, x, y, z)
		switch x {
		case 1:
			if x == 6 && y == 6 {
				inst = HALT
			} else {
				inst = &LD8{tableR[y], tableR[z]}
			}
		default:
			errCh <- fmt.Errorf("TODO - impl %02X [%02X]", n, prefix)
			continue
		}

		iCh <- inst

		prefix = 0
	}
	//	close(iCh)
	close(errCh)
}

var tableR []Loc8 = []Loc8{B, C, D, E, H, L, Contents{HL}, A}

func decomposeByte(n byte) (byte, byte, byte, byte, byte) {
	// We follow terminology from http://www.z80.info/decoding.htm
	// x = the opcode's 1st octal digit (i.e. bits 7-6)
	// y = the opcode's 2nd octal digit (i.e. bits 5-3)
	// z = the opcode's 3rd octal digit (i.e. bits 2-0)
	// p = y rightshifted one position (i.e. bits 5-4)
	// q = y modulo 2 (i.e. bit 3)
	z := n & 0x07
	y := (n >> 3) & 0x07
	x := (n >> 6) & 0x07
	p := y >> 1
	q := y & 0x01

	return x, y, z, p, q
}
<|endoftext|>


<commit_before>package pcap

import (
	"fmt"
	"net"
	"strings"
)

// Type constants.
const (
	TypeIP  = 0x0800
	TypeARP = 0x0806
	TypeIP6 = 0x86DD

	IPICMP = 1
	IPInIP = 4
	IPTCP  = 6
	IPUDP  = 17
)

// Port from sf-pcap.c file.
const (
	TcpdumpMagic          = 0xa1b2c3d4
	KuznetsovTcpdumpMagic = 0xa1b2cd34
	FmesqiutaTcpdumpMagic = 0xa1b234cd
	NavtelTcpdumpMagic    = 0xa12b3c4d
	NsecTcpdumpMagic      = 0xa1b23c4d
)

// DLT* are the types that are the same on all platforms, and that have been
// defined by <net/bpf.h> for ages.
const (
	DLTNULL    = 0  // BSD loopback encapsulation
	DLTEN10MB  = 1  // Ethernet (10Mb)
	DLTEN3MB   = 2  // Experimental Ethernet (3Mb)
	DLTAX25    = 3  // Amateur Radio AX.25
	DLTPRONET  = 4  // Proteon ProNET Token Ring
	DLTCHAOS   = 5  // Chaos
	DLTIEEE802 = 6  // 802.5 Token Ring
	DLTARCNET  = 7  // ARCNET, with BSD-style header
	DLTSLIP    = 8  // Serial Line IP
	DLTPPP     = 9  // Point-to-point Protocol
	DLTFDDI    = 10 // FDDI
)

const errbufSize = 256

// LinkType constants according to pcap-linktype(7).
const (
	LinkTypeNull      = DLTNULL
	LinkTypeEthernet  = DLTEN10MB
	LinkTypeTokenRing = DLTIEEE802

	LinkTypeExpEthernet = DLTEN3MB /* 3Mb experimental Ethernet */
	LinkTypeAX25        = DLTAX25
	LinkTypePRONET      = DLTPRONET
	LinkTypeCHAOS       = DLTCHAOS
	LinkTypeARCNETBSD   = DLTARCNET /* BSD-style headers */
	LinkTypeSLIP        = DLTSLIP
	LinkTypePPP         = DLTPPP
	LinkTypeFDDI        = DLTFDDI

	LinkTypeARCNET         = 7
	LinkTypeATMRFC1483     = 100
	LinkTypeRAW            = 101
	LinkTypePPPHDLC        = 50
	LinkTypePPPETHER       = 51
	LinkTypeCHDLC          = 104
	LinkTypeIEEE80211      = 105
	LinkTypeFRELAY         = 107
	LinkTypeLOOP           = 108
	LinkTypeLINUXSLL       = 113
	LinkTypeLTALK          = 104
	LinkTypePFLOG          = 117
	LinkTypePRISMHeader    = 119
	LINKTypeIPOverFC       = 122
	LinkTypeSUNATM         = 123
	LinkTypeIEEE80211Radio = 127
	LinkTypeARCNETLinux    = 129
	LinkTypeLinuxIRDA      = 144
	LinkTypeLinuxLAPD      = 177
)

type addrHdr interface {
	SrcAddr() string
	DestAddr() string
	Len() int
}

type addrStringer interface {
	String(addr addrHdr) string
}

func decodemac(pkt []byte) uint64 {
	mac := uint64(0)
	for i := 0; i < 6; i++ {
		mac = (mac << 8) + uint64(pkt[i])
	}
	return mac
}

// ARPHdr is a ARP packet header.
type ARPHdr struct {
	Addrtype          uint16
	Protocol          uint16
	HwAddressSize     uint8
	ProtAddressSize   uint8
	Operation         uint16
	SourceHwAddress   []byte
	SourceProtAddress []byte
	DestHwAddress     []byte
	DestProtAddress   []byte
}

func (arp *ARPHdr) String() (s string) {
	switch arp.Operation {
	case 1:
		s = "ARP request"
	case 2:
		s = "ARP Reply"
	}
	if arp.Addrtype == LinkTypeEthernet && arp.Protocol == TypeIP {
		s = fmt.Sprintf("%012x (%s) > %012x (%s)",
			decodemac(arp.SourceHwAddress), arp.SourceProtAddress,
			decodemac(arp.DestHwAddress), arp.DestProtAddress)
	} else {
		s = fmt.Sprintf("addrtype = %d protocol = %d", arp.Addrtype, arp.Protocol)
	}
	return
}

// Len returns the (calculated) ARP payload length.
func (arp *ARPHdr) Len() int {
	return int(8 + 2*arp.HwAddressSize + 2*arp.ProtAddressSize)
}

// IPHdr is the header of an IP packet.
type IPHdr struct {
	Version    uint8
	Ihl        uint8
	Tos        uint8
	Length     uint16
	ID         uint16
	Flags      uint8
	FragOffset uint16
	Ttl        uint8
	Protocol   uint8
	Checksum   uint16
	SrcIP      []byte
	DestIP     []byte
}

// SrcAddr returns the string version of the source IP.
func (ip *IPHdr) SrcAddr() string { return net.IP(ip.SrcIP).String() }

// DestAddr returns the string version of the destination IP.
func (ip *IPHdr) DestAddr() string { return net.IP(ip.DestIP).String() }

// Len returns the ip.Length.
func (ip *IPHdr) Len() int { return int(ip.Length) }

// TCPHdr is the header of a TCP packet.
type TCPHdr struct {
	SrcPort    uint16
	DestPort   uint16
	Seq        uint32
	Ack        uint32
	DataOffset uint8
	Flags      uint16
	Window     uint16
	Checksum   uint16
	Urgent     uint16
	Data       []byte
}

// TCP flags.
const (
	TCPFIN = 1 << iota
	TCPSYN
	TCPRST
	TCPPSH
	TCPACK
	TCPURG
	TCPECE
	TCPCWR
	TCPNS
)

// String TODO
func (tcp *TCPHdr) String(hdr addrHdr) string {
	return fmt.Sprintf("TCP %s:%d > %s:%d %s SEQ=%d ACK=%d LEN=%d",
		hdr.SrcAddr(), int(tcp.SrcPort), hdr.DestAddr(), int(tcp.DestPort),
		tcp.FlagsString(), int64(tcp.Seq), int64(tcp.Ack), hdr.Len())
}

// FlagsString TODO
func (tcp *TCPHdr) FlagsString() string {
	var sflags []string
	if 0 != (tcp.Flags & TCPSYN) {
		sflags = append(sflags, "syn")
	}
	if 0 != (tcp.Flags & TCPFIN) {
		sflags = append(sflags, "fin")
	}
	if 0 != (tcp.Flags & TCPACK) {
		sflags = append(sflags, "ack")
	}
	if 0 != (tcp.Flags & TCPPSH) {
		sflags = append(sflags, "psh")
	}
	if 0 != (tcp.Flags & TCPRST) {
		sflags = append(sflags, "rst")
	}
	if 0 != (tcp.Flags & TCPURG) {
		sflags = append(sflags, "urg")
	}
	if 0 != (tcp.Flags & TCPNS) {
		sflags = append(sflags, "ns")
	}
	if 0 != (tcp.Flags & TCPCWR) {
		sflags = append(sflags, "cwr")
	}
	if 0 != (tcp.Flags & TCPECE) {
		sflags = append(sflags, "ece")
	}
	return fmt.Sprintf("[%s]", strings.Join(sflags, " "))
}

// UDPHdr is the header of a UDP packet.
type UDPHdr struct {
	SrcPort  uint16
	DestPort uint16
	Length   uint16
	Checksum uint16
}

func (udp *UDPHdr) String(hdr addrHdr) string {
	return fmt.Sprintf("UDP %s:%d > %s:%d LEN=%d CHKSUM=%d",
		hdr.SrcAddr(), int(udp.SrcPort), hdr.DestAddr(), int(udp.DestPort),
		int(udp.Length), int(udp.Checksum))
}

// ICMPHdr is the header of an ICMP packet.
type ICMPHdr struct {
	Type     uint8
	Code     uint8
	Checksum uint16
	ID       uint16
	Seq      uint16
	Data     []byte
}

// String TODO
func (icmp *ICMPHdr) String(hdr addrHdr) string {
	return fmt.Sprintf("ICMP %s > %s Type = %d Code = %d ",
		hdr.SrcAddr(), hdr.DestAddr(), icmp.Type, icmp.Code)
}

// TypeString TODO
func (icmp *ICMPHdr) TypeString() (result string) {
	switch icmp.Type {
	case 0:
		result = fmt.Sprintf("Echo reply seq=%d", icmp.Seq)
	case 3:
		switch icmp.Code {
		case 0:
			result = "Network unreachable"
		case 1:
			result = "Host unreachable"
		case 2:
			result = "Protocol unreachable"
		case 3:
			result = "Port unreachable"
		default:
			result = "Destination unreachable"
		}
	case 8:
		result = fmt.Sprintf("Echo request seq=%d", icmp.Seq)
	case 30:
		result = "Traceroute"
	}
	return
}

// IP6Hdr is the header of an IPv6 packet.
type IP6Hdr struct {
	// http://www.networksorcery.com/enp/protocol/ipv6.htm
	Version      uint8  // 4 bits
	TrafficClass uint8  // 8 bits
	FlowLabel    uint32 // 20 bits
	Length       uint16 // 16 bits
	NextHeader   uint8  // 8 bits, same as Protocol in IPHdr
	HopLimit     uint8  // 8 bits
	SrcIP        []byte // 16 bytes
	DestIP       []byte // 16 bytes
}

// SrcAddr returns the string version of the source IP.
func (ip6 *IP6Hdr) SrcAddr() string { return net.IP(ip6.SrcIP).String() }

// DestAddr returns the string version of the destination IP.
func (ip6 *IP6Hdr) DestAddr() string { return net.IP(ip6.DestIP).String() }

// Len returns the ip6.Length.
func (ip6 *IP6Hdr) Len() int { return int(ip6.Length) }
<commit_msg>Use C values for constants<commit_after>package pcap

/*
#include <pcap.h>
*/
import "C"

import (
	"fmt"
	"net"
	"strings"
)

// Type constants.
const (
	TypeIP  = 0x0800
	TypeARP = 0x0806
	TypeIP6 = 0x86DD

	IPICMP = 1
	IPInIP = 4
	IPTCP  = 6
	IPUDP  = 17
)

// Port from sf-pcap.c file.
const (
	TcpdumpMagic          = 0xa1b2c3d4
	KuznetsovTcpdumpMagic = 0xa1b2cd34
	FmesqiutaTcpdumpMagic = 0xa1b234cd
	NavtelTcpdumpMagic    = 0xa12b3c4d
	NsecTcpdumpMagic      = 0xa1b23c4d
)

// DLT* are the types that are the same on all platforms, and that have been
// defined by <net/bpf.h> for ages.
// See http://www.tcpdump.org/linktypes.html
const (
	DLTNULL    = C.DLT_NULL
	DLTEN10MB  = C.DLT_EN10MB  // Ethernet (10Mb)
	DLTEN3MB   = C.DLT_EN3MB   // Experimental Ethernet (3Mb)
	DLTAX25    = C.DLT_AX25    // Amateur Radio AX.25
	DLTPRONET  = C.DLT_PRONET  // Proteon ProNET Token Ring
	DLTCHAOS   = C.DLT_CHAOS   // Chaos
	DLTIEEE802 = C.DLT_IEEE802 // 802.5 Token Ring
	DLTARCNET  = C.DLT_ARCNET  // ARCNET, with BSD-style header
	DLTSLIP    = C.DLT_SLIP    // Serial Line IP
	DLTPPP     = C.DLT_PPP     // Point-to-point Protocol
	DLTFDDI    = C.DLT_FDDI    // FDDI
)

const errbufSize = 256

// LinkType constants according to pcap-linktype(7).
const (
	LinkTypeNull      = DLTNULL
	LinkTypeEthernet  = DLTEN10MB
	LinkTypeTokenRing = DLTIEEE802

	LinkTypeExpEthernet = DLTEN3MB /* 3Mb experimental Ethernet */
	LinkTypeAX25        = DLTAX25
	LinkTypePRONET      = DLTPRONET
	LinkTypeCHAOS       = DLTCHAOS
	LinkTypeARCNETBSD   = DLTARCNET /* BSD-style headers */
	LinkTypeSLIP        = DLTSLIP
	LinkTypePPP         = DLTPPP
	LinkTypeFDDI        = DLTFDDI

	LinkTypeARCNET         = 7
	LinkTypeATMRFC1483     = 100
	LinkTypeRAW            = 101
	LinkTypePPPHDLC        = 50
	LinkTypePPPETHER       = 51
	LinkTypeCHDLC          = 104
	LinkTypeIEEE80211      = 105
	LinkTypeFRELAY         = 107
	LinkTypeLOOP           = 108
	LinkTypeLINUXSLL       = 113
	LinkTypeLTALK          = 104
	LinkTypePFLOG          = 117
	LinkTypePRISMHeader    = 119
	LinkTypeIPOverFC       = 122
	LinkTypeSUNATM         = 123
	LinkTypeIEEE80211Radio = 127
	LinkTypeARCNETLinux    = 129
	LinkTypeLinuxIRDA      = 144
	LinkTypeLinuxLAPD      = 177
)

type addrHdr interface {
	SrcAddr() string
	DestAddr() string
	Len() int
}

type addrStringer interface {
	String(addr addrHdr) string
}

func decodemac(pkt []byte) uint64 {
	mac := uint64(0)
	for i := 0; i < 6; i++ {
		mac = (mac << 8) + uint64(pkt[i])
	}
	return mac
}

// ARPHdr is a ARP packet header.
type ARPHdr struct {
	Addrtype          uint16
	Protocol          uint16
	HwAddressSize     uint8
	ProtAddressSize   uint8
	Operation         uint16
	SourceHwAddress   []byte
	SourceProtAddress []byte
	DestHwAddress     []byte
	DestProtAddress   []byte
}

func (arp *ARPHdr) String() (s string) {
	switch arp.Operation {
	case 1:
		s = "ARP request"
	case 2:
		s = "ARP Reply"
	}
	if arp.Addrtype == LinkTypeEthernet && arp.Protocol == TypeIP {
		s = fmt.Sprintf("%012x (%s) > %012x (%s)",
			decodemac(arp.SourceHwAddress), arp.SourceProtAddress,
			decodemac(arp.DestHwAddress), arp.DestProtAddress)
	} else {
		s = fmt.Sprintf("addrtype = %d protocol = %d", arp.Addrtype, arp.Protocol)
	}
	return
}

// Len returns the (calculated) ARP payload length.
func (arp *ARPHdr) Len() int {
	return int(8 + 2*arp.HwAddressSize + 2*arp.ProtAddressSize)
}

// IPHdr is the header of an IP packet.
type IPHdr struct {
	Version    uint8
	Ihl        uint8
	Tos        uint8
	Length     uint16
	ID         uint16
	Flags      uint8
	FragOffset uint16
	Ttl        uint8
	Protocol   uint8
	Checksum   uint16
	SrcIP      []byte
	DestIP     []byte
}

// SrcAddr returns the string version of the source IP.
func (ip *IPHdr) SrcAddr() string { return net.IP(ip.SrcIP).String() }

// DestAddr returns the string version of the destination IP.
func (ip *IPHdr) DestAddr() string { return net.IP(ip.DestIP).String() }

// Len returns the ip.Length.
func (ip *IPHdr) Len() int { return int(ip.Length) }

// TCPHdr is the header of a TCP packet.
type TCPHdr struct {
	SrcPort    uint16
	DestPort   uint16
	Seq        uint32
	Ack        uint32
	DataOffset uint8
	Flags      uint16
	Window     uint16
	Checksum   uint16
	Urgent     uint16
	Data       []byte
}

// TCP flags.
const (
	TCPFIN = 1 << iota
	TCPSYN
	TCPRST
	TCPPSH
	TCPACK
	TCPURG
	TCPECE
	TCPCWR
	TCPNS
)

// String TODO
func (tcp *TCPHdr) String(hdr addrHdr) string {
	return fmt.Sprintf("TCP %s:%d > %s:%d %s SEQ=%d ACK=%d LEN=%d",
		hdr.SrcAddr(), int(tcp.SrcPort), hdr.DestAddr(), int(tcp.DestPort),
		tcp.FlagsString(), int64(tcp.Seq), int64(tcp.Ack), hdr.Len())
}

// FlagsString TODO
func (tcp *TCPHdr) FlagsString() string {
	var sflags []string
	if 0 != (tcp.Flags & TCPSYN) {
		sflags = append(sflags, "syn")
	}
	if 0 != (tcp.Flags & TCPFIN) {
		sflags = append(sflags, "fin")
	}
	if 0 != (tcp.Flags & TCPACK) {
		sflags = append(sflags, "ack")
	}
	if 0 != (tcp.Flags & TCPPSH) {
		sflags = append(sflags, "psh")
	}
	if 0 != (tcp.Flags & TCPRST) {
		sflags = append(sflags, "rst")
	}
	if 0 != (tcp.Flags & TCPURG) {
		sflags = append(sflags, "urg")
	}
	if 0 != (tcp.Flags & TCPNS) {
		sflags = append(sflags, "ns")
	}
	if 0 != (tcp.Flags & TCPCWR) {
		sflags = append(sflags, "cwr")
	}
	if 0 != (tcp.Flags & TCPECE) {
		sflags = append(sflags, "ece")
	}
	return fmt.Sprintf("[%s]", strings.Join(sflags, " "))
}

// UDPHdr is the header of a UDP packet.
type UDPHdr struct {
	SrcPort  uint16
	DestPort uint16
	Length   uint16
	Checksum uint16
}

func (udp *UDPHdr) String(hdr addrHdr) string {
	return fmt.Sprintf("UDP %s:%d > %s:%d LEN=%d CHKSUM=%d",
		hdr.SrcAddr(), int(udp.SrcPort), hdr.DestAddr(), int(udp.DestPort),
		int(udp.Length), int(udp.Checksum))
}

// ICMPHdr is the header of an ICMP packet.
type ICMPHdr struct {
	Type     uint8
	Code     uint8
	Checksum uint16
	ID       uint16
	Seq      uint16
	Data     []byte
}

// String TODO
func (icmp *ICMPHdr) String(hdr addrHdr) string {
	return fmt.Sprintf("ICMP %s > %s Type = %d Code = %d ",
		hdr.SrcAddr(), hdr.DestAddr(), icmp.Type, icmp.Code)
}

// TypeString TODO
func (icmp *ICMPHdr) TypeString() (result string) {
	switch icmp.Type {
	case 0:
		result = fmt.Sprintf("Echo reply seq=%d", icmp.Seq)
	case 3:
		switch icmp.Code {
		case 0:
			result = "Network unreachable"
		case 1:
			result = "Host unreachable"
		case 2:
			result = "Protocol unreachable"
		case 3:
			result = "Port unreachable"
		default:
			result = "Destination unreachable"
		}
	case 8:
		result = fmt.Sprintf("Echo request seq=%d", icmp.Seq)
	case 30:
		result = "Traceroute"
	}
	return
}

// IP6Hdr is the header of an IPv6 packet.
type IP6Hdr struct {
	// http://www.networksorcery.com/enp/protocol/ipv6.htm
	Version      uint8  // 4 bits
	TrafficClass uint8  // 8 bits
	FlowLabel    uint32 // 20 bits
	Length       uint16 // 16 bits
	NextHeader   uint8  // 8 bits, same as Protocol in IPHdr
	HopLimit     uint8  // 8 bits
	SrcIP        []byte // 16 bytes
	DestIP       []byte // 16 bytes
}

// SrcAddr returns the string version of the source IP.
func (ip6 *IP6Hdr) SrcAddr() string { return net.IP(ip6.SrcIP).String() }

// DestAddr returns the string version of the destination IP.
func (ip6 *IP6Hdr) DestAddr() string { return net.IP(ip6.DestIP).String() }

// Len returns the ip6.Length.
func (ip6 *IP6Hdr) Len() int { return int(ip6.Length) }
<|endoftext|>


<commit_before>package defect

import (
	"reflect"
	"testing"
)

type Error string

var _ error = Error("")

func (e Error) Error() string { return string(e) }

// Asserts that obtained and expected are equal.  If they are not, sets the test as an error,
// prints the optional message, followed by the values of obtained and expected.
func Equal(t *testing.T, obtained, expected interface{}, message ...interface{}) {
	if obtained != expected {
		t.Error(append(message, []interface{}{
			"\n",
			"obtained:", obtained, "\n",
			"expected:", expected, "\n"}...))
	}
}

// Asserts that obtained and expected are equal using reflect.DeepEqual.  If they are not,
// sets the test as an error, prints the optional message, followed by the values of obtained
// and expected.
func DeepEqual(t *testing.T, obtained, expected interface{}, message ...interface{}) {
	if !reflect.DeepEqual(obtained, expected) {
		t.Error(append(message, []interface{}{
			"\n",
			"obtained:", obtained, "\n",
			"expected:", expected, "\n"}...))
	}
}
<commit_msg>Improve output<commit_after>package defect

import (
	"reflect"
	"testing"
)

type Error string

var _ error = Error("")

func (e Error) Error() string { return string(e) }

// Asserts that obtained and expected are equal.  If they are not, sets the test as an error,
// prints the optional message, followed by the values of obtained and expected.
func Equal(t *testing.T, obtained, expected interface{}, message ...interface{}) {
	if obtained != expected {
		t.Error(append(message, []interface{}{
			"\n",
			"obtained:", obtained, "\n",
			"expected:", expected, "\n"}...)...)
	}
}

// Asserts that obtained and expected are equal using reflect.DeepEqual.  If they are not,
// sets the test as an error, prints the optional message, followed by the values of obtained
// and expected.
func DeepEqual(t *testing.T, obtained, expected interface{}, message ...interface{}) {
	if !reflect.DeepEqual(obtained, expected) {
		t.Error(append(message, []interface{}{
			"\n",
			"obtained:", obtained, "\n",
			"expected:", expected, "\n"}...)...)
	}
}
<|endoftext|>


<commit_before>package handler

import (
	"fmt"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/constants"
	modelServer "github.com/vladpereskokov/Technopark_HighLoad-nginx/src/models/server"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/utils"
	"log"
	"net"
	"net/url"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

const HTTP_CONSTANTS_CONFIG = "configs/http.json"

type Handler struct {
	Connection net.Conn
	Request    *modelServer.Request
	Response   *modelServer.Response
	Constants  *modelServer.Constants
	Dir        string
}

type HandlerFunc func(chan net.Conn)

func CreateHandler(dir string) (handlerFunc HandlerFunc) {
	httpConstantsConfig := new(modelServer.Constants)

	err := utils.FromFile(HTTP_CONSTANTS_CONFIG, &httpConstantsConfig)
	if err != nil {
		log.Panicf("can not init http config: %v", err)
	}

	return func(channel chan net.Conn) {
		handler := Handler{}
		handler.create(httpConstantsConfig, dir)

		go handler.start(channel)
	}
}

func (handler *Handler) create(config *modelServer.Constants, dir string) {
	handler.Request = modelServer.InitRequest()
	handler.Response = modelServer.InitResponse()

	handler.Response.SetStatus(200, config.Statuses)

	handler.Constants = config
	handler.Dir = dir
}

func (handler *Handler) start(channel chan net.Conn) {
	for {
		handler.Connection = <-channel
		handler.handle()
	}
}

func (handler *Handler) handle() {
	handler.readRequest()
	handler.requestHandle()
	handler.writeResponse()
	handler.closeConn()
}

func (handler *Handler) readRequest() {
	buffer := make([]byte, 1024)

	_, err := handler.Connection.Read(buffer)
	if err != nil {
		fmt.Println("Error reading:", err.Error())

		return
	}

	handler.parseRequest(string(buffer))
}

func (handler *Handler) parseRequest(query string) {
	splitedQuery := strings.Split(query, "\r\n")[0]
	queryParts := strings.Split(splitedQuery, " ")

	if len(queryParts) != 3 {
		handler.Response.SetStatus(400, handler.Constants.Statuses)

		return
	}

	handler.Request.Method.SetMethod(queryParts[0])
	parsed_url, err := url.Parse(queryParts[1])

	if err != nil || !strings.HasPrefix(queryParts[2], "HTTP/") {
		handler.Response.SetStatus(400, handler.Constants.Statuses)
	}

	handler.Request.Url = parsed_url
}

func (handler *Handler) requestHandle() {
	if !handler.Response.IsOk() {
		handler.setContentHeaders(nil)
		return
	}

	if !handler.Constants.Methods.Contains(handler.Request.Method.Type) {
		handler.Response.SetStatus(405, handler.Constants.Statuses)
	} else {
		handler.preProcessPath()
	}
}

func (handler *Handler) preProcessPath() {
	handler.Request.SetPath(handler.Dir + handler.Request.GetPath())
	file_info := handler.check_path(false)

	if file_info != nil && file_info.IsDir() {
		handler.Request.SetPath(handler.Request.GetPath() + constants.INDEX_FILE)
		file_info = handler.check_path(true)
	}

	handler.setContentHeaders(file_info)
}

func (handler *Handler) check_path(is_dir bool) os.FileInfo {
	request_path := handler.Request.GetPath()

	clear_path := path.Clean(request_path)
	handler.Request.SetPath(clear_path)

	info, err := os.Stat(request_path)
	if err != nil {
		if os.IsNotExist(err) && !is_dir {
			handler.Response.SetStatus(404, handler.Constants.Statuses)
		} else {
			handler.Response.SetStatus(403, handler.Constants.Statuses)
		}
	} else if !strings.Contains(clear_path, handler.Dir) {
		handler.Response.SetStatus(403, handler.Constants.Statuses)
	}
	return info
}

func (handler *Handler) setContentHeaders(info os.FileInfo) {
	if handler.Response.IsOk() {
		handler.Response.SetHeader("Content-Length", strconv.Itoa(int(info.Size())))
		handler.Response.SetHeader("Content-Type", handler.get_content_type())
	} else {
		handler.Response.SetHeader("Content-Length",
			strconv.Itoa(len(handler.Response.GetErrorBody(handler.Response.Status.Message))))
		handler.Response.SetHeader("Content-Type", constants.ERROR_BODY_MIME_TYPE)
	}
}

func (handler *Handler) get_content_type() string {
	extension := ""

	requestPath := handler.Request.GetPath()
	lastDot := strings.LastIndex(requestPath, ".")

	if lastDot >= 0 {
		extension = requestPath[lastDot:]
	}

	cType := handler.Constants.ContentTypes.GetType(extension)

	if len(cType) != 0 {
		return cType
	} else {
		return constants.DEFAULT_MIME_TYPE
	}
}

func (handler Handler) writeResponse() {
	handler.write(constants.HTTP_VERSION + " " + handler.Response.Status.Message)
	handler.writeHeader()
}

func (handler Handler) writeHeader() {
	handler.writeCommonHeaders()
	handler.writeSpecificHeaders()
	handler.write("")
	if handler.Request.Method.Type != "HEAD" {
		handler.writeBody()
	}
}

func (handler Handler) writeCommonHeaders() {
	handler.write("Date: " + time.Now().String())
	handler.write("Server: " + constants.SERVER)
	handler.write("Connection: close")
}

func (handler Handler) writeSpecificHeaders() {
	for key, value := range handler.Response.Headers {
		handler.write(key + ": " + value)
	}
}

func (handler Handler) writeBody() {
	if handler.Response.IsOk() {
		handler.writeOkBody()
	} else {
		handler.writeErrorBody()
	}
}

func (handler Handler) writeOkBody() {
	file, err := handler.Response.GetOkBody(handler.Request.GetPath())
	if err != nil {
		fmt.Println("Can't open file ", handler.Request.GetPath())
		return
	}

	handler.write(string(file))
}

func (handler Handler) writeErrorBody() {
	body := handler.Response.GetErrorBody(handler.Response.Status.Message)

	handler.write(body)
}

func (handler Handler) write(content string) {
	handler.Connection.Write([]byte(content + "\r\n"))
}

func (handler *Handler) closeConn() {
	handler.Connection.Close()
}
<commit_msg>change response<commit_after>package handler

import (
	"fmt"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/constants"
	modelServer "github.com/vladpereskokov/Technopark_HighLoad-nginx/src/models/server"
	"github.com/vladpereskokov/Technopark_HighLoad-nginx/src/utils"
	"log"
	"net"
	"net/url"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

const HTTP_CONSTANTS_CONFIG = "configs/http.json"

type Handler struct {
	Connection net.Conn
	Request    *modelServer.Request
	Response   *modelServer.Response
	Constants  *modelServer.Constants
	Dir        string
}

type HandlerFunc func(chan net.Conn)

func CreateHandler(dir string) (handlerFunc HandlerFunc) {
	httpConstantsConfig := new(modelServer.Constants)

	err := utils.FromFile(HTTP_CONSTANTS_CONFIG, &httpConstantsConfig)
	if err != nil {
		log.Panicf("can not init http config: %v", err)
	}

	return func(channel chan net.Conn) {
		handler := Handler{}
		handler.create(httpConstantsConfig, dir)

		go handler.start(channel)
	}
}

func (handler *Handler) create(config *modelServer.Constants, dir string) {
	handler.Request = modelServer.InitRequest()
	handler.Response = modelServer.InitResponse()

	handler.Response.SetStatus(200, config.Statuses)

	handler.Constants = config
	handler.Dir = dir
}

func (handler *Handler) start(channel chan net.Conn) {
	for {
		handler.Connection = <-channel
		handler.handle()
	}
}

func (handler *Handler) handle() {
	handler.readRequest()
	handler.requestHandle()
	handler.writeResponse()
	handler.closeConn()
}

func (handler *Handler) readRequest() {
	buffer := make([]byte, 1024)

	_, err := handler.Connection.Read(buffer)
	if err != nil {
		fmt.Println("Error reading:", err.Error())

		return
	}

	handler.parseRequest(string(buffer))
}

func (handler *Handler) parseRequest(query string) {
	splitedQuery := strings.Split(query, "\r\n")[0]
	queryParts := strings.Split(splitedQuery, " ")

	if len(queryParts) != 3 {
		handler.Response.SetStatus(400, handler.Constants.Statuses)

		return
	}

	handler.Request.Method.SetMethod(queryParts[0])
	parsed_url, err := url.Parse(queryParts[1])

	if err != nil || !strings.HasPrefix(queryParts[2], "HTTP/") {
		handler.Response.SetStatus(400, handler.Constants.Statuses)
	}

	handler.Request.Url = parsed_url
}

func (handler *Handler) requestHandle() {
	if !handler.Response.IsOk() {
		handler.setContentHeaders(nil)
		return
	}

	if !handler.Constants.Methods.Contains(handler.Request.Method.Type) {
		handler.Response.SetStatus(405, handler.Constants.Statuses)
	} else {
		handler.preProcessPath()
	}
}

func (handler *Handler) preProcessPath() {
	handler.Request.SetPath(handler.Dir + handler.Request.GetPath())
	file_info := handler.check_path(false)

	if file_info != nil && file_info.IsDir() {
		handler.Request.SetPath(handler.Request.GetPath() + constants.INDEX_FILE)
		file_info = handler.check_path(true)
	}

	handler.setContentHeaders(file_info)
}

func (handler *Handler) check_path(is_dir bool) os.FileInfo {
	request_path := handler.Request.GetPath()

	clear_path := path.Clean(request_path)
	handler.Request.SetPath(clear_path)

	info, err := os.Stat(request_path)
	if err != nil {
		if os.IsNotExist(err) && !is_dir {
			handler.Response.SetStatus(404, handler.Constants.Statuses)
		} else {
			handler.Response.SetStatus(403, handler.Constants.Statuses)
		}
	} else if !strings.Contains(clear_path, handler.Dir) {
		handler.Response.SetStatus(403, handler.Constants.Statuses)
	}
	return info
}

func (handler *Handler) setContentHeaders(info os.FileInfo) {
	if handler.Response.IsOk() {
		handler.Response.SetHeader("Content-Length", strconv.Itoa(int(info.Size())))
		handler.Response.SetHeader("Content-Type", handler.get_content_type())
	} else {
		handler.Response.SetHeader("Content-Length",
			strconv.Itoa(len(handler.Response.GetErrorBody(handler.Response.Status.Message))))
		handler.Response.SetHeader("Content-Type", constants.ERROR_BODY_MIME_TYPE)
	}
}

func (handler *Handler) get_content_type() string {
	extension := ""

	requestPath := handler.Request.GetPath()
	lastDot := strings.LastIndex(requestPath, ".")

	if lastDot >= 0 {
		extension = requestPath[lastDot:]
	}

	cType := handler.Constants.ContentTypes.GetType(extension)

	if len(cType) != 0 {
		return cType
	} else {
		return constants.DEFAULT_MIME_TYPE
	}
}

func (handler Handler) writeResponse() {
	handler.write(constants.HTTP_VERSION + " " +
		strconv.Itoa(handler.Response.Status.Code) + " " + handler.Response.Status.Message)
	handler.writeHeader()

	handler.write("")
	if handler.Request.Method.Type != "HEAD" {
		handler.writeBody()
	}

	handler.write("\r\n")
}

func (handler Handler) writeHeader() {
	handler.writeCommonHeaders()
	handler.writeSpecificHeaders()
}

func (handler Handler) writeCommonHeaders() {
	handler.write("Date: " + time.Now().String())
	handler.write("Server: " + constants.SERVER)
	handler.write("Connection: close")
}

func (handler Handler) writeSpecificHeaders() {
	for key, value := range handler.Response.Headers {
		handler.write(key + ": " + value)
	}
}

func (handler Handler) writeBody() {
	if handler.Response.IsOk() {
		handler.writeOkBody()
	} else {
		handler.writeErrorBody()
	}
}

func (handler Handler) writeOkBody() {
	file, err := handler.Response.GetOkBody(handler.Request.GetPath())
	if err != nil {
		fmt.Println("Can't open file ", handler.Request.GetPath())
		return
	}

	handler.write(string(file))
}

func (handler Handler) writeErrorBody() {
	body := handler.Response.GetErrorBody(handler.Response.Status.Message)

	handler.write(body)
}

func (handler Handler) write(content string) {
	handler.Connection.Write([]byte(content + "\r\n"))
}

func (handler *Handler) closeConn() {
	handler.Connection.Close()
}
<|endoftext|>


<commit_before>package djinn

import (
	"bytes"
	"fmt"
	"strings"
	"testing"
)

type TemplateData struct {
	Title string
	Data  map[string]interface{}
}

func MustContain(t *testing.T, str *string, check string) {
	index := strings.Index(*str, check)
	if index < 0 {
		fmt.Printf("Template did not contain %s\n", check)
		t.Fail()
		return
	}
	*str = (*str)[index:]
}

func TplRun(t *testing.T, j *Djinn, name string, data interface{}, check ...string) {
	w := &bytes.Buffer{}
	err := j.Render(w, name, data)
	if err != nil {
		fmt.Println(err)
		t.Fail()
		return
	}

	//from cache
	j.Render(w, name, data)

	str := w.String()
	fmt.Println(str)

	for _, c := range check {
		MustContain(t, &str, c)
	}

}

func TestTemplate(t *testing.T) {
	m1 := map[string]string{
		"vars.html":                      `<title>{{.Title}}</title> Key={{ .Data.Key }}`,
		"Folder/Main-file_name.html.dji": tplMain,
		"sub1.html":                      tplSub1,
		"sub2.html":                      tplSub2,
	}

	m2 := map[string]string{
		"varsa.html":                      `<title>{{.Title}}</title> Key={{ .Data.Key }}`,
		"Folder/Main-file_namea.html.dji": tplMain,
		"sub1a.html":                      tplSub1,
		"sub2a.html":                      tplSub2a,
	}

	loader1 := &MapLoader{m: m1}

	loader2 := &MapLoader{m: m2}

	loader3 := NewDirLoader("./test/templates")

	loader4 := NewDirLoader("./test/additional/templates")

	j1 := New()
	j1.AddLoaders(loader1, loader2)

	j2 := New()
	j2.AddLoaders(loader3, loader4)

	j3 := New()
	j3.AddLoaders(loader1, loader4)

	data := &TemplateData{
		Title: "Hello World",
		Data: map[string]interface{}{
			"Key":   "Value",
			"Slice": []string{"One", "Two", "Three"},
		},
	}

	data1 := &TemplateData{
		Title: "Hello World A",
		Data: map[string]interface{}{
			"Key":   "Value A",
			"Slice": []string{"A", "B", "C"},
		},
	}

	js := []*Djinn{
		j1,
		j2,
		j3,
	}

	for _, j := range js {
		TplRun(t, j, "vars.html", data, "<title>Hello World</title>", "Key=Value")
		TplRun(t, j, "sub2.html", data, "", "<SUB1>", "<SUB2>", "</SUB2>", "</SUB1>", "")
		TplRun(t, j, "sub1.html", data, "", "<SUB1>", "</SUB1>", "")
		TplRun(t, j, "varsa.html", data1, "<title>Hello World A</title>", "Key=Value A")
		TplRun(t, j, "sub2a.html", data1, "", "<SUB1>", "<SUB2A>", "</SUB2A>", "</SUB1>", "")
		TplRun(t, j, "sub1a.html", data1, "", "<SUB1>", "</SUB1>", "")
	}
}

var tplMain string = `
{{ template "body" }}
`

var tplSub1 string = `{{ extends "Folder/Main-file_name.html.dji" }}
{{ define "body" }}
<SUB1>

{{ template "content" .Data }}
</SUB1>
{{ end }}

{{ define "content" }}
	{{ if eq 1 1 }}
		{{ range .Slice }}
			{{ . }}
	{{ else }}
		NO SLICE
		{{ end }}
	{{ else }}
	{{ end }}
<DEFAULT CONTENT>
{{ end }}
`

var tplSub2 string = `
{{ extends 'sub1.html' }}

{{ define "content" }}
<SUB2></SUB2>
{{ end }}`

var tplSub2a string = `
{{ extends 'sub1.html' }}

{{ define "content" }}
<SUB2A></SUB2A>
{{ end }}`
<commit_msg>maps are reference types not requiring the extra indirection of a pointer<commit_after>package djinn

import (
	"bytes"
	"fmt"
	"strings"
	"testing"
)

type TemplateData struct {
	Title string
	Data  map[string]interface{}
}

func MustContain(t *testing.T, str *string, check string) {
	index := strings.Index(*str, check)
	if index < 0 {
		fmt.Printf("Template did not contain %s\n", check)
		t.Fail()
		return
	}
	*str = (*str)[index:]
}

func TplRun(t *testing.T, j *Djinn, name string, data interface{}, check ...string) {
	w := &bytes.Buffer{}
	err := j.Render(w, name, data)
	if err != nil {
		fmt.Println(err)
		t.Fail()
		return
	}

	//from cache
	j.Render(w, name, data)

	str := w.String()
	fmt.Println(str)

	for _, c := range check {
		MustContain(t, &str, c)
	}

}

func TestTemplate(t *testing.T) {
	m1 := map[string]string{
		"vars.html":                      `<title>{{.Title}}</title> Key={{ .Data.Key }}`,
		"Folder/Main-file_name.html.dji": tplMain,
		"sub1.html":                      tplSub1,
		"sub2.html":                      tplSub2,
	}

	m2 := map[string]string{
		"varsa.html":                      `<title>{{.Title}}</title> Key={{ .Data.Key }}`,
		"Folder/Main-file_namea.html.dji": tplMain,
		"sub1a.html":                      tplSub1,
		"sub2a.html":                      tplSub2a,
	}

	loader1 := &MapLoader{m: m1}

	fmt.Printf("%+v\n", loader1.ListTemplates())

	loader2 := &MapLoader{m: m2}

	loader3 := NewDirLoader("./test/templates")

	loader4 := NewDirLoader("./test/additional/templates")

	j1 := New()
	j1.AddLoaders(loader1, loader2)

	j2 := New()
	j2.AddLoaders(loader3, loader4)

	j3 := New()
	j3.AddLoaders(loader1, loader4)

	data := &TemplateData{
		Title: "Hello World",
		Data: map[string]interface{}{
			"Key":   "Value",
			"Slice": []string{"One", "Two", "Three"},
		},
	}

	data1 := &TemplateData{
		Title: "Hello World A",
		Data: map[string]interface{}{
			"Key":   "Value A",
			"Slice": []string{"A", "B", "C"},
		},
	}

	js := []*Djinn{
		j1,
		j2,
		j3,
	}

	for _, j := range js {
		TplRun(t, j, "vars.html", data, "<title>Hello World</title>", "Key=Value")
		TplRun(t, j, "sub2.html", data, "", "<SUB1>", "<SUB2>", "</SUB2>", "</SUB1>", "")
		TplRun(t, j, "sub1.html", data, "", "<SUB1>", "</SUB1>", "")
		TplRun(t, j, "varsa.html", data1, "<title>Hello World A</title>", "Key=Value A")
		TplRun(t, j, "sub2a.html", data1, "", "<SUB1>", "<SUB2A>", "</SUB2A>", "</SUB1>", "")
		TplRun(t, j, "sub1a.html", data1, "", "<SUB1>", "</SUB1>", "")
	}
}

var tplMain string = `
{{ template "body" }}
`

var tplSub1 string = `{{ extends "Folder/Main-file_name.html.dji" }}
{{ define "body" }}
<SUB1>

{{ template "content" .Data }}
</SUB1>
{{ end }}

{{ define "content" }}
	{{ if eq 1 1 }}
		{{ range .Slice }}
			{{ . }}
	{{ else }}
		NO SLICE
		{{ end }}
	{{ else }}
	{{ end }}
<DEFAULT CONTENT>
{{ end }}
`

var tplSub2 string = `
{{ extends 'sub1.html' }}

{{ define "content" }}
<SUB2></SUB2>
{{ end }}`

var tplSub2a string = `
{{ extends 'sub1.html' }}

{{ define "content" }}
<SUB2A></SUB2A>
{{ end }}`
<|endoftext|>


<commit_before>package ds

import (
	"context"

	"cloud.google.com/go/datastore"
)

// DeleteByKey deletes data from datastore by key
func (client *Client) DeleteByKey(ctx context.Context, key *datastore.Key) error {
	err := client.Delete(ctx, key)
	if client.Cache != nil {
		client.Cache.Del(key)
	}
	return err
}

// DeleteByKeys deletes data from datastore by keys
func (client *Client) DeleteByKeys(ctx context.Context, keys []*datastore.Key) error {
	err := client.DeleteMulti(ctx, keys)
	if client.Cache != nil {
		client.Cache.DelMulti(keys)
	}
	return err
}

// DeleteByID deletes data from datastore by IDKey
func (client *Client) DeleteByID(ctx context.Context, kind string, id int64) error {
	if id == 0 {
		return datastore.ErrInvalidKey
	}
	return client.Delete(ctx, datastore.IDKey(kind, id, nil))
}

// DeleteByStringID deletes data from datastore by IDKey
func (client *Client) DeleteByStringID(ctx context.Context, kind string, id string) error {
	tid := parseID(id)
	if tid == 0 {
		return datastore.ErrInvalidKey
	}
	return client.Delete(ctx, datastore.IDKey(kind, tid, nil))
}

// DeleteByIDs deletes data from datastore by IDKeys
func (client *Client) DeleteByIDs(ctx context.Context, kind string, ids []int64) error {
	keys := make([]*datastore.Key, len(ids))
	for i, id := range ids {
		if id == 0 {
			return datastore.ErrInvalidKey
		}
		keys[i] = datastore.IDKey(kind, id, nil)
	}
	return client.DeleteMulti(ctx, keys)
}

// DeleteByStringIDs deletes data from datastore by IDKeys
func (client *Client) DeleteByStringIDs(ctx context.Context, kind string, ids []string) error {
	k := kind
	keys := make([]*datastore.Key, len(ids))
	for i, id := range ids {
		tid := parseID(id)
		if tid == 0 {
			return datastore.ErrInvalidKey
		}
		keys[i] = datastore.IDKey(k, tid, nil)
	}
	return client.DeleteMulti(ctx, keys)
}

// DeleteByName deletes data from datastore by NameKey
func (client *Client) DeleteByName(ctx context.Context, kind string, name string) error {
	if len(name) == 0 {
		return datastore.ErrInvalidKey
	}
	return client.Delete(ctx, datastore.NameKey(kind, name, nil))
}

// DeleteByNames deletes data from datastore by NameKeys
func (client *Client) DeleteByNames(ctx context.Context, kind string, names []string) error {
	keys := make([]*datastore.Key, len(names))
	for i, name := range names {
		if len(name) == 0 {
			return datastore.ErrInvalidKey
		}
		keys[i] = datastore.NameKey(kind, name, nil)
	}
	return client.DeleteMulti(ctx, keys)
}

// DeleteModel deletes data by get key from model
func (client *Client) DeleteModel(ctx context.Context, src interface{}) error {
	key := ExtractKey(src)
	if key == nil {
		return datastore.ErrInvalidKey
	}
	return client.Delete(ctx, key)
}

// DeleteModels deletes data by get keys from models
func (client *Client) DeleteModels(ctx context.Context, src interface{}) error {
	keys := ExtractKeys(src)
	if len(keys) == 0 {
		return datastore.ErrInvalidKey
	}
	return client.DeleteMulti(ctx, keys)
}
<commit_msg>use delete by key when delete from other func<commit_after>package ds

import (
	"context"

	"cloud.google.com/go/datastore"
)

// DeleteByKey deletes data from datastore by key
func (client *Client) DeleteByKey(ctx context.Context, key *datastore.Key) error {
	err := client.Delete(ctx, key)
	if client.Cache != nil {
		client.Cache.Del(key)
	}
	return err
}

// DeleteByKeys deletes data from datastore by keys
func (client *Client) DeleteByKeys(ctx context.Context, keys []*datastore.Key) error {
	err := client.DeleteMulti(ctx, keys)
	if client.Cache != nil {
		client.Cache.DelMulti(keys)
	}
	return err
}

// DeleteByID deletes data from datastore by IDKey
func (client *Client) DeleteByID(ctx context.Context, kind string, id int64) error {
	if id == 0 {
		return datastore.ErrInvalidKey
	}
	return client.DeleteByKey(ctx, datastore.IDKey(kind, id, nil))
}

// DeleteByStringID deletes data from datastore by IDKey
func (client *Client) DeleteByStringID(ctx context.Context, kind string, id string) error {
	tid := parseID(id)
	if tid == 0 {
		return datastore.ErrInvalidKey
	}
	return client.DeleteByKey(ctx, datastore.IDKey(kind, tid, nil))
}

// DeleteByIDs deletes data from datastore by IDKeys
func (client *Client) DeleteByIDs(ctx context.Context, kind string, ids []int64) error {
	keys := make([]*datastore.Key, len(ids))
	for i, id := range ids {
		if id == 0 {
			return datastore.ErrInvalidKey
		}
		keys[i] = datastore.IDKey(kind, id, nil)
	}
	return client.DeleteByKeys(ctx, keys)
}

// DeleteByStringIDs deletes data from datastore by IDKeys
func (client *Client) DeleteByStringIDs(ctx context.Context, kind string, ids []string) error {
	k := kind
	keys := make([]*datastore.Key, len(ids))
	for i, id := range ids {
		tid := parseID(id)
		if tid == 0 {
			return datastore.ErrInvalidKey
		}
		keys[i] = datastore.IDKey(k, tid, nil)
	}
	return client.DeleteByKeys(ctx, keys)
}

// DeleteByName deletes data from datastore by NameKey
func (client *Client) DeleteByName(ctx context.Context, kind string, name string) error {
	if len(name) == 0 {
		return datastore.ErrInvalidKey
	}
	return client.DeleteByKey(ctx, datastore.NameKey(kind, name, nil))
}

// DeleteByNames deletes data from datastore by NameKeys
func (client *Client) DeleteByNames(ctx context.Context, kind string, names []string) error {
	keys := make([]*datastore.Key, len(names))
	for i, name := range names {
		if len(name) == 0 {
			return datastore.ErrInvalidKey
		}
		keys[i] = datastore.NameKey(kind, name, nil)
	}
	return client.DeleteByKeys(ctx, keys)
}

// DeleteModel deletes data by get key from model
func (client *Client) DeleteModel(ctx context.Context, src interface{}) error {
	key := ExtractKey(src)
	if key == nil {
		return datastore.ErrInvalidKey
	}
	return client.DeleteByKey(ctx, key)
}

// DeleteModels deletes data by get keys from models
func (client *Client) DeleteModels(ctx context.Context, src interface{}) error {
	keys := ExtractKeys(src)
	if len(keys) == 0 {
		return datastore.ErrInvalidKey
	}
	return client.DeleteByKeys(ctx, keys)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"io"
	"log"
	"os"

	"github.com/miekg/dns"
)

var dnsServer string
var listen string
var hostsPath string
var blocked = []string{}

func init() {
	flag.StringVar(&dnsServer, "dns-server", "192.168.1.1:domain",
		"DNS server for proxy not blocked queries")
	flag.StringVar(&listen, "listen", ":domain", "Listen is pair 'ip:port'")
	flag.StringVar(&hostsPath, "hosts-path", "hosts", "Path to hosts file")
	flag.Parse()

	log.Printf("Start with: listen: %s; dns-server: %s; hosts-path: %s\n",
		listen, dnsServer, hostsPath)

	loadBlocked()
}

func loadBlocked() {
	file, openErr := os.Open(hostsPath)
	if nil != openErr {
		panic(openErr)
	}
	defer file.Close()
	buffer := bufio.NewReader(file)
	for {
		line, readErr := buffer.ReadString('\n')
		if readErr == io.EOF {
			break
		} else if nil != readErr {
			panic(readErr)
		}

		host := line[0 : len(line)-1]
		blocked = append(blocked, host)
	}
	log.Printf("Loaded %d domains", len(blocked))
}

func isBlocked(requestMesage *dns.Msg) bool {
	if 1 != len(requestMesage.Question) {
		log.Printf("Can not process message with multiple questions")
		return false
	}

	question := requestMesage.Question[0]
	for _, name := range blocked {
		if dns.Fqdn(name) == question.Name {
			return true
		}
	}
	return false
}

func proxyRequest(writer dns.ResponseWriter, requestMessage *dns.Msg) {
	responseMessage, exchangeErr := dns.Exchange(requestMessage, dnsServer)

	if nil == exchangeErr {
		log.Printf("Response message: %+v\n", responseMessage)
		writeResponse(writer, responseMessage)
	} else {
		log.Printf("Exchange error: %s\n", exchangeErr)

		errorMessage := new(dns.Msg)
		errorMessage.SetRcode(requestMessage, dns.RcodeServerFailure)
		log.Printf("Error message: %+v", errorMessage)

		writeResponse(writer, errorMessage)
	}
}

func blockedRequest(writer dns.ResponseWriter, requestMessage *dns.Msg) {
	responseMessage := new(dns.Msg)
	responseMessage.SetRcode(requestMessage, dns.RcodeRefused)
	log.Printf("Block response: %+v\n", responseMessage)
	writeResponse(writer, responseMessage)
}

func handler(writer dns.ResponseWriter, requestMessage *dns.Msg) {
	log.Printf("Query message: %+v\n", requestMessage)

	if isBlocked(requestMessage) {
		blockedRequest(writer, requestMessage)
	} else {
		proxyRequest(writer, requestMessage)
	}
}

func writeResponse(writer dns.ResponseWriter, message *dns.Msg) {
	if writeErr := writer.WriteMsg(message); nil == writeErr {
		log.Printf("Writer success\n")
	} else {
		log.Printf("Writer error: %s\n", writeErr)
	}
}

func main() {
	server := &dns.Server{
		Addr:    listen,
		Net:     "udp",
		Handler: dns.HandlerFunc(handler),
	}

	if serverErr := server.ListenAndServe(); nil != serverErr {
		log.Fatal(serverErr)
	}
}
<commit_msg>Use go logging instead log<commit_after>package main

import (
	"bufio"
	"flag"
	"io"
	"os"

	"github.com/miekg/dns"
	"github.com/op/go-logging"
)

var logger = formatedLogger()

var dnsServer string
var listen string
var hostsPath string
var blocked = []string{}

func init() {
	flag.StringVar(&dnsServer, "dns-server", "192.168.1.1:domain",
		"DNS server for proxy not blocked queries")
	flag.StringVar(&listen, "listen", ":domain", "Listen is pair 'ip:port'")
	flag.StringVar(&hostsPath, "hosts-path", "hosts", "Path to hosts file")
	flag.Parse()

	logger.Infof("Start with: listen: %s; dns-server: %s; hosts-path: %s",
		listen, dnsServer, hostsPath)

	loadBlocked()
}

func formatedLogger() *logging.Logger {
	logger := logging.MustGetLogger("dnsblocker")
	logger.SetBackend(
		logging.MultiLogger(
			logging.NewBackendFormatter(
				logging.NewLogBackend(os.Stdout, "", 0),
				logging.MustStringFormatter(
					"%{color}%{time:15:04:05.000} [%{level:.5s}] %{message}%{color:reset}",
				),
			),
		),
	)
	return logger
}

func loadBlocked() {
	file, openErr := os.Open(hostsPath)
	if nil != openErr {
		panic(openErr)
	}
	defer file.Close()
	buffer := bufio.NewReader(file)
	for {
		line, readErr := buffer.ReadString('\n')
		if readErr == io.EOF {
			break
		} else if nil != readErr {
			panic(readErr)
		}

		host := line[0 : len(line)-1]
		blocked = append(blocked, host)
	}
	logger.Infof("Loaded %d domains", len(blocked))
}

func isBlocked(requestMesage *dns.Msg) bool {
	if 1 != len(requestMesage.Question) {
		logger.Warning("Can not process message with multiple questions")
		return false
	}

	question := requestMesage.Question[0]
	for _, name := range blocked {
		if dns.Fqdn(name) == question.Name {
			return true
		}
	}
	return false
}

func proxyRequest(writer dns.ResponseWriter, requestMessage *dns.Msg) {
	responseMessage, exchangeErr := dns.Exchange(requestMessage, dnsServer)

	if nil == exchangeErr {
		logger.Debug("Response message: %+v", responseMessage)
		writeResponse(writer, responseMessage)
	} else {
		logger.Errorf("Exchange error: %s", exchangeErr)

		errorMessage := new(dns.Msg)
		errorMessage.SetRcode(requestMessage, dns.RcodeServerFailure)
		logger.Errorf("Error message: %+v", errorMessage)

		writeResponse(writer, errorMessage)
	}
}

func blockedRequest(writer dns.ResponseWriter, requestMessage *dns.Msg) {
	responseMessage := new(dns.Msg)
	responseMessage.SetRcode(requestMessage, dns.RcodeRefused)
	logger.Debugf("Block response: %+v", responseMessage)
	writeResponse(writer, responseMessage)
}

func handler(writer dns.ResponseWriter, requestMessage *dns.Msg) {
	logger.Debugf("Query message: %+v", requestMessage)

	if isBlocked(requestMessage) {
		blockedRequest(writer, requestMessage)
	} else {
		proxyRequest(writer, requestMessage)
	}
}

func writeResponse(writer dns.ResponseWriter, message *dns.Msg) {
	if writeErr := writer.WriteMsg(message); nil == writeErr {
		logger.Debug("Writer success")
	} else {
		logger.Errorf("Writer error: %s", writeErr)
	}
}

func main() {
	server := &dns.Server{
		Addr:    listen,
		Net:     "udp",
		Handler: dns.HandlerFunc(handler),
	}

	if serverErr := server.ListenAndServe(); nil != serverErr {
		logger.Fatal(serverErr)
	}
}
<|endoftext|>


<commit_before>package whatlanggo

import (
	"sort"
	"unicode"
)

const maxDist = 300

//Detect language and script of the given text.
func Detect(text string) Info {
	return DetectWithOptions(text, Options{})
}

//DetectLang detects only the language by a given text.
func DetectLang(text string) Lang {
	return Detect(text).Lang
}

//DetectLangWithOptions detects only the language of the given text with the provided options.
func DetectLangWithOptions(text string, options Options) Lang {
	return DetectWithOptions(text, options).Lang
}

//DetectWithOptions detects the language and script of the given text with the provided options.
func DetectWithOptions(text string, options Options) Info {
	script := DetectScript(text)
	if script != nil {
		lang, confidence := detectLangBaseOnScript(text, options, script)
		return Info{
			Lang:   lang,
			Script: script,
			Confidence: confidence,
		}
	}
	return Info{}

}

func detectLangBaseOnScript(text string, options Options, script *unicode.RangeTable) (Lang, float64) {
	switch script {
	case unicode.Latin:
		return detectLangInProfiles(text, options, latinLangs)
	case unicode.Cyrillic:
		return detectLangInProfiles(text, options, cyrillicLangs)
	case unicode.Devanagari:
		return detectLangInProfiles(text, options, devanagariLangs)
	case unicode.Hebrew:
		return detectLangInProfiles(text, options, hebrewLangs)
	case unicode.Ethiopic:
		return detectLangInProfiles(text, options, ethiopicLangs)
	case unicode.Arabic:
		return detectLangInProfiles(text, options, arabicLangs)
	case unicode.Han:
		return Cmn, 1
	case unicode.Bengali:
		return Ben, 1
	case unicode.Hangul:
		return Kor, 1
	case unicode.Georgian:
		return Kat, 1
	case unicode.Greek:
		return Ell, 1
	case unicode.Kannada:
		return Kan, 1
	case unicode.Tamil:
		return Tam, 1
	case unicode.Thai:
		return Tha, 1
	case unicode.Gujarati:
		return Guj, 1
	case unicode.Gurmukhi:
		return Pan, 1
	case unicode.Telugu:
		return Tel, 1
	case unicode.Malayalam:
		return Mal, 1
	case unicode.Oriya:
		return Ori, 1
	case unicode.Myanmar:
		return Mya, 1
	case unicode.Sinhala:
		return Sin, 1
	case unicode.Khmer:
		return Khm, 1
	case _HiraganaKatakana:
		return Jpn, 1
	}
	return -1, 0
}
func detectLangInProfiles(text string, options Options, langProfileList langProfileList) (Lang, float64) {
	trigrams := getTrigramsWithPositions(text)
	type langDistance struct {
		lang Lang
		dist int
	}
	langDistances := []langDistance{}

	for lang, langTrigrams := range langProfileList {
		if len(options.Whitelist) != 0 {
			//Skip non-whitelisted languages.
			if _, ok := options.Whitelist[lang]; !ok {
				continue
			}
		} else if len(options.Blacklist) != 0 {
			//skip blacklisted languages.
			if _, ok := options.Blacklist[lang]; ok {
				continue
			}
		}

		dist := calculateDistance(langTrigrams, trigrams)
		langDistances = append(langDistances, langDistance{lang, dist})
	}

	if len(langDistances) == 0 {
		return -1, 0
	}

	sort.SliceStable(langDistances, func(i, j int) bool { return langDistances[i].dist < langDistances[j].dist })
	lang_dist1 := langDistances[0];
    lang_dist2 := langDistances[1];
    score1 := 90000 - lang_dist1.dist;
	score2 := 90000 - lang_dist2.dist;

	var confidence float64
	if score1 == 0 {
        // If score1 is 0, score2 is 0 as well, because array is sorted.
        // Therefore there is no language to return.
        return -1, 0
    } else if score2 == 0 {
        // If score2 is 0, return first language, to prevent division by zero in the rate formula.
        // In this case confidence is calculated by another formula.
        // At this point there are two options:
        // * Text contains random characters that accidentally match trigrams of one of the languages
        // * Text really matches one of the languages.
        //
        // Number 500.0 is based on experiments and common sense expectations.
        confidence = float64((score1) / 500.0)
        if confidence > 1.0 {
            confidence = 1.0
        }
        return lang_dist1.lang, confidence
	}

	rate := float64((score1 - score2)) / float64(score2);

    // Hyperbola function. Everything that is above the function has confidence = 1.0
    // If rate is below, confidence is calculated proportionally.
    // Numbers 12.0 and 0.05 are obtained experimentally, so the function represents common sense.
    //
    confident_rate := float64(12.0 / len(trigrams)) + 0.05;
    if rate > confident_rate {
        confidence = 1.0
    } else {
        confidence = rate / confident_rate
    };

    return lang_dist1.lang, confidence
}

func calculateDistance(langTrigrams []string, textTrigrams map[string]int) int {
	var dist, totalDist int
	for i, trigram := range langTrigrams {
		if n, ok := textTrigrams[trigram]; ok {
			dist = abs(n - i)
		} else {
			dist = maxDist
		}
		totalDist += dist
	}

	return totalDist
}
<commit_msg>Added confidence<commit_after>package whatlanggo

import (
	"sort"
	"unicode"
)

const maxDist = 300

//Detect language and script of the given text.
func Detect(text string) Info {
	return DetectWithOptions(text, Options{})
}

//DetectLang detects only the language by a given text.
func DetectLang(text string) Lang {
	return Detect(text).Lang
}

//DetectLangWithOptions detects only the language of the given text with the provided options.
func DetectLangWithOptions(text string, options Options) Lang {
	return DetectWithOptions(text, options).Lang
}

//DetectWithOptions detects the language and script of the given text with the provided options.
func DetectWithOptions(text string, options Options) Info {
	script := DetectScript(text)
	if script != nil {
		lang, confidence := detectLangBaseOnScript(text, options, script)
		return Info{
			Lang:   lang,
			Script: script,
			Confidence: confidence,
		}
	}
	return Info{
		Lang: -1,
		Script: nil,
		Confidence: 0,
	}
}

func detectLangBaseOnScript(text string, options Options, script *unicode.RangeTable) (Lang, float64) {
	switch script {
	case unicode.Latin:
		return detectLangInProfiles(text, options, latinLangs)
	case unicode.Cyrillic:
		return detectLangInProfiles(text, options, cyrillicLangs)
	case unicode.Devanagari:
		return detectLangInProfiles(text, options, devanagariLangs)
	case unicode.Hebrew:
		return detectLangInProfiles(text, options, hebrewLangs)
	case unicode.Ethiopic:
		return detectLangInProfiles(text, options, ethiopicLangs)
	case unicode.Arabic:
		return detectLangInProfiles(text, options, arabicLangs)
	case unicode.Han:
		return Cmn, 1
	case unicode.Bengali:
		return Ben, 1
	case unicode.Hangul:
		return Kor, 1
	case unicode.Georgian:
		return Kat, 1
	case unicode.Greek:
		return Ell, 1
	case unicode.Kannada:
		return Kan, 1
	case unicode.Tamil:
		return Tam, 1
	case unicode.Thai:
		return Tha, 1
	case unicode.Gujarati:
		return Guj, 1
	case unicode.Gurmukhi:
		return Pan, 1
	case unicode.Telugu:
		return Tel, 1
	case unicode.Malayalam:
		return Mal, 1
	case unicode.Oriya:
		return Ori, 1
	case unicode.Myanmar:
		return Mya, 1
	case unicode.Sinhala:
		return Sin, 1
	case unicode.Khmer:
		return Khm, 1
	case _HiraganaKatakana:
		return Jpn, 1
	}
	return -1, 0
}
func detectLangInProfiles(text string, options Options, langProfileList langProfileList) (Lang, float64) {
	trigrams := getTrigramsWithPositions(text)
	type langDistance struct {
		lang Lang
		dist int
	}
	langDistances := []langDistance{}

	for lang, langTrigrams := range langProfileList {
		if len(options.Whitelist) != 0 {
			//Skip non-whitelisted languages.
			if _, ok := options.Whitelist[lang]; !ok {
				continue
			}
		} else if len(options.Blacklist) != 0 {
			//skip blacklisted languages.
			if _, ok := options.Blacklist[lang]; ok {
				continue
			}
		}

		dist := calculateDistance(langTrigrams, trigrams)
		langDistances = append(langDistances, langDistance{lang, dist})
	}

	if len(langDistances) == 0 {
		return -1, 0
	}

	sort.SliceStable(langDistances, func(i, j int) bool { return langDistances[i].dist < langDistances[j].dist })
	lang_dist1 := langDistances[0];
    lang_dist2 := langDistances[1];
    score1 := 90000 - lang_dist1.dist;
	score2 := 90000 - lang_dist2.dist;

	var confidence float64
	if score1 == 0 {
        // If score1 is 0, score2 is 0 as well, because array is sorted.
        // Therefore there is no language to return.
        return -1, 0
    } else if score2 == 0 {
        // If score2 is 0, return first language, to prevent division by zero in the rate formula.
        // In this case confidence is calculated by another formula.
        // At this point there are two options:
        // * Text contains random characters that accidentally match trigrams of one of the languages
        // * Text really matches one of the languages.
        //
        // Number 500.0 is based on experiments and common sense expectations.
        confidence = float64((score1) / 500.0)
        if confidence > 1.0 {
            confidence = 1.0
        }
        return lang_dist1.lang, confidence
	}

	rate := float64((score1 - score2)) / float64(score2);

    // Hyperbola function. Everything that is above the function has confidence = 1.0
    // If rate is below, confidence is calculated proportionally.
    // Numbers 12.0 and 0.05 are obtained experimentally, so the function represents common sense.
    //
    confident_rate := float64(12.0 / len(trigrams)) + 0.05;
    if rate > confident_rate {
        confidence = 1.0
    } else {
        confidence = rate / confident_rate
    };

    return lang_dist1.lang, confidence
}

func calculateDistance(langTrigrams []string, textTrigrams map[string]int) int {
	var dist, totalDist int
	for i, trigram := range langTrigrams {
		if n, ok := textTrigrams[trigram]; ok {
			dist = abs(n - i)
		} else {
			dist = maxDist
		}
		totalDist += dist
	}

	return totalDist
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

// CmdDatacenter subcommand
import (
	"errors"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/fatih/color"
	"github.com/urfave/cli"
)

// ListDatacenters ...
var ListDatacenters = cli.Command{
	Name:      "list",
	Usage:     "List available datacenters.",
	ArgsUsage: " ",
	Description: `List available datacenters.

   Example:
    $ ernest datacenter list
	`,
	Action: func(c *cli.Context) error {
		m, cfg := setup(c)
		datacenters, err := m.ListDatacenters(cfg.Token)
		if err != nil {
			color.Red(err.Error())
			return err
		}

		w := new(tabwriter.Writer)
		w.Init(os.Stdout, 0, 8, 0, '\t', 0)

		fmt.Fprintln(w, "NAME\tTYPE")
		for _, datacenter := range datacenters {
			str := fmt.Sprintf("%s\t%s", datacenter.Name, datacenter.Type)
			fmt.Fprintln(w, str)
		}
		w.Flush()
		return nil
	},
}

// CreateAWSDatacenter ...
var CreateAWSDatacenter = cli.Command{
	Name:  "aws",
	Usage: "Create a new aws datacenter.",
	Description: `Create a new AWS datacenter on the targeted instance of Ernest.

	Example:
	 $ ernest datacenter create aws --region region --token token --secret secret my_datacenter
	 `,
	ArgsUsage: "<datacenter-name>",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "region",
			Value: "",
			Usage: "Datacenter region",
		},
		cli.StringFlag{
			Name:  "token",
			Value: "",
			Usage: "AWS Token",
		},
		cli.StringFlag{
			Name:  "secret",
			Value: "",
			Usage: "AWS Secret",
		},
		cli.BoolFlag{
			Name:  "fake",
			Usage: "Fake datacenter",
		},
	},
	Action: func(c *cli.Context) error {
		if len(c.Args()) < 1 {
			msg := "You should specify the datacenter name"
			color.Red(msg)
			return errors.New(msg)
		}

		name := c.Args()[0]

		token := c.String("token")
		if token == "" {
			msg := "Token not specified"
			color.Red(msg)
			return errors.New(msg)
		}

		secret := c.String("secret")
		if token == "" {
			msg := "Secret not specified"
			color.Red(msg)
			return errors.New(msg)
		}

		region := c.String("region")
		if region == "" {
			msg := "Region not specified"
			color.Red(msg)
			return errors.New(msg)
		}

		rtype := "aws"

		if c.Bool("fake") {
			rtype = "fakeaws"
		}
		m, cfg := setup(c)
		_, err := m.CreateAWSDatacenter(cfg.Token, name, rtype, region, token, secret)
		if err != nil {
			color.Red(err.Error())
		}
		return nil
	},
}

// CreateVcloudDatacenter ...
var CreateVcloudDatacenter = cli.Command{
	Name:  "vcloud",
	Usage: "Create a new vcloud datacenter.",
	Description: `Create a new vcloud datacenter on the targeted instance of Ernest.

   Example:
    $ ernest datacenter create vcloud --datacenter-user username --datacenter-password xxxx --datacenter-org MY-ORG-NAME --vse-url http://vse.url mydatacenter https://myernest.com MY-PUBLIC-NETWORK
	`,
	ArgsUsage: "<datacenter-name> <vcloud-url> <network-name>",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "datacenter-user",
			Value: "",
			Usage: "User to be configured with the datacenter",
		},
		cli.StringFlag{
			Name:  "datacenter-password",
			Value: "",
			Usage: "Password related with user",
		},
		cli.StringFlag{
			Name:  "datacenter-org",
			Value: "",
			Usage: "vCloud Organization name",
		},
		cli.StringFlag{
			Name:  "vse-url",
			Value: "",
			Usage: "VSE URL",
		},
		cli.BoolFlag{
			Name:  "fake",
			Usage: "Fake datacenter",
		},
	},
	Action: func(c *cli.Context) error {
		if len(c.Args()) < 3 {
			msg := "You should specify the datacenter name, vcloud URL and network name"
			color.Red(msg)
			return errors.New(msg)
		}
		name := c.Args()[0]
		user := c.String("datacenter-user") + "@" + c.String("datacenter-org")
		if user == "" {
			msg := "User not specified"
			color.Red(msg)
			return errors.New(msg)
		}
		password := c.String("datacenter-password")
		if password == "" {
			msg := "Password not specified"
			color.Red(msg)
			return errors.New("Password not specified")
		}
		rtype := "vcloud"
		if c.Bool("fake") {
			rtype = "fakevcloud"
		}
		m, cfg := setup(c)
		_, err := m.CreateVcloudDatacenter(cfg.Token, name, rtype, user, password, c.Args()[1], c.Args()[2], c.String("vse-url"))
		if err != nil {
			color.Red(err.Error())
		}
		return nil
	},
}

// CreateDatacenters ...
var CreateDatacenters = cli.Command{
	Name:        "create",
	Usage:       "Create a new datacenter.",
	Description: "Create a new datacenter on the targeted instance of Ernest.",
	Subcommands: []cli.Command{
		CreateVcloudDatacenter,
		CreateAWSDatacenter,
	},
}

// CmdDatacenter ...
var CmdDatacenter = cli.Command{
	Name:  "datacenter",
	Usage: "Datacenter related subcommands",
	Subcommands: []cli.Command{
		ListDatacenters,
		CreateDatacenters,
	},
}
<commit_msg>Fixed typo<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

// CmdDatacenter subcommand
import (
	"errors"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/fatih/color"
	"github.com/urfave/cli"
)

// ListDatacenters ...
var ListDatacenters = cli.Command{
	Name:      "list",
	Usage:     "List available datacenters.",
	ArgsUsage: " ",
	Description: `List available datacenters.

   Example:
    $ ernest datacenter list
	`,
	Action: func(c *cli.Context) error {
		m, cfg := setup(c)
		datacenters, err := m.ListDatacenters(cfg.Token)
		if err != nil {
			color.Red(err.Error())
			return err
		}

		w := new(tabwriter.Writer)
		w.Init(os.Stdout, 0, 8, 0, '\t', 0)

		fmt.Fprintln(w, "NAME\tTYPE")
		for _, datacenter := range datacenters {
			str := fmt.Sprintf("%s\t%s", datacenter.Name, datacenter.Type)
			fmt.Fprintln(w, str)
		}
		w.Flush()
		return nil
	},
}

// CreateAWSDatacenter ...
var CreateAWSDatacenter = cli.Command{
	Name:  "aws",
	Usage: "Create a new aws datacenter.",
	Description: `Create a new AWS datacenter on the targeted instance of Ernest.

	Example:
	 $ ernest datacenter create aws --region region --token token --secret secret my_datacenter
	 `,
	ArgsUsage: "<datacenter-name>",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "region",
			Value: "",
			Usage: "Datacenter region",
		},
		cli.StringFlag{
			Name:  "token",
			Value: "",
			Usage: "AWS Token",
		},
		cli.StringFlag{
			Name:  "secret",
			Value: "",
			Usage: "AWS Secret",
		},
		cli.BoolFlag{
			Name:  "fake",
			Usage: "Fake datacenter",
		},
	},
	Action: func(c *cli.Context) error {
		if len(c.Args()) < 1 {
			msg := "You should specify the datacenter name"
			color.Red(msg)
			return errors.New(msg)
		}

		name := c.Args()[0]

		token := c.String("token")
		if token == "" {
			msg := "Token not specified"
			color.Red(msg)
			return errors.New(msg)
		}

		secret := c.String("secret")
		if secret == "" {
			msg := "Secret not specified"
			color.Red(msg)
			return errors.New(msg)
		}

		region := c.String("region")
		if region == "" {
			msg := "Region not specified"
			color.Red(msg)
			return errors.New(msg)
		}

		rtype := "aws"

		if c.Bool("fake") {
			rtype = "fakeaws"
		}
		m, cfg := setup(c)
		_, err := m.CreateAWSDatacenter(cfg.Token, name, rtype, region, token, secret)
		if err != nil {
			color.Red(err.Error())
		}
		return nil
	},
}

// CreateVcloudDatacenter ...
var CreateVcloudDatacenter = cli.Command{
	Name:  "vcloud",
	Usage: "Create a new vcloud datacenter.",
	Description: `Create a new vcloud datacenter on the targeted instance of Ernest.

   Example:
    $ ernest datacenter create vcloud --datacenter-user username --datacenter-password xxxx --datacenter-org MY-ORG-NAME --vse-url http://vse.url mydatacenter https://myernest.com MY-PUBLIC-NETWORK
	`,
	ArgsUsage: "<datacenter-name> <vcloud-url> <network-name>",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "datacenter-user",
			Value: "",
			Usage: "User to be configured with the datacenter",
		},
		cli.StringFlag{
			Name:  "datacenter-password",
			Value: "",
			Usage: "Password related with user",
		},
		cli.StringFlag{
			Name:  "datacenter-org",
			Value: "",
			Usage: "vCloud Organization name",
		},
		cli.StringFlag{
			Name:  "vse-url",
			Value: "",
			Usage: "VSE URL",
		},
		cli.BoolFlag{
			Name:  "fake",
			Usage: "Fake datacenter",
		},
	},
	Action: func(c *cli.Context) error {
		if len(c.Args()) < 3 {
			msg := "You should specify the datacenter name, vcloud URL and network name"
			color.Red(msg)
			return errors.New(msg)
		}
		name := c.Args()[0]
		user := c.String("datacenter-user") + "@" + c.String("datacenter-org")
		if user == "" {
			msg := "User not specified"
			color.Red(msg)
			return errors.New(msg)
		}
		password := c.String("datacenter-password")
		if password == "" {
			msg := "Password not specified"
			color.Red(msg)
			return errors.New("Password not specified")
		}
		rtype := "vcloud"
		if c.Bool("fake") {
			rtype = "fakevcloud"
		}
		m, cfg := setup(c)
		_, err := m.CreateVcloudDatacenter(cfg.Token, name, rtype, user, password, c.Args()[1], c.Args()[2], c.String("vse-url"))
		if err != nil {
			color.Red(err.Error())
		}
		return nil
	},
}

// CreateDatacenters ...
var CreateDatacenters = cli.Command{
	Name:        "create",
	Usage:       "Create a new datacenter.",
	Description: "Create a new datacenter on the targeted instance of Ernest.",
	Subcommands: []cli.Command{
		CreateVcloudDatacenter,
		CreateAWSDatacenter,
	},
}

// CmdDatacenter ...
var CmdDatacenter = cli.Command{
	Name:  "datacenter",
	Usage: "Datacenter related subcommands",
	Subcommands: []cli.Command{
		ListDatacenters,
		CreateDatacenters,
	},
}
<|endoftext|>


<commit_before>package main

import (
//	"net"
	"net/http"
	"log"
//	"io/ioutil"
	"flag"
	"os"
	"path/filepath"
	"regexp"
	"fmt"
//	"reflect"
	"strconv"
	"time"
//	"strings"
	"html/template"
)

var (
	rootdir string
	port string
	address string
	verbose bool
)

var (
	d Query
)

var templates *template.Template

func init() {
	flag.StringVar(&rootdir, "root", "current directory", "webroot directory")
	flag.StringVar(&rootdir, "d", "current directory", "webroot directory" + " (shorthand)")
	flag.StringVar(&port,"port", "8080", "listen port")
	flag.StringVar(&port,"p", "8080", "listen port" + " (shorthand)")
	flag.StringVar(&address, "address", "*", "listen address")
	flag.StringVar(&address, "l", "*", "listen address" + " (shorthand)")
	flag.BoolVar(&verbose, "verbose", false, "be verbose")
	flag.BoolVar(&verbose, "v", false, "be verbose" + " (shorthand)")
}

func debug(s string) {
	if verbose {
		log.Print(s)
	}
}

func debugln(v ...interface{}) {
	if verbose {
		log.Println(v ...)
	}
}

var validLog = regexp.MustCompile("^/log/([a-zA-Z0-9-]+)/([0-9]+[.]{0,1}[0-9]*)(/([ts])/([0-9]+))?/?$")
var validURLs = regexp.MustCompile("^/")

func logHandler(w http.ResponseWriter, r *http.Request) {
	m := validLog.FindStringSubmatch(r.URL.Path)
	if len(m) == 0 {
		http.Error(w, "Sensor not found", http.StatusNotFound)
		return
	}
	debug("Sensor " + m[1] + " sent value " + m[2])
	//if ! d.Exists(m[1]) {
	//	d.Add(m[1])
	//}
	v, _ := strconv.ParseFloat(m[2], 64)
	if m[4] != "" {
		t, _ := strconv.ParseInt(m[5], 10, 64)
		if m[4] == "t" {
			d.StoreT(m[1], v, time.Unix(t, 0))
		} else {
			d.StoreT(m[1], v, time.Unix(time.Now().Unix() - t, 0))
		}
	} else {
		d.Store(m[1], v)
	}
	debugln("Sensor " + m[1] + " now contains:", d.Load(m[1]))
	fmt.Fprintf(w, "ok")
}

type HomePage struct {
	SensorList template.HTML
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	var sl string
	for _, s := range d.List() {
		sl += `

                                    <a href="view/` + s + `">` + s + `

`
	}
	templates = template.Must(template.ParseFiles(rootdir + "/templates/home.html")) // Remove when finish frontend
	err := templates.ExecuteTemplate(w, "home.html", HomePage{template.HTML(sl)})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func makeHandler(fn func (http.ResponseWriter, *http.Request)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		m := validURLs.FindStringSubmatch(r.URL.Path)
		if m == nil {
			http.NotFound(w, r)
			return
		}
		fn(w, r)
	}
}

func main() {
	flag.Parse()
	var err error
	if rootdir == "current directory" {
		rootdir, err =  filepath.Abs(filepath.Dir(os.Args[0]))
	} else {
		rootdir, err = filepath.Abs(filepath.Dir(rootdir))
	}
	if err != nil {
		log.Fatal(err)
	}

	if address == "*" {
		address = ""
	}

	t := Database{ make(map[string] sensorlog) }
	d = t
	templates = template.Must(template.ParseFiles(rootdir + "/templates/home.html"))

	http.HandleFunc("/log/", logHandler)
	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir(rootdir + "/assets"))))
//	http.Handle("/", http.FileServer(http.Dir(rootdir)))
	http.HandleFunc("/", makeHandler(homeHandler))

	log.Print("Starting webserver. Listening on " + address + ":" + port)
	log.Print("Webroot set to \"" + rootdir + "\".")
	err = http.ListenAndServe(address + ":" + port, nil)
	if err != nil {
		log.Fatal("Couldn't start server. ListenAndServe: ", err)
	}
}

<commit_msg>added query function, where the server returns a sensor' data in JSON<commit_after>package main

import (
//	"net"
	"net/http"
	"log"
//	"io/ioutil"
	"flag"
	"os"
	"path/filepath"
	"regexp"
	"fmt"
//	"reflect"
	"strconv"
	"time"
//	"strings"
	"html/template"
	"encoding/json"
)

var (
	rootdir string
	port string
	address string
	verbose bool
)

var (
	d Query
)

var templates *template.Template

func init() {
	flag.StringVar(&rootdir, "root", "current directory", "webroot directory")
	flag.StringVar(&rootdir, "d", "current directory", "webroot directory" + " (shorthand)")
	flag.StringVar(&port,"port", "8080", "listen port")
	flag.StringVar(&port,"p", "8080", "listen port" + " (shorthand)")
	flag.StringVar(&address, "address", "*", "listen address")
	flag.StringVar(&address, "l", "*", "listen address" + " (shorthand)")
	flag.BoolVar(&verbose, "verbose", false, "be verbose")
	flag.BoolVar(&verbose, "v", false, "be verbose" + " (shorthand)")
}

func debug(s string) {
	if verbose {
		log.Print(s)
	}
}

func debugln(v ...interface{}) {
	if verbose {
		log.Println(v ...)
	}
}

var validLog = regexp.MustCompile("^/log/([a-zA-Z0-9-]+)/([0-9]+[.]{0,1}[0-9]*)(/([ts])/([0-9]+))?/?$")
var validQuery = regexp.MustCompile("^/q/([a-zA-Z0-9-]+)/?$")
var validURLs = regexp.MustCompile("^/")

func logHandler(w http.ResponseWriter, r *http.Request) {
	m := validLog.FindStringSubmatch(r.URL.Path)
	if len(m) == 0 {
		http.Error(w, "Sensor not found", http.StatusNotFound)
		return
	}
	debug("Sensor " + m[1] + " sent value " + m[2])
	//if ! d.Exists(m[1]) {
	//	d.Add(m[1])
	//}
	v, _ := strconv.ParseFloat(m[2], 64)
	if m[4] != "" {
		t, _ := strconv.ParseInt(m[5], 10, 64)
		if m[4] == "t" {
			d.StoreT(m[1], v, time.Unix(t, 0))
		} else {
			d.StoreT(m[1], v, time.Unix(time.Now().Unix() - t, 0))
		}
	} else {
		d.Store(m[1], v)
	}
	debugln("Sensor " + m[1] + " now contains:", d.Load(m[1]))
	fmt.Fprintf(w, "ok")
}

func queryHandler(w http.ResponseWriter, r *http.Request) {
	m := validQuery.FindStringSubmatch(r.URL.Path)
        if len(m) == 0 {
                http.Error(w, "Sensor not found", http.StatusNotFound)
                return
        }
	if ! d.Exists(m[1]) {
		http.Error(w, "Sensor not found", http.StatusNotFound)
                return
        }
	debugln("Query for sensor " + m[1])
	a, _ := json.Marshal(d.Load(m[1]))
	fmt.Fprintf(w, string(a))
}

type HomePage struct {
	SensorList template.HTML
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	var sl string
	for _, s := range d.List() {
		sl += `

                   <a href="view/` + s + `">` + s + `

`
	}
	templates = template.Must(template.ParseFiles(rootdir + "/templates/home.html")) // Remove when finish frontend
	err := templates.ExecuteTemplate(w, "home.html", HomePage{template.HTML(sl)})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func makeHandler(fn func (http.ResponseWriter, *http.Request)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		m := validURLs.FindStringSubmatch(r.URL.Path)
		if m == nil {
			http.NotFound(w, r)
			return
		}
		fn(w, r)
	}
}

func main() {
	flag.Parse()
	var err error
	if rootdir == "current directory" {
		rootdir, err =  filepath.Abs(filepath.Dir(os.Args[0]))
	} else {
		rootdir, err = filepath.Abs(filepath.Dir(rootdir))
	}
	if err != nil {
		log.Fatal(err)
	}

	if address == "*" {
		address = ""
	}

	t := Database{ make(map[string] sensorlog) }
	d = t
	templates = template.Must(template.ParseFiles(rootdir + "/templates/home.html"))

	http.HandleFunc("/log/", logHandler)
	http.HandleFunc("/q/", queryHandler)
	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir(rootdir + "/assets"))))
//	http.Handle("/", http.FileServer(http.Dir(rootdir)))
	http.HandleFunc("/", makeHandler(homeHandler))

	log.Print("Starting webserver. Listening on " + address + ":" + port)
	log.Print("Webroot set to \"" + rootdir + "\".")
	err = http.ListenAndServe(address + ":" + port, nil)
	if err != nil {
		log.Fatal("Couldn't start server. ListenAndServe: ", err)
	}
}

<|endoftext|>


<commit_before>package cc1100

import (
	"bytes"
	"fmt"

	"github.com/ecc1/gpio"
	"github.com/ecc1/radio"
	"github.com/ecc1/spi"
)

const (
	spiSpeed  = 6000000 // Hz
	gpioPin   = 14      // Intel Edison GPIO connected to GDO0
	hwVersion = 0x0014
)

type Radio struct {
	device       *spi.Device
	interruptPin gpio.InputPin

	radioStarted       bool
	receiveBuffer      bytes.Buffer
	transmittedPackets chan radio.Packet
	receivedPackets    chan radio.Packet
	interrupt          chan struct{}
	stats              radio.Statistics
}

func Open() (*Radio, error) {
	dev, err := spi.Open(spiSpeed)
	if err != nil {
		return nil, err
	}
	err = dev.SetMaxSpeed(spiSpeed)
	if err != nil {
		return nil, err
	}
	pin, err := gpio.Input(gpioPin, "both", false)
	if err != nil {
		return nil, err
	}
	r := &Radio{
		device:             dev,
		interruptPin:       pin,
		transmittedPackets: make(chan radio.Packet, 100),
		receivedPackets:    make(chan radio.Packet, 10),
		interrupt:          make(chan struct{}, 10),
	}
	v, err := r.Version()
	if err == nil && v != hwVersion {
		err = fmt.Errorf("unexpected hardware version (%04X instead of %04X)", v, hwVersion)
	}
	return r, err
}

func (r *Radio) Init(frequency uint32) error {
	err := r.Reset()
	if err != nil {
		return err
	}
	err = r.InitRF(frequency)
	if err != nil {
		return err
	}
	r.Start()
	return nil
}

func (r *Radio) Statistics() radio.Statistics {
	return r.stats
}
<commit_msg>Don't use buffered channel for interrupts<commit_after>package cc1100

import (
	"bytes"
	"fmt"

	"github.com/ecc1/gpio"
	"github.com/ecc1/radio"
	"github.com/ecc1/spi"
)

const (
	spiSpeed  = 6000000 // Hz
	gpioPin   = 14      // Intel Edison GPIO connected to GDO0
	hwVersion = 0x0014
)

type Radio struct {
	device       *spi.Device
	interruptPin gpio.InputPin

	radioStarted       bool
	receiveBuffer      bytes.Buffer
	transmittedPackets chan radio.Packet
	receivedPackets    chan radio.Packet
	interrupt          chan struct{}
	stats              radio.Statistics
}

func Open() (*Radio, error) {
	dev, err := spi.Open(spiSpeed)
	if err != nil {
		return nil, err
	}
	err = dev.SetMaxSpeed(spiSpeed)
	if err != nil {
		return nil, err
	}
	pin, err := gpio.Input(gpioPin, "both", false)
	if err != nil {
		return nil, err
	}
	r := &Radio{
		device:             dev,
		interruptPin:       pin,
		transmittedPackets: make(chan radio.Packet, 100),
		receivedPackets:    make(chan radio.Packet, 100),
		interrupt:          make(chan struct{}),
	}
	v, err := r.Version()
	if err == nil && v != hwVersion {
		err = fmt.Errorf("unexpected hardware version (%04X instead of %04X)", v, hwVersion)
	}
	return r, err
}

func (r *Radio) Init(frequency uint32) error {
	err := r.Reset()
	if err != nil {
		return err
	}
	err = r.InitRF(frequency)
	if err != nil {
		return err
	}
	r.Start()
	return nil
}

func (r *Radio) Statistics() radio.Statistics {
	return r.stats
}
<|endoftext|>


<commit_before>package jwalker

import (
	"encoding/json"
	"fmt"
	"strconv"
)

// W ...
type W struct {
	obj      interface{}
	location string
	failure  string
}

// New ...
func New(b []byte) (*W, error) {
	w := W{}
	err := json.Unmarshal(b, &w.obj)
	return &w, err
}

// String
func (w *W) String() string {
	return fmt.Sprintf("%v", w.obj)
}

// Ok return true if the instance is not invalid
func (w *W) Ok() bool {
	return w.failure == ""
}

// Location returns the current location
func (w *W) Location() string {
	return w.location
}

// Failure returns the current failure
func (w *W) Failure() string {
	return w.failure
}

// Trace returns a string with the current location and current failure (if any)
func (w *W) Trace() string {
	if w.failure == "" {
		return w.location + " (no failures)"
	}
	return "[location] => " + w.location + " [failure] => " + w.failure
}

// Key descends into the supplied key and returns a new W object
// constructed with the descended value.
func (w *W) Key(key string) *W {

	if !w.Ok() {
		return w
	}

	// Verify Map
	mapped, ok := w.obj.(map[string]interface{})
	if !ok {
		w.failure = "key: " + key + " (not a map)"
		return w
	}

	// Verify Key
	value, ok := mapped[key]
	if !ok {
		w.failure = "key: " + key + " (key does not exist)"
		return w
	}

	child := &W{obj: value}

	// Append Location
	child.location = w.location
	child.appendLocation("key: " + key)
	return child
}

// Keys returns a slice of strings containing all keys if the instance is a map
// If the instance is not a map, it returns an empty slice
func (w *W) Keys() []string {

	// Verify Map
	mapped, ok := w.obj.(map[string]interface{})
	if !ok {
		return []string{}
	}

	// Extract Keys
	result := make([]string, 0, len(mapped))
	for key := range mapped {
		result = append(result, key)
	}

	return result
}

// At descends into the supplied array index and returns a new W object
// constructed with the descended value.
func (w *W) At(i int) *W {

	if !w.Ok() {
		return w
	}

	// Verify Array
	array, ok := w.obj.([]interface{})
	if !ok {
		w.failure = fmt.Sprintf("at: %d (not an array)", i)
		return w
	}

	// Verify At
	if i < 0 || i >= len(array) {
		w.failure = fmt.Sprintf("at: %d (out of range, size=%d)", i, len(array))
		return w
	}

	value := array[i]
	child := &W{obj: value}

	// Append Location
	child.location = w.location
	child.appendLocation("at: " + strconv.Itoa(i))
	return child
}

// Len returns the length of the instance's object array
// If the object is not an array then it returns 0
func (w *W) Len() int {

	// Verify Array (Return Zero If Not Array)
	array, ok := w.obj.([]interface{})
	if !ok {
		return 0
	}

	return len(array)
}

// S returns a string if the object is a string
func (w *W) S() (string, bool) {
	if s, ok := w.obj.(string); ok {
		return s, true
	}
	return "", false
}

// I returns a string if the object is a string
func (w *W) I() (int, bool) {
	if f, ok := w.F64(); ok {
		return int(f), true
	}
	return 0, false
}

// U32 returns a uint32 if the object is a string
func (w *W) U32() (uint32, bool) {
	if f, ok := w.F64(); ok {
		return uint32(f), true
	}
	return 0, false
}

// F64 returns the float64 value of the instance's object data
func (w *W) F64() (float64, bool) {
	if f, ok := w.obj.(float64); ok {
		return f, true
	}
	return 0, false
}

// KeyS returns the string for the given key
func (w *W) KeyS(key string) (string, bool) {
	child := w.Key(key)
	if !child.Ok() {
		return "", false
	}

	v, ok := child.S()
	if !ok {
		return "", false
	}

	return v, true
}

// KeyF64 returns the float64 for the given key
func (w *W) KeyF64(key string) (float64, bool) {
	child := w.Key(key)
	if !child.Ok() {
		return 0, false
	}

	v, ok := child.F64()
	if !ok {
		return 0, false
	}

	return v, true
}

// KeyI returns the int value for the given key
func (w *W) KeyI(key string) (int, bool) {
	child := w.Key(key)
	if !child.Ok() {
		return 0, false
	}

	v, ok := child.I()
	if !ok {
		return 0, false
	}

	return v, true
}

// KeyU32 returns the uint32 value for the given key
func (w *W) KeyU32(key string) (uint32, bool) {
	child := w.Key(key)
	if !child.Ok() {
		return 0, false
	}

	v, ok := child.U32()
	if !ok {
		return 0, false
	}

	return v, true
}

// AtS returns the string at the given index
func (w *W) AtS(i int) (string, bool) {
	child := w.At(i)
	if !child.Ok() {
		return "", false
	}

	v, ok := child.S()
	if !ok {
		return "", false
	}

	return v, true
}

// AppendLocation ...
func (w *W) appendLocation(l string) {

	// Separator (If Non-Empty)
	if w.location != "" {
		w.location += " | "
	}

	w.location += l
}
<commit_msg>Fixed comments<commit_after>package jwalker

import (
	"encoding/json"
	"fmt"
	"strconv"
)

// W ...
type W struct {
	obj      interface{}
	location string
	failure  string
}

// New ...
func New(b []byte) (*W, error) {
	w := W{}
	err := json.Unmarshal(b, &w.obj)
	return &w, err
}

// String
func (w *W) String() string {
	return fmt.Sprintf("%v", w.obj)
}

// Ok return true if the instance is not invalid
func (w *W) Ok() bool {
	return w.failure == ""
}

// Location returns the current location
func (w *W) Location() string {
	return w.location
}

// Failure returns the current failure
func (w *W) Failure() string {
	return w.failure
}

// Trace returns a string with the current location and current failure (if any)
func (w *W) Trace() string {
	if w.failure == "" {
		return w.location + " (no failures)"
	}
	return "[location] => " + w.location + " [failure] => " + w.failure
}

// Key descends into the supplied key and returns a new W object
// constructed with the descended value.
func (w *W) Key(key string) *W {

	if !w.Ok() {
		return w
	}

	// Verify Map
	mapped, ok := w.obj.(map[string]interface{})
	if !ok {
		w.failure = "key: " + key + " (not a map)"
		return w
	}

	// Verify Key
	value, ok := mapped[key]
	if !ok {
		w.failure = "key: " + key + " (key does not exist)"
		return w
	}

	child := &W{obj: value}

	// Append Location
	child.location = w.location
	child.appendLocation("key: " + key)
	return child
}

// Keys returns a slice of strings containing all keys if the instance is a map
// If the instance is not a map, it returns an empty slice
func (w *W) Keys() []string {

	// Verify Map
	mapped, ok := w.obj.(map[string]interface{})
	if !ok {
		return []string{}
	}

	// Extract Keys
	result := make([]string, 0, len(mapped))
	for key := range mapped {
		result = append(result, key)
	}

	return result
}

// At descends into the supplied array index and returns a new W object
// constructed with the descended value.
func (w *W) At(i int) *W {

	if !w.Ok() {
		return w
	}

	// Verify Array
	array, ok := w.obj.([]interface{})
	if !ok {
		w.failure = fmt.Sprintf("at: %d (not an array)", i)
		return w
	}

	// Verify At
	if i < 0 || i >= len(array) {
		w.failure = fmt.Sprintf("at: %d (out of range, size=%d)", i, len(array))
		return w
	}

	value := array[i]
	child := &W{obj: value}

	// Append Location
	child.location = w.location
	child.appendLocation("at: " + strconv.Itoa(i))
	return child
}

// Len returns the length of the instance's object array
// If the object is not an array then it returns 0
func (w *W) Len() int {

	// Verify Array (Return Zero If Not Array)
	array, ok := w.obj.([]interface{})
	if !ok {
		return 0
	}

	return len(array)
}

// S returns a string if the object is a string
func (w *W) S() (string, bool) {
	if s, ok := w.obj.(string); ok {
		return s, true
	}
	return "", false
}

// I returns an integer if the object is an integer
func (w *W) I() (int, bool) {
	if f, ok := w.F64(); ok {
		return int(f), true
	}
	return 0, false
}

// U32 returns a uint32 if the object is a string
func (w *W) U32() (uint32, bool) {
	if f, ok := w.F64(); ok {
		return uint32(f), true
	}
	return 0, false
}

// F64 returns the float64 value of the instance's object data
func (w *W) F64() (float64, bool) {
	if f, ok := w.obj.(float64); ok {
		return f, true
	}
	return 0, false
}

// KeyS returns the string value for the given key
func (w *W) KeyS(key string) (string, bool) {
	child := w.Key(key)
	if !child.Ok() {
		return "", false
	}

	v, ok := child.S()
	if !ok {
		return "", false
	}

	return v, true
}

// KeyF64 returns the float64 value for the given key
func (w *W) KeyF64(key string) (float64, bool) {
	child := w.Key(key)
	if !child.Ok() {
		return 0, false
	}

	v, ok := child.F64()
	if !ok {
		return 0, false
	}

	return v, true
}

// KeyI returns the int value for the given key
func (w *W) KeyI(key string) (int, bool) {
	child := w.Key(key)
	if !child.Ok() {
		return 0, false
	}

	v, ok := child.I()
	if !ok {
		return 0, false
	}

	return v, true
}

// KeyU32 returns the uint32 value for the given key
func (w *W) KeyU32(key string) (uint32, bool) {
	child := w.Key(key)
	if !child.Ok() {
		return 0, false
	}

	v, ok := child.U32()
	if !ok {
		return 0, false
	}

	return v, true
}

// AtS returns the string at the given index
func (w *W) AtS(i int) (string, bool) {
	child := w.At(i)
	if !child.Ok() {
		return "", false
	}

	v, ok := child.S()
	if !ok {
		return "", false
	}

	return v, true
}

// AppendLocation ...
func (w *W) appendLocation(l string) {

	// Separator (If Non-Empty)
	if w.location != "" {
		w.location += " | "
	}

	w.location += l
}
<|endoftext|>


<commit_before>package network

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os/exec"
	"regexp"
)

// DelVeth deletes a virtual ethernet interface.
var DelVeth = func(endpointID string) error {
	_, name := VethPairNames(endpointID)
	if err := linkDelete("", name); err != nil {
		return err
	}
	return nil
}

// AddVeth creates a virtual ethernet interface.
var AddVeth = func(endpointID string) (string, error) {
	tmpPeer, name := VethPairNames(endpointID)

	// Create veth pair
	err := ipExec("", "link add %s type veth peer name %s", name, tmpPeer)
	if err != nil {
		return "", fmt.Errorf("error adding veth %s with peer %s: %v",
			name, tmpPeer, err)
	}

	// Set the host side link status to up
	if err = ipExec("", "link set %s up", name); err != nil {
		return "", fmt.Errorf("error bringing veth %s up: %v", name, err)
	}

	if err = ipExec("", "link set dev %s mtu %d", tmpPeer, innerMTU); err != nil {
		return "", fmt.Errorf("error setting peer %s MTU: %v", tmpPeer, err)
	}

	return tmpPeer, nil
}

// LinkExists reports whether or not the virtual link exists.
var LinkExists = func(namespace, name string) (bool, error) {
	cmd := fmt.Sprintf("ip link show %s", name)
	if namespace != "" {
		cmd = fmt.Sprintf("ip netns exec %s %s", namespace, cmd)
	}
	stdout, _, err := shVerbose(cmd)
	// If err is of type *ExitError then that means it has a non-zero exit
	// code which we are okay with
	if _, ok := err.(*exec.ExitError); !ok && err != nil {
		err = fmt.Errorf("error checking if link %s exists in %s: %s",
			name, namespaceName(namespace), err)
		return false, err
	}
	if string(stdout) == "" {
		return false, nil
	}
	return true, nil
}

// Interprets the empty string as the "root" namespace
func linkDelete(namespace, name string) error {
	if err := ipExec(namespace, "link delete %s", name); err != nil {
		return fmt.Errorf("error deleting link %s in %s: %s",
			name, namespaceName(namespace), err)
	}
	return nil
}

// Lists all veths in the root namespace
func listVeths() ([]string, error) {
	var veths []string

	stdout, _, err := ipExecVerbose("", "link show type veth")
	if err != nil {
		return nil, fmt.Errorf("failed to list veths: %s", err)
	}

	scanner := bufio.NewScanner(bytes.NewReader(stdout))
	skipRE := regexp.MustCompile("^\\s+.*")
	vethRE := regexp.MustCompile("^\\d+: (\\w+)@.*")
	for scanner.Scan() {
		line := scanner.Text()
		if skipRE.FindStringIndex(line) != nil {
			// Skip if the line begins with whitespace
			continue
		}
		match := vethRE.FindStringSubmatch(line)
		if match == nil || len(match) != 2 {
			return nil, errors.New("list of veths is not parsing properly")
		}
		veths = append(veths, match[1])
	}
	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("scanner error while getting veths: %s", err)
	}
	return veths, nil
}

func listIP(namespace, dev string) ([]string, error) {
	var ips []string

	stdout, _, err := ipExecVerbose(namespace, "addr list dev %s", dev)
	if err != nil {
		return nil, fmt.Errorf("failed to list ip addresses in %s: %s",
			namespaceName(namespace), err)
	}

	re, _ := regexp.Compile(`(?:inet|inet6) (\S+)`)
	for _, v := range re.FindAllSubmatch(stdout, -1) {
		ips = append(ips, string(v[1]))
	}

	return ips, nil
}

func addIP(namespace, ip, dev string) error {
	err := ipExec(namespace, "addr add %s dev %s", ip, dev)
	if err != nil {
		return fmt.Errorf("failed to add ip %s to %s in %s: %s",
			ip, dev, namespaceName(namespace), err)
	}
	return nil
}

func delIP(namespace, ip, dev string) error {
	err := ipExec(namespace, "addr del %s dev %s", ip, dev)
	if err != nil {
		return fmt.Errorf("failed to delete ip %s in %s: %s",
			ip, namespaceName(namespace), err)
	}
	return nil
}
<commit_msg>network: Remove dead listVeths() function<commit_after>package network

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

// DelVeth deletes a virtual ethernet interface.
var DelVeth = func(endpointID string) error {
	_, name := VethPairNames(endpointID)
	if err := linkDelete("", name); err != nil {
		return err
	}
	return nil
}

// AddVeth creates a virtual ethernet interface.
var AddVeth = func(endpointID string) (string, error) {
	tmpPeer, name := VethPairNames(endpointID)

	// Create veth pair
	err := ipExec("", "link add %s type veth peer name %s", name, tmpPeer)
	if err != nil {
		return "", fmt.Errorf("error adding veth %s with peer %s: %v",
			name, tmpPeer, err)
	}

	// Set the host side link status to up
	if err = ipExec("", "link set %s up", name); err != nil {
		return "", fmt.Errorf("error bringing veth %s up: %v", name, err)
	}

	if err = ipExec("", "link set dev %s mtu %d", tmpPeer, innerMTU); err != nil {
		return "", fmt.Errorf("error setting peer %s MTU: %v", tmpPeer, err)
	}

	return tmpPeer, nil
}

// LinkExists reports whether or not the virtual link exists.
var LinkExists = func(namespace, name string) (bool, error) {
	cmd := fmt.Sprintf("ip link show %s", name)
	if namespace != "" {
		cmd = fmt.Sprintf("ip netns exec %s %s", namespace, cmd)
	}
	stdout, _, err := shVerbose(cmd)
	// If err is of type *ExitError then that means it has a non-zero exit
	// code which we are okay with
	if _, ok := err.(*exec.ExitError); !ok && err != nil {
		err = fmt.Errorf("error checking if link %s exists in %s: %s",
			name, namespaceName(namespace), err)
		return false, err
	}
	if string(stdout) == "" {
		return false, nil
	}
	return true, nil
}

// Interprets the empty string as the "root" namespace
func linkDelete(namespace, name string) error {
	if err := ipExec(namespace, "link delete %s", name); err != nil {
		return fmt.Errorf("error deleting link %s in %s: %s",
			name, namespaceName(namespace), err)
	}
	return nil
}

func listIP(namespace, dev string) ([]string, error) {
	var ips []string

	stdout, _, err := ipExecVerbose(namespace, "addr list dev %s", dev)
	if err != nil {
		return nil, fmt.Errorf("failed to list ip addresses in %s: %s",
			namespaceName(namespace), err)
	}

	re, _ := regexp.Compile(`(?:inet|inet6) (\S+)`)
	for _, v := range re.FindAllSubmatch(stdout, -1) {
		ips = append(ips, string(v[1]))
	}

	return ips, nil
}

func addIP(namespace, ip, dev string) error {
	err := ipExec(namespace, "addr add %s dev %s", ip, dev)
	if err != nil {
		return fmt.Errorf("failed to add ip %s to %s in %s: %s",
			ip, dev, namespaceName(namespace), err)
	}
	return nil
}

func delIP(namespace, ip, dev string) error {
	err := ipExec(namespace, "addr del %s dev %s", ip, dev)
	if err != nil {
		return fmt.Errorf("failed to delete ip %s in %s: %s",
			ip, namespaceName(namespace), err)
	}
	return nil
}
<|endoftext|>