<commit_before>package pb

import (
	"fmt"
	"io"
	"math"
	"strings"
	"sync/atomic"
	"time"
)

const (
	// Default refresh rate - 200ms
	DEFAULT_REFRESH_RATE = time.Millisecond * 200
	FORMAT               = "[=>-]"
)

// DEPRECATED
// variables for backward compatibility, from now do not work
// use pb.Format and pb.SetRefreshRate
var (
	DefaultRefreshRate                         = DEFAULT_REFRESH_RATE
	BarStart, BarEnd, Empty, Current, CurrentN string
)

// Create new progress bar object
func New(total int) (pb *ProgressBar) {
	return New64(int64(total))
}

// Create new progress bar object uding int64 as total
func New64(total int64) (pb *ProgressBar) {
	pb = &ProgressBar{
		Total:        total,
		RefreshRate:  DEFAULT_REFRESH_RATE,
		ShowPercent:  true,
		ShowCounters: true,
		ShowBar:      true,
		ShowTimeLeft: true,
	}
	pb.Format(FORMAT)
	return
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

// Callback for custom output
// For example:
// bar.Callback = func(s string) {
//     mySuperPrint(s)
// }
//
type Callback func(out string)

type ProgressBar struct {
	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)

	Total                            int64
	RefreshRate                      time.Duration
	ShowPercent, ShowCounters        bool
	ShowSpeed, ShowTimeLeft, ShowBar bool
	Output                           io.Writer
	Callback                         Callback
	NotPrint                         bool
	Units                            int
	Width                            int
	ForceWidth                       bool

	isFinish  bool
	startTime time.Time

	prefix, postfix string

	BarStart string
	BarEnd   string
	Empty    string
	Current  string
	CurrentN string
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	if pb.Total == 0 {
		pb.ShowBar = false
		pb.ShowTimeLeft = false
		pb.ShowPercent = false
	}
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// Set prefix string
func (pb *ProgressBar) Prefix(prefix string) (bar *ProgressBar) {
	pb.prefix = prefix
	return pb
}

// Set postfix string
func (pb *ProgressBar) Postfix(postfix string) (bar *ProgressBar) {
	pb.postfix = postfix
	return pb
}

// Set custom format for bar
// Example: bar.Format("[=>_]")
func (pb *ProgressBar) Format(format string) (bar *ProgressBar) {
	bar = pb
	formatEntries := strings.Split(format, "")
	if len(formatEntries) != 5 {
		return
	}
	pb.BarStart = formatEntries[0]
	pb.BarEnd = formatEntries[4]
	pb.Empty = formatEntries[3]
	pb.Current = formatEntries[1]
	pb.CurrentN = formatEntries[2]
	return
}

// Set bar refresh rate
func (pb *ProgressBar) SetRefreshRate(rate time.Duration) (bar *ProgressBar) {
	bar = pb
	pb.RefreshRate = rate
	return
}

// Set units
// bar.SetUnits(U_NO) - by default
// bar.SetUnits(U_BYTES) - for Mb, Kb, etc
func (pb *ProgressBar) SetUnits(units int) (bar *ProgressBar) {
	bar = pb
	switch units {
	case U_NO, U_BYTES:
		pb.Units = units
	}
	return
}

// Set width, if width is bigger than terminal width, will be ignored
func (pb *ProgressBar) SetWidth(width int) (bar *ProgressBar) {
	bar = pb
	pb.Width = width
	return
}

// Forze the width
func (pb *ProgressBar) ForzeWidth(width int) (bar *ProgressBar) {
	bar = pb
	pb.Width = width
	pb.ForceWidth = true
	return
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	if !pb.NotPrint {
		fmt.Println()
	}
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(str)
}

// implement io.Writer
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// implement io.Reader
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// Create new proxy reader over bar
func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
	return &Reader{r, pb}
}

func (pb *ProgressBar) write(current int64) {
	width := pb.getWidth()

	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		if pb.Total > 0 {
			countersBox = fmt.Sprintf("%s / %s ", Format(current, pb.Units), Format(pb.Total, pb.Units))
		} else {
			countersBox = Format(current, pb.Units) + " "
		}
	}

	// time left
	if pb.ShowTimeLeft && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		if left > 0 {
			timeLeftBox = left.String()
		}
	}

	// speed
	if pb.ShowSpeed && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		speed := float64(current) / (float64(fromStart) / float64(time.Second))
		speedBox = Format(int64(speed), pb.Units) + "/s "
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+pb.BarStart+pb.BarEnd+percentBox+timeLeftBox+speedBox+pb.prefix+pb.postfix)
		if size > 0 {
			curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
			emptCount := size - curCount
			barBox = pb.BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(pb.Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN
			}

			barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd
		}
	}

	// check len
	out = pb.prefix + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	// and print!
	switch {
	case pb.Output != nil:
		fmt.Fprint(pb.Output, "\r"+out+end)
	case pb.Callback != nil:
		pb.Callback(out + end)
	case !pb.NotPrint:
		fmt.Print("\r" + out + end)
	}
}

func (pb *ProgressBar) getWidth() int {
	if pb.ForceWidth {
		return pb.Width
	}

	width := pb.Width
	termWidth, _ := terminalWidth()
	if width == 0 || termWidth <= width {
		width = termWidth
	}

	return width
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	oc = -1
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<commit_msg>force width fixes<commit_after>package pb

import (
	"fmt"
	"io"
	"math"
	"strings"
	"sync/atomic"
	"time"
)

const (
	// Default refresh rate - 200ms
	DEFAULT_REFRESH_RATE = time.Millisecond * 200
	FORMAT               = "[=>-]"
)

// DEPRECATED
// variables for backward compatibility, from now do not work
// use pb.Format and pb.SetRefreshRate
var (
	DefaultRefreshRate                         = DEFAULT_REFRESH_RATE
	BarStart, BarEnd, Empty, Current, CurrentN string
)

// Create new progress bar object
func New(total int) (pb *ProgressBar) {
	return New64(int64(total))
}

// Create new progress bar object uding int64 as total
func New64(total int64) (pb *ProgressBar) {
	pb = &ProgressBar{
		Total:        total,
		RefreshRate:  DEFAULT_REFRESH_RATE,
		ShowPercent:  true,
		ShowCounters: true,
		ShowBar:      true,
		ShowTimeLeft: true,
	}
	pb.Format(FORMAT)
	return
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

// Callback for custom output
// For example:
// bar.Callback = func(s string) {
//     mySuperPrint(s)
// }
//
type Callback func(out string)

type ProgressBar struct {
	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)

	Total                            int64
	RefreshRate                      time.Duration
	ShowPercent, ShowCounters        bool
	ShowSpeed, ShowTimeLeft, ShowBar bool
	Output                           io.Writer
	Callback                         Callback
	NotPrint                         bool
	Units                            int
	Width                            int
	ForceWidth                       bool

	isFinish  bool
	startTime time.Time

	prefix, postfix string

	BarStart string
	BarEnd   string
	Empty    string
	Current  string
	CurrentN string
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	if pb.Total == 0 {
		pb.ShowBar = false
		pb.ShowTimeLeft = false
		pb.ShowPercent = false
	}
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// Set prefix string
func (pb *ProgressBar) Prefix(prefix string) (bar *ProgressBar) {
	pb.prefix = prefix
	return pb
}

// Set postfix string
func (pb *ProgressBar) Postfix(postfix string) (bar *ProgressBar) {
	pb.postfix = postfix
	return pb
}

// Set custom format for bar
// Example: bar.Format("[=>_]")
func (pb *ProgressBar) Format(format string) (bar *ProgressBar) {
	bar = pb
	formatEntries := strings.Split(format, "")
	if len(formatEntries) != 5 {
		return
	}
	pb.BarStart = formatEntries[0]
	pb.BarEnd = formatEntries[4]
	pb.Empty = formatEntries[3]
	pb.Current = formatEntries[1]
	pb.CurrentN = formatEntries[2]
	return
}

// Set bar refresh rate
func (pb *ProgressBar) SetRefreshRate(rate time.Duration) (bar *ProgressBar) {
	bar = pb
	pb.RefreshRate = rate
	return
}

// Set units
// bar.SetUnits(U_NO) - by default
// bar.SetUnits(U_BYTES) - for Mb, Kb, etc
func (pb *ProgressBar) SetUnits(units int) (bar *ProgressBar) {
	bar = pb
	switch units {
	case U_NO, U_BYTES:
		pb.Units = units
	}
	return
}

// Set width, if width is bigger than terminal width, will be ignored
func (pb *ProgressBar) SetWidth(width int) (bar *ProgressBar) {
	bar = pb
	pb.Width = width
	pb.ForceWidth = false
	return
}

// Force the width
func (pb *ProgressBar) ForceWidth(width int) (bar *ProgressBar) {
	bar = pb
	pb.Width = width
	pb.ForceWidth = true
	return
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	if !pb.NotPrint {
		fmt.Println()
	}
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(str)
}

// implement io.Writer
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// implement io.Reader
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// Create new proxy reader over bar
func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
	return &Reader{r, pb}
}

func (pb *ProgressBar) write(current int64) {
	width := pb.getWidth()

	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		if pb.Total > 0 {
			countersBox = fmt.Sprintf("%s / %s ", Format(current, pb.Units), Format(pb.Total, pb.Units))
		} else {
			countersBox = Format(current, pb.Units) + " "
		}
	}

	// time left
	if pb.ShowTimeLeft && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		if left > 0 {
			timeLeftBox = left.String()
		}
	}

	// speed
	if pb.ShowSpeed && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		speed := float64(current) / (float64(fromStart) / float64(time.Second))
		speedBox = Format(int64(speed), pb.Units) + "/s "
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+pb.BarStart+pb.BarEnd+percentBox+timeLeftBox+speedBox+pb.prefix+pb.postfix)
		if size > 0 {
			curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
			emptCount := size - curCount
			barBox = pb.BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(pb.Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN
			}

			barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd
		}
	}

	// check len
	out = pb.prefix + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	// and print!
	switch {
	case pb.Output != nil:
		fmt.Fprint(pb.Output, "\r"+out+end)
	case pb.Callback != nil:
		pb.Callback(out + end)
	case !pb.NotPrint:
		fmt.Print("\r" + out + end)
	}
}

func (pb *ProgressBar) getWidth() int {
	if pb.ForceWidth {
		return pb.Width
	}

	width := pb.Width
	termWidth, _ := terminalWidth()
	if width == 0 || termWidth <= width {
		width = termWidth
	}

	return width
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	oc = -1
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"sync"
	"time"

	"github.com/nictuku/dht"
	nn "github.com/op/go-nanomsg"
)

type BusMessage struct {
	From    string
	To      string
	Seq int64
	Payload []string
}

func NewBusMessage(data []byte, err error) (*BusMessage, error) {
	if err != nil {
		return nil, err
	}

	rv := &BusMessage{}
	if err = json.Unmarshal(data, rv); err != nil {
		return nil, err
	}
	return rv, nil
}

func (b *BusMessage) Bytes() []byte {
	m, err := json.Marshal(b)
	if err != nil {
		log.Fatalf(`can't marshall bus message to json: %s`, err)
	}
	return m
}

type Friend struct {
	name     string
	msg      *BusMessage
	lastSeen time.Time
	mtx      *sync.Mutex
}

func NewFriend(name string) *Friend {
	return &Friend{name: name, mtx: &sync.Mutex{}, lastSeen: time.Now()}
}

func (f *Friend) String() string {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg == nil {
		return fmt.Sprintf(`Name: %s, no message, last seen: %s`, f.name, f.lastSeen)
	}

	return fmt.Sprintf("Name: %s, last message: %s (ID: %d), last seen: %s ago", f.name, f.msg.Payload, f.msg.Seq, time.Now().Sub(f.lastSeen))
}

func (f *Friend) HandleMessage(msg *BusMessage) {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg != nil && f.msg.Seq >= msg.Seq {
		/* We've already seen this message */
		log.Printf(`ignoring message from %s with Seq=%d (already got %d)`, f.name, msg.Seq, f.msg.Seq)
		return
	}

	f.msg = msg
	f.lastSeen = time.Now()
}

type PeerManager struct {
	d          *dht.DHT
	bus        *nn.BusSocket
	nick       string
	friends    map[string]*Friend
	oldfriends map[string]*Friend
	venue      string
	sequence   int64
	mtx        *sync.RWMutex
}

func NewPeerManager() *PeerManager {
	conf := dht.NewConfig()
	conf.Port = 55000
	conf.CleanupPeriod = 3 * time.Second

	pm := PeerManager{}

	var err error
	pm.bus, err = nn.NewBusSocket()
	if err != nil {
		log.Fatalf(`can't create BUS socket: %s`, err)
	}

	if pm.d, err = dht.New(conf); err != nil {
		log.Fatalf(`can't create DHT: %s`, err)
	}

	sum := sha1.Sum([]byte("LetsMeetHere"))
	pm.venue = hex.EncodeToString(sum[:])

	buf := make([]byte, 4)
	rand.Read(buf)
	pm.nick = hex.EncodeToString(buf)

	log.Printf(`My nickname is %s`, pm.nick)
	log.Printf(`I will meet my friends at %s`, pm.venue)

	pm.friends = make(map[string]*Friend)
	pm.oldfriends = make(map[string]*Friend)

	pm.mtx = &sync.RWMutex{}

	return &pm
}

func (pm *PeerManager) String() string {
	pm.mtx.RLock()
	defer pm.mtx.RUnlock()

	s := []string{
		fmt.Sprintf("DHT: Port: %d", pm.d.Port()),
		fmt.Sprintf("\r\nI am %s", pm.nick),
		fmt.Sprintf("I have %d friend(s)", len(pm.friends)),
		fmt.Sprintf("We're meeting at '%s'", pm.venue),
		"\r\nThese are my friends:\r\n",
	}

	for _, f := range pm.friends {
		s = append(s, f.String())
	}

	s = append(s, "\r\nI haven't heard from these guys in a while:\r\n")
	for _, f := range pm.oldfriends {
		s = append(s, f.String())
	}

	return strings.Join(s, "\r\n")
}

func (pm *PeerManager) Publish(dst string, payload []string) error {
	pm.mtx.Lock()
	pm.sequence++
	m := &BusMessage{From: pm.nick, To: dst, Seq: pm.sequence, Payload: payload}
	pm.mtx.Unlock()

	_, err := pm.bus.Send(m.Bytes(), 0)
	return err
}

func (pm *PeerManager) Loop() {
	ih, err := dht.DecodeInfoHash(pm.venue)
	if err != nil {
		log.Printf(`can't decode infohash: %s`, err)
		return
	}

	if err := pm.d.Start(); err != nil {
		log.Printf(`can't start DHT: %s`, err)
		return
	}

	log.Printf(`DHT bound to port %d`, pm.d.Port())

	ep, err := pm.bus.Bind(fmt.Sprintf("tcp://*:%d", pm.d.Port()))
	if err != nil {
		log.Fatalf(`can't bind BUS socket: %s`, err)
	}
	log.Printf(`BUS endpoint: %s`, ep)

	go pm.drainPeers()

	go func() {
		for {
			time.Sleep(2 * time.Second)
			pm.mtx.Lock()
			for name, f := range pm.friends {
				f.mtx.Lock()
				if f.lastSeen.Add(10 * time.Second).Before(time.Now()) {
					log.Printf(`haven't heard from %s in a while`, name)
					pm.oldfriends[name] = f
					delete(pm.friends, name)
				}
				f.mtx.Unlock()
			}
			pm.mtx.Unlock()
		}
	}()

	go func() {
		for {
			/* Receive message */
			m, err := NewBusMessage(pm.bus.Recv(0))
			if err != nil {
				log.Printf(`can't receive message from bus: %s`, err)
				continue
			}

			/* Ignore messages from ourselves */
			if m.From == pm.nick {
				continue
			}

			/* Ignore messages not to 'everyone' or us */
			if m.To != pm.nick && m.To != "*" {
				continue
			}

			log.Printf(`tgt: %s, src: %s, msg: %v`, m.To, m.From, m.Payload)

			pm.mtx.Lock()
			f, ok := pm.friends[m.From]
			if !ok {
				f = NewFriend(m.From)
				pm.friends[m.From] = f
			}
			pm.mtx.Unlock()

			f.HandleMessage(m)

			if !ok {
				log.Printf(`%s is a new friend!`, m.From)
				pm.Publish(m.From, []string{"hello friend :)"})
			}
		}
	}()

	go func() {
		i := 0
		for {
			pm.Publish("*", []string{"I'm alive", fmt.Sprintf("%d", i)})
			i++
			time.Sleep(5 * time.Second)
		}
	}()

	for {
		pm.d.PeersRequest(string(ih), true)
		time.Sleep(5 * time.Second)
	}
}

func (pm *PeerManager) drainPeers() {
	log.Printf(`draining DHT`)
	seen := make(map[string]struct{})

	for r := range pm.d.PeersRequestResults {
		for _, peers := range r {
			for _, x := range peers {
				addr := dht.DecodePeerAddress(x)
				if _, ok := seen[addr]; !ok {
					pm.connectToPeer(addr)
				}
				seen[addr] = struct{}{}
			}
		}
	}
}

func (pm *PeerManager) connectToPeer(addr string) {
	if _, err := pm.bus.Connect(fmt.Sprintf("tcp://%s", addr)); err != nil {
		log.Printf(`can't connect SUB to %s: %s`, addr, err)
	}
}
<commit_msg>Less spammy logging<commit_after>package main

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"sync"
	"time"

	"github.com/nictuku/dht"
	nn "github.com/op/go-nanomsg"
)

type BusMessage struct {
	From    string
	To      string
	Seq int64
	Payload []string
}

func NewBusMessage(data []byte, err error) (*BusMessage, error) {
	if err != nil {
		return nil, err
	}

	rv := &BusMessage{}
	if err = json.Unmarshal(data, rv); err != nil {
		return nil, err
	}
	return rv, nil
}

func (b *BusMessage) Bytes() []byte {
	m, err := json.Marshal(b)
	if err != nil {
		log.Fatalf(`can't marshall bus message to json: %s`, err)
	}
	return m
}

type Friend struct {
	name     string
	msg      *BusMessage
	lastSeen time.Time
	mtx      *sync.Mutex
}

func NewFriend(name string) *Friend {
	return &Friend{name: name, mtx: &sync.Mutex{}, lastSeen: time.Now()}
}

func (f *Friend) String() string {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg == nil {
		return fmt.Sprintf(`Name: %s, no message, last seen: %s`, f.name, f.lastSeen)
	}

	return fmt.Sprintf("Name: %s, last message: %s (ID: %d), last seen: %s ago", f.name, f.msg.Payload, f.msg.Seq, time.Now().Sub(f.lastSeen))
}

func (f *Friend) HandleMessage(m *BusMessage) {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg != nil && f.msg.Seq >= m.Seq {
		/* We've already seen this message */
		return
	}

	f.msg = m
	f.lastSeen = time.Now()

	log.Printf(`tgt: %s, src: %s, msg: %v`, m.To, m.From, m.Payload)
}

type PeerManager struct {
	d          *dht.DHT
	bus        *nn.BusSocket
	nick       string
	friends    map[string]*Friend
	oldfriends map[string]*Friend
	venue      string
	sequence   int64
	mtx        *sync.RWMutex
}

func NewPeerManager() *PeerManager {
	conf := dht.NewConfig()
	conf.Port = 55000
	conf.CleanupPeriod = 3 * time.Second

	pm := PeerManager{}

	var err error
	pm.bus, err = nn.NewBusSocket()
	if err != nil {
		log.Fatalf(`can't create BUS socket: %s`, err)
	}

	if pm.d, err = dht.New(conf); err != nil {
		log.Fatalf(`can't create DHT: %s`, err)
	}

	sum := sha1.Sum([]byte("LetsMeetHere"))
	pm.venue = hex.EncodeToString(sum[:])

	buf := make([]byte, 4)
	rand.Read(buf)
	pm.nick = hex.EncodeToString(buf)

	log.Printf(`My nickname is %s`, pm.nick)
	log.Printf(`I will meet my friends at %s`, pm.venue)

	pm.friends = make(map[string]*Friend)
	pm.oldfriends = make(map[string]*Friend)

	pm.mtx = &sync.RWMutex{}

	return &pm
}

func (pm *PeerManager) String() string {
	pm.mtx.RLock()
	defer pm.mtx.RUnlock()

	s := []string{
		fmt.Sprintf("DHT: Port: %d", pm.d.Port()),
		fmt.Sprintf("\r\nI am %s", pm.nick),
		fmt.Sprintf("I have %d friend(s)", len(pm.friends)),
		fmt.Sprintf("We're meeting at '%s'", pm.venue),
		"\r\nThese are my friends:\r\n",
	}

	for _, f := range pm.friends {
		s = append(s, f.String())
	}

	s = append(s, "\r\nI haven't heard from these guys in a while:\r\n")
	for _, f := range pm.oldfriends {
		s = append(s, f.String())
	}

	return strings.Join(s, "\r\n")
}

func (pm *PeerManager) Publish(dst string, payload []string) error {
	pm.mtx.Lock()
	pm.sequence++
	m := &BusMessage{From: pm.nick, To: dst, Seq: pm.sequence, Payload: payload}
	pm.mtx.Unlock()

	_, err := pm.bus.Send(m.Bytes(), 0)
	return err
}

func (pm *PeerManager) Loop() {
	ih, err := dht.DecodeInfoHash(pm.venue)
	if err != nil {
		log.Printf(`can't decode infohash: %s`, err)
		return
	}

	if err := pm.d.Start(); err != nil {
		log.Printf(`can't start DHT: %s`, err)
		return
	}

	log.Printf(`DHT bound to port %d`, pm.d.Port())

	ep, err := pm.bus.Bind(fmt.Sprintf("tcp://*:%d", pm.d.Port()))
	if err != nil {
		log.Fatalf(`can't bind BUS socket: %s`, err)
	}
	log.Printf(`BUS endpoint: %s`, ep)

	go pm.drainPeers()

	go func() {
		for {
			time.Sleep(2 * time.Second)
			pm.mtx.Lock()
			for name, f := range pm.friends {
				f.mtx.Lock()
				if f.lastSeen.Add(10 * time.Second).Before(time.Now()) {
					log.Printf(`haven't heard from %s in a while`, name)
					pm.oldfriends[name] = f
					delete(pm.friends, name)
				}
				f.mtx.Unlock()
			}
			pm.mtx.Unlock()
		}
	}()

	go func() {
		for {
			/* Receive message */
			m, err := NewBusMessage(pm.bus.Recv(0))
			if err != nil {
				log.Printf(`can't receive message from bus: %s`, err)
				continue
			}

			/* Ignore messages from ourselves */
			if m.From == pm.nick {
				continue
			}

			/* Ignore messages not to 'everyone' or us */
			if m.To != pm.nick && m.To != "*" {
				continue
			}

			pm.mtx.Lock()
			f, ok := pm.friends[m.From]
			if !ok {
				f = NewFriend(m.From)
				pm.friends[m.From] = f
			}
			pm.mtx.Unlock()

			f.HandleMessage(m)

			if !ok {
				log.Printf(`%s is a new friend!`, m.From)
				pm.Publish(m.From, []string{"hello friend :)"})
			}
		}
	}()

	go func() {
		i := 0
		for {
			pm.Publish("*", []string{"I'm alive", fmt.Sprintf("%d", i)})
			i++
			time.Sleep(5 * time.Second)
		}
	}()

	for {
		pm.d.PeersRequest(string(ih), true)
		time.Sleep(5 * time.Second)
	}
}

func (pm *PeerManager) drainPeers() {
	log.Printf(`draining DHT`)
	seen := make(map[string]struct{})

	for r := range pm.d.PeersRequestResults {
		for _, peers := range r {
			for _, x := range peers {
				addr := dht.DecodePeerAddress(x)
				if _, ok := seen[addr]; !ok {
					pm.connectToPeer(addr)
				}
				seen[addr] = struct{}{}
			}
		}
	}
}

func (pm *PeerManager) connectToPeer(addr string) {
	if _, err := pm.bus.Connect(fmt.Sprintf("tcp://%s", addr)); err != nil {
		log.Printf(`can't connect SUB to %s: %s`, addr, err)
	}
}
<|endoftext|>


<commit_before>package gsh

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/google/shlex"
)

type FuncMap map[string](func(*Session, []string) error)

func New() *Session {
	s := Session{}
	s.Env = envMap(os.Environ())
	s.alias = make(map[string][]string)
	s.fmap = FuncMap{
		"alias":   Alias,
		"cp":      Copy,
		"echo":    Echo,
		"export":  Export,
		"mkdir":   Mkdir,
		"mv":      Move,
		"unalias": Unalias,
		"which":   Which,
	}
	return &s
}

func (s *Session) GetEnv(key string) string {
	return s.Env[key]
}

func (s *Session) PutEnv(key string, val string) {
	s.Env[key] = val
}

func (s *Session) SetError(e error) {
	s.err = e
}
func (s *Session) Error() error {
	return s.err
}

func (s *Session) Funcs(funcs FuncMap) *Session {
	for k, v := range funcs {
		if v == nil {
			delete(s.fmap, k)
		} else {
			s.fmap[k] = v
		}
	}
	return s
}

func (s *Session) Script(str string) *Session {
	// break apart script into single commands
	s.cmds = unbreak(str)
	return s
}

func (s *Session) Output() ([]byte, error) {
	var stdout bytes.Buffer
	var stderr bytes.Buffer
	s.Stdout = &stdout
	s.Stderr = &stderr

	err := s.Run()
	if err != nil {
		return nil, err
	}
	return stdout.Bytes(), nil
}

func (s *Session) Exec(cmds ...string) error {
	if s.Error() != nil {
		return nil
	}
	switch len(cmds) {
	case 0:
		return fmt.Errorf("Exec called without args?")
	case 1:
		s.cmds = unbreak(cmds[0])
	default:
		s.cmds = cmds
	}
	return s.Run()
}

func (s *Session) Run() error {
	if s.Error() != nil {
		return nil
	}
	for _, cmd := range s.cmds {
		// replace all ${  } shell variables
		cmd = os.Expand(cmd,
			(func(key string) string { return s.Env[key] }))

		parts, err := shlex.Split(cmd)
		if err != nil {
			s.SetError(fmt.Errorf("Bad line %q: %s", cmd, err))
			return err
		}
		// effectively blank line
		if len(parts) == 0 {
			continue
		}

		log.Printf("RUNNING: %s", cmd)

		// TODO: is arg0 an environment override
		// only for external commands I think

		// Insert Alias
		if newargs, ok := s.alias[parts[0]]; ok {
			parts = append(newargs, parts[1:]...)
		}

		fn, ok := s.fmap[parts[0]]
		if ok {
			err := fn(s, parts)
			if err != nil {
				s.SetError(err)
				return err
			}
			continue
		}
		log.Printf("Shelling out... not in map: %s", parts[0])
		// ok shell out
		execCmd := exec.Command(parts[0], parts[1:]...)

		// set up environment
		execCmd.Stdin = nil
		execCmd.Stdout = s.Stdout
		execCmd.Stderr = s.Stderr

		// TODO DIR/PATH
		// TODO ENV

		err = execCmd.Run()
		if err != nil {
			s.SetError(err)
			return err
		}
	}
	return nil
}

func Export(s *Session, cli []string) error {
	if len(cli) != 2 {
		return fmt.Errorf("%s: Expected only 1 arg: got %v", cli[0], cli[1:])
	}
	//name := cli[0]
	kv := cli[1]
	idx := strings.IndexByte(kv, '=')
	if idx == -1 {
		return fmt.Errorf("didnt find key/value")
	}
	s.PutEnv(kv[:idx], kv[idx+1:])
	return nil
}

func Echo(s *Session, cli []string) error {
	//name := cli[0]
	fargs := cli[1:]

	// no flags

	s.Stdout.Write([]byte(strings.Join(fargs, " ")))

	return nil
}

func Which(s *Session, cli []string) error {
	//name := cli[0]
	fargs := cli[1:]

	// no flags
	cmd, err := exec.LookPath(fargs[0])
	if err != nil {
		return err
	}
	s.Stdout.Write([]byte(cmd))
	return nil
}

func Mkdir(s *Session, cli []string) error {
	name := cli[0]
	fargs := cli[1:]
	var parents bool
	f := flag.NewFlagSet(name, flag.ContinueOnError)
	f.BoolVar(&parents, "p", false, "create parent directories")
	err := f.Parse(fargs)
	if err != nil {
		return err
	}
	for _, dirs := range f.Args() {
		if parents {
			err = os.MkdirAll(dirs, 0777)
		} else {
			err = os.Mkdir(dirs, 0777)
		}
		if err != nil {
			return err
		}
	}
	return nil
}

func Alias(s *Session, cli []string) error {
	name, fargs := cli[0], cli[1:]
	f := flag.NewFlagSet(name, flag.ExitOnError)
	for err := f.Parse(fargs); err != nil; {
		return err
	}
	args := f.Args()
	switch len(args) {
	case 0:
		return fmt.Errorf("%s requires at least one arg", name)
	case 1:
		aliasargs, ok := s.alias[args[0]]
		if !ok {
			return fmt.Errorf("%s: not found %s", name, fargs[0])
		}
		s.Stdout.Write([]byte(strings.Join(aliasargs, " ")))
		s.Stdout.Write([]byte("\n"))
		return nil
	default:
		s.alias[args[0]] = args[1:]
		return nil
	}
}

func Unalias(s *Session, cli []string) error {
	name, fargs := cli[0], cli[1:]
	f := flag.NewFlagSet(name, flag.ExitOnError)
	err := f.Parse(fargs)
	if err != nil {
		return err
	}
	args := f.Args()
	switch len(args) {
	case 0:
		return fmt.Errorf("%s requires at least one arg", name)
	case 1:
		delete(s.alias, args[0])
		return nil
	default:
		return fmt.Errorf("%s too many args", name)
	}
}

type Session struct {
	err   error
	alias map[string][]string
	fmap  map[string](func(*Session, []string) error)
	cmds  []string

	Env    map[string]string
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer
}

// envMap converts an environment in []string{"k=v"}
// map[k] = v
func envMap(orig []string) map[string]string {
	out := make(map[string]string)
	for _, kv := range orig {
		idx := strings.IndexByte(kv, '=')
		if idx != -1 {
			key := kv[:idx]
			val := kv[idx+1:]
			out[key] = val
		}
	}
	log.Printf("DONE")
	return out
}

func newEnviron(env map[string]string, inherit bool) []string { //map[string]string {
	environ := make([]string, 0, len(env))
	if inherit {
		for _, line := range os.Environ() {
			for k := range env {
				if strings.HasPrefix(line, k+"=") {
					goto CONTINUE
				}
			}
			environ = append(environ, line)
		CONTINUE:
		}
	}
	for k, v := range env {
		environ = append(environ, k+"="+v)
	}
	return environ
}

// unbreak takes a lines and
func unbreak(s string) []string {
	lines := strings.Split(s, "\n")
	cmds := make([]string, 0, len(lines))
	last := ""
	for _, line := range lines {
		if strings.HasPrefix(line, "\\") {
			last = last + line[0:len(line)-1]
		} else if len(last) > 0 {
			cmds = append(cmds, last+line)
			last = ""
		} else {
			cmds = append(cmds, line)
		}
	}
	if len(last) > 0 {
		// dangle.. itgnore for now
		cmds = append(cmds, last)
	}
	/*
		for i, ll := range cmds {
			log.Printf("LINE %d: %s", i+1, ll)
		}
	*/
	return cmds
}

func Move(s *Session, cli []string) error {
	name := cli[0]
	fargs := cli[1:]
	useGlob := false
	f := flag.NewFlagSet(name, flag.ContinueOnError)
	f.BoolVar(&useGlob, "glob", false, "treat sources as globs")
	err := f.Parse(fargs)
	if err != nil {
		return err
	}
	args := f.Args()
	if len(args) < 2 {
		return fmt.Errorf("Expected at least 2 args")
	}

	dest, src := args[len(args)-1], args[:len(args)-1]
	if useGlob {
		sources := []string{}
		for _, val := range src {
			matches, err := filepath.Glob(val)
			if err != nil {
				return err
			}
			sources = append(sources, matches...)
		}
		if len(sources) == 0 {
			return fmt.Errorf("No matching files")
		}
		src = sources
	}

	if fileIsDirectory(dest) {
		for _, val := range src {
			base := filepath.Base(val)
			srcdest := filepath.Join(dest, base)
			os.Rename(val, srcdest)
			if err != nil {
				return fmt.Errorf("%s %s %s failed: %s",
					name, val, srcdest, err)
			}
		}
		return nil
	}

	// destination is not a directory
	if len(src) != 1 {
		return fmt.Errorf("Last arg is not a directory")
	}
	return os.Rename(src[0], dest)
}

func copyFile(src, dst string) error {
	log.Printf("---> Copying %s to %s", src, dst)
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, in)
	cerr := out.Close()
	if err != nil {
		return err
	}
	return cerr
}

func Copy(s *Session, cli []string) error {
	name := cli[0]
	fargs := cli[1:]
	useGlob := false
	f := flag.NewFlagSet(name, flag.ContinueOnError)
	f.BoolVar(&useGlob, "glob", false, "treat sources as globs")
	err := f.Parse(fargs)
	if err != nil {
		return fmt.Errorf("%s: %s", name, err)
	}
	args := f.Args()
	if len(args) < 2 {
		return fmt.Errorf("%s: Expected at least 2 args", name)
	}

	dest, src := args[len(args)-1], args[:len(args)-1]
	if useGlob {
		sources := []string{}
		for _, val := range src {
			matches, err := filepath.Glob(val)
			if err != nil {
				return fmt.Errorf("%s: glob for %q failed: %s",
					name, val, err)
			}
			sources = append(sources, matches...)
		}
		if len(sources) == 0 {
			return fmt.Errorf("%s: No matching files for %v",
				name, src)
		}
		src = sources
	}

	if fileIsDirectory(dest) {
		for _, val := range src {
			base := filepath.Base(val)
			srcdest := filepath.Join(dest, base)
			copyFile(val, srcdest)
			if err != nil {
				return fmt.Errorf("%s %s %s failed: %s",
					name, val, srcdest, err)
			}
		}
		return nil
	}

	// destination is not a directory
	if len(src) != 1 {
		return fmt.Errorf("Last arg is not a directory")
	}
	return copyFile(src[0], dest)
}
<commit_msg>code to debug alias<commit_after>package gsh

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/google/shlex"
)

type FuncMap map[string](func(*Session, []string) error)

func New() *Session {
	s := Session{}
	s.Env = envMap(os.Environ())
	s.alias = make(map[string][]string)
	s.fmap = FuncMap{
		"alias":   Alias,
		"cp":      Copy,
		"echo":    Echo,
		"export":  Export,
		"mkdir":   Mkdir,
		"mv":      Move,
		"unalias": Unalias,
		"which":   Which,
	}
	return &s
}

func (s *Session) GetEnv(key string) string {
	return s.Env[key]
}

func (s *Session) PutEnv(key string, val string) {
	s.Env[key] = val
}

func (s *Session) SetError(e error) {
	s.err = e
}
func (s *Session) Error() error {
	return s.err
}

func (s *Session) Funcs(funcs FuncMap) *Session {
	for k, v := range funcs {
		if v == nil {
			delete(s.fmap, k)
		} else {
			s.fmap[k] = v
		}
	}
	return s
}

func (s *Session) Script(str string) *Session {
	// break apart script into single commands
	s.cmds = unbreak(str)
	return s
}

func (s *Session) Output() ([]byte, error) {
	var stdout bytes.Buffer
	var stderr bytes.Buffer
	s.Stdout = &stdout
	s.Stderr = &stderr

	err := s.Run()
	if err != nil {
		return nil, err
	}
	return stdout.Bytes(), nil
}

func (s *Session) Exec(cmds ...string) error {
	if s.Error() != nil {
		return nil
	}
	switch len(cmds) {
	case 0:
		return fmt.Errorf("Exec called without args?")
	case 1:
		s.cmds = unbreak(cmds[0])
	default:
		s.cmds = cmds
	}
	return s.Run()
}

func (s *Session) Run() error {
	if s.Error() != nil {
		return nil
	}
	for _, cmd := range s.cmds {
		// replace all ${  } shell variables
		cmd = os.Expand(cmd,
			(func(key string) string { return s.Env[key] }))

		parts, err := shlex.Split(cmd)
		if err != nil {
			s.SetError(fmt.Errorf("Bad line %q: %s", cmd, err))
			return err
		}
		// effectively blank line
		if len(parts) == 0 {
			continue
		}

		log.Printf("RUNNING: %s", cmd)

		// TODO: is arg0 an environment override
		// only for external commands I think

		// Insert Alias
		if newargs, ok := s.alias[parts[0]]; ok {
			parts = append(newargs, parts[1:]...)
			log.Printf("ALIAS: %s", Strings.Join(parts, " "))
		}

		fn, ok := s.fmap[parts[0]]
		if ok {
			err := fn(s, parts)
			if err != nil {
				s.SetError(err)
				return err
			}
			continue
		}
		log.Printf("Shelling out... not in map: %s", parts[0])
		// ok shell out
		execCmd := exec.Command(parts[0], parts[1:]...)

		// set up environment
		execCmd.Stdin = nil
		execCmd.Stdout = s.Stdout
		execCmd.Stderr = s.Stderr

		// TODO DIR/PATH
		// TODO ENV

		err = execCmd.Run()
		if err != nil {
			s.SetError(err)
			return err
		}
	}
	return nil
}

func Export(s *Session, cli []string) error {
	if len(cli) != 2 {
		return fmt.Errorf("%s: Expected only 1 arg: got %v", cli[0], cli[1:])
	}
	//name := cli[0]
	kv := cli[1]
	idx := strings.IndexByte(kv, '=')
	if idx == -1 {
		return fmt.Errorf("didnt find key/value")
	}
	s.PutEnv(kv[:idx], kv[idx+1:])
	return nil
}

func Echo(s *Session, cli []string) error {
	//name := cli[0]
	fargs := cli[1:]

	// no flags

	s.Stdout.Write([]byte(strings.Join(fargs, " ")))

	return nil
}

func Which(s *Session, cli []string) error {
	//name := cli[0]
	fargs := cli[1:]

	// no flags
	cmd, err := exec.LookPath(fargs[0])
	if err != nil {
		return err
	}
	s.Stdout.Write([]byte(cmd))
	return nil
}

func Mkdir(s *Session, cli []string) error {
	name := cli[0]
	fargs := cli[1:]
	var parents bool
	f := flag.NewFlagSet(name, flag.ContinueOnError)
	f.BoolVar(&parents, "p", false, "create parent directories")
	err := f.Parse(fargs)
	if err != nil {
		return err
	}
	for _, dirs := range f.Args() {
		if parents {
			err = os.MkdirAll(dirs, 0777)
		} else {
			err = os.Mkdir(dirs, 0777)
		}
		if err != nil {
			return err
		}
	}
	return nil
}

func Alias(s *Session, cli []string) error {
	name, fargs := cli[0], cli[1:]
	f := flag.NewFlagSet(name, flag.ExitOnError)
	for err := f.Parse(fargs); err != nil; {
		return err
	}
	args := f.Args()
	switch len(args) {
	case 0:
		return fmt.Errorf("%s requires at least one arg", name)
	case 1:
		aliasargs, ok := s.alias[args[0]]
		if !ok {
			return fmt.Errorf("%s: not found %s", name, fargs[0])
		}
		s.Stdout.Write([]byte(strings.Join(aliasargs, " ")))
		s.Stdout.Write([]byte("\n"))
		return nil
	default:
		s.alias[args[0]] = args[1:]
		return nil
	}
}

func Unalias(s *Session, cli []string) error {
	name, fargs := cli[0], cli[1:]
	f := flag.NewFlagSet(name, flag.ExitOnError)
	err := f.Parse(fargs)
	if err != nil {
		return err
	}
	args := f.Args()
	switch len(args) {
	case 0:
		return fmt.Errorf("%s requires at least one arg", name)
	case 1:
		delete(s.alias, args[0])
		return nil
	default:
		return fmt.Errorf("%s too many args", name)
	}
}

type Session struct {
	err   error
	alias map[string][]string
	fmap  map[string](func(*Session, []string) error)
	cmds  []string

	Env    map[string]string
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer
}

// envMap converts an environment in []string{"k=v"}
// map[k] = v
func envMap(orig []string) map[string]string {
	out := make(map[string]string)
	for _, kv := range orig {
		idx := strings.IndexByte(kv, '=')
		if idx != -1 {
			key := kv[:idx]
			val := kv[idx+1:]
			out[key] = val
		}
	}
	log.Printf("DONE")
	return out
}

func newEnviron(env map[string]string, inherit bool) []string { //map[string]string {
	environ := make([]string, 0, len(env))
	if inherit {
		for _, line := range os.Environ() {
			for k := range env {
				if strings.HasPrefix(line, k+"=") {
					goto CONTINUE
				}
			}
			environ = append(environ, line)
		CONTINUE:
		}
	}
	for k, v := range env {
		environ = append(environ, k+"="+v)
	}
	return environ
}

// unbreak takes a lines and
func unbreak(s string) []string {
	lines := strings.Split(s, "\n")
	cmds := make([]string, 0, len(lines))
	last := ""
	for _, line := range lines {
		if strings.HasPrefix(line, "\\") {
			last = last + line[0:len(line)-1]
		} else if len(last) > 0 {
			cmds = append(cmds, last+line)
			last = ""
		} else {
			cmds = append(cmds, line)
		}
	}
	if len(last) > 0 {
		// dangle.. itgnore for now
		cmds = append(cmds, last)
	}
	/*
		for i, ll := range cmds {
			log.Printf("LINE %d: %s", i+1, ll)
		}
	*/
	return cmds
}

func Move(s *Session, cli []string) error {
	name := cli[0]
	fargs := cli[1:]
	useGlob := false
	f := flag.NewFlagSet(name, flag.ContinueOnError)
	f.BoolVar(&useGlob, "glob", false, "treat sources as globs")
	err := f.Parse(fargs)
	if err != nil {
		return err
	}
	args := f.Args()
	if len(args) < 2 {
		return fmt.Errorf("Expected at least 2 args")
	}

	dest, src := args[len(args)-1], args[:len(args)-1]
	if useGlob {
		sources := []string{}
		for _, val := range src {
			matches, err := filepath.Glob(val)
			if err != nil {
				return err
			}
			sources = append(sources, matches...)
		}
		if len(sources) == 0 {
			return fmt.Errorf("No matching files")
		}
		src = sources
	}

	if fileIsDirectory(dest) {
		for _, val := range src {
			base := filepath.Base(val)
			srcdest := filepath.Join(dest, base)
			os.Rename(val, srcdest)
			if err != nil {
				return fmt.Errorf("%s %s %s failed: %s",
					name, val, srcdest, err)
			}
		}
		return nil
	}

	// destination is not a directory
	if len(src) != 1 {
		return fmt.Errorf("Last arg is not a directory")
	}
	return os.Rename(src[0], dest)
}

func copyFile(src, dst string) error {
	log.Printf("---> Copying %s to %s", src, dst)
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, in)
	cerr := out.Close()
	if err != nil {
		return err
	}
	return cerr
}

func Copy(s *Session, cli []string) error {
	name := cli[0]
	fargs := cli[1:]
	useGlob := false
	f := flag.NewFlagSet(name, flag.ContinueOnError)
	f.BoolVar(&useGlob, "glob", false, "treat sources as globs")
	err := f.Parse(fargs)
	if err != nil {
		return fmt.Errorf("%s: %s", name, err)
	}
	args := f.Args()
	if len(args) < 2 {
		return fmt.Errorf("%s: Expected at least 2 args", name)
	}

	dest, src := args[len(args)-1], args[:len(args)-1]
	if useGlob {
		sources := []string{}
		for _, val := range src {
			matches, err := filepath.Glob(val)
			if err != nil {
				return fmt.Errorf("%s: glob for %q failed: %s",
					name, val, err)
			}
			sources = append(sources, matches...)
		}
		if len(sources) == 0 {
			return fmt.Errorf("%s: No matching files for %v",
				name, src)
		}
		src = sources
	}

	if fileIsDirectory(dest) {
		for _, val := range src {
			base := filepath.Base(val)
			srcdest := filepath.Join(dest, base)
			copyFile(val, srcdest)
			if err != nil {
				return fmt.Errorf("%s %s %s failed: %s",
					name, val, srcdest, err)
			}
		}
		return nil
	}

	// destination is not a directory
	if len(src) != 1 {
		return fmt.Errorf("Last arg is not a directory")
	}
	return copyFile(src[0], dest)
}
<|endoftext|>


<commit_before>package ut

// Any takes a slice and a func. If the func ever returns true Any will
// return true
//
//      s := []int{1,2,3,4,5,6,7}
//      ut.Any(s, func(i interface{}) bool {
//          return i.(int) > 3
//      }) // true
//
func Any(s interface{}, f func(interface{}) bool) bool {
	for _, obj := range s.([]interface{}) {
		if f(obj) {
			return true
		}
	}
	return false
}

// Contains checks a slice to see if an object exists inside of it. Note the
// slice can be of any type.
//
//      s := []string{"hello","world"}
//      ut.Contains(s, "hello") // true
//      s = []interface{}{"hello","world", 1000}
//      if ut.Contains(s, 1000) // true
//
func Contains(s interface{}, o interface{}) bool {
	for _, obj := range s.([]interface{}) {
		if obj == o {
			return true
		}
	}
	return false
}

// Pluck extracts a list of property values from a map
//
//      objs := []map[string]interface{}{
//          {"a": 1},
//          {"b": 2},
//          {"a": 3},
//	    }
//      ut.Pluck(objs, "a") // [1,3]
//
func Pluck(s []map[string]interface{}, str string) []interface{} {
	var returned []interface{}

	for _, mp := range s {
		o := mp[str]
		if o != nil {
			returned = append(returned, o)
		}
	}

	return returned
}

func SlicesEqual(a interface{}, b interface{}) bool {
	if len(a.([]interface{})) != len(b.([]interface{})) {
		return false
	}
	for i, v := range a.([]interface{}) {
		if v != b.([]interface{})[i] {
			return false
		}
	}
	return true
}
<commit_msg>updating<commit_after>package ut

// Any takes a slice and a func. If the func ever returns true Any will
// return true
//
//      s := []int{1,2,3,4,5,6,7}
//      ut.Any(s, func(i interface{}) bool {
//          return i.(int) > 3
//      }) // true
//
func Any(s interface{}, f func(interface{}) bool) bool {
	for _, obj := range s.([]interface{}) {
		if f(obj) {
			return true
		}
	}
	return false
}

// Contains checks a slice to see if an object exists inside of it. Note the
// slice can be of any type.
//
//      s := []string{"hello","world"}
//      ut.Contains(s, "hello") // true
//      s = []interface{}{"hello","world", 1000}
//      if ut.Contains(s, 1000) // true
//
func Contains(s interface{}, o interface{}) bool {
	for _, obj := range s.([]interface{}) {
		if obj == o {
			return true
		}
	}
	return false
}

// Pluck extracts a list of property values from a map
//
//      objs := []map[string]interface{}{
//          {"a": 1},
//          {"b": 2},
//          {"a": 3},
//      }
//      ut.Pluck(objs, "a") // [1,3]
//
func Pluck(s []map[string]interface{}, str string) []interface{} {
	var returned []interface{}

	for _, mp := range s {
		o := mp[str]
		if o != nil {
			returned = append(returned, o)
		}
	}

	return returned
}

func SlicesEqual(a interface{}, b interface{}) bool {
	if len(a.([]interface{})) != len(b.([]interface{})) {
		return false
	}
	for i, v := range a.([]interface{}) {
		if v != b.([]interface{})[i] {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package rsa

import (
	"fmt"
	"godot/pkcs1"
	"godot/rand"
	"godot/rsa/pss"
	"godot/usage"
	"godot/util"
	"godot/x509"
	"math/big"
	"os"
)

func createRSA(l int) *pkcs1.RSAPrivateKey {
	var rsa = new(pkcs1.RSAPrivateKey)

	rsa.Version = big.NewInt(0)
	rsa.Prime1 = rand.Prime(l/2) // prime p
	rsa.Prime2 = rand.Prime(l/2) // prime q
	rsa.Modulus = new(big.Int).Mul(rsa.Prime1, rsa.Prime2)
	rsa.PublicExponent = big.NewInt(65537)

	pMinus := new(big.Int).Sub(rsa.Prime1, big.NewInt(1))
	qMinus := new(big.Int).Sub(rsa.Prime1, big.NewInt(1))
	phi := new(big.Int).Mul(pMinus, qMinus)

	rsa.PrivateExponent = new(big.Int).ModInverse(rsa.PublicExponent, phi)
	// CRT auxiliary parameters
	rsa.Exponent1 = new(big.Int).Mod(rsa.PrivateExponent, pMinus)
	rsa.Exponent2 = new(big.Int).Mod(rsa.PrivateExponent, qMinus)
	rsa.Coefficient = new(big.Int).ModInverse(rsa.Prime2, rsa.Prime1)

	return rsa
}

func Verify(args []string) {
	var in, key, sig *os.File

	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "-i":
			fallthrough
		case "--in":
			util.OpenFile(&in, util.GetArg(args, &i))
		case "-k":
			fallthrough
		case "--key":
			util.OpenFile(&key, util.GetArg(args, &i))
		case "-s":
			fallthrough
		case "--sig":
			util.OpenFile(&sig, util.GetArg(args, &i))
		default:
			usage.Print();
			os.Exit(1);
		}
	}

	if key == nil || sig == nil {
		usage.Print();
		os.Exit(1);
	}
	if in == nil {
		in = os.Stdin
	}

	rsaPub := x509.ReadRSA(key)
	if len(rsaPub.Modulus.Bytes()) != 512 {
		fmt.Fprintf(os.Stderr, "invalid key size\n")
		os.Exit(1)
	}

	sigBody := util.ReadAll(sig)
	if len(sigBody) != 512 {
		fmt.Fprintf(os.Stderr, "invalid signature size\n")
		os.Exit(1)
	}

	s := new(big.Int).SetBytes(sigBody)
	m := new(big.Int).Exp(s, rsaPub.PublicExponent, rsaPub.Modulus)

	fmt.Fprintf(os.Stderr, "%x\n", m.Bytes())

	if pss.Verify(in, m, 4095) == true {
		fmt.Fprintf(os.Stdout, "ok\n")
		os.Exit(0)
	} else {
		fmt.Fprintf(os.Stdout, "not ok\n")
		os.Exit(1)
	}
}

func Sign(args []string) {
	var in, out, key *os.File

	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "-i":
			fallthrough
		case "--in":
			util.OpenFile(&in, util.GetArg(args, &i))
		case "-k":
			fallthrough
		case "--key":
			util.OpenKey(&key, util.GetArg(args, &i))
		case "-o":
			fallthrough
		case "--out":
			util.CreateFile(&out, util.GetArg(args, &i))
		default:
			usage.Print();
			os.Exit(1);
		}
	}

	if key == nil {
		usage.Print();
		os.Exit(1);
	}
	if in == nil {
		in = os.Stdin
	}
	if out == nil {
		out = os.Stdout
	}

	rsa := pkcs1.ReadRSA(key)
	if len(rsa.Modulus.Bytes()) != 512 ||
	   len(rsa.PrivateExponent.Bytes()) != 512 {
		fmt.Fprintf(os.Stderr, "invalid key size\n")
		os.Exit(1)
	}

	m := pss.Encode(in, 4095)
	out.Write(new(big.Int).Exp(m, rsa.PrivateExponent, rsa.Modulus).Bytes())

	util.CloseFile(in)
	util.CloseFile(out)
}

func Pub(args []string) {
	var in, out *os.File

	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "-i":
			fallthrough
		case "--in":
			util.OpenKey(&in, util.GetArg(args, &i))
		case "-o":
			fallthrough
		case "--out":
			util.CreateFile(&out, util.GetArg(args, &i))
		default:
			usage.Print();
			os.Exit(1);
		}
	}

	if in == nil {
		in = os.Stdin
	}
	if out == nil {
		out = os.Stdout
	}

	x509.WriteRSA(pkcs1.ReadRSA(in), out)
	util.CloseFile(in);
	util.CloseFile(out);
}

func New(args []string) {
	var out *os.File

	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "-o":
			fallthrough
		case "--out":
			util.CreateFile(&out, util.GetArg(args, &i))
		default:
			usage.Print();
			os.Exit(1);
		}
	}

	if out == nil {
		out = os.Stdout
	}

	pkcs1.WriteRSA(createRSA(4096), out)
	util.CloseFile(out)
}
<commit_msg>fix sneaky bug<commit_after>package rsa

import (
	"fmt"
	"godot/pkcs1"
	"godot/rand"
	"godot/rsa/pss"
	"godot/usage"
	"godot/util"
	"godot/x509"
	"math/big"
	"os"
)

func createRSA(l int) *pkcs1.RSAPrivateKey {
	var rsa = new(pkcs1.RSAPrivateKey)

	rsa.Version = big.NewInt(0)
	rsa.Prime1 = rand.Prime(l/2) // prime p
	rsa.Prime2 = rand.Prime(l/2) // prime q
	rsa.Modulus = new(big.Int).Mul(rsa.Prime1, rsa.Prime2)
	rsa.PublicExponent = big.NewInt(65537)

	pMinus := new(big.Int).Sub(rsa.Prime1, big.NewInt(1))
	qMinus := new(big.Int).Sub(rsa.Prime2, big.NewInt(1))
	phi := new(big.Int).Mul(pMinus, qMinus)

	rsa.PrivateExponent = new(big.Int).ModInverse(rsa.PublicExponent, phi)
	// CRT auxiliary parameters
	rsa.Exponent1 = new(big.Int).Mod(rsa.PrivateExponent, pMinus)
	rsa.Exponent2 = new(big.Int).Mod(rsa.PrivateExponent, qMinus)
	rsa.Coefficient = new(big.Int).ModInverse(rsa.Prime2, rsa.Prime1)

	return rsa
}

func Verify(args []string) {
	var in, key, sig *os.File

	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "-i":
			fallthrough
		case "--in":
			util.OpenFile(&in, util.GetArg(args, &i))
		case "-k":
			fallthrough
		case "--key":
			util.OpenFile(&key, util.GetArg(args, &i))
		case "-s":
			fallthrough
		case "--sig":
			util.OpenFile(&sig, util.GetArg(args, &i))
		default:
			usage.Print();
			os.Exit(1);
		}
	}

	if key == nil || sig == nil {
		usage.Print();
		os.Exit(1);
	}
	if in == nil {
		in = os.Stdin
	}

	rsaPub := x509.ReadRSA(key)
	if len(rsaPub.Modulus.Bytes()) != 512 {
		fmt.Fprintf(os.Stderr, "invalid key size\n")
		os.Exit(1)
	}

	sigBody := util.ReadAll(sig)
	if len(sigBody) != 512 {
		fmt.Fprintf(os.Stderr, "invalid signature size\n")
		os.Exit(1)
	}

	s := new(big.Int).SetBytes(sigBody)
	m := new(big.Int).Exp(s, rsaPub.PublicExponent, rsaPub.Modulus)

	fmt.Fprintf(os.Stderr, "%x\n", m.Bytes())

	if pss.Verify(in, m, 4095) == true {
		fmt.Fprintf(os.Stdout, "ok\n")
		os.Exit(0)
	} else {
		fmt.Fprintf(os.Stdout, "not ok\n")
		os.Exit(1)
	}
}

func Sign(args []string) {
	var in, out, key *os.File

	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "-i":
			fallthrough
		case "--in":
			util.OpenFile(&in, util.GetArg(args, &i))
		case "-k":
			fallthrough
		case "--key":
			util.OpenKey(&key, util.GetArg(args, &i))
		case "-o":
			fallthrough
		case "--out":
			util.CreateFile(&out, util.GetArg(args, &i))
		default:
			usage.Print();
			os.Exit(1);
		}
	}

	if key == nil {
		usage.Print();
		os.Exit(1);
	}
	if in == nil {
		in = os.Stdin
	}
	if out == nil {
		out = os.Stdout
	}

	rsa := pkcs1.ReadRSA(key)
	if len(rsa.Modulus.Bytes()) != 512 ||
	   len(rsa.PrivateExponent.Bytes()) != 512 {
		fmt.Fprintf(os.Stderr, "invalid key size\n")
		os.Exit(1)
	}

	m := pss.Encode(in, 4095)
	out.Write(new(big.Int).Exp(m, rsa.PrivateExponent, rsa.Modulus).Bytes())

	util.CloseFile(in)
	util.CloseFile(out)
}

func Pub(args []string) {
	var in, out *os.File

	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "-i":
			fallthrough
		case "--in":
			util.OpenKey(&in, util.GetArg(args, &i))
		case "-o":
			fallthrough
		case "--out":
			util.CreateFile(&out, util.GetArg(args, &i))
		default:
			usage.Print();
			os.Exit(1);
		}
	}

	if in == nil {
		in = os.Stdin
	}
	if out == nil {
		out = os.Stdout
	}

	x509.WriteRSA(pkcs1.ReadRSA(in), out)
	util.CloseFile(in);
	util.CloseFile(out);
}

func New(args []string) {
	var out *os.File

	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "-o":
			fallthrough
		case "--out":
			util.CreateFile(&out, util.GetArg(args, &i))
		default:
			usage.Print();
			os.Exit(1);
		}
	}

	if out == nil {
		out = os.Stdout
	}

	pkcs1.WriteRSA(createRSA(4096), out)
	util.CloseFile(out)
}
<|endoftext|>


<commit_before>package main

import (
	"log"
)

func main() {
	tests := [][]int32{{1, 2, 3, 4, 5}}

	for _, test := range tests {
		log.Printf("LeftRotate(%v) == %v\n", test, LeftRotate(test, 2))
	}
}

// left-rotate n, x times
func LeftRotate(n []int32, x int32) []int32 {
	if len(n) <= 1 {
		return n
	}

  var j int32
	for j = 0; j < x; j++ {
		tmp := n[len(n)-1]

		for i := len(n) - 1; i > 0; i-- {
			n[i] = n[i-1]
		}

		n[0] = tmp
	}

	return n
}
<commit_msg>Working version<commit_after>package main

import (
	"log"
)

func main() {
	tests := [][]int32{{1, 2, 3, 4, 5}}

	for _, test := range tests {
		log.Printf("LeftRotate(%v) == %v\n", test, LeftRotate(test, 2))
	}
}

// left-rotate n, x times
func LeftRotate(n []int32, x int32) []int32 {
  if len(n) <= 1 {
    return n
  }

  var j int32
  for j = 0; j < x; j++ {
    tmp := n[0]

    for i := 1; i < len(n); i++ {
      n[i-1] = n[i]
    }

    n[len(n)-1] = tmp
  }

  return n
}

// right-rotate n, x times
func RightRotate(n []int32, x int32) []int32 {
	if len(n) <= 1 {
		return n
	}

  var j int32
	for j = 0; j < x; j++ {
		tmp := n[len(n)-1]

		for i := len(n) - 1; i > 0; i-- {
			n[i] = n[i-1]
		}

		n[0] = tmp
	}

	return n
}
<|endoftext|>


<commit_before>// +build go1.4
//go:generate protoc --go_out=accp -Iaccp accp/accp.proto
//go:generate protoc --go_out=acpb -Iacpb acpb/ac.proto
//go:generate protoc --python_out=client-scripts/weechat/ -Iacpb acpb/ac.proto
//make version
//echo "package main\nvar Version string '`date +%Y%m%d`'\n" > version.go
// ACD: Arsene Crypto Daemon main file
package main

import (
	"fmt"
	"os"
	"os/signal" // XXX deactivated
	//    "time"
	//    "log" // XXX deactivated
	// XXX temporary..
	//"crypto/rand"
	//"github.com/unix4fun/ac/accp"
	"flag"
	"github.com/unix4fun/ac/acpb"
	"syscall" // XXX deactivated

	//"runtime/pprof"
)

func usage(mycmd string) {
	fmt.Fprintf(os.Stderr, "%s [options]", mycmd)
}

func handleStdin() (err error) {
	buf := make([]byte, 4096)
	for {
		n, err := os.Stdin.Read(buf[0:])
		if err != nil {
			return err
		}

		//fmt.Fprintf(os.Stderr, "STDIN READ: %d bytes\n", n)
		msgReply, acErr := acpb.HandleACMsg(buf[:n])
		if acErr != nil {
			//fmt.Println(acErr)
			if msgReply != nil {
				os.Stdout.Write(msgReply)
			}
			return acErr
		}

		os.Stdout.Write(msgReply)
		return nil
	} /* end of for() */
	// XXX need to return Error.New() really...
	return nil
}

func main() {
	Version := acVersion

	fmt.Fprintf(os.Stderr, "[+] ac-%s\nstart\n", Version)

	/*
	   if len(os.Args) != 1 {
	       Usage(os.Args[0])
	       os.Exit(1)
	   }
	*/

	/*
		f, err := os.Create("toto.pprof")
		if err != nil {
			panic(err)
		}

		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	*/

	/*
		ctx, err := accp.CreateACContext([]byte("#prout"), 0xdeadbeef)
		rnd := make([]byte, 32)

		keyzm := make([]byte, 32)
		_, err = rand.Read(keyzm)
		ctx.SetKey(keyzm)

		fmt.Printf("-- NONCE: %08x\n", ctx.GetNonce())

		toto := []byte("ldkaklj l adlkajs dlaksjd laskjd lsakdjal kdjsa ldkhjdsakhjdkjsahdkjsahdkjsa hdhsa kdhsa kjd askj dakjsh dkjsah dkjsa hdkjsa hdkjsa hdkjsa hdkja hkjdas hkjd hsakjd hsakjdjhdakjhd akj hdkjsa hdkjajs kda k4;lk mm m432,m ,m.,m4 32mmmmmmm432 ,m432, m,43m2 ,miui4u3i2o u879879s98fdscncnnnv ,;l;a;lkeq;wl;lk;qk1209002p32p[o4p32opop4o3popopo5p4lklk54lklkl4nmnmdahkjhdakjhakjgnbnmbnamnbnmn,5mn2,m,mn,mn453,mn,mn,m43n,m,mn,mn,m3ndsjhkjhdauyicytzxytuzyc xrtyrzcxrecztrexrectxrzextcrzxecztrxceztrxcetrzcezrtextrcexztrxectxuzyioocofslfdjslkfjsdkjfsldjlkjglfkjfldkjlkdsjfglksjfdlkjlweyeytwqretyqwreqwyureqjk kh kjh kjhkashalkdjas dsajk kdja daksjd akdja dlajd lsakjda lsjdas dalskjda lkdjsa lkdajd lasjdl sajdlkas jlkdajs dlksaj dlksaj lkaj lk3qjlk23j4 l23kj42 lj42 l3kj42 3j4lk23j4 l32j4lk32 jlk32j4 23lkj4 lk32j l 4k23j4 32lk4j2 lkj423 lk4j2 l4lk32j4lk23j l4j32lk4 lk2 j4lk32 j4lj4l32 j4l32 jlk432 jlk4 32jl4 32lk4 j32lkj4lk32 j4l j4lk2 jlk432 jlk4 j32l j432lk j4lk32 j4lk32 a")
		//toto := []byte("pouet pouet pouet")
	*/
	/*
			pouet, err := accp.CompressData(toto)
			if err != nil {
				panic(err)
			}
			prout, err := accp.DecompressData(pouet)
			if err != nil {
				panic(err)
			}

		fmt.Printf("PROUT LEN: %d\n", len(prout))
		fmt.Printf("TOTO LEN: %d\n", len(toto))
	*/

	/*
		fmt.Printf("TOTO PREDICT NACL LEN: %d\n", accp.PredictLenNACL(toto))

		//for t := 0; t < 20; t++ {
		cmsg, err := accp.CreateACMessageNACL(ctx, rnd, toto, []byte("spoty"))
		if err != nil {
			panic(err)
		}
		fmt.Printf("TOTO REAL NACL LEN: %d\n", len(cmsg))

		fmt.Printf("ACMessageNACL: %s\n", cmsg)
		fmt.Printf("-- NONCE: %08x\n", ctx.GetNonce())

		plain, perr := accp.OpenACMessageNACL(ctx, rnd, cmsg, []byte("spoty"), []byte("hiuu"))
		if perr != nil {
			panic(perr)
		}
		fmt.Printf("PLAIN: %s\n", plain)
		fmt.Printf("-- NONCE: %08x\n", ctx.GetNonce())
	*/

	/*
		jeob, err := accp.CreateMyKeys(rand.Reader, string("jeob"), string("user@user.com"), string("freenode"))
		spoty, err := accp.CreateMyKeys(rand.Reader, string("spoty"), string("userizkjdsk@user.com"), string("freenode"))

		//func CreateKXMessageNACL(context *SecKey, rnd []byte, peerPubkey, myPrivkey *[32]byte, channel, myNick, peerNick []byte) (out []byte, err error) {
		kxmsg, err := accp.CreateKXMessageNACL(ctx, rnd, jeob.GetPubkey(), spoty.GetPrivkey(), []byte("#prout"), []byte("spoty"), []byte("jeob"))
		fmt.Printf("KXMessageNACL: %s\n", kxmsg)
		fmt.Printf("-- NONCE: %08x\n", ctx.GetNonce())

		//func OpenKXMessageNACL(peerPubkey, myPrivkey *[32]byte, cmsg, channel, myNick, peerNick []byte) (context *SecKey, SecRnd []byte, err error) {
		_, rnd, err = accp.OpenKXMessageNACL(spoty.GetPubkey(), jeob.GetPrivkey(), kxmsg, []byte("#prout"), []byte("jeob"), []byte("spoty"))
		if err != nil {
			panic(err)
		}
	*/

	/*
		tcmsg, terr := accp.CreateACMessageNACL(ctx, rnd, []byte("proutprout tagada tsoin tsoin"), []byte("spoty"))
		if terr != nil {
			panic(terr)
		}
		fmt.Printf("ACMessage: %s\n", tcmsg)

		plain, perr = accp.OpenACMessageNACL(ctx, rnd, tcmsg, []byte("spoty"), []byte("hiuu"))
		if perr != nil {
			panic(perr)
		}
		fmt.Printf("PLAIN: %s\n", plain)
	*/
	//}

	//os.Exit(1)

	// parsing the RSA code...
	rsaFlag := flag.Bool("rsagen", false, "generate RSA identity keys")
	// we cannot use more than 2048K anyway why bother with a flag then
	//bitOpt := flag.Int("client", 2048, "generate Client SSL Certificate")
	flag.Parse()

	fmt.Printf("rsaFlag: %v\n", *rsaFlag)
	fmt.Printf("argc: %d\n", len(flag.Args()))

	if len(flag.Args()) != 0 {
		usage(os.Args[0])
		flag.PrintDefaults()
		os.Exit(1)
	}

	if rsaFlag == true {
		// generate a set of identity RSA keys and save them to file encrypted
		accp.GenRSAKeys()
	} else {
		// find and load the keys in memory to sign our requests
		// private key will need to be unlocked using PB request
		accp.LoadRSAKeys()
		// memory storage maps init..
		acpb.ACmap = make(acpb.PSKMap)
		acpb.ACrun = true

		// XXX TODO: this is not stable enough but should do the trick for now..
		// it is not clear what happens if the ACrun = false is done first
		// but i close the socket on both sides.. and it should clean the
		// socket file running... let's test with the script now :)
		// XXX deactivated
		sig := make(chan os.Signal, 2)
		signal.Notify(sig, os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT, syscall.SIGSEGV, syscall.SIGINT)
		//    signal.Notify(sig, nil)
		go func() {
			<-sig
			acpb.ACrun = false
			fmt.Fprintf(os.Stderr, "[+] exiting...!\n")
			os.Exit(3)
		}()

		for acpb.ACrun == true {
			handleStdin()
		}
	}
	os.Exit(0)
}
<commit_msg>just allow the build<commit_after>// +build go1.4
//go:generate protoc --go_out=accp -Iaccp accp/accp.proto
//go:generate protoc --go_out=acpb -Iacpb acpb/ac.proto
//go:generate protoc --python_out=client-scripts/weechat/ -Iacpb acpb/ac.proto
//make version
//echo "package main\nvar Version string '`date +%Y%m%d`'\n" > version.go
// ACD: Arsene Crypto Daemon main file
package main

import (
	"fmt"
	"os"
	"os/signal" // XXX deactivated
	//    "time"
	//    "log" // XXX deactivated
	// XXX temporary..
	//"crypto/rand"
	//"github.com/unix4fun/ac/accp"
	"flag"
	"github.com/unix4fun/ac/acpb"
	"syscall" // XXX deactivated

	//"runtime/pprof"
)

func usage(mycmd string) {
	fmt.Fprintf(os.Stderr, "%s [options]", mycmd)
}

func handleStdin() (err error) {
	buf := make([]byte, 4096)
	for {
		n, err := os.Stdin.Read(buf[0:])
		if err != nil {
			return err
		}

		//fmt.Fprintf(os.Stderr, "STDIN READ: %d bytes\n", n)
		msgReply, acErr := acpb.HandleACMsg(buf[:n])
		if acErr != nil {
			//fmt.Println(acErr)
			if msgReply != nil {
				os.Stdout.Write(msgReply)
			}
			return acErr
		}

		os.Stdout.Write(msgReply)
		return nil
	} /* end of for() */
	// XXX need to return Error.New() really...
	return nil
}

func main() {
	Version := acVersion

	fmt.Fprintf(os.Stderr, "[+] ac-%s\nstart\n", Version)

	/*
	   if len(os.Args) != 1 {
	       Usage(os.Args[0])
	       os.Exit(1)
	   }
	*/

	/*
		f, err := os.Create("toto.pprof")
		if err != nil {
			panic(err)
		}

		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	*/

	/*
		ctx, err := accp.CreateACContext([]byte("#prout"), 0xdeadbeef)
		rnd := make([]byte, 32)

		keyzm := make([]byte, 32)
		_, err = rand.Read(keyzm)
		ctx.SetKey(keyzm)

		fmt.Printf("-- NONCE: %08x\n", ctx.GetNonce())

		toto := []byte("ldkaklj l adlkajs dlaksjd laskjd lsakdjal kdjsa ldkhjdsakhjdkjsahdkjsahdkjsa hdhsa kdhsa kjd askj dakjsh dkjsah dkjsa hdkjsa hdkjsa hdkjsa hdkja hkjdas hkjd hsakjd hsakjdjhdakjhd akj hdkjsa hdkjajs kda k4;lk mm m432,m ,m.,m4 32mmmmmmm432 ,m432, m,43m2 ,miui4u3i2o u879879s98fdscncnnnv ,;l;a;lkeq;wl;lk;qk1209002p32p[o4p32opop4o3popopo5p4lklk54lklkl4nmnmdahkjhdakjhakjgnbnmbnamnbnmn,5mn2,m,mn,mn453,mn,mn,m43n,m,mn,mn,m3ndsjhkjhdauyicytzxytuzyc xrtyrzcxrecztrexrectxrzextcrzxecztrxceztrxcetrzcezrtextrcexztrxectxuzyioocofslfdjslkfjsdkjfsldjlkjglfkjfldkjlkdsjfglksjfdlkjlweyeytwqretyqwreqwyureqjk kh kjh kjhkashalkdjas dsajk kdja daksjd akdja dlajd lsakjda lsjdas dalskjda lkdjsa lkdajd lasjdl sajdlkas jlkdajs dlksaj dlksaj lkaj lk3qjlk23j4 l23kj42 lj42 l3kj42 3j4lk23j4 l32j4lk32 jlk32j4 23lkj4 lk32j l 4k23j4 32lk4j2 lkj423 lk4j2 l4lk32j4lk23j l4j32lk4 lk2 j4lk32 j4lj4l32 j4l32 jlk432 jlk4 32jl4 32lk4 j32lkj4lk32 j4l j4lk2 jlk432 jlk4 j32l j432lk j4lk32 j4lk32 a")
		//toto := []byte("pouet pouet pouet")
	*/
	/*
			pouet, err := accp.CompressData(toto)
			if err != nil {
				panic(err)
			}
			prout, err := accp.DecompressData(pouet)
			if err != nil {
				panic(err)
			}

		fmt.Printf("PROUT LEN: %d\n", len(prout))
		fmt.Printf("TOTO LEN: %d\n", len(toto))
	*/

	/*
		fmt.Printf("TOTO PREDICT NACL LEN: %d\n", accp.PredictLenNACL(toto))

		//for t := 0; t < 20; t++ {
		cmsg, err := accp.CreateACMessageNACL(ctx, rnd, toto, []byte("spoty"))
		if err != nil {
			panic(err)
		}
		fmt.Printf("TOTO REAL NACL LEN: %d\n", len(cmsg))

		fmt.Printf("ACMessageNACL: %s\n", cmsg)
		fmt.Printf("-- NONCE: %08x\n", ctx.GetNonce())

		plain, perr := accp.OpenACMessageNACL(ctx, rnd, cmsg, []byte("spoty"), []byte("hiuu"))
		if perr != nil {
			panic(perr)
		}
		fmt.Printf("PLAIN: %s\n", plain)
		fmt.Printf("-- NONCE: %08x\n", ctx.GetNonce())
	*/

	/*
		jeob, err := accp.CreateMyKeys(rand.Reader, string("jeob"), string("user@user.com"), string("freenode"))
		spoty, err := accp.CreateMyKeys(rand.Reader, string("spoty"), string("userizkjdsk@user.com"), string("freenode"))

		//func CreateKXMessageNACL(context *SecKey, rnd []byte, peerPubkey, myPrivkey *[32]byte, channel, myNick, peerNick []byte) (out []byte, err error) {
		kxmsg, err := accp.CreateKXMessageNACL(ctx, rnd, jeob.GetPubkey(), spoty.GetPrivkey(), []byte("#prout"), []byte("spoty"), []byte("jeob"))
		fmt.Printf("KXMessageNACL: %s\n", kxmsg)
		fmt.Printf("-- NONCE: %08x\n", ctx.GetNonce())

		//func OpenKXMessageNACL(peerPubkey, myPrivkey *[32]byte, cmsg, channel, myNick, peerNick []byte) (context *SecKey, SecRnd []byte, err error) {
		_, rnd, err = accp.OpenKXMessageNACL(spoty.GetPubkey(), jeob.GetPrivkey(), kxmsg, []byte("#prout"), []byte("jeob"), []byte("spoty"))
		if err != nil {
			panic(err)
		}
	*/

	/*
		tcmsg, terr := accp.CreateACMessageNACL(ctx, rnd, []byte("proutprout tagada tsoin tsoin"), []byte("spoty"))
		if terr != nil {
			panic(terr)
		}
		fmt.Printf("ACMessage: %s\n", tcmsg)

		plain, perr = accp.OpenACMessageNACL(ctx, rnd, tcmsg, []byte("spoty"), []byte("hiuu"))
		if perr != nil {
			panic(perr)
		}
		fmt.Printf("PLAIN: %s\n", plain)
	*/
	//}

	//os.Exit(1)

	// parsing the RSA code...
	rsaFlag := flag.Bool("rsagen", false, "generate RSA identity keys")
	// we cannot use more than 2048K anyway why bother with a flag then
	//bitOpt := flag.Int("client", 2048, "generate Client SSL Certificate")
	flag.Parse()

	fmt.Printf("rsaFlag: %v\n", *rsaFlag)
	fmt.Printf("argc: %d\n", len(flag.Args()))

	if len(flag.Args()) != 0 {
		usage(os.Args[0])
		flag.PrintDefaults()
		os.Exit(1)
	}

	if *rsaFlag == true {
		// generate a set of identity RSA keys and save them to file encrypted
		//accp.GenRSAKeys()
	} else {
		// find and load the keys in memory to sign our requests
		// private key will need to be unlocked using PB request
		//accp.LoadRSAKeys()
		// memory storage maps init..
		acpb.ACmap = make(acpb.PSKMap)
		acpb.ACrun = true

		// XXX TODO: this is not stable enough but should do the trick for now..
		// it is not clear what happens if the ACrun = false is done first
		// but i close the socket on both sides.. and it should clean the
		// socket file running... let's test with the script now :)
		// XXX deactivated
		sig := make(chan os.Signal, 2)
		signal.Notify(sig, os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT, syscall.SIGSEGV, syscall.SIGINT)
		//    signal.Notify(sig, nil)
		go func() {
			<-sig
			acpb.ACrun = false
			fmt.Fprintf(os.Stderr, "[+] exiting...!\n")
			os.Exit(3)
		}()

		for acpb.ACrun == true {
			handleStdin()
		}
	}
	os.Exit(0)
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ldap

import (
	"errors"
	"fmt"
	"github.com/mavricknz/asn1-ber"
)

type AddRequest struct {
	DN         string
	Attributes []EntryAttribute
	Controls   []Control
}

func (req *AddRequest) RecordType() uint8 {
	return AddRecord
}

func (l *Conn) Add(addReq *AddRequest) *Error {
	messageID := l.nextMessageID()
	encodedAdd, err := encodeAddRequest(addReq)
	if err != nil {
		return err
	}

	packet, err := requestBuildPacket(messageID, encodedAdd, addReq.Controls)
	if err != nil {
		return err
	}

	if l.Debug {
		ber.PrintPacket(packet)
	}

	channel, err := l.sendMessage(packet)

	if err != nil {
		return err
	}

	if channel == nil {
		return NewError(ErrorNetwork, errors.New("Could not send message"))
	}

	defer l.finishMessage(messageID)
	if l.Debug {
		fmt.Printf("%d: waiting for response\n", messageID)
	}

	packet = <-channel

	if l.Debug {
		fmt.Printf("%d: got response %p\n", messageID, packet)
	}

	if packet == nil {
		return NewError(ErrorNetwork, errors.New("Could not retrieve message"))
	}

	if l.Debug {
		if err := addLDAPDescriptions(packet); err != nil {
			return NewError(ErrorDebugging, err)
		}
		ber.PrintPacket(packet)
	}

	result_code, result_description := getLDAPResultCode(packet)

	if result_code != 0 {
		return NewError(result_code, errors.New(result_description))
	}

	if l.Debug {
		fmt.Printf("%d: returning\n", messageID)
	}
	// success
	return nil
}

/*
   AddRequest ::= [APPLICATION 8] SEQUENCE {
        entry           LDAPDN,
        attributes      AttributeList }

   AttributeList ::= SEQUENCE OF attribute Attribute

   Attribute ::= SEQUENCE {
        type       AttributeDescription,
        vals       SET OF value AttributeValue } // vals is not empty
*/
func encodeAddRequest(addReq *AddRequest) (*ber.Packet, *Error) {
	addPacket := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, ApplicationMap[ApplicationAddRequest])
	addPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, addReq.DN, "LDAP DN"))

	attributeList := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeList")

	for _, attr := range addReq.Attributes {
		attribute := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
		attribute.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, attr.Name, "Attribute Desc"))
		if len(attr.Values) == 0 {
			return nil, NewError(ErrorEncoding, errors.New("Attribute "+attr.Name+" had no values."))
		}
		valuesSet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "Attribute Value Set")
		for _, val := range attr.Values {
			valuesSet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, val, "AttributeValue"))
		}
		attribute.AppendChild(valuesSet)
		attributeList.AppendChild(attribute)
	}
	addPacket.AppendChild(attributeList)
	return addPacket, nil
}

func (req *AddRequest) Bytes() []byte {
	encoded, _ := encodeAddRequest(req)
	return encoded.Bytes()
}

func NewAddRequest(dn string) (req *AddRequest) {
	req = &AddRequest{DN: dn, Attributes: make([]EntryAttribute, 0, 5), Controls: make([]Control, 0)}
	return
}

func (req *AddRequest) AddAttribute(attr *EntryAttribute) {
	req.Attributes = append(req.Attributes, *attr)
}

func (req *AddRequest) AddAttributes(attrs []EntryAttribute) {
	req.Attributes = append(req.Attributes, attrs...)
}

// Basic LDIF dump, no formating, etc
func (addReq *AddRequest) DumpAddRequest() (dump string) {
	dump = fmt.Sprintf("dn: %s\n", addReq.DN)
	for _, attr := range addReq.Attributes {
		for _, val := range attr.Values {
			dump += fmt.Sprintf("%s: %s\n", attr.Name, val)
		}
	}
	dump += fmt.Sprintf("\n")
	return
}

func (req *AddRequest) AddControl(control Control) {
	if req.Controls == nil {
		req.Controls = make([]Control, 0)
	}
	req.Controls = append(req.Controls, control)
}
<commit_msg>Refactored to use Entry as struct member.<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ldap

import (
	"errors"
	"fmt"
	"github.com/mavricknz/asn1-ber"
)

type AddRequest struct {
	Entry    *Entry
	Controls []Control
}

func (req *AddRequest) RecordType() uint8 {
	return AddRecord
}

func (l *Conn) Add(addReq *AddRequest) *Error {
	messageID := l.nextMessageID()
	encodedAdd, err := encodeAddRequest(addReq)
	if err != nil {
		return err
	}

	packet, err := requestBuildPacket(messageID, encodedAdd, addReq.Controls)
	if err != nil {
		return err
	}

	if l.Debug {
		ber.PrintPacket(packet)
	}

	channel, err := l.sendMessage(packet)

	if err != nil {
		return err
	}

	if channel == nil {
		return NewError(ErrorNetwork, errors.New("Could not send message"))
	}

	defer l.finishMessage(messageID)
	if l.Debug {
		fmt.Printf("%d: waiting for response\n", messageID)
	}

	packet = <-channel

	if l.Debug {
		fmt.Printf("%d: got response %p\n", messageID, packet)
	}

	if packet == nil {
		return NewError(ErrorNetwork, errors.New("Could not retrieve message"))
	}

	if l.Debug {
		if err := addLDAPDescriptions(packet); err != nil {
			return NewError(ErrorDebugging, err)
		}
		ber.PrintPacket(packet)
	}

	result_code, result_description := getLDAPResultCode(packet)

	if result_code != 0 {
		return NewError(result_code, errors.New(result_description))
	}

	if l.Debug {
		fmt.Printf("%d: returning\n", messageID)
	}
	// success
	return nil
}

/*
   AddRequest ::= [APPLICATION 8] SEQUENCE {
        entry           LDAPDN,
        attributes      AttributeList }

   AttributeList ::= SEQUENCE OF attribute Attribute

   Attribute ::= SEQUENCE {
        type       AttributeDescription,
        vals       SET OF value AttributeValue } // vals is not empty
*/
func encodeAddRequest(addReq *AddRequest) (*ber.Packet, *Error) {
	addPacket := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, ApplicationMap[ApplicationAddRequest])
	addPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, addReq.Entry.DN, "LDAP DN"))

	attributeList := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeList")

	for _, attr := range addReq.Entry.Attributes {
		attribute := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
		attribute.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, attr.Name, "Attribute Desc"))
		if len(attr.Values) == 0 {
			return nil, NewError(ErrorEncoding, errors.New("Attribute "+attr.Name+" had no values."))
		}
		valuesSet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "Attribute Value Set")
		for _, val := range attr.Values {
			valuesSet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, val, "AttributeValue"))
		}
		attribute.AppendChild(valuesSet)
		attributeList.AppendChild(attribute)
	}
	addPacket.AppendChild(attributeList)
	return addPacket, nil
}

func (req *AddRequest) Bytes() []byte {
	encoded, _ := encodeAddRequest(req)
	return encoded.Bytes()
}

func NewAddRequest(dn string) (req *AddRequest) {
	req = &AddRequest{Entry: NewEntry(dn), Controls: make([]Control, 0)}
	return
}

func (req *AddRequest) AddAttribute(attr *EntryAttribute) {
	req.Entry.AddAttributeValues(attr.Name, attr.Values)
}

func (req *AddRequest) AddAttributes(attrs []EntryAttribute) {
	for _, attr := range attrs {
		req.Entry.AddAttributeValues(attr.Name, attr.Values)
	}
}

// DumpAddRequest - Basic LDIF "like" dump for testing, no formating, etc
func (addReq *AddRequest) DumpAddRequest() (dump string) {
	dump = fmt.Sprintf("dn: %s\n", addReq.Entry.DN)
	for _, attr := range addReq.Entry.Attributes {
		for _, val := range attr.Values {
			dump += fmt.Sprintf("%s: %s\n", attr.Name, val)
		}
	}
	dump += fmt.Sprintf("\n")
	return
}

func (req *AddRequest) AddControl(control Control) {
	if req.Controls == nil {
		req.Controls = make([]Control, 0)
	}
	req.Controls = append(req.Controls, control)
}
<|endoftext|>


<commit_before>package jshapi

import (
	"fmt"
	"log"
	"path"
	"strings"

	"goji.io"
	"goji.io/pat"

	"github.com/derekdowling/goji2-logger"
)

// API is used to direct HTTP requests to resources
type API struct {
	*goji.Mux
	prefix    string
	Resources map[string]*Resource
	Debug     bool
}

// New initializes a new top level API Resource Handler. The most basic implementation
// is:
//
//	// optionally, set your own logger
//	jshapi.Logger = yourLogger
//
//	// create a new API
//	api := jshapi.New("<prefix>", nil)
func New(prefix string, debug bool) *API {

	// ensure that our top level prefix is "/" prefixed
	if !strings.HasPrefix(prefix, "/") {
		prefix = fmt.Sprintf("/%s", prefix)
	}

	// create our new logger
	api := &API{
		Mux:       goji.NewMux(),
		prefix:    prefix,
		Resources: map[string]*Resource{},
		Debug:     debug,
	}

	// register logger middleware
	gojilogger := gojilogger.New(Logger, debug)
	api.UseC(gojilogger.Middleware)

	return api
}

// Add implements mux support for a given resource which is effectively handled as:
// pat.New("/(prefix/)resource.Plu*)
func (a *API) Add(resource *Resource) {

	// track our associated resources, will enable auto-generation docs later
	a.Resources[resource.Type] = resource

	// Because of how prefix matches work:
	// https://godoc.org/github.com/goji/goji/pat#hdr-Prefix_Matches
	// We need two separate routes,
	// /(prefix/)resources
	matcher := path.Join(a.prefix, resource.Type)
	a.Mux.HandleC(pat.New(matcher), resource)

	// And:
	// /(prefix/)resources/*
	idMatcher := path.Join(a.prefix, resource.Type, "*")
	log.Printf("idMatcher = %+v\n", idMatcher)
	a.Mux.HandleC(pat.New(idMatcher), resource)
}

// RouteTree prints out all accepted routes for the API that use jshapi implemented
// ways of adding routes through resources: NewCRUDResource(), .Get(), .Post, .Delete(),
// .Patch(), .List(), and .NewAction()
func (a *API) RouteTree() string {
	var routes string

	for _, resource := range a.Resources {
		routes = strings.Join([]string{routes, resource.RouteTree()}, "")
	}

	return routes
}
<commit_msg>Removing debug<commit_after>package jshapi

import (
	"fmt"
	"path"
	"strings"

	"goji.io"
	"goji.io/pat"

	"github.com/derekdowling/goji2-logger"
)

// API is used to direct HTTP requests to resources
type API struct {
	*goji.Mux
	prefix    string
	Resources map[string]*Resource
	Debug     bool
}

// New initializes a new top level API Resource Handler. The most basic implementation
// is:
//
//	// optionally, set your own logger
//	jshapi.Logger = yourLogger
//
//	// create a new API
//	api := jshapi.New("<prefix>", nil)
func New(prefix string, debug bool) *API {

	// ensure that our top level prefix is "/" prefixed
	if !strings.HasPrefix(prefix, "/") {
		prefix = fmt.Sprintf("/%s", prefix)
	}

	// create our new logger
	api := &API{
		Mux:       goji.NewMux(),
		prefix:    prefix,
		Resources: map[string]*Resource{},
		Debug:     debug,
	}

	// register logger middleware
	gojilogger := gojilogger.New(Logger, debug)
	api.UseC(gojilogger.Middleware)

	return api
}

// Add implements mux support for a given resource which is effectively handled as:
// pat.New("/(prefix/)resource.Plu*)
func (a *API) Add(resource *Resource) {

	// track our associated resources, will enable auto-generation docs later
	a.Resources[resource.Type] = resource

	// Because of how prefix matches work:
	// https://godoc.org/github.com/goji/goji/pat#hdr-Prefix_Matches
	// We need two separate routes,
	// /(prefix/)resources
	matcher := path.Join(a.prefix, resource.Type)
	a.Mux.HandleC(pat.New(matcher), resource)

	// And:
	// /(prefix/)resources/*
	idMatcher := path.Join(a.prefix, resource.Type, "*")
	a.Mux.HandleC(pat.New(idMatcher), resource)
}

// RouteTree prints out all accepted routes for the API that use jshapi implemented
// ways of adding routes through resources: NewCRUDResource(), .Get(), .Post, .Delete(),
// .Patch(), .List(), and .NewAction()
func (a *API) RouteTree() string {
	var routes string

	for _, resource := range a.Resources {
		routes = strings.Join([]string{routes, resource.RouteTree()}, "")
	}

	return routes
}
<|endoftext|>


<commit_before>package dskvs

import (
	"path/filepath"
	"sync"
)

const (
	// MAJOR_VERSION is used to ensure that incompatible fileformat versions are
	// not loaded in memory.
	MAJOR_VERSION uint16 = 0
	// MINOR_VERSION is used to differentiate between fileformat versions. It might
	// be used for migrations if a future change to dskvs breaks the original
	// fileformat contract
	MINOR_VERSION uint16 = 1
	// PATCH_VERSION is used for the same reasons as MINOR_VERSION
	PATCH_VERSION uint64 = 0
)

var (
	// CollKeySep is the value used by dskvs to separate the
	// collection part of the full key from the member part.  This is usually
	// '/' on Unix systems.
	CollKeySep = string(filepath.Separator)

	storeExistsLock sync.RWMutex
	storeExists     map[string]bool
	jan             janitor
)

func init() {
	storeExists = make(map[string]bool)
	jan = newJanitor()
}

// Store provides methods to manipulate the data held in memory and on disk at
// the path that was specified when you instantiated it.  Every store instance
// points at a different path location on disk.  Beware if you create a store
// that lives within the tree of another store.  There's no garantee to what
// will happen, aside perhaps a garantee that things will go wrong.
type Store struct {
	isLoaded    bool
	storagePath string
	coll        *collections
}

/*
	Meta operations on Store
*/

// NewStore instantiate a new store reading from the specified path
func NewStore(path string) (*Store, error) {

	if !isValidPath(path) {
		return nil, errorPathInvalid(path)
	}

	basepath := expandPath(path)
	return &Store{
		false,                    // isLoaded
		basepath,                 // storagePath
		newCollections(basepath), // collections
	}, nil
}

// Load retrieves previously persisted entries and load them in memory.
// Every file is checked for consistency with a SHA1 checksum.  A file that
// is not consistent will be ignored, a log message emitted and an error
// returned.  This call will block until all collections have been replenished.
func (s *Store) Load() error {
	storeExistsLock.RLock()
	exists := storeExists[s.storagePath]
	storeExistsLock.RUnlock()

	if exists {
		return errorPathInUse(s.storagePath)
	}

	storeExistsLock.Lock()
	storeExists[s.storagePath] = true
	storeExistsLock.Unlock()

	err := jan.loadStore(s)
	if err != nil {
		return err
	}
	jan.run()

	s.isLoaded = true
	return nil
}

// Close finishes writing dirty updates and closes all the files. It reports
// any error that occured doing so. This call will block until the writes are
// completed.
func (s *Store) Close() error {
	if !s.isLoaded {
		return errorStoreNotLoaded(s)
	}

	s.isLoaded = false

	storeExistsLock.Lock()
	delete(storeExists, s.storagePath)
	storeExistsLock.Unlock()

	err := jan.unloadStore(s)
	if err != nil {
		jan.die()
		return err
	}

	return nil
}

// Get returns the value referenced by the `fullKey` given in argument. A
// `fullKey` is a string that has a collection identifier and a member
// identifier, separated by `CollKeySep`, Ex:
//
//	val, err := store.Get("artists/daft_punk")
//
// will get the value attached to Daft Punk, from within the Artists
// collection
func (s *Store) Get(fullKey string) ([]byte, error) {
	if !s.isLoaded {
		return nil, errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(fullKey); err != nil {
		return nil, err
	}

	if isCollectionKey(fullKey) {
		return nil, errorGetIsColl(fullKey)
	}

	coll, key := splitKeys(fullKey)

	return s.coll.get(coll, key)
}

// GetAll returns all the members' value in the collection `coll`.
func (s *Store) GetAll(coll string) ([][]byte, error) {
	if !s.isLoaded {
		return nil, errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(coll); err != nil {
		return nil, err
	}

	if !isCollectionKey(coll) {
		return nil, errorGetAllIsNotColl(coll)
	}

	return s.coll.getCollection(coll)
}

// Put saves the given value into the key location.  `fullKey` should be a
// member,  not a collection.  There is no `PutAll` version of this
// call.  If you wish to add a collection all at once, iterate over your
// collection and call `Put` on each member.
func (s *Store) Put(fullKey string, value []byte) error {
	if !s.isLoaded {
		return errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(fullKey); err != nil {
		return err
	}

	if isCollectionKey(fullKey) {
		return errorPutIsColl(fullKey, string(value))
	}

	coll, key := splitKeys(fullKey)

	s.coll.put(coll, key, value)
	return nil
}

// Delete removes member with `fullKey` from the storage.
func (s *Store) Delete(fullKey string) error {
	if !s.isLoaded {
		return errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(fullKey); err != nil {
		return err
	}

	if isCollectionKey(fullKey) {
		return errorDeleteIsColl(fullKey)
	}

	coll, key := splitKeys(fullKey)

	return s.coll.deleteKey(coll, key)
}

// DeleteAll removes all the members in collection `coll`
func (s *Store) DeleteAll(coll string) error {
	if !s.isLoaded {
		return errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(coll); err != nil {
		return err
	}

	if !isCollectionKey(coll) {
		return errorDeleteAllIsNotColl(coll)
	}

	return s.coll.deleteCollection(coll)
}
<commit_msg>Add warning not to modify the data you `Get` or `GetAll` directly.<commit_after>package dskvs

import (
	"path/filepath"
	"sync"
)

const (
	// MAJOR_VERSION is used to ensure that incompatible fileformat versions are
	// not loaded in memory.
	MAJOR_VERSION uint16 = 0
	// MINOR_VERSION is used to differentiate between fileformat versions. It might
	// be used for migrations if a future change to dskvs breaks the original
	// fileformat contract
	MINOR_VERSION uint16 = 1
	// PATCH_VERSION is used for the same reasons as MINOR_VERSION
	PATCH_VERSION uint64 = 0
)

var (
	// CollKeySep is the value used by dskvs to separate the
	// collection part of the full key from the member part.  This is usually
	// '/' on Unix systems.
	CollKeySep = string(filepath.Separator)

	storeExistsLock sync.RWMutex
	storeExists     map[string]bool
	jan             janitor
)

func init() {
	storeExists = make(map[string]bool)
	jan = newJanitor()
}

// Store provides methods to manipulate the data held in memory and on disk at
// the path that was specified when you instantiated it.  Every store instance
// points at a different path location on disk.  Beware if you create a store
// that lives within the tree of another store.  There's no garantee to what
// will happen, aside perhaps a garantee that things will go wrong.
type Store struct {
	isLoaded    bool
	storagePath string
	coll        *collections
}

/*
	Meta operations on Store
*/

// NewStore instantiate a new store reading from the specified path
func NewStore(path string) (*Store, error) {

	if !isValidPath(path) {
		return nil, errorPathInvalid(path)
	}

	basepath := expandPath(path)
	return &Store{
		false,                    // isLoaded
		basepath,                 // storagePath
		newCollections(basepath), // collections
	}, nil
}

// Load retrieves previously persisted entries and load them in memory.
// Every file is checked for consistency with a SHA1 checksum.  A file that
// is not consistent will be ignored, a log message emitted and an error
// returned.  This call will block until all collections have been replenished.
func (s *Store) Load() error {
	storeExistsLock.RLock()
	exists := storeExists[s.storagePath]
	storeExistsLock.RUnlock()

	if exists {
		return errorPathInUse(s.storagePath)
	}

	storeExistsLock.Lock()
	storeExists[s.storagePath] = true
	storeExistsLock.Unlock()

	err := jan.loadStore(s)
	if err != nil {
		return err
	}
	jan.run()

	s.isLoaded = true
	return nil
}

// Close finishes writing dirty updates and closes all the files. It reports
// any error that occured doing so. This call will block until the writes are
// completed.
func (s *Store) Close() error {
	if !s.isLoaded {
		return errorStoreNotLoaded(s)
	}

	s.isLoaded = false

	storeExistsLock.Lock()
	delete(storeExists, s.storagePath)
	storeExistsLock.Unlock()

	err := jan.unloadStore(s)
	if err != nil {
		jan.die()
		return err
	}

	return nil
}

// Get returns the value referenced by the `fullKey` given in argument. A
// `fullKey` is a string that has a collection identifier and a member
// identifier, separated by `CollKeySep`, Ex:
//
//	val, err := store.Get("artists/daft_punk")
//
// will get the value attached to Daft Punk, from within the Artists
// collection
//
// ATTENTION : do not modify the value of the slices that are returned to
// you.
func (s *Store) Get(fullKey string) ([]byte, error) {
	if !s.isLoaded {
		return nil, errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(fullKey); err != nil {
		return nil, err
	}

	if isCollectionKey(fullKey) {
		return nil, errorGetIsColl(fullKey)
	}

	coll, key := splitKeys(fullKey)

	return s.coll.get(coll, key)
}

// GetAll returns all the members in the collection `coll`.
//
// ATTENTION : do not modify the value of the slices that are returned to
// you.
func (s *Store) GetAll(coll string) ([][]byte, error) {
	if !s.isLoaded {
		return nil, errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(coll); err != nil {
		return nil, err
	}

	if !isCollectionKey(coll) {
		return nil, errorGetAllIsNotColl(coll)
	}

	return s.coll.getCollection(coll)
}

// Put saves the given value into the key location.  `fullKey` should be a
// member,  not a collection.  There is no `PutAll` version of this
// call.  If you wish to add a collection all at once, iterate over your
// collection and call `Put` on each member.
func (s *Store) Put(fullKey string, value []byte) error {
	if !s.isLoaded {
		return errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(fullKey); err != nil {
		return err
	}

	if isCollectionKey(fullKey) {
		return errorPutIsColl(fullKey, string(value))
	}

	coll, key := splitKeys(fullKey)

	s.coll.put(coll, key, value)
	return nil
}

// Delete removes member with `fullKey` from the storage.
func (s *Store) Delete(fullKey string) error {
	if !s.isLoaded {
		return errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(fullKey); err != nil {
		return err
	}

	if isCollectionKey(fullKey) {
		return errorDeleteIsColl(fullKey)
	}

	coll, key := splitKeys(fullKey)

	return s.coll.deleteKey(coll, key)
}

// DeleteAll removes all the members in collection `coll`
func (s *Store) DeleteAll(coll string) error {
	if !s.isLoaded {
		return errorStoreNotLoaded(s)
	}

	if err := checkKeyValid(coll); err != nil {
		return err
	}

	if !isCollectionKey(coll) {
		return errorDeleteAllIsNotColl(coll)
	}

	return s.coll.deleteCollection(coll)
}
<|endoftext|>