<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/pkg/errors"
	"log"
	"math/rand"
	"net"
	"os"
	"strings"
	"time"
)

const road_width = 40
const road_lenght = 20
const Car_width = 16
const Car_lenght = 7
const result_width = 76
const max_players_in_top = 10

type Config struct {
	Log                 *log.Logger
	AcidPath, ScorePath string
}

type Point struct {
	X, Y int
}

type Player struct {
	Name  string
	Score int64
}

type GameData struct {
	Roads      [][]byte
	Car, Clear []byte
	Top        []Player
}

type RoundData struct {
	player                                   Player
	CarPosition, bombPosition, bonusPosition Point
	BombFactor, BonusFactor, Speed           int
	GameOver                                 []byte
}

func generateRoad(reverse bool) []byte {
	road := make([]byte, road_width*road_lenght)
	midline := reverse
	for row := 0; row < road_lenght; row++ {
		for column := 0; column < road_width; column++ {
			var symbol byte
			if column == 0 || column == road_width-2 {
				symbol = byte('|')
			} else if column == road_width-1 {
				symbol = byte('\n')
			} else if column == road_width/2-1 {
				if midline {
					symbol = byte('|')
				} else {
					symbol = byte(' ')
				}
				midline = !midline
			} else {
				symbol = byte(' ')
			}
			road[row*road_width+column] = symbol
		}

	}
	return road
}

func getAcid(conf *Config, fileName string) ([]byte, error) {
	fileStat, err := os.Stat(conf.AcidPath + "/" + fileName)
	if err != nil {
		conf.Log.Printf("Acid %s does not exist: %v\n", fileName, err)
		return []byte{}, err
	}

	acid := make([]byte, fileStat.Size())
	f, err := os.OpenFile(conf.AcidPath+"/"+fileName, os.O_RDONLY, os.ModePerm)
	if err != nil {
		conf.Log.Printf("Error while opening %s: %v\n", fileName, err)
		os.Exit(1)
	}
	defer f.Close()

	f.Read(acid)

	return acid, nil
}

func updatePosition(conn net.Conn, position *Point) {
	for {
		direction := make([]byte, 1)

		_, err := conn.Read(direction)
		if err != nil {
			return
		}

		switch direction[0] {
		case 68:
			// Left
			position.X--
		case 67:
			// Right
			position.X++
		case 65:
			// Up
			position.Y--
		case 66:
			// Down
			position.Y++
		}
	}
}

func updateScore(roundData *RoundData) {
	for {
		roundData.player.Score++
		time.Sleep(time.Duration(roundData.Speed) * time.Millisecond)
	}

}

func readName(conf *Config, conn net.Conn) (string, error) {
	conn.Write([]byte("Enter your name:"))
	io := bufio.NewReader(conn)
	name, err := io.ReadString('\n')
	if err != nil {
		conf.Log.Println("Error while name reading", err)
		return "", err
	}
	if name == "" {
		conf.Log.Println("Empty name")
		return "", errors.New("Empty name")
	}
	if len(name) > result_width/2 {
		conf.Log.Println("Too long name")
		return "", errors.New("Too long name")
	}
	return strings.Replace(name, "\n", "", -1), nil
}

func gameOver(conf *Config, conn net.Conn, roundData *RoundData, gameData *GameData) {

	conn.Write(gameData.Clear)

	// First we print current player result:
	// Score
	scoreStr := fmt.Sprintf("%d", roundData.player.Score)
	for i, char := range scoreStr {
		roundData.GameOver[i] = byte(char)
	}
	//:
	roundData.GameOver[result_width/2] = byte(':')
	//Name
	for i, char := range []byte(roundData.player.Name) {
		roundData.GameOver[result_width-1-len(roundData.player.Name)+i] = byte(char)
	}

	// Then we check on which place is current player
	inserted := false
	for i, player := range gameData.Top {
		if roundData.player.Score >= player.Score {
			// Insert new record
			gameData.Top = append(gameData.Top[:i], append([]Player{roundData.player}, gameData.Top[i:]...)...)
			inserted = true
			break
		}
	}
	if !inserted {
		gameData.Top = append(gameData.Top, roundData.player)
	}

	// Remove slowest user if top is full
	if len(gameData.Top) >= max_players_in_top {
		gameData.Top = gameData.Top[:max_players_in_top]
	}

	//TOP
	copy(roundData.GameOver[1*result_width+result_width/2-1:2*result_width+result_width/2+2], []byte("TOP"))

	// Then print new top
	for place, player := range gameData.Top {
		// Score
		scoreStr := fmt.Sprintf("%d", player.Score)
		for i, char := range scoreStr {
			roundData.GameOver[(2+place)*result_width+i] = byte(char)
		}
		//:
		roundData.GameOver[(2+place)*result_width+result_width/2] = byte(':')
		//Name
		for i, char := range []byte(player.Name) {
			roundData.GameOver[(2+place)*result_width+result_width-1-len(player.Name)+i] = byte(char)
		}
	}

	conn.Write(roundData.GameOver)
	// We do not need to check for error because user should not care, but logs are written
	saveScore(conf, gameData)
}

func saveScore(conf *Config, gameData *GameData) error {
	b, err := json.Marshal(gameData.Top)
	if err != nil {
		conf.Log.Println(err)
		return err
	}

	// Being sure file was not there
	os.Remove(conf.ScorePath + "/score.json")
	scoreFile, err := os.OpenFile(conf.ScorePath+"/score.json", os.O_RDWR|os.O_CREATE, 0600)
	if err != nil {
		conf.Log.Println(err)
		return err
	}
	defer scoreFile.Close()

	scoreFile.Write(b)
	return nil
}

func round(conf *Config, conn net.Conn, gameData *GameData) {
	defer conn.Close()

	roundData := RoundData{}
	roundData.CarPosition = Point{12, 12}
	roundData.bombPosition = Point{road_width, road_lenght}
	roundData.bonusPosition = Point{road_width, road_lenght}
	roundData.GameOver, _ = getAcid(conf, "game_over.txt")

	roundData.BombFactor = 10
	roundData.BonusFactor = 123
	roundData.Speed = 200

	name, err := readName(conf, conn)
	if err != nil {
		return
	}
	roundData.player.Name = name
	go updateScore(&roundData)
	go updatePosition(conn, &roundData.CarPosition)

	for {
		if roundData.CarPosition.X < 1 || roundData.CarPosition.X > 23 || roundData.CarPosition.Y < 1 || roundData.CarPosition.Y > 12 {
			// Hit the wall
			gameOver(conf, conn, &roundData, gameData)
			return
		} else if roundData.CarPosition.X <= roundData.bombPosition.X && roundData.CarPosition.X+Car_width-1 > roundData.bombPosition.X &&
			roundData.CarPosition.Y < roundData.bombPosition.Y && roundData.CarPosition.Y+Car_lenght-1 > roundData.bombPosition.Y {
			// Hit the bomb
			gameOver(conf, conn, &roundData, gameData)
			return
		} else if roundData.CarPosition.X <= roundData.bonusPosition.X && roundData.CarPosition.X+Car_width-1 > roundData.bonusPosition.X &&
			roundData.CarPosition.Y < roundData.bonusPosition.Y && roundData.CarPosition.Y+Car_lenght-1 > roundData.bonusPosition.Y {
			roundData.player.Score+=10
		}

		for i := range gameData.Roads {
			data := make([]byte, len(gameData.Roads[i]))
			copy(data, gameData.Roads[i])

			// Moving cursor at the beginning
			_, err := conn.Write(gameData.Clear)
			if err != nil {
				return
			}

			// Checking and updating complexity
			if roundData.player.Score > 100 && roundData.player.Score < 200 {
				roundData.Speed = 150
			} else if roundData.player.Score >= 200 && roundData.player.Score < 400 {
				roundData.BonusFactor = 5
				roundData.Speed = 100
			} else if roundData.player.Score >= 400 && roundData.player.Score < 600 {
				roundData.BonusFactor = 10
				roundData.BombFactor = 5
			} else if roundData.player.Score >= 600 {
				roundData.BonusFactor = 123
				roundData.BombFactor = 1
				roundData.Speed = 80
			}

			// Applying the bonus
			if roundData.bonusPosition.Y < road_lenght {
				data[roundData.bonusPosition.Y*road_width+roundData.bonusPosition.X] = byte('$')
				roundData.bonusPosition.Y++
			} else if rand.Int()%roundData.BonusFactor == 0 {
				roundData.bonusPosition.X, roundData.bonusPosition.Y = rand.Intn(road_width-3)+1, 0
			}

			// Applying the bomb
			if roundData.bombPosition.Y < road_lenght {
				data[roundData.bombPosition.Y*road_width+roundData.bombPosition.X] = byte('X')
				roundData.bombPosition.Y++
			} else if rand.Int()%roundData.BombFactor == 0 {
				roundData.bombPosition.X, roundData.bombPosition.Y = rand.Intn(road_width-3)+1, 0
			}

			// Applying the Car
			for line := 0; line < 7; line++ {
				copy(data[((roundData.CarPosition.Y+line)*road_width+roundData.CarPosition.X):((roundData.CarPosition.Y+line)*road_width+roundData.CarPosition.X)+15], gameData.Car[line*Car_width:line*Car_width+15])
			}

			// Applying the score
			scoreStr := fmt.Sprintf("%d", roundData.player.Score)
			for i := range scoreStr {
				data[i] = byte(scoreStr[i])

			}

			_, err = conn.Write(data)
			if err != nil {
				return
			}
			time.Sleep(time.Duration(roundData.Speed) * time.Millisecond)
		}
	}
}

func main() {
	var logFile string
	conf := &Config{}

	flag.StringVar(&logFile, "l", "/var/log/race.log", "Log file")
	flag.StringVar(&conf.AcidPath, "a", "/Users/leoleovich/go/src/github.com/leoleovich/race/artifacts", "Artifacts location")
	flag.StringVar(&conf.ScorePath, "s", "/Users/leoleovich/go/src/github.com/leoleovich/race/artifacts", "Score location")
	flag.Parse()

	logfile, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
	conf.Log = log.New(logfile, "", log.Ldate|log.Lmicroseconds|log.Lshortfile)

	l, err := net.Listen("tcp", ":4242")
	if err != nil {
		conf.Log.Println(err)
		os.Exit(2)
	}
	defer l.Close()

	gameData := GameData{}
	gameData.Roads = [][]byte{generateRoad(false), generateRoad(true)}
	gameData.Car, _ = getAcid(conf, "car.txt")
	gameData.Clear, _ = getAcid(conf, "clear.txt")
	scoreData, _ := getAcid(conf, "score.json")
	err = json.Unmarshal(scoreData, &gameData.Top)

	for {
		conn, err := l.Accept()
		if err != nil {
			conf.Log.Println("Failed to accept request", err)
		}
		go round(conf, conn, &gameData)
	}
}
<commit_msg>Reset bonus after it was taken<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/pkg/errors"
	"log"
	"math/rand"
	"net"
	"os"
	"strings"
	"time"
)

const road_width = 40
const road_lenght = 20
const Car_width = 16
const Car_lenght = 7
const result_width = 76
const max_players_in_top = 10

type Config struct {
	Log                 *log.Logger
	AcidPath, ScorePath string
}

type Point struct {
	X, Y int
}

type Player struct {
	Name  string
	Score int64
}

type GameData struct {
	Roads      [][]byte
	Car, Clear []byte
	Top        []Player
}

type RoundData struct {
	player                                   Player
	CarPosition, bombPosition, bonusPosition Point
	BombFactor, BonusFactor, Speed           int
	GameOver                                 []byte
}

func generateRoad(reverse bool) []byte {
	road := make([]byte, road_width*road_lenght)
	midline := reverse
	for row := 0; row < road_lenght; row++ {
		for column := 0; column < road_width; column++ {
			var symbol byte
			if column == 0 || column == road_width-2 {
				symbol = byte('|')
			} else if column == road_width-1 {
				symbol = byte('\n')
			} else if column == road_width/2-1 {
				if midline {
					symbol = byte('|')
				} else {
					symbol = byte(' ')
				}
				midline = !midline
			} else {
				symbol = byte(' ')
			}
			road[row*road_width+column] = symbol
		}

	}
	return road
}

func getAcid(conf *Config, fileName string) ([]byte, error) {
	fileStat, err := os.Stat(conf.AcidPath + "/" + fileName)
	if err != nil {
		conf.Log.Printf("Acid %s does not exist: %v\n", fileName, err)
		return []byte{}, err
	}

	acid := make([]byte, fileStat.Size())
	f, err := os.OpenFile(conf.AcidPath+"/"+fileName, os.O_RDONLY, os.ModePerm)
	if err != nil {
		conf.Log.Printf("Error while opening %s: %v\n", fileName, err)
		os.Exit(1)
	}
	defer f.Close()

	f.Read(acid)

	return acid, nil
}

func updatePosition(conn net.Conn, position *Point) {
	for {
		direction := make([]byte, 1)

		_, err := conn.Read(direction)
		if err != nil {
			return
		}

		switch direction[0] {
		case 68:
			// Left
			position.X--
		case 67:
			// Right
			position.X++
		case 65:
			// Up
			position.Y--
		case 66:
			// Down
			position.Y++
		}
	}
}

func updateScore(roundData *RoundData) {
	for {
		roundData.player.Score++
		time.Sleep(time.Duration(roundData.Speed) * time.Millisecond)
	}

}

func readName(conf *Config, conn net.Conn) (string, error) {
	conn.Write([]byte("Enter your name:"))
	io := bufio.NewReader(conn)
	name, err := io.ReadString('\n')
	if err != nil {
		conf.Log.Println("Error while name reading", err)
		return "", err
	}
	if name == "" {
		conf.Log.Println("Empty name")
		return "", errors.New("Empty name")
	}
	if len(name) > result_width/2 {
		conf.Log.Println("Too long name")
		return "", errors.New("Too long name")
	}
	return strings.Replace(name, "\n", "", -1), nil
}

func gameOver(conf *Config, conn net.Conn, roundData *RoundData, gameData *GameData) {

	conn.Write(gameData.Clear)

	// First we print current player result:
	// Score
	scoreStr := fmt.Sprintf("%d", roundData.player.Score)
	for i, char := range scoreStr {
		roundData.GameOver[i] = byte(char)
	}
	//:
	roundData.GameOver[result_width/2] = byte(':')
	//Name
	for i, char := range []byte(roundData.player.Name) {
		roundData.GameOver[result_width-1-len(roundData.player.Name)+i] = byte(char)
	}

	// Then we check on which place is current player
	inserted := false
	for i, player := range gameData.Top {
		if roundData.player.Score >= player.Score {
			// Insert new record
			gameData.Top = append(gameData.Top[:i], append([]Player{roundData.player}, gameData.Top[i:]...)...)
			inserted = true
			break
		}
	}
	if !inserted {
		gameData.Top = append(gameData.Top, roundData.player)
	}

	// Remove slowest user if top is full
	if len(gameData.Top) >= max_players_in_top {
		gameData.Top = gameData.Top[:max_players_in_top]
	}

	//TOP
	copy(roundData.GameOver[1*result_width+result_width/2-1:2*result_width+result_width/2+2], []byte("TOP"))

	// Then print new top
	for place, player := range gameData.Top {
		// Score
		scoreStr := fmt.Sprintf("%d", player.Score)
		for i, char := range scoreStr {
			roundData.GameOver[(2+place)*result_width+i] = byte(char)
		}
		//:
		roundData.GameOver[(2+place)*result_width+result_width/2] = byte(':')
		//Name
		for i, char := range []byte(player.Name) {
			roundData.GameOver[(2+place)*result_width+result_width-1-len(player.Name)+i] = byte(char)
		}
	}

	conn.Write(roundData.GameOver)
	// We do not need to check for error because user should not care, but logs are written
	saveScore(conf, gameData)
}

func saveScore(conf *Config, gameData *GameData) error {
	b, err := json.Marshal(gameData.Top)
	if err != nil {
		conf.Log.Println(err)
		return err
	}

	// Being sure file was not there
	os.Remove(conf.ScorePath + "/score.json")
	scoreFile, err := os.OpenFile(conf.ScorePath+"/score.json", os.O_RDWR|os.O_CREATE, 0600)
	if err != nil {
		conf.Log.Println(err)
		return err
	}
	defer scoreFile.Close()

	scoreFile.Write(b)
	return nil
}

func round(conf *Config, conn net.Conn, gameData *GameData) {
	defer conn.Close()

	roundData := RoundData{}
	roundData.CarPosition = Point{12, 12}
	roundData.bombPosition = Point{road_width, road_lenght}
	roundData.bonusPosition = Point{road_width, road_lenght}
	roundData.GameOver, _ = getAcid(conf, "game_over.txt")

	roundData.BombFactor = 10
	roundData.BonusFactor = 123
	roundData.Speed = 200

	name, err := readName(conf, conn)
	if err != nil {
		return
	}
	roundData.player.Name = name
	go updateScore(&roundData)
	go updatePosition(conn, &roundData.CarPosition)

	for {
		if roundData.CarPosition.X < 1 || roundData.CarPosition.X > 23 || roundData.CarPosition.Y < 1 || roundData.CarPosition.Y > 12 {
			// Hit the wall
			gameOver(conf, conn, &roundData, gameData)
			return
		} else if roundData.CarPosition.X <= roundData.bombPosition.X && roundData.CarPosition.X+Car_width-1 > roundData.bombPosition.X &&
			roundData.CarPosition.Y < roundData.bombPosition.Y && roundData.CarPosition.Y+Car_lenght-1 > roundData.bombPosition.Y {
			// Hit the bomb
			gameOver(conf, conn, &roundData, gameData)
			return
		} else if roundData.CarPosition.X <= roundData.bonusPosition.X && roundData.CarPosition.X+Car_width-1 > roundData.bonusPosition.X &&
			roundData.CarPosition.Y < roundData.bonusPosition.Y && roundData.CarPosition.Y+Car_lenght-1 > roundData.bonusPosition.Y {
			roundData.player.Score+=10
			roundData.bonusPosition = Point{road_width, road_lenght}
		}

		for i := range gameData.Roads {
			data := make([]byte, len(gameData.Roads[i]))
			copy(data, gameData.Roads[i])

			// Moving cursor at the beginning
			_, err := conn.Write(gameData.Clear)
			if err != nil {
				return
			}

			// Checking and updating complexity
			if roundData.player.Score > 100 && roundData.player.Score < 200 {
				roundData.Speed = 150
			} else if roundData.player.Score >= 200 && roundData.player.Score < 400 {
				roundData.BonusFactor = 5
				roundData.Speed = 100
			} else if roundData.player.Score >= 400 && roundData.player.Score < 600 {
				roundData.BonusFactor = 10
				roundData.BombFactor = 5
			} else if roundData.player.Score >= 600 {
				roundData.BonusFactor = 123
				roundData.BombFactor = 1
				roundData.Speed = 80
			}

			// Applying the bonus
			if roundData.bonusPosition.Y < road_lenght {
				data[roundData.bonusPosition.Y*road_width+roundData.bonusPosition.X] = byte('$')
				roundData.bonusPosition.Y++
			} else if rand.Int()%roundData.BonusFactor == 0 {
				roundData.bonusPosition.X, roundData.bonusPosition.Y = rand.Intn(road_width-3)+1, 0
			}

			// Applying the bomb
			if roundData.bombPosition.Y < road_lenght {
				data[roundData.bombPosition.Y*road_width+roundData.bombPosition.X] = byte('X')
				roundData.bombPosition.Y++
			} else if rand.Int()%roundData.BombFactor == 0 {
				roundData.bombPosition.X, roundData.bombPosition.Y = rand.Intn(road_width-3)+1, 0
			}

			// Applying the Car
			for line := 0; line < 7; line++ {
				copy(data[((roundData.CarPosition.Y+line)*road_width+roundData.CarPosition.X):((roundData.CarPosition.Y+line)*road_width+roundData.CarPosition.X)+15], gameData.Car[line*Car_width:line*Car_width+15])
			}

			// Applying the score
			scoreStr := fmt.Sprintf("%d", roundData.player.Score)
			for i := range scoreStr {
				data[i] = byte(scoreStr[i])

			}

			_, err = conn.Write(data)
			if err != nil {
				return
			}
			time.Sleep(time.Duration(roundData.Speed) * time.Millisecond)
		}
	}
}

func main() {
	var logFile string
	conf := &Config{}

	flag.StringVar(&logFile, "l", "/var/log/race.log", "Log file")
	flag.StringVar(&conf.AcidPath, "a", "/Users/leoleovich/go/src/github.com/leoleovich/race/artifacts", "Artifacts location")
	flag.StringVar(&conf.ScorePath, "s", "/Users/leoleovich/go/src/github.com/leoleovich/race/artifacts", "Score location")
	flag.Parse()

	logfile, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
	conf.Log = log.New(logfile, "", log.Ldate|log.Lmicroseconds|log.Lshortfile)

	l, err := net.Listen("tcp", ":4242")
	if err != nil {
		conf.Log.Println(err)
		os.Exit(2)
	}
	defer l.Close()

	gameData := GameData{}
	gameData.Roads = [][]byte{generateRoad(false), generateRoad(true)}
	gameData.Car, _ = getAcid(conf, "car.txt")
	gameData.Clear, _ = getAcid(conf, "clear.txt")
	scoreData, _ := getAcid(conf, "score.json")
	err = json.Unmarshal(scoreData, &gameData.Top)

	for {
		conn, err := l.Accept()
		if err != nil {
			conf.Log.Println("Failed to accept request", err)
		}
		go round(conf, conn, &gameData)
	}
}
<|endoftext|>


<commit_before>package rain

import (
	"crypto/rand"
	"net"
	"sync"

	"github.com/cenkalti/log"

	"github.com/cenkalti/rain/internal/connection"
	"github.com/cenkalti/rain/internal/logger"
	"github.com/cenkalti/rain/internal/protocol"
	"github.com/cenkalti/rain/internal/torrent"
)

// Limits
const (
	maxPeerServe      = 200
	maxPeerPerTorrent = 50
	downloadSlots     = 4
	uploadSlots       = 4
)

// http://www.bittorrent.org/beps/bep_0020.html
var peerIDPrefix = []byte("-RN" + build + "-")
var build = "0001"

func SetLogLevel(l log.Level) { logger.LogLevel = l }

type Rain struct {
	config        *Config
	peerID        protocol.PeerID
	listener      *net.TCPListener
	transfers     map[protocol.InfoHash]*transfer // all active transfers
	transfersSKey map[[20]byte]*transfer          // for encryption
	transfersM    sync.Mutex
	log           logger.Logger
}

// New returns a pointer to new Rain BitTorrent client.
func New(c *Config) (*Rain, error) {
	peerID, err := generatePeerID()
	if err != nil {
		return nil, err
	}
	return &Rain{
		config:        c,
		peerID:        peerID,
		transfers:     make(map[protocol.InfoHash]*transfer),
		transfersSKey: make(map[[20]byte]*transfer),
		log:           logger.New("rain"),
	}, nil
}

func generatePeerID() (protocol.PeerID, error) {
	var id protocol.PeerID
	copy(id[:], peerIDPrefix)
	_, err := rand.Read(id[len(peerIDPrefix):])
	return id, err
}

// Listen peer port and accept incoming peer connections.
func (r *Rain) Listen() error {
	var err error
	addr := &net.TCPAddr{Port: r.config.Port}
	r.listener, err = net.ListenTCP("tcp4", addr)
	if err != nil {
		return err
	}
	r.log.Notice("Listening peers on tcp://" + r.listener.Addr().String())
	go r.accepter()
	return nil
}

func (r *Rain) Close() error { return r.listener.Close() }

func (r *Rain) accepter() {
	limit := make(chan struct{}, maxPeerServe)
	for {
		conn, err := r.listener.Accept()
		if err != nil {
			r.log.Error(err)
			return
		}
		limit <- struct{}{}
		go func(conn net.Conn) {
			defer func() {
				// if err := recover(); err != nil {
				// r.log.Critical(err)
				// }
				conn.Close()
				<-limit
			}()
			r.servePeerConn(newPeer(conn))
		}(conn)
	}
}

func (r *Rain) PeerID() protocol.PeerID { return r.peerID }
func (r *Rain) Port() uint16            { return uint16(r.listener.Addr().(*net.TCPAddr).Port) }

func (r *Rain) servePeerConn(p *peer) {
	p.log.Debugln("Serving peer", p.conn.RemoteAddr())

	getSKey := func(sKeyHash [20]byte) (sKey []byte) {
		r.transfersM.Lock()
		t, ok := r.transfersSKey[sKeyHash]
		r.transfersM.Unlock()
		if ok {
			sKey = t.torrent.Info.Hash[:]
		}
		return
	}

	hasInfoHash := func(ih protocol.InfoHash) bool {
		r.transfersM.Lock()
		_, ok := r.transfers[ih]
		r.transfersM.Unlock()
		return ok
	}

	_, _, ih, _, err := connection.Accept(p.conn, r.config.Encryption.ForceIncoming, getSKey, hasInfoHash, [8]byte{}, r.peerID)
	if err != nil {
		if err == connection.ErrOwnConnection {
			r.log.Debug(err)
		} else {
			r.log.Error(err)
		}
		return
	}

	r.transfersM.Lock()
	t, ok := r.transfers[ih]
	r.transfersM.Unlock()
	if !ok {
		r.log.Debug("Transfer is removed during incoming handshake")
		return
	}

	p.log.Debugln("servePeerConn: Handshake completed")
	p.Serve(t)
}

// Download starts a download and waits for it to finish.
func (r *Rain) Download(torrentPath, where string) error {
	torrent, err := torrent.New(torrentPath)
	if err != nil {
		return err
	}
	r.log.Debugf("Parsed torrent file: %#v", torrent)

	t, err := r.newTransfer(torrent, where)
	if err != nil {
		return err
	}

	go t.Run()
	<-t.Finished

	return nil
}

func (r *Rain) DownloadMagnet(url, where string) error {
	panic("not implemented")
}
<commit_msg>do not panic when serving<commit_after>package rain

import (
	"crypto/rand"
	"net"
	"sync"

	"github.com/cenkalti/log"

	"github.com/cenkalti/rain/internal/connection"
	"github.com/cenkalti/rain/internal/logger"
	"github.com/cenkalti/rain/internal/protocol"
	"github.com/cenkalti/rain/internal/torrent"
)

// Limits
const (
	maxPeerServe      = 200
	maxPeerPerTorrent = 50
	downloadSlots     = 4
	uploadSlots       = 4
)

// http://www.bittorrent.org/beps/bep_0020.html
var peerIDPrefix = []byte("-RN" + build + "-")
var build = "0001"

func SetLogLevel(l log.Level) { logger.LogLevel = l }

type Rain struct {
	config        *Config
	peerID        protocol.PeerID
	listener      *net.TCPListener
	transfers     map[protocol.InfoHash]*transfer // all active transfers
	transfersSKey map[[20]byte]*transfer          // for encryption
	transfersM    sync.Mutex
	log           logger.Logger
}

// New returns a pointer to new Rain BitTorrent client.
func New(c *Config) (*Rain, error) {
	peerID, err := generatePeerID()
	if err != nil {
		return nil, err
	}
	return &Rain{
		config:        c,
		peerID:        peerID,
		transfers:     make(map[protocol.InfoHash]*transfer),
		transfersSKey: make(map[[20]byte]*transfer),
		log:           logger.New("rain"),
	}, nil
}

func generatePeerID() (protocol.PeerID, error) {
	var id protocol.PeerID
	copy(id[:], peerIDPrefix)
	_, err := rand.Read(id[len(peerIDPrefix):])
	return id, err
}

// Listen peer port and accept incoming peer connections.
func (r *Rain) Listen() error {
	var err error
	addr := &net.TCPAddr{Port: r.config.Port}
	r.listener, err = net.ListenTCP("tcp4", addr)
	if err != nil {
		return err
	}
	r.log.Notice("Listening peers on tcp://" + r.listener.Addr().String())
	go r.accepter()
	return nil
}

func (r *Rain) Close() error { return r.listener.Close() }

func (r *Rain) accepter() {
	limit := make(chan struct{}, maxPeerServe)
	for {
		conn, err := r.listener.Accept()
		if err != nil {
			r.log.Error(err)
			return
		}
		limit <- struct{}{}
		go func(conn net.Conn) {
			defer func() {
				if err := recover(); err != nil {
					r.log.Critical(err)
				}
				conn.Close()
				<-limit
			}()
			r.servePeerConn(newPeer(conn))
		}(conn)
	}
}

func (r *Rain) PeerID() protocol.PeerID { return r.peerID }
func (r *Rain) Port() uint16            { return uint16(r.listener.Addr().(*net.TCPAddr).Port) }

func (r *Rain) servePeerConn(p *peer) {
	p.log.Debugln("Serving peer", p.conn.RemoteAddr())

	getSKey := func(sKeyHash [20]byte) (sKey []byte) {
		r.transfersM.Lock()
		t, ok := r.transfersSKey[sKeyHash]
		r.transfersM.Unlock()
		if ok {
			sKey = t.torrent.Info.Hash[:]
		}
		return
	}

	hasInfoHash := func(ih protocol.InfoHash) bool {
		r.transfersM.Lock()
		_, ok := r.transfers[ih]
		r.transfersM.Unlock()
		return ok
	}

	_, _, ih, _, err := connection.Accept(p.conn, r.config.Encryption.ForceIncoming, getSKey, hasInfoHash, [8]byte{}, r.peerID)
	if err != nil {
		if err == connection.ErrOwnConnection {
			r.log.Debug(err)
		} else {
			r.log.Error(err)
		}
		return
	}

	r.transfersM.Lock()
	t, ok := r.transfers[ih]
	r.transfersM.Unlock()
	if !ok {
		r.log.Debug("Transfer is removed during incoming handshake")
		return
	}

	p.log.Debugln("servePeerConn: Handshake completed")
	p.Serve(t)
}

// Download starts a download and waits for it to finish.
func (r *Rain) Download(torrentPath, where string) error {
	torrent, err := torrent.New(torrentPath)
	if err != nil {
		return err
	}
	r.log.Debugf("Parsed torrent file: %#v", torrent)

	t, err := r.newTransfer(torrent, where)
	if err != nil {
		return err
	}

	go t.Run()
	<-t.Finished

	return nil
}

func (r *Rain) DownloadMagnet(url, where string) error {
	panic("not implemented")
}
<|endoftext|>


<commit_before>//Package gsm provides a parser for dongle scanneruration file for asterisk. The
//scanneruration format is a subset of the astersk dial plan.
//
// The abstract syntax tree is basic, and made to accomodate the urgent need to
// parse the scanneruration file and also as a means to see if scanning is done
// well will the scanner.
//
//TODO(gernest) rewrite the AST and move it into a separate package.
package parser

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"

	"github.com/FarmRadioHangar/fessboxconfig/ast"
	"github.com/FarmRadioHangar/fessboxconfig/scanner"
)

// Ast is an abstract syntax tree for a scanneruration object. The scanneruration
// format should be section based( or you can say namespacing).
type Ast struct {
	sections []*NodeSection
}

//Section returns the section named name or an error if the section is not found
//in the Ast
func (a *Ast) Section(name string) (*NodeSection, error) {
	for _, v := range a.sections {
		if v.name == name {
			return v, nil
		}
	}
	return nil, errors.New("section not found")
}

//ToJSON marhalls *Ast to a json string and writes the result to dst
func (a *Ast) ToJSON(dst io.Writer) error {
	o := make(map[string]interface{})
	for _, v := range a.sections {
		sec := make(map[string]interface{})
		for _, value := range v.values {
			sec[value.key] = value.value
		}
		o[v.name] = sec
	}
	return json.NewEncoder(dst).Encode(o)
}

//LoadJSON loads AST from json src
func (a *Ast) LoadJSON(src []byte) error {
	var obj map[string]interface{}
	err := json.Unmarshal(src, &obj)
	if err != nil {
		return err
	}
	for key, value := range obj {
		ns := &NodeSection{name: key}
		switch value.(type) {
		case map[string]interface{}:
			sec := value.(map[string]interface{})
			for k, v := range sec {
				ident := &nodeIdent{}
				ident.key = k
				ident.value = fmt.Sprint(v)
				ns.values = append(ns.values, ident)
			}
		}
		a.sections = append(a.sections, ns)
	}
	return nil
}

func PrintAst(dst io.Writer, src *Ast) {
	for _, v := range src.sections {
		if v.name == "main" {
			fmt.Fprintf(dst, "\n\n")
			for _, sub := range v.values {
				fmt.Fprintf(dst, "%s=%s \n", sub.key, sub.value)
			}
			fmt.Fprint(dst, "\n\n")
			continue
		}
		fmt.Fprintf(dst, "\n [%s]\n", v.name)
		for _, sub := range v.values {
			fmt.Fprintf(dst, "%s=%s \n", sub.key, sub.value)
		}
		fmt.Fprint(dst, "\n\n")
		continue
	}
}

//NodeSection represent a section in the scanneruration object. Sections are name
//spaces that contains scannerurations definitions under them.
type NodeSection struct {
	name   string
	line   int
	values []*nodeIdent
}

//Get access the key definition and returns its value or an error if the key is
//not part of the section.
func (n *NodeSection) Get(key string) (string, error) {
	for _, v := range n.values {
		if v.key == key {
			return v.value, nil
		}
	}
	return "", errors.New("key not found")
}

//nodeIdent represents a scanneruration definition, which can be the key value
//definition.
type nodeIdent struct {
	key   string
	value string
	line  int
}

// Parser is a Parser for scanneruration files. It supports utf-8 encoded
// scanneruration files.
//
// Only modem scanneruration files are supported for the momment.
type Parser struct {
	tokens  []*ast.Token
	Ast     *Ast
	currPos int
}

//NewParser returns a new Parser that parses input from src. The returned Parser
//supports gsm modem scanneruration format only.
func NewParser(src io.Reader) (*Parser, error) {
	s := scanner.NewScanner(src)
	var toks []*ast.Token
	var err error
	var tok *ast.Token
	for err == nil {
		tok, err = s.Scan()
		if err != nil {
			if err.Error() != io.EOF.Error() {
				return nil, err
			}

			// we are at the end of the input
			break
		}
		if tok != nil {
			switch tok.Type {
			case ast.WhiteSpace, ast.Comment:

				// Skip comments and whitespaces but preserve the newlines to aid in
				// parsing
				continue
			default:
				toks = append(toks, tok)
			}

		}
	}
	return &Parser{tokens: toks, Ast: &Ast{}}, nil
}

// Parse parses the scanned input and return its *Ast or arror if any.
func (p *Parser) Parse() (*Ast, error) {
	var err error
	if err != nil {
		return nil, err
	}
	mainSec := &NodeSection{name: "main"}
END:
	for {
		tok := p.next()
		if tok.Type == ast.EOF {
			break END
		}
		switch tok.Type {
		case ast.LBrace:
			p.rewind()
			err = p.parseSection()
			if err != nil {
				break END
			}
		case ast.Ident:
			p.rewind()
			err = p.parseIdent(mainSec)
			if err != nil {
				break END
			}

		}
	}
	if err != nil {
		return nil, err
	}
	p.Ast.sections = append([]*NodeSection{mainSec}, p.Ast.sections...)
	return p.Ast, err
}

func (p *Parser) next() *ast.Token {
	if p.currPos >= len(p.tokens)-1 {
		return &ast.Token{Type: ast.EOF}
	}
	t := p.tokens[p.currPos]
	p.currPos++
	return t
}

func (p *Parser) seek(at int) {
	p.currPos = at
}

func (p *Parser) parseSection() (err error) {
	left := p.next()
	if left.Type != ast.LBrace {
		return errors.New("bad token")
	}
	ns := &NodeSection{}
	completeName := false
END:
	for {
	BEGIN:
		tok := p.next()
		if tok.Type == ast.EOF {
			p.rewind()
			break END
		}

		if !completeName {
			switch tok.Type {
			case ast.Ident:
				ns.name = ns.name + tok.Text
				goto BEGIN
			case ast.RBrace:
				completeName = true
				goto BEGIN
			}
		}
		switch tok.Type {
		case ast.NLine:
			n1 := p.next()
			if n1.Type == ast.NLine {
				n2 := p.next()
				if n2.Type == ast.NLine {
					break END
				}
				p.rewind()
				goto BEGIN
			}
			goto BEGIN
		case ast.Ident:
			p.rewind()
			err = p.parseIdent(ns)
			if err != nil {
				break END
			}
		default:
			break END
		}
	}
	if err == nil {
		p.Ast.sections = append(p.Ast.sections, ns)
	}
	return
}

func (p *Parser) rewind() {
	p.currPos--
}

func (p *Parser) parseIdent(sec *NodeSection) (err error) {
	n := &nodeIdent{}
	doneKey := false
END:
	for {
	BEGIN:
		tok := p.next()
		if tok.Type == ast.EOF {
			p.rewind()
			break END
		}

		if !doneKey {
			switch tok.Type {
			case ast.Ident:
				n.key = n.key + tok.Text
				goto BEGIN
			case ast.Assign:
				doneKey = true
				goto BEGIN
			default:
				err = errors.New("some fish")
				break END
			}

		}
		switch tok.Type {
		case ast.Ident:
			n.value = n.value + tok.Text
			goto BEGIN
		case ast.NLine:
			break END
		default:
			err = errors.New("some fish")
			break END
		}
	}
	if err == nil {
		sec.values = append(sec.values, n)
	}

	return
}
<commit_msg>Update configuration file<commit_after>//Package gsm provides a parser for  asterisk configuration files
//
// The abstract syntax tree is basic, and made to accomodate the urgent need to
// parse the scanneruration file and also as a means to see if scanning is done
// well will the scanner.
//
//TODO(gernest) rewrite the AST and move it into a separate package.
package parser

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"

	"github.com/FarmRadioHangar/fessboxconfig/ast"
	"github.com/FarmRadioHangar/fessboxconfig/scanner"
)

// Ast is an abstract syntax tree for a scanneruration object. The scanneruration
// format should be section based( or you can say namespacing).
type Ast struct {
	sections []*NodeSection
}

//Section returns the section named name or an error if the section is not found
//in the Ast
func (a *Ast) Section(name string) (*NodeSection, error) {
	for _, v := range a.sections {
		if v.name == name {
			return v, nil
		}
	}
	return nil, errors.New("section not found")
}

//ToJSON marhalls *Ast to a json string and writes the result to dst
func (a *Ast) ToJSON(dst io.Writer) error {
	o := make(map[string]interface{})
	for _, v := range a.sections {
		sec := make(map[string]interface{})
		for _, value := range v.values {
			sec[value.key] = value.value
		}
		o[v.name] = sec
	}
	return json.NewEncoder(dst).Encode(o)
}

//LoadJSON loads AST from json src
func (a *Ast) LoadJSON(src []byte) error {
	var obj map[string]interface{}
	err := json.Unmarshal(src, &obj)
	if err != nil {
		return err
	}
	for key, value := range obj {
		ns := &NodeSection{name: key}
		switch value.(type) {
		case map[string]interface{}:
			sec := value.(map[string]interface{})
			for k, v := range sec {
				ident := &nodeIdent{}
				ident.key = k
				ident.value = fmt.Sprint(v)
				ns.values = append(ns.values, ident)
			}
		}
		a.sections = append(a.sections, ns)
	}
	return nil
}

func PrintAst(dst io.Writer, src *Ast) {
	for _, v := range src.sections {
		if v.name == "main" {
			fmt.Fprintf(dst, "\n\n")
			for _, sub := range v.values {
				fmt.Fprintf(dst, "%s=%s \n", sub.key, sub.value)
			}
			fmt.Fprint(dst, "\n\n")
			continue
		}
		fmt.Fprintf(dst, "\n [%s]\n", v.name)
		for _, sub := range v.values {
			fmt.Fprintf(dst, "%s=%s \n", sub.key, sub.value)
		}
		fmt.Fprint(dst, "\n\n")
		continue
	}
}

//NodeSection represent a section in the scanneruration object. Sections are name
//spaces that contains scannerurations definitions under them.
type NodeSection struct {
	name   string
	line   int
	values []*nodeIdent
}

//Get access the key definition and returns its value or an error if the key is
//not part of the section.
func (n *NodeSection) Get(key string) (string, error) {
	for _, v := range n.values {
		if v.key == key {
			return v.value, nil
		}
	}
	return "", errors.New("key not found")
}

//nodeIdent represents a scanneruration definition, which can be the key value
//definition.
type nodeIdent struct {
	key   string
	value string
	line  int
}

// Parser is a Parser for scanneruration files. It supports utf-8 encoded
// scanneruration files.
//
// Only modem scanneruration files are supported for the momment.
type Parser struct {
	tokens  []*ast.Token
	Ast     *Ast
	currPos int
}

//NewParser returns a new Parser that parses input from src. The returned Parser
//supports gsm modem scanneruration format only.
func NewParser(src io.Reader) (*Parser, error) {
	s := scanner.NewScanner(src)
	var toks []*ast.Token
	var err error
	var tok *ast.Token
	for err == nil {
		tok, err = s.Scan()
		if err != nil {
			if err.Error() != io.EOF.Error() {
				return nil, err
			}

			// we are at the end of the input
			break
		}
		if tok != nil {
			switch tok.Type {
			case ast.WhiteSpace, ast.Comment:

				// Skip comments and whitespaces but preserve the newlines to aid in
				// parsing
				continue
			default:
				toks = append(toks, tok)
			}

		}
	}
	return &Parser{tokens: toks, Ast: &Ast{}}, nil
}

// Parse parses the scanned input and return its *Ast or arror if any.
func (p *Parser) Parse() (*Ast, error) {
	var err error
	if err != nil {
		return nil, err
	}
	mainSec := &NodeSection{name: "main"}
END:
	for {
		tok := p.next()
		if tok.Type == ast.EOF {
			break END
		}
		switch tok.Type {
		case ast.LBrace:
			p.rewind()
			err = p.parseSection()
			if err != nil {
				break END
			}
		case ast.Ident:
			p.rewind()
			err = p.parseIdent(mainSec)
			if err != nil {
				break END
			}

		}
	}
	if err != nil {
		return nil, err
	}
	p.Ast.sections = append([]*NodeSection{mainSec}, p.Ast.sections...)
	return p.Ast, err
}

func (p *Parser) next() *ast.Token {
	if p.currPos >= len(p.tokens)-1 {
		return &ast.Token{Type: ast.EOF}
	}
	t := p.tokens[p.currPos]
	p.currPos++
	return t
}

func (p *Parser) seek(at int) {
	p.currPos = at
}

func (p *Parser) parseSection() (err error) {
	left := p.next()
	if left.Type != ast.LBrace {
		return errors.New("bad token")
	}
	ns := &NodeSection{}
	completeName := false
END:
	for {
	BEGIN:
		tok := p.next()
		if tok.Type == ast.EOF {
			p.rewind()
			break END
		}

		if !completeName {
			switch tok.Type {
			case ast.Ident:
				ns.name = ns.name + tok.Text
				goto BEGIN
			case ast.RBrace:
				completeName = true
				goto BEGIN
			}
		}
		switch tok.Type {
		case ast.NLine:
			n1 := p.next()
			if n1.Type == ast.NLine {
				n2 := p.next()
				if n2.Type == ast.NLine {
					break END
				}
				p.rewind()
				goto BEGIN
			}
			goto BEGIN
		case ast.Ident:
			p.rewind()
			err = p.parseIdent(ns)
			if err != nil {
				break END
			}
		default:
			break END
		}
	}
	if err == nil {
		p.Ast.sections = append(p.Ast.sections, ns)
	}
	return
}

func (p *Parser) rewind() {
	p.currPos--
}

func (p *Parser) parseIdent(sec *NodeSection) (err error) {
	n := &nodeIdent{}
	doneKey := false
END:
	for {
	BEGIN:
		tok := p.next()
		if tok.Type == ast.EOF {
			p.rewind()
			break END
		}

		if !doneKey {
			switch tok.Type {
			case ast.Ident:
				n.key = n.key + tok.Text
				goto BEGIN
			case ast.Assign:
				doneKey = true
				goto BEGIN
			default:
				err = errors.New("some fish")
				break END
			}

		}
		switch tok.Type {
		case ast.Ident:
			n.value = n.value + tok.Text
			goto BEGIN
		case ast.NLine:
			break END
		default:
			err = errors.New("some fish")
			break END
		}
	}
	if err == nil {
		sec.values = append(sec.values, n)
	}

	return
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"gopkg.in/mgo.v2"

	germanEntity "github.com/peteraba/d5/lib/german/entity"
	"github.com/peteraba/d5/lib/server"
	"github.com/peteraba/d5/lib/util"
)

const name = "parser"
const version = "0.1"
const usage = `
Parser supports CLI and Server mode.

In CLI mode it expects input data on standard input, in server mode as raw POST body

Usage:
  parser [--server] [--port=<n>] [--debug] [--user]
  parser -h | --help
  parser -v | --version

Options:
  -s, --server    run in server mode
  -p, --port=<n>  port to open (server mode only) [default: 10010]
  -d, --debug     skip ticks and generate fake data concurrently
  -v, --version   show version information
  -h, --help      show help information
  -u, --user      user the data belongs to (cli mode only)

Accepted input data:
  - Raw JSON data to parse
`

/**
* DOMAIN
 */
func logParseErrors(isDebug bool, parseErrors []string) {
	if !isDebug {
		return
	}

	for _, word := range parseErrors {
		log.Printf("Failed: %v\n", word)
	}
}

func parseDictionary(dictionary [][8]string, user string) ([]germanEntity.Word, []string) {
	var (
		words       = []germanEntity.Word{}
		parseErrors = []string{}
	)

	for _, rawWord := range dictionary {
		word, german := createWord(rawWord, user)

		words = append(words, word)

		if german == "" {
			continue
		}

		parseErrors = append(parseErrors, german)
	}

	return words, parseErrors
}

func createWord(word [8]string, user string) (germanEntity.Word, string) {
	var (
		w                  germanEntity.Word
		articleOrAuxiliary = word[0]
		german             = word[1]
		english            = word[2]
		third              = word[3]
		category           = word[4]
		learned            = word[5]
		score              = word[6]
		tags               = word[7]
	)

	if english == "" {
		return w, german
	}

	switch category {
	case "adj":
		w = germanEntity.NewAdjective(german, english, third, user, learned, score, tags)
		break
	case "noun":
		if germanEntity.NounRegexp.MatchString(german) {
			w = germanEntity.NewNoun(articleOrAuxiliary, german, english, third, user, learned, score, tags)
		}
		break
	case "verb":
		if germanEntity.VerbRegexp.MatchString(german) {
			w = germanEntity.NewVerb(articleOrAuxiliary, german, english, third, user, learned, score, tags)
		}
		break
	default:
		w = germanEntity.NewAny(german, english, third, category, user, learned, score, tags, []string{})
	}

	if w != nil {
		return w, ""
	}

	w = germanEntity.NewAny(german, english, third, category, user, learned, score, tags, []string{"Parsing failed."})

	return w, german
}

/**
 * CLI
 */

func serveCli(isDebug bool, user string) {
	err := cliHandler(isDebug, user)

	util.LogFatalErr(err, isDebug)
}

func cliHandler(isDebug bool, user string) error {
	input, err := util.ReadStdInput()
	if err != nil {
		return err
	}

	words, parseErrors := getParserData(input, user)

	logParseErrors(isDebug, parseErrors)

	b, err := json.Marshal(words)
	if err != nil {
		return err
	}

	fmt.Println(string(b))

	return nil
}

/**
 * SERVER
 */

func startServer(port int, isDebug bool) {
	s := server.MakeServer(port, nil, isDebug)

	s.AddHandler("/", parseHandle, server.PostOnly)

	s.Start()
}

func parseHandle(w http.ResponseWriter, r *http.Request, mgoDb *mgo.Database, isDebug bool) error {
	words, parseErrors := getServerParserData(r)
	logParseErrors(isDebug, parseErrors)

	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	err := json.NewEncoder(w).Encode(words)

	return err
}

func getServerParserData(r *http.Request) ([]germanEntity.Word, []string) {
	rawBody, _ := ioutil.ReadAll(r.Body)
	user := r.FormValue("user")

	return getParserData(rawBody, user)
}

/**
 * INPUT PARSING
 */

func getParserData(rawInput []byte, user string) ([]germanEntity.Word, []string) {
	var dictionary = [][8]string{}

	err := json.Unmarshal(rawInput, &dictionary)
	if err {
		return []germanEntity.Word{}, []string{}
	}

	words, parseErrors := parseDictionary(dictionary, user)

	return words, parseErrors
}

/**
 * MAIN
 */

func main() {
	cliArguments := util.GetCliArguments(usage, name, version)
	isServer, port, isDebug := util.GetServerOptions(cliArguments)
	user, _ := cliArguments["--server"].(string)

	if isServer {
		startServer(port, isDebug)
	} else {
		serveCli(isDebug, user)
	}
}
<commit_msg>Parser build fixed<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"gopkg.in/mgo.v2"

	germanEntity "github.com/peteraba/d5/lib/german/entity"
	"github.com/peteraba/d5/lib/server"
	"github.com/peteraba/d5/lib/util"
)

const name = "parser"
const version = "0.1"
const usage = `
Parser supports CLI and Server mode.

In CLI mode it expects input data on standard input, in server mode as raw POST body

Usage:
  parser [--server] [--port=<n>] [--debug] [--user]
  parser -h | --help
  parser -v | --version

Options:
  -s, --server    run in server mode
  -p, --port=<n>  port to open (server mode only) [default: 10010]
  -d, --debug     skip ticks and generate fake data concurrently
  -v, --version   show version information
  -h, --help      show help information
  -u, --user      user the data belongs to (cli mode only)

Accepted input data:
  - Raw JSON data to parse
`

/**
* DOMAIN
 */
func logParseErrors(isDebug bool, parseErrors []string) {
	if !isDebug {
		return
	}

	for _, word := range parseErrors {
		log.Printf("Failed: %v\n", word)
	}
}

func parseDictionary(dictionary [][8]string, user string) ([]germanEntity.Word, []string) {
	var (
		words       = []germanEntity.Word{}
		parseErrors = []string{}
	)

	for _, rawWord := range dictionary {
		word, german := createWord(rawWord, user)

		words = append(words, word)

		if german == "" {
			continue
		}

		parseErrors = append(parseErrors, german)
	}

	return words, parseErrors
}

func createWord(word [8]string, user string) (germanEntity.Word, string) {
	var (
		w                  germanEntity.Word
		articleOrAuxiliary = word[0]
		german             = word[1]
		english            = word[2]
		third              = word[3]
		category           = word[4]
		learned            = word[5]
		score              = word[6]
		tags               = word[7]
	)

	if english == "" {
		return w, german
	}

	switch category {
	case "adj":
		w = germanEntity.NewAdjective(german, english, third, user, learned, score, tags)
		break
	case "noun":
		if germanEntity.NounRegexp.MatchString(german) {
			w = germanEntity.NewNoun(articleOrAuxiliary, german, english, third, user, learned, score, tags)
		}
		break
	case "verb":
		if germanEntity.VerbRegexp.MatchString(german) {
			w = germanEntity.NewVerb(articleOrAuxiliary, german, english, third, user, learned, score, tags)
		}
		break
	default:
		w = germanEntity.NewAny(german, english, third, category, user, learned, score, tags, []string{})
	}

	if w != nil {
		return w, ""
	}

	w = germanEntity.NewAny(german, english, third, category, user, learned, score, tags, []string{"Parsing failed."})

	return w, german
}

/**
 * CLI
 */

func serveCli(isDebug bool, user string) {
	err := cliHandler(isDebug, user)

	util.LogFatalErr(err, isDebug)
}

func cliHandler(isDebug bool, user string) error {
	input, err := util.ReadStdInput()
	if err != nil {
		return err
	}

	words, parseErrors := getParserData(input, user)

	logParseErrors(isDebug, parseErrors)

	b, err := json.Marshal(words)
	if err != nil {
		return err
	}

	fmt.Println(string(b))

	return nil
}

/**
 * SERVER
 */

func startServer(port int, isDebug bool) {
	s := server.MakeServer(port, nil, isDebug)

	s.AddHandler("/", parseHandle, server.PostOnly)

	s.Start()
}

func parseHandle(w http.ResponseWriter, r *http.Request, mgoDb *mgo.Database, isDebug bool) error {
	words, parseErrors := getServerParserData(r)
	logParseErrors(isDebug, parseErrors)

	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	err := json.NewEncoder(w).Encode(words)

	return err
}

func getServerParserData(r *http.Request) ([]germanEntity.Word, []string) {
	rawBody, _ := ioutil.ReadAll(r.Body)
	user := r.FormValue("user")

	return getParserData(rawBody, user)
}

/**
 * INPUT PARSING
 */

func getParserData(rawInput []byte, user string) ([]germanEntity.Word, []string) {
	var dictionary = [][8]string{}

	err := json.Unmarshal(rawInput, &dictionary)
	if err != nil {
		return []germanEntity.Word{}, []string{}
	}

	words, parseErrors := parseDictionary(dictionary, user)

	return words, parseErrors
}

/**
 * MAIN
 */

func main() {
	cliArguments := util.GetCliArguments(usage, name, version)
	isServer, port, isDebug := util.GetServerOptions(cliArguments)
	user, _ := cliArguments["--server"].(string)

	if isServer {
		startServer(port, isDebug)
	} else {
		serveCli(isDebug, user)
	}
}
<|endoftext|>


<commit_before>package schema

import "testing"

func TestCastAny(t *testing.T) {
	got, err := castAny("foo")
	if err != nil {
		t.Fatalf("err want:nil got:%q", err)
	}
	want := "foo"
	if want != got {
		t.Fatalf("val want:%s got:%s", want, got)
	}
}

func TestEncodeAny(t *testing.T) {
	got, err := encodeAny(10)
	if err != nil {
		t.Fatalf("err want:nil got:%q", err)
	}
	want := "10"
	if want != got {
		t.Fatalf("val want:%s got:%s", want, got)
	}
}
<commit_msg>Added matryer/is<commit_after>package schema

import (
	"testing"

	"github.com/matryer/is"
)

func TestCastAny(t *testing.T) {
	is := is.New(t)

	got, err := castAny("foo")
	is.NoErr(err)
	is.Equal("foo", got)
}

func TestEncodeAny(t *testing.T) {
	is := is.New(t)

	got, err := encodeAny(10)
	is.NoErr(err)
	is.Equal("10", got)
}
<|endoftext|>


<commit_before>// RTLAMR - An rtl-sdr receiver for smart meters operating in the 900MHz ISM band.
// Copyright (C) 2015 Douglas Hall
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"encoding/xml"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/signal"
	"runtime/pprof"
	"time"

	"github.com/bemasher/rtlamr/parse"
	"github.com/bemasher/rtltcp"

	_ "github.com/bemasher/rtlamr/idm"
	_ "github.com/bemasher/rtlamr/r900"
	_ "github.com/bemasher/rtlamr/scm"
	_ "github.com/bemasher/rtlamr/scmplus"
)

var rcvr Receiver

type Receiver struct {
	rtltcp.SDR
	p  parse.Parser
	fc parse.FilterChain
}

func (rcvr *Receiver) NewReceiver() {
	var err error
	if rcvr.p, err = parse.NewParser(*msgType, *symbolLength, *decimation); err != nil {
		log.Fatal(err)
	}

	// Connect to rtl_tcp server.
	if err := rcvr.Connect(nil); err != nil {
		log.Fatal(err)
	}

	rcvr.HandleFlags()

	cfg := rcvr.p.Cfg()

	gainFlagSet := false
	flag.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "centerfreq":
			cfg.CenterFreq = uint32(rcvr.Flags.CenterFreq)
		case "samplerate":
			cfg.SampleRate = int(rcvr.Flags.SampleRate)
		case "gainbyindex", "tunergainmode", "tunergain", "agcmode":
			gainFlagSet = true
		case "unique":
			rcvr.fc.Add(NewUniqueFilter())
		case "filterid":
			rcvr.fc.Add(meterID)
		case "filtertype":
			rcvr.fc.Add(meterType)
		}
	})

	rcvr.SetCenterFreq(cfg.CenterFreq)
	rcvr.SetSampleRate(uint32(cfg.SampleRate))

	if !gainFlagSet {
		rcvr.SetGainMode(true)
	}

	if !*quiet {
		rcvr.p.Log()
	}

	// Tell the user how many gain settings were reported by rtl_tcp.
	if !*quiet {
		log.Println("GainCount:", rcvr.SDR.Info.GainCount)
	}

	return
}

func (rcvr *Receiver) Run() {
	// Setup signal channel for interruption.
	sigint := make(chan os.Signal, 1)
	signal.Notify(sigint, os.Kill, os.Interrupt)

	// Setup time limit channel
	tLimit := make(<-chan time.Time, 1)
	if *timeLimit != 0 {
		tLimit = time.After(*timeLimit)
	}

	in, out := io.Pipe()

	go func() {
		tcpBlock := make([]byte, 16384)
		for {
			n, err := rcvr.Read(tcpBlock)
			if err != nil {
				return
			}
			out.Write(tcpBlock[:n])
		}
	}()

	block := make([]byte, rcvr.p.Cfg().BlockSize2)

	start := time.Now()
	for {
		// Exit on interrupt or time limit, otherwise receive.
		select {
		case <-sigint:
			return
		case <-tLimit:
			fmt.Println("Time Limit Reached:", time.Since(start))
			return
		default:
			// Read new sample block.
			_, err := io.ReadFull(in, block)
			if err != nil {
				log.Fatal("Error reading samples: ", err)
			}

			pktFound := false
			indices := rcvr.p.Dec().Decode(block)

			for _, pkt := range rcvr.p.Parse(indices) {
				if !rcvr.fc.Match(pkt) {
					continue
				}

				var msg parse.LogMessage
				msg.Time = time.Now()
				msg.Offset, _ = sampleFile.Seek(0, os.SEEK_CUR)
				msg.Length = rcvr.p.Cfg().BufferLength << 1
				msg.Message = pkt

				err = encoder.Encode(msg)
				if err != nil {
					log.Fatal("Error encoding message: ", err)
				}

				// The XML encoder doesn't write new lines after each
				// element, add them.
				if _, ok := encoder.(*xml.Encoder); ok {
					fmt.Fprintln(logFile)
				}

				pktFound = true
				if *single {
					if len(meterID.UintMap) == 0 {
						break
					} else {
						delete(meterID.UintMap, uint(pkt.MeterID()))
					}
				}
			}

			if pktFound {
				if *sampleFilename != os.DevNull {
					_, err = sampleFile.Write(rcvr.p.Dec().IQ)
					if err != nil {
						log.Fatal("Error writing raw samples to file:", err)
					}
				}
				if *single && len(meterID.UintMap) == 0 {
					return
				}
			}
		}
	}
}

func init() {
	log.SetFlags(log.Lshortfile | log.Lmicroseconds)
}

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")

func main() {
	rcvr.RegisterFlags()
	RegisterFlags()

	flag.Parse()
	HandleFlags()

	rcvr.NewReceiver()

	defer logFile.Close()
	defer sampleFile.Close()
	defer rcvr.Close()

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	rcvr.Run()
}
<commit_msg>Check lowercase version of msgType against registered parsers.<commit_after>// RTLAMR - An rtl-sdr receiver for smart meters operating in the 900MHz ISM band.
// Copyright (C) 2015 Douglas Hall
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"encoding/xml"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/signal"
	"runtime/pprof"
	"strings"
	"time"

	"github.com/bemasher/rtlamr/parse"
	"github.com/bemasher/rtltcp"

	_ "github.com/bemasher/rtlamr/idm"
	_ "github.com/bemasher/rtlamr/r900"
	_ "github.com/bemasher/rtlamr/scm"
	_ "github.com/bemasher/rtlamr/scmplus"
)

var rcvr Receiver

type Receiver struct {
	rtltcp.SDR
	p  parse.Parser
	fc parse.FilterChain
}

func (rcvr *Receiver) NewReceiver() {
	var err error
	if rcvr.p, err = parse.NewParser(strings.ToLower(*msgType), *symbolLength, *decimation); err != nil {
		log.Fatal(err)
	}

	// Connect to rtl_tcp server.
	if err := rcvr.Connect(nil); err != nil {
		log.Fatal(err)
	}

	rcvr.HandleFlags()

	cfg := rcvr.p.Cfg()

	gainFlagSet := false
	flag.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "centerfreq":
			cfg.CenterFreq = uint32(rcvr.Flags.CenterFreq)
		case "samplerate":
			cfg.SampleRate = int(rcvr.Flags.SampleRate)
		case "gainbyindex", "tunergainmode", "tunergain", "agcmode":
			gainFlagSet = true
		case "unique":
			rcvr.fc.Add(NewUniqueFilter())
		case "filterid":
			rcvr.fc.Add(meterID)
		case "filtertype":
			rcvr.fc.Add(meterType)
		}
	})

	rcvr.SetCenterFreq(cfg.CenterFreq)
	rcvr.SetSampleRate(uint32(cfg.SampleRate))

	if !gainFlagSet {
		rcvr.SetGainMode(true)
	}

	if !*quiet {
		rcvr.p.Log()
	}

	// Tell the user how many gain settings were reported by rtl_tcp.
	if !*quiet {
		log.Println("GainCount:", rcvr.SDR.Info.GainCount)
	}

	return
}

func (rcvr *Receiver) Run() {
	// Setup signal channel for interruption.
	sigint := make(chan os.Signal, 1)
	signal.Notify(sigint, os.Kill, os.Interrupt)

	// Setup time limit channel
	tLimit := make(<-chan time.Time, 1)
	if *timeLimit != 0 {
		tLimit = time.After(*timeLimit)
	}

	in, out := io.Pipe()

	go func() {
		tcpBlock := make([]byte, 16384)
		for {
			n, err := rcvr.Read(tcpBlock)
			if err != nil {
				return
			}
			out.Write(tcpBlock[:n])
		}
	}()

	block := make([]byte, rcvr.p.Cfg().BlockSize2)

	start := time.Now()
	for {
		// Exit on interrupt or time limit, otherwise receive.
		select {
		case <-sigint:
			return
		case <-tLimit:
			fmt.Println("Time Limit Reached:", time.Since(start))
			return
		default:
			// Read new sample block.
			_, err := io.ReadFull(in, block)
			if err != nil {
				log.Fatal("Error reading samples: ", err)
			}

			pktFound := false
			indices := rcvr.p.Dec().Decode(block)

			for _, pkt := range rcvr.p.Parse(indices) {
				if !rcvr.fc.Match(pkt) {
					continue
				}

				var msg parse.LogMessage
				msg.Time = time.Now()
				msg.Offset, _ = sampleFile.Seek(0, os.SEEK_CUR)
				msg.Length = rcvr.p.Cfg().BufferLength << 1
				msg.Message = pkt

				err = encoder.Encode(msg)
				if err != nil {
					log.Fatal("Error encoding message: ", err)
				}

				// The XML encoder doesn't write new lines after each
				// element, add them.
				if _, ok := encoder.(*xml.Encoder); ok {
					fmt.Fprintln(logFile)
				}

				pktFound = true
				if *single {
					if len(meterID.UintMap) == 0 {
						break
					} else {
						delete(meterID.UintMap, uint(pkt.MeterID()))
					}
				}
			}

			if pktFound {
				if *sampleFilename != os.DevNull {
					_, err = sampleFile.Write(rcvr.p.Dec().IQ)
					if err != nil {
						log.Fatal("Error writing raw samples to file:", err)
					}
				}
				if *single && len(meterID.UintMap) == 0 {
					return
				}
			}
		}
	}
}

func init() {
	log.SetFlags(log.Lshortfile | log.Lmicroseconds)
}

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")

func main() {
	rcvr.RegisterFlags()
	RegisterFlags()

	flag.Parse()
	HandleFlags()

	rcvr.NewReceiver()

	defer logFile.Close()
	defer sampleFile.Close()
	defer rcvr.Close()

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	rcvr.Run()
}
<|endoftext|>


<commit_before>package swp

import (
	"sync"
	"time"
)

// RecvState tracks the receiver's sliding window state.
type RecvState struct {
	Net               Network
	Inbox             string
	NextFrameExpected Seqno
	Rxq               []*RxqSlot
	RecvWindowSize    Seqno
	mut               sync.Mutex
	Timeout           time.Duration
	RecvHistory       []*Packet

	MsgRecv chan *Packet

	ReqStop chan bool
	Done    chan bool

	RecvSz       int64
	DiscardCount int64

	snd *SenderState
}

// NewRecvState makes a new RecvState manager.
func NewRecvState(net Network, recvSz int64, timeout time.Duration, inbox string, snd *SenderState) *RecvState {
	return &RecvState{
		Net:            net,
		Inbox:          inbox,
		RecvWindowSize: Seqno(recvSz),
		Rxq:            make([]*RxqSlot, recvSz),
		Timeout:        timeout,
		RecvHistory:    make([]*Packet, 0),
		ReqStop:        make(chan bool),
		Done:           make(chan bool),
		RecvSz:         recvSz,
		snd:            snd,
	}
}

// RecvStart receives. It receives both data and acks from earlier sends.
// It starts a go routine in the background.
func (r *RecvState) Start() error {
	mr, err := r.Net.Listen(r.Inbox)
	if err != nil {
		return err
	}
	r.MsgRecv = mr

	go func() {
	recvloop:
		for {
			//q("%v top of recvloop, receiver NFE: %v",
			// r.Inbox, r.NextFrameExpected)
			select {
			case <-r.ReqStop:
				//q("%v recvloop sees ReqStop, shutting down.", r.Inbox)
				close(r.Done)
				return
			case pack := <-r.MsgRecv:
				//q("%v recvloop sees packet '%#v'", r.Inbox, pack)
				if pack.AckOnly {
					r.snd.GotAck <- AckStatus{
						AckNum:            pack.AckNum,
						NFE:               r.NextFrameExpected,
						RWS:               r.RecvWindowSize,
						AckCameWithPacket: pack.SeqNum,
					}
				} else {
					// actual data received, receiver side stuff:
					slot := r.Rxq[pack.SeqNum%r.RecvWindowSize]
					if !InWindow(pack.SeqNum, r.NextFrameExpected, r.NextFrameExpected+r.RecvWindowSize-1) {
						// Variation from the textbook algorithm: In the
						// presence of packet loss, if we drop certain packets,
						// the sender may re-try forever if we have non-overlapping windows.
						// So we'll ack every 5th present known good values anyway,
						// which relieves the livelock without being too chatty.
						q("%v pack.SeqNum %v outside receiver's window [%v, %v], dropping it",
							r.Inbox, pack.SeqNum, r.NextFrameExpected,
							r.NextFrameExpected+r.RecvWindowSize-1)
						r.DiscardCount++
						if r.DiscardCount%5 == 0 {
							r.ack(r.NextFrameExpected-1, pack.From)
						}
						continue recvloop
					}
					slot.Received = true
					slot.Pack = pack
					//q("%v packet %#v queued for ordered delivery, checking to see if we can deliver now",
					//	r.Inbox, slot.Pack)

					if pack.SeqNum == r.NextFrameExpected {
						//q("%v packet.SeqNum %v matches r.NextFrameExpected",
						//	r.Inbox, pack.SeqNum)
						for slot.Received {

							q("%v actual in-order receive happening for SeqNum %v",
								r.Inbox, slot.Pack.SeqNum)
							r.RecvHistory = append(r.RecvHistory, slot.Pack)
							q("%v r.RecvHistory now has length %v", r.Inbox, len(r.RecvHistory))

							slot.Received = false
							slot.Pack = nil
							r.NextFrameExpected++
							slot = r.Rxq[r.NextFrameExpected%r.RecvWindowSize]
						}
						r.ack(r.NextFrameExpected-1, pack.From)
					} else {
						//q("%v packet SeqNum %v was not NextFrameExpected %v; stored packet but not delivered.",
						//	r.Inbox, pack.SeqNum, r.NextFrameExpected)
					}
				}
			}
		}
	}()
	return nil
}

// ack is a helper function, used in the recvloop above
func (r *RecvState) ack(seqno Seqno, dest string) {
	q("%v about to send ack with AckNum: %v to %v",
		r.Inbox, seqno, dest)
	// send ack
	ack := &Packet{
		From:    r.Inbox,
		Dest:    dest,
		SeqNum:  -99, // => ack flag
		AckNum:  seqno,
		AckOnly: true,
	}
	r.snd.SendAck <- ack
}

// Stop the RecvState componennt
func (r *RecvState) Stop() {
	r.mut.Lock()
	select {
	case <-r.ReqStop:
	default:
		close(r.ReqStop)
	}
	r.mut.Unlock()
	<-r.Done
}
<commit_msg>atg. 006 receiver acks them all, similar to tcp<commit_after>package swp

import (
	"sync"
	"time"
)

// RecvState tracks the receiver's sliding window state.
type RecvState struct {
	Net               Network
	Inbox             string
	NextFrameExpected Seqno
	Rxq               []*RxqSlot
	RecvWindowSize    Seqno
	mut               sync.Mutex
	Timeout           time.Duration
	RecvHistory       []*Packet

	MsgRecv chan *Packet

	ReqStop chan bool
	Done    chan bool

	RecvSz       int64
	DiscardCount int64

	snd *SenderState
}

// NewRecvState makes a new RecvState manager.
func NewRecvState(net Network, recvSz int64, timeout time.Duration, inbox string, snd *SenderState) *RecvState {
	return &RecvState{
		Net:            net,
		Inbox:          inbox,
		RecvWindowSize: Seqno(recvSz),
		Rxq:            make([]*RxqSlot, recvSz),
		Timeout:        timeout,
		RecvHistory:    make([]*Packet, 0),
		ReqStop:        make(chan bool),
		Done:           make(chan bool),
		RecvSz:         recvSz,
		snd:            snd,
	}
}

// RecvStart receives. It receives both data and acks from earlier sends.
// It starts a go routine in the background.
func (r *RecvState) Start() error {
	mr, err := r.Net.Listen(r.Inbox)
	if err != nil {
		return err
	}
	r.MsgRecv = mr

	go func() {
	recvloop:
		for {
			//q("%v top of recvloop, receiver NFE: %v",
			// r.Inbox, r.NextFrameExpected)
			select {
			case <-r.ReqStop:
				//q("%v recvloop sees ReqStop, shutting down.", r.Inbox)
				close(r.Done)
				return
			case pack := <-r.MsgRecv:
				//q("%v recvloop sees packet '%#v'", r.Inbox, pack)
				if pack.AckOnly {
					r.snd.GotAck <- AckStatus{
						AckNum:            pack.AckNum,
						NFE:               r.NextFrameExpected,
						RWS:               r.RecvWindowSize,
						AckCameWithPacket: pack.SeqNum,
					}
				} else {
					// actual data received, receiver side stuff:
					slot := r.Rxq[pack.SeqNum%r.RecvWindowSize]
					if !InWindow(pack.SeqNum, r.NextFrameExpected, r.NextFrameExpected+r.RecvWindowSize-1) {
						// Variation from the textbook algorithm: In the
						// presence of packet loss, if we drop certain packets,
						// the sender may re-try forever if we have non-overlapping windows.
						// So we'll ack out of bounds known good values anyway.
						// We could also do every 5th discard, but we want to get
						// the flow control ramp-up-from-zero correct and not acking
						// may inhibit that.
						q("%v pack.SeqNum %v outside receiver's window [%v, %v], dropping it",
							r.Inbox, pack.SeqNum, r.NextFrameExpected,
							r.NextFrameExpected+r.RecvWindowSize-1)
						r.DiscardCount++
						r.ack(r.NextFrameExpected-1, pack.From)
						continue recvloop
					}
					slot.Received = true
					slot.Pack = pack
					//q("%v packet %#v queued for ordered delivery, checking to see if we can deliver now",
					//	r.Inbox, slot.Pack)

					if pack.SeqNum == r.NextFrameExpected {
						//q("%v packet.SeqNum %v matches r.NextFrameExpected",
						//	r.Inbox, pack.SeqNum)
						for slot.Received {

							q("%v actual in-order receive happening for SeqNum %v",
								r.Inbox, slot.Pack.SeqNum)
							r.RecvHistory = append(r.RecvHistory, slot.Pack)
							q("%v r.RecvHistory now has length %v", r.Inbox, len(r.RecvHistory))

							slot.Received = false
							slot.Pack = nil
							r.NextFrameExpected++
							slot = r.Rxq[r.NextFrameExpected%r.RecvWindowSize]
						}
						r.ack(r.NextFrameExpected-1, pack.From)
					} else {
						//q("%v packet SeqNum %v was not NextFrameExpected %v; stored packet but not delivered.",
						//	r.Inbox, pack.SeqNum, r.NextFrameExpected)
					}
				}
			}
		}
	}()
	return nil
}

// ack is a helper function, used in the recvloop above
func (r *RecvState) ack(seqno Seqno, dest string) {
	q("%v about to send ack with AckNum: %v to %v",
		r.Inbox, seqno, dest)
	// send ack
	ack := &Packet{
		From:    r.Inbox,
		Dest:    dest,
		SeqNum:  -99, // => ack flag
		AckNum:  seqno,
		AckOnly: true,
	}
	r.snd.SendAck <- ack
}

// Stop the RecvState componennt
func (r *RecvState) Stop() {
	r.mut.Lock()
	select {
	case <-r.ReqStop:
	default:
		close(r.ReqStop)
	}
	r.mut.Unlock()
	<-r.Done
}
<|endoftext|>


<commit_before>// Package repr attempts to represent Go values in a form that can be copy-and-pasted into source
// code directly.
//
// Some values (such as pointers to basic types) can not be represented directly in
// Go. These values will be output as `&<value>`. eg. `&23`
package repr

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"reflect"
	"unsafe"
)

// "Real" names of basic kinds, used to differentiate type aliases.
var realKindName = map[reflect.Kind]string{
	reflect.Bool:       "bool",
	reflect.Int:        "int",
	reflect.Int8:       "int8",
	reflect.Int16:      "int16",
	reflect.Int32:      "int32",
	reflect.Int64:      "int64",
	reflect.Uint:       "uint",
	reflect.Uint8:      "uint8",
	reflect.Uint16:     "uint16",
	reflect.Uint32:     "uint32",
	reflect.Uint64:     "uint64",
	reflect.Uintptr:    "uintptr",
	reflect.Float32:    "float32",
	reflect.Float64:    "float64",
	reflect.Complex64:  "complex64",
	reflect.Complex128: "complex128",
	reflect.Array:      "array",
	reflect.Chan:       "chan",
	reflect.Func:       "func",
	reflect.Map:        "map",
	reflect.Slice:      "slice",
	reflect.String:     "string",
}

var goStringerType = reflect.TypeOf((*fmt.GoStringer)(nil)).Elem()

// Default prints to os.Stdout with two space indentation.
var Default = New(os.Stdout, Indent("  "))

// An Option modifies the default behaviour of a Printer.
type Option func(o *Printer)

// Indent output by this much.
func Indent(indent string) Option { return func(o *Printer) { o.indent = indent } }

// NoIndent disables indenting.
func NoIndent() Option { return Indent("") }

// OmitEmpty sets whether empty field members should be omitted from output.
func OmitEmpty(omitEmpty bool) Option { return func(o *Printer) { o.omitEmpty = omitEmpty } }

func IgnoreGoStringer() Option { return func(o *Printer) { o.ignoreGoStringer = true } }

// Hide excludes the given types from representation, instead just printing the name of the type.
func Hide(ts ...interface{}) Option {
	return func(o *Printer) {
		for _, t := range ts {
			rt := reflect.Indirect(reflect.ValueOf(t)).Type()
			o.exclude[rt] = true
		}
	}
}

// Printer represents structs in a printable manner.
type Printer struct {
	indent           string
	omitEmpty        bool
	ignoreGoStringer bool
	exclude          map[reflect.Type]bool
	w                io.Writer
}

// New creates a new Printer on w with the given Options.
func New(w io.Writer, options ...Option) *Printer {
	p := &Printer{
		w:         w,
		indent:    "  ",
		omitEmpty: true,
		exclude:   map[reflect.Type]bool{},
	}
	for _, option := range options {
		option(p)
	}
	return p
}

func (p *Printer) nextIndent(indent string) string {
	if p.indent != "" {
		return indent + p.indent
	}
	return ""
}

func (p *Printer) thisIndent(indent string) string {
	if p.indent != "" {
		return indent
	}
	return ""
}

// Print the values.
func (p *Printer) Print(vs ...interface{}) {
	for i, v := range vs {
		if i > 0 {
			fmt.Fprint(p.w, " ")
		}
		p.reprValue(map[reflect.Value]bool{}, reflect.ValueOf(v), "")
	}
}

// Println prints each value on a new line.
func (p *Printer) Println(vs ...interface{}) {
	for i, v := range vs {
		if i > 0 {
			fmt.Fprint(p.w, " ")
		}
		p.reprValue(map[reflect.Value]bool{}, reflect.ValueOf(v), "")
	}
	fmt.Fprintln(p.w)
}

func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent string) { // nolint: gocyclo
	if seen[v] {
		fmt.Fprint(p.w, "...")
		return
	}
	seen[v] = true
	defer delete(seen, v)

	if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Map || v.Kind() == reflect.Chan || v.Kind() == reflect.Slice || v.Kind() == reflect.Func || v.Kind() == reflect.Interface) && v.IsNil() {
		fmt.Fprint(p.w, "nil")
		return
	}
	if p.exclude[v.Type()] {
		fmt.Fprintf(p.w, "%s...", v.Type().Name())
		return
	}
	t := v.Type()
	// If we can't access a private field directly with reflection, try and do so via unsafe.
	if !v.CanInterface() && v.CanAddr() {
		uv := reflect.NewAt(t, unsafe.Pointer(v.UnsafeAddr())).Elem()
		if uv.CanInterface() {
			v = uv
		}
	}
	// Attempt to use fmt.GoStringer interface.
	if t.Implements(goStringerType) {
		fmt.Fprint(p.w, v.Interface().(fmt.GoStringer).GoString())
		return
	}
	in := p.thisIndent(indent)
	ni := p.nextIndent(indent)
	switch v.Kind() {
	case reflect.Slice, reflect.Array:
		if p.omitEmpty && v.Len() == 0 {
			return
		}
		fmt.Fprintf(p.w, "%s{", v.Type())
		if v.Len() == 0 {
			fmt.Fprint(p.w, "}")
		} else {
			if p.indent != "" {
				fmt.Fprintf(p.w, "\n")
			}
			for i := 0; i < v.Len(); i++ {
				e := v.Index(i)
				fmt.Fprintf(p.w, "%s", ni)
				p.reprValue(seen, e, ni)
				if p.indent != "" {
					fmt.Fprintf(p.w, ",\n")
				} else if i < v.Len()-1 {
					fmt.Fprintf(p.w, ", ")
				}
			}
			fmt.Fprintf(p.w, "%s}", in)
		}

	case reflect.Chan:
		fmt.Fprintf(p.w, "make(")
		fmt.Fprintf(p.w, "%s", v.Type())
		fmt.Fprintf(p.w, ", %d)", v.Cap())

	case reflect.Map:
		fmt.Fprintf(p.w, "%s{", v.Type())
		if p.indent != "" && v.Len() != 0 {
			fmt.Fprintf(p.w, "\n")
		}
		for i, k := range v.MapKeys() {
			kv := v.MapIndex(k)
			fmt.Fprintf(p.w, "%s", ni)
			p.reprValue(seen, k, ni)
			fmt.Fprintf(p.w, ": ")
			p.reprValue(seen, kv, ni)
			if p.indent != "" {
				fmt.Fprintf(p.w, ",\n")
			} else if i < v.Len()-1 {
				fmt.Fprintf(p.w, ", ")
			}
		}
		fmt.Fprintf(p.w, "%s}", in)

	case reflect.Struct:
		fmt.Fprintf(p.w, "%s{", v.Type())
		if p.indent != "" && v.NumField() != 0 {
			fmt.Fprintf(p.w, "\n")
		}
		for i := 0; i < v.NumField(); i++ {
			t := v.Type().Field(i)
			f := v.Field(i)
			if p.omitEmpty && isZero(f) {
				continue
			}
			fmt.Fprintf(p.w, "%s%s: ", ni, t.Name)
			p.reprValue(seen, f, ni)
			if p.indent != "" {
				fmt.Fprintf(p.w, ",\n")
			} else if i < v.NumField()-1 {
				fmt.Fprintf(p.w, ", ")
			}
		}
		fmt.Fprintf(p.w, "%s}", indent)

	case reflect.Ptr:
		if v.IsNil() {
			fmt.Fprintf(p.w, "nil")
			return
		}
		fmt.Fprintf(p.w, "&")
		p.reprValue(seen, v.Elem(), indent)

	case reflect.String:
		if t.Name() != "string" {
			fmt.Fprintf(p.w, "%s(%q)", t, v.String())
		} else {
			fmt.Fprintf(p.w, "%q", v.String())
		}

	case reflect.Interface:
		if v.IsNil() {
			fmt.Fprintf(p.w, "interface {}(nil)")
		} else {
			p.reprValue(seen, v.Elem(), indent)
		}

	default:
		if t.Name() != realKindName[t.Kind()] {
			fmt.Fprintf(p.w, "%s(%v)", t, v)
		} else {
			fmt.Fprintf(p.w, "%v", v)
		}
	}
}

// String returns a string representing v.
func String(v interface{}, options ...Option) string {
	w := bytes.NewBuffer(nil)
	options = append([]Option{NoIndent()}, options...)
	p := New(w, options...)
	p.Print(v)
	return w.String()
}

func extractOptions(vs ...interface{}) (args []interface{}, options []Option) {
	for _, v := range vs {
		if o, ok := v.(Option); ok {
			options = append(options, o)
		} else {
			args = append(args, v)
		}
	}
	return
}

// Println prints v to os.Stdout, one per line.
func Println(vs ...interface{}) {
	args, options := extractOptions(vs...)
	New(os.Stdout, options...).Println(args...)
}

// Print writes a representation of v to os.Stdout, separated by spaces.
func Print(vs ...interface{}) {
	args, options := extractOptions(vs...)
	New(os.Stdout, options...).Print(args...)
}

func isZero(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
		return v.IsNil()
	}
	return false
}
<commit_msg>Respect IgnoreGoString().<commit_after>// Package repr attempts to represent Go values in a form that can be copy-and-pasted into source
// code directly.
//
// Some values (such as pointers to basic types) can not be represented directly in
// Go. These values will be output as `&<value>`. eg. `&23`
package repr

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"reflect"
	"unsafe"
)

// "Real" names of basic kinds, used to differentiate type aliases.
var realKindName = map[reflect.Kind]string{
	reflect.Bool:       "bool",
	reflect.Int:        "int",
	reflect.Int8:       "int8",
	reflect.Int16:      "int16",
	reflect.Int32:      "int32",
	reflect.Int64:      "int64",
	reflect.Uint:       "uint",
	reflect.Uint8:      "uint8",
	reflect.Uint16:     "uint16",
	reflect.Uint32:     "uint32",
	reflect.Uint64:     "uint64",
	reflect.Uintptr:    "uintptr",
	reflect.Float32:    "float32",
	reflect.Float64:    "float64",
	reflect.Complex64:  "complex64",
	reflect.Complex128: "complex128",
	reflect.Array:      "array",
	reflect.Chan:       "chan",
	reflect.Func:       "func",
	reflect.Map:        "map",
	reflect.Slice:      "slice",
	reflect.String:     "string",
}

var goStringerType = reflect.TypeOf((*fmt.GoStringer)(nil)).Elem()

// Default prints to os.Stdout with two space indentation.
var Default = New(os.Stdout, Indent("  "))

// An Option modifies the default behaviour of a Printer.
type Option func(o *Printer)

// Indent output by this much.
func Indent(indent string) Option { return func(o *Printer) { o.indent = indent } }

// NoIndent disables indenting.
func NoIndent() Option { return Indent("") }

// OmitEmpty sets whether empty field members should be omitted from output.
func OmitEmpty(omitEmpty bool) Option { return func(o *Printer) { o.omitEmpty = omitEmpty } }

func IgnoreGoStringer() Option { return func(o *Printer) { o.ignoreGoStringer = true } }

// Hide excludes the given types from representation, instead just printing the name of the type.
func Hide(ts ...interface{}) Option {
	return func(o *Printer) {
		for _, t := range ts {
			rt := reflect.Indirect(reflect.ValueOf(t)).Type()
			o.exclude[rt] = true
		}
	}
}

// Printer represents structs in a printable manner.
type Printer struct {
	indent           string
	omitEmpty        bool
	ignoreGoStringer bool
	exclude          map[reflect.Type]bool
	w                io.Writer
}

// New creates a new Printer on w with the given Options.
func New(w io.Writer, options ...Option) *Printer {
	p := &Printer{
		w:         w,
		indent:    "  ",
		omitEmpty: true,
		exclude:   map[reflect.Type]bool{},
	}
	for _, option := range options {
		option(p)
	}
	return p
}

func (p *Printer) nextIndent(indent string) string {
	if p.indent != "" {
		return indent + p.indent
	}
	return ""
}

func (p *Printer) thisIndent(indent string) string {
	if p.indent != "" {
		return indent
	}
	return ""
}

// Print the values.
func (p *Printer) Print(vs ...interface{}) {
	for i, v := range vs {
		if i > 0 {
			fmt.Fprint(p.w, " ")
		}
		p.reprValue(map[reflect.Value]bool{}, reflect.ValueOf(v), "")
	}
}

// Println prints each value on a new line.
func (p *Printer) Println(vs ...interface{}) {
	for i, v := range vs {
		if i > 0 {
			fmt.Fprint(p.w, " ")
		}
		p.reprValue(map[reflect.Value]bool{}, reflect.ValueOf(v), "")
	}
	fmt.Fprintln(p.w)
}

func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent string) { // nolint: gocyclo
	if seen[v] {
		fmt.Fprint(p.w, "...")
		return
	}
	seen[v] = true
	defer delete(seen, v)

	if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Map || v.Kind() == reflect.Chan || v.Kind() == reflect.Slice || v.Kind() == reflect.Func || v.Kind() == reflect.Interface) && v.IsNil() {
		fmt.Fprint(p.w, "nil")
		return
	}
	if p.exclude[v.Type()] {
		fmt.Fprintf(p.w, "%s...", v.Type().Name())
		return
	}
	t := v.Type()
	// If we can't access a private field directly with reflection, try and do so via unsafe.
	if !v.CanInterface() && v.CanAddr() {
		uv := reflect.NewAt(t, unsafe.Pointer(v.UnsafeAddr())).Elem()
		if uv.CanInterface() {
			v = uv
		}
	}
	// Attempt to use fmt.GoStringer interface.
	if !p.ignoreGoStringer && t.Implements(goStringerType) {
		fmt.Fprint(p.w, v.Interface().(fmt.GoStringer).GoString())
		return
	}
	in := p.thisIndent(indent)
	ni := p.nextIndent(indent)
	switch v.Kind() {
	case reflect.Slice, reflect.Array:
		if p.omitEmpty && v.Len() == 0 {
			return
		}
		fmt.Fprintf(p.w, "%s{", v.Type())
		if v.Len() == 0 {
			fmt.Fprint(p.w, "}")
		} else {
			if p.indent != "" {
				fmt.Fprintf(p.w, "\n")
			}
			for i := 0; i < v.Len(); i++ {
				e := v.Index(i)
				fmt.Fprintf(p.w, "%s", ni)
				p.reprValue(seen, e, ni)
				if p.indent != "" {
					fmt.Fprintf(p.w, ",\n")
				} else if i < v.Len()-1 {
					fmt.Fprintf(p.w, ", ")
				}
			}
			fmt.Fprintf(p.w, "%s}", in)
		}

	case reflect.Chan:
		fmt.Fprintf(p.w, "make(")
		fmt.Fprintf(p.w, "%s", v.Type())
		fmt.Fprintf(p.w, ", %d)", v.Cap())

	case reflect.Map:
		fmt.Fprintf(p.w, "%s{", v.Type())
		if p.indent != "" && v.Len() != 0 {
			fmt.Fprintf(p.w, "\n")
		}
		for i, k := range v.MapKeys() {
			kv := v.MapIndex(k)
			fmt.Fprintf(p.w, "%s", ni)
			p.reprValue(seen, k, ni)
			fmt.Fprintf(p.w, ": ")
			p.reprValue(seen, kv, ni)
			if p.indent != "" {
				fmt.Fprintf(p.w, ",\n")
			} else if i < v.Len()-1 {
				fmt.Fprintf(p.w, ", ")
			}
		}
		fmt.Fprintf(p.w, "%s}", in)

	case reflect.Struct:
		fmt.Fprintf(p.w, "%s{", v.Type())
		if p.indent != "" && v.NumField() != 0 {
			fmt.Fprintf(p.w, "\n")
		}
		for i := 0; i < v.NumField(); i++ {
			t := v.Type().Field(i)
			f := v.Field(i)
			if p.omitEmpty && isZero(f) {
				continue
			}
			fmt.Fprintf(p.w, "%s%s: ", ni, t.Name)
			p.reprValue(seen, f, ni)
			if p.indent != "" {
				fmt.Fprintf(p.w, ",\n")
			} else if i < v.NumField()-1 {
				fmt.Fprintf(p.w, ", ")
			}
		}
		fmt.Fprintf(p.w, "%s}", indent)

	case reflect.Ptr:
		if v.IsNil() {
			fmt.Fprintf(p.w, "nil")
			return
		}
		fmt.Fprintf(p.w, "&")
		p.reprValue(seen, v.Elem(), indent)

	case reflect.String:
		if t.Name() != "string" {
			fmt.Fprintf(p.w, "%s(%q)", t, v.String())
		} else {
			fmt.Fprintf(p.w, "%q", v.String())
		}

	case reflect.Interface:
		if v.IsNil() {
			fmt.Fprintf(p.w, "interface {}(nil)")
		} else {
			p.reprValue(seen, v.Elem(), indent)
		}

	default:
		if t.Name() != realKindName[t.Kind()] {
			fmt.Fprintf(p.w, "%s(%v)", t, v)
		} else {
			fmt.Fprintf(p.w, "%v", v)
		}
	}
}

// String returns a string representing v.
func String(v interface{}, options ...Option) string {
	w := bytes.NewBuffer(nil)
	options = append([]Option{NoIndent()}, options...)
	p := New(w, options...)
	p.Print(v)
	return w.String()
}

func extractOptions(vs ...interface{}) (args []interface{}, options []Option) {
	for _, v := range vs {
		if o, ok := v.(Option); ok {
			options = append(options, o)
		} else {
			args = append(args, v)
		}
	}
	return
}

// Println prints v to os.Stdout, one per line.
func Println(vs ...interface{}) {
	args, options := extractOptions(vs...)
	New(os.Stdout, options...).Println(args...)
}

// Print writes a representation of v to os.Stdout, separated by spaces.
func Print(vs ...interface{}) {
	args, options := extractOptions(vs...)
	New(os.Stdout, options...).Print(args...)
}

func isZero(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
		return v.IsNil()
	}
	return false
}
<|endoftext|>


<commit_before>package dnsr

var root = `
;       This file holds the information on root name servers needed to
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers).
;
;       This file is made available by InterNIC
;       under anonymous FTP as
;           file                /domain/named.cache
;           on server           FTP.INTERNIC.NET
;       -OR-                    RS.INTERNIC.NET
;
;       last update:     July 25, 2019
;       related version of root zone:     2019072501
;
; FORMERLY NS.INTERNIC.NET
;
.                        3600000      NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:ba3e::2:30
;
; FORMERLY NS1.ISI.EDU
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     199.9.14.201
B.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:200::b
;
; FORMERLY C.PSI.NET
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
C.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2::c
;
; FORMERLY TERP.UMD.EDU
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     199.7.91.13
D.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2d::d
;
; FORMERLY NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
E.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:a8::e
;
; FORMERLY NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
;
; FORMERLY NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
G.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:12::d0d
;
; FORMERLY AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     198.97.190.53
H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::53
;
; FORMERLY NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
I.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fe::53
;
; OPERATED BY VERISIGN, INC.
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:c27::2:30
;
; OPERATED BY RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
;
; OPERATED BY ICANN
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
L.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:9f::42
;
; OPERATED BY WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
; End of file`
<commit_msg>auto-update<commit_after>package dnsr

var root = `
;       This file holds the information on root name servers needed to
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers).
;
;       This file is made available by InterNIC
;       under anonymous FTP as
;           file                /domain/named.cache
;           on server           FTP.INTERNIC.NET
;       -OR-                    RS.INTERNIC.NET
;
;       last update:     July 26, 2019
;       related version of root zone:     2019072602
;
; FORMERLY NS.INTERNIC.NET
;
.                        3600000      NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:ba3e::2:30
;
; FORMERLY NS1.ISI.EDU
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     199.9.14.201
B.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:200::b
;
; FORMERLY C.PSI.NET
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
C.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2::c
;
; FORMERLY TERP.UMD.EDU
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     199.7.91.13
D.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2d::d
;
; FORMERLY NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
E.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:a8::e
;
; FORMERLY NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
;
; FORMERLY NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
G.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:12::d0d
;
; FORMERLY AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     198.97.190.53
H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::53
;
; FORMERLY NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
I.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fe::53
;
; OPERATED BY VERISIGN, INC.
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:c27::2:30
;
; OPERATED BY RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
;
; OPERATED BY ICANN
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
L.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:9f::42
;
; OPERATED BY WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
; End of file`
<|endoftext|>


<commit_before>package rabbit

import (
	"errors"
	"fmt"

	"github.com/nu7hatch/gouuid"
	"github.com/streadway/amqp"
)

type RabbitChannel struct {
	uuid       string
	connection *amqp.Connection
	channel    *amqp.Channel
}

func NewRabbitChannel(conn *amqp.Connection) (*RabbitChannel, error) {
	id, err := uuid.NewV4()
	if err != nil {
		return nil, err
	}
	rabbitCh := &RabbitChannel{
		uuid:       id.String(),
		connection: conn,
	}
	if err := rabbitCh.Connect(); err != nil {
		return nil, err
	}
	return rabbitCh, nil

}

func (r *RabbitChannel) Connect() error {
	var err error
	r.channel, err = r.connection.Channel()
	if err != nil {
		return err
	}
	return nil
}

func (r *RabbitChannel) Close() error {
	if r.channel == nil {
		return errors.New("Channel is nil")
	}
	return r.channel.Close()
}

func (r *RabbitChannel) Publish(exchange, routingKey string, message amqp.Publishing) error {
	if r.channel == nil {
		return errors.New("Channel is nil")
	}
	return r.channel.Publish(exchange, routingKey, false, false, message)
}

func (r *RabbitChannel) DeclareExchange(exchange string) error {
	return r.channel.ExchangeDeclare(exchange, "topic", false, false, false, false, nil)
}

func (r *RabbitChannel) DeclareQueue(queue string) error {
	_, err := r.channel.QueueDeclare(queue, false, true, false, false, nil)
	return err
}

func (r *RabbitChannel) DeclareDurableQueue(queue string) error {
	_, err := r.channel.QueueDeclare(queue, true, false, false, false, nil)
	return err
}

func (r *RabbitChannel) DeclareReplyQueue(queue string) error {
	_, err := r.channel.QueueDeclare(queue, false, true, true, false, nil)
	return err
}

func (r *RabbitChannel) ConsumeQueue(queue string) (<-chan amqp.Delivery, error) {
	return r.channel.Consume(queue, r.uuid, false, false, false, false, nil)
}

func (r *RabbitChannel) BindQueue(queue, exchange string) error {
	return r.channel.QueueBind(queue, fmt.Sprintf("%s.#", queue), exchange, false, nil)
}
<commit_msg>Expand and document fields passed when creating queues and exchanges<commit_after>package rabbit

import (
	"errors"
	"fmt"

	"github.com/nu7hatch/gouuid"
	"github.com/streadway/amqp"
)

type RabbitChannel struct {
	uuid       string
	connection *amqp.Connection
	channel    *amqp.Channel
}

func NewRabbitChannel(conn *amqp.Connection) (*RabbitChannel, error) {
	id, err := uuid.NewV4()
	if err != nil {
		return nil, err
	}
	rabbitCh := &RabbitChannel{
		uuid:       id.String(),
		connection: conn,
	}
	if err := rabbitCh.Connect(); err != nil {
		return nil, err
	}
	return rabbitCh, nil

}

func (r *RabbitChannel) Connect() error {
	var err error
	r.channel, err = r.connection.Channel()
	if err != nil {
		return err
	}
	return nil
}

func (r *RabbitChannel) Close() error {
	if r.channel == nil {
		return errors.New("Channel is nil")
	}
	return r.channel.Close()
}

func (r *RabbitChannel) Publish(exchange, routingKey string, message amqp.Publishing) error {
	if r.channel == nil {
		return errors.New("Channel is nil")
	}
	return r.channel.Publish(exchange, routingKey, false, false, message)
}

func (r *RabbitChannel) DeclareExchange(exchange string) error {
	return r.channel.ExchangeDeclare(
		exchange, // name
		"topic",  // kind
		false,    // durable
		false,    // autoDelete
		false,    // internal
		false,    // noWait
		nil,      // args
	)
}

func (r *RabbitChannel) DeclareQueue(queue string) error {
	_, err := r.channel.QueueDeclare(
		queue, // name
		false, // durable
		true,  // autoDelete
		false, // exclusive
		false, // noWait
		nil,   // args
	)
	return err
}

func (r *RabbitChannel) DeclareDurableQueue(queue string) error {
	_, err := r.channel.QueueDeclare(
		queue, // name
		true,  // durable
		false, // autoDelete
		false, // exclusive
		false, // noWait
		nil,   // args
	)
	return err
}

func (r *RabbitChannel) DeclareReplyQueue(queue string) error {
	_, err := r.channel.QueueDeclare(
		queue, // name
		false, // durable
		true,  // autoDelete
		true,  // exclusive
		false, // noWait
		nil,   // args
	)
	return err
}

func (r *RabbitChannel) ConsumeQueue(queue string) (<-chan amqp.Delivery, error) {
	return r.channel.Consume(
		queue,  // queue
		r.uuid, // consumer
		false,  // autoAck
		false,  // exclusive
		false,  // nolocal
		false,  // nowait
		nil,    // args
	)
}

func (r *RabbitChannel) BindQueue(queue, exchange string) error {
	return r.channel.QueueBind(queue, fmt.Sprintf("%s.#", queue), exchange, false, nil)
}
<|endoftext|>