<commit_before>package sync

import (
	"database/sql"
	"errors"
	"fmt"
	"log"
	"strings"
	"time"

	_ "github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/go-sql-driver/mysql"
)

//should come from config (file) somewhere...
const default_connection_string = "root:root123@/syncmysport?charset=utf8,parseTime=true"

type DbSyncInt interface {
	UpdateSyncTask(sync SyncTask) (int, error)
	StoreSyncTask(sync SyncTask) (int64, int64, SyncTask, error)
	RetrieveAllSyncTasks() ([]SyncTask, error)
	FindSyncTaskByToken(token string) (*SyncTask, error)
	CreateTableIfNotExist() error
	CountActiveUsers() (int, error)
}

type DbSync struct {
	ConnectionString string
}

func CreateSyncDbRepo(dbString string) DbSyncInt {
	if dbString != "" {
		dbString = makeDbStringHerokuCompliant(dbString)
		appendedConnectionString := fmt.Sprintf("%s", dbString)
		log.Printf("Connection string was: %s, now is %s", dbString, appendedConnectionString)
		return &DbSync{appendedConnectionString}
	} else {
		return &DbSync{default_connection_string}
	}
}

func (db DbSync) CreateTableIfNotExist() error {
	dbCon, err := sql.Open("mysql", db.ConnectionString)
	if err != nil {
		return err
	}
	defer dbCon.Close()

	_, err = dbCon.Exec(`
	CREATE TABLE IF NOT EXISTS sync (
    uid INT(10) NOT NULL AUTO_INCREMENT,
    rk_key VARCHAR(64) NULL DEFAULT NULL,
    rk_refresh_token VARCHAR(64) DEFAULT NULL,
    last_succesfull_retrieve DATETIME NULL DEFAULT NULL,
	environment varchar(36) NOT NULL DEFAULT "Prod",
	stv_key VARCHAR(64) NULL DEFAULT NULL,
    stv_refresh_token VARCHAR(64) DEFAULT NULL,
    PRIMARY KEY (uid)
  );`)
	if err != nil {
		return err
	}
	log.Printf("Create table sync\n")
	return nil
}

func (db DbSync) CountActiveUsers() (int, error) {
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	defer dbCon.Close()
	rows, err := dbCon.Query("SELECT COUNT(*) FROM sync WHERE rk_key != '' AND rk_key IS NOT NULL AND stv_key != '' AND stv_key IS NOT NULL")

	if err != nil {
		return 0, err
	}
	count := 0
	for rows.Next() {
		err := rows.Scan(&count)
		if err != nil {
			return count, err
		}
	}
	defer rows.Close()

	return count, nil
}

func (db DbSync) UpdateSyncTask(sync SyncTask) (int, error) {
	if sync.Uid == -1 {
		return 0, errors.New("SyncTask was never stored before, use StoreSyncTask")
	}
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	defer dbCon.Close()

	stmtOut, err := dbCon.Prepare("UPDATE sync SET rk_key=?, stv_key=?, stv_refresh_token=?, last_succesfull_retrieve=? WHERE uid = ?")
	if err != nil {
		return 0, errors.New("Error preparing UPDATE statement for Task")
	}
	defer stmtOut.Close()

	res, err := stmtOut.Exec(sync.RunkeeperToken, sync.StravaToken, sync.StravaRefreshToken, createStringOutOfUnixTime(sync.LastSeenTimestamp), sync.Uid)
	if err != nil {
		return 0, errors.New("Error executing the UPDATE statement for Task")
	}

	i, err := res.RowsAffected()
	if err != nil {
		return 0, errors.New("Error reading rows affected after UPDATE")
	}
	return int(i), nil
}

/*
* Returns 1) Created Id, 2) Rows changed/added, 3)synctask, 4) error
 */
func (db DbSync) StoreSyncTask(sync SyncTask) (int64, int64, SyncTask, error) {
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	defer dbCon.Close()

	stmtOut, err := dbCon.Prepare("INSERT INTO sync(rk_key, stv_key, stv_refresh_token, last_succesfull_retrieve, environment) VALUES(?,?,?,?)")
	if err != nil {
		log.Printf("err: %s", err)
		return 0, 0, sync, err
	}
	defer stmtOut.Close()
	res, err := stmtOut.Exec(sync.RunkeeperToken, sync.StravaToken, sync.StravaRefreshToken, createStringOutOfUnixTime(sync.LastSeenTimestamp), sync.Environment)
	if err != nil {
		log.Printf("err: %s", err)
		return 0, 0, sync, err
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		log.Printf("err: %s", err)
		return 0, 0, sync, err
	}
	rowCnt, err := res.RowsAffected()
	if err != nil {
		log.Printf("err: %s", err)
		return 0, 0, sync, err
	}
	sync.Uid = lastId
	return lastId, rowCnt, sync, nil
}

func (db DbSync) RetrieveAllSyncTasks() ([]SyncTask, error) {
	log.Printf("Connecting to DB using conn string %s", db.ConnectionString)
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	stmtOut, err :=
		dbCon.Prepare("SELECT uid, rk_key, stv_key, last_succesfull_retrieve, environment, stv_refresh_token, rk_refresh_token FROM sync WHERE rk_key != '' AND stv_key != ''")
	if err != nil {
		panic(err.Error()) // proper error handling instead of panic in your app
	}
	defer stmtOut.Close()
	defer dbCon.Close()

	rows, err := stmtOut.Query()
	defer rows.Close()

	result := make([]SyncTask, 0)
	for rows.Next() {
		var rkToken string
		var stvToken string
		var rkRefreshToken string
		var stvRefreshToken string
		var uid int64
		var lastSeenTime string
		var environment string

		rows.Scan(&uid, &rkToken, &stvToken, &lastSeenTime, &environment, &stvRefreshToken, &rkRefreshToken)
		unixTime, err := createUnixTimeOutOfString(lastSeenTime)
		if err != nil {
			log.Printf("Error while loading Sync tasks from database: %s", err)
			return result, err // proper error handling instead of panic in your app
		}

		sync := CreateSyncTask(rkToken, rkRefreshToken, stvToken, stvRefreshToken, unixTime, environment)
		sync.Uid = uid
		result = append(result, *sync)
	}
	return result, nil
}

func (db DbSync) FindSyncTaskByToken(token string) (*SyncTask, error) {
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	defer dbCon.Close()
	stmtOut, err := dbCon.Prepare("SELECT * FROM sync WHERE rk_key = ? OR stv_key = ? OR stv_refresh_token = ?")
	if err != nil {
		panic(err.Error()) // proper error handling instead of panic in your app
	}
	defer stmtOut.Close()

	rows, err := stmtOut.Query(token, token, token)
	defer rows.Close()

	for rows.Next() {
		var uid int64
		var rkToken string
		var stvToken string
		var lastSeen string
		var environment string
		var stv_refresh_token string
		var rk_refresh_token string

		err = rows.Scan(&uid, &rkToken, &stvToken, &lastSeen, &environment, &stv_refresh_token, &rk_refresh_token)
		if err != nil {
			log.Printf("Error while getting results from db for token %s", token)
			return nil, err
		}
		unixTime, err := createUnixTimeOutOfString(lastSeen)
		if err != nil {
			log.Printf("Error while converting timestamp from db %s", lastSeen)
			return nil, err
		}
		task := CreateSyncTask(rkToken, rk_refresh_token, stvToken, stv_refresh_token, unixTime, environment)
		task.Uid = uid
		return task, nil
	}
	return nil, nil
}

func makeDbStringHerokuCompliant(dbString string) string {
	dbStringWithoutProtocol := strings.Replace(dbString, "mysql://", "", 1)
	parts := strings.Split(dbStringWithoutProtocol, "@")
	userAndPassword := strings.Split(parts[0], ":")

	addr := strings.Split(parts[1], "/")[0]
	dbName := strings.Split(strings.Split(parts[1], "/")[1], "?")[0]

	resultString := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s", userAndPassword[0], userAndPassword[1], addr, dbName)
	return resultString
}

func createUnixTimeOutOfString(lastSeen string) (int, error) {
	timestamp, err := time.Parse("2006-01-02 15:04:05", lastSeen)

	if err != nil {
		return 0, err
	}
	return int(timestamp.Unix()), nil
}

func createStringOutOfUnixTime(t int) string {
	return time.Unix(int64(t), 0).Format("2006-01-02 15:04:05")
}
<commit_msg>Fix order of params for CreateTask<commit_after>package sync

import (
	"database/sql"
	"errors"
	"fmt"
	"log"
	"strings"
	"time"

	_ "github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/go-sql-driver/mysql"
)

//should come from config (file) somewhere...
const default_connection_string = "root:root123@/syncmysport?charset=utf8,parseTime=true"

type DbSyncInt interface {
	UpdateSyncTask(sync SyncTask) (int, error)
	StoreSyncTask(sync SyncTask) (int64, int64, SyncTask, error)
	RetrieveAllSyncTasks() ([]SyncTask, error)
	FindSyncTaskByToken(token string) (*SyncTask, error)
	CreateTableIfNotExist() error
	CountActiveUsers() (int, error)
}

type DbSync struct {
	ConnectionString string
}

func CreateSyncDbRepo(dbString string) DbSyncInt {
	if dbString != "" {
		dbString = makeDbStringHerokuCompliant(dbString)
		appendedConnectionString := fmt.Sprintf("%s", dbString)
		log.Printf("Connection string was: %s, now is %s", dbString, appendedConnectionString)
		return &DbSync{appendedConnectionString}
	} else {
		return &DbSync{default_connection_string}
	}
}

func (db DbSync) CreateTableIfNotExist() error {
	dbCon, err := sql.Open("mysql", db.ConnectionString)
	if err != nil {
		return err
	}
	defer dbCon.Close()

	_, err = dbCon.Exec(`
	CREATE TABLE IF NOT EXISTS sync (
    uid INT(10) NOT NULL AUTO_INCREMENT,
    rk_key VARCHAR(64) NULL DEFAULT NULL,
    rk_refresh_token VARCHAR(64) DEFAULT NULL,
    last_succesfull_retrieve DATETIME NULL DEFAULT NULL,
	environment varchar(36) NOT NULL DEFAULT "Prod",
	stv_key VARCHAR(64) NULL DEFAULT NULL,
    stv_refresh_token VARCHAR(64) DEFAULT NULL,
    PRIMARY KEY (uid)
  );`)
	if err != nil {
		return err
	}
	log.Printf("Create table sync\n")
	return nil
}

func (db DbSync) CountActiveUsers() (int, error) {
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	defer dbCon.Close()
	rows, err := dbCon.Query("SELECT COUNT(*) FROM sync WHERE rk_key != '' AND rk_key IS NOT NULL AND stv_key != '' AND stv_key IS NOT NULL")

	if err != nil {
		return 0, err
	}
	count := 0
	for rows.Next() {
		err := rows.Scan(&count)
		if err != nil {
			return count, err
		}
	}
	defer rows.Close()

	return count, nil
}

func (db DbSync) UpdateSyncTask(sync SyncTask) (int, error) {
	if sync.Uid == -1 {
		return 0, errors.New("SyncTask was never stored before, use StoreSyncTask")
	}
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	defer dbCon.Close()

	stmtOut, err := dbCon.Prepare("UPDATE sync SET rk_key=?, stv_key=?, stv_refresh_token=?, last_succesfull_retrieve=? WHERE uid = ?")
	if err != nil {
		return 0, errors.New("Error preparing UPDATE statement for Task")
	}
	defer stmtOut.Close()

	res, err := stmtOut.Exec(sync.RunkeeperToken, sync.StravaToken, sync.StravaRefreshToken, createStringOutOfUnixTime(sync.LastSeenTimestamp), sync.Uid)
	if err != nil {
		return 0, errors.New("Error executing the UPDATE statement for Task")
	}

	i, err := res.RowsAffected()
	if err != nil {
		return 0, errors.New("Error reading rows affected after UPDATE")
	}
	return int(i), nil
}

/*
* Returns 1) Created Id, 2) Rows changed/added, 3)synctask, 4) error
 */
func (db DbSync) StoreSyncTask(sync SyncTask) (int64, int64, SyncTask, error) {
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	defer dbCon.Close()

	stmtOut, err := dbCon.Prepare("INSERT INTO sync(rk_key, stv_key, stv_refresh_token, last_succesfull_retrieve, environment) VALUES(?,?,?,?)")
	if err != nil {
		log.Printf("err: %s", err)
		return 0, 0, sync, err
	}
	defer stmtOut.Close()
	res, err := stmtOut.Exec(sync.RunkeeperToken, sync.StravaToken, sync.StravaRefreshToken, createStringOutOfUnixTime(sync.LastSeenTimestamp), sync.Environment)
	if err != nil {
		log.Printf("err: %s", err)
		return 0, 0, sync, err
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		log.Printf("err: %s", err)
		return 0, 0, sync, err
	}
	rowCnt, err := res.RowsAffected()
	if err != nil {
		log.Printf("err: %s", err)
		return 0, 0, sync, err
	}
	sync.Uid = lastId
	return lastId, rowCnt, sync, nil
}

func (db DbSync) RetrieveAllSyncTasks() ([]SyncTask, error) {
	log.Printf("Connecting to DB using conn string %s", db.ConnectionString)
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	stmtOut, err :=
		dbCon.Prepare("SELECT uid, rk_key, stv_key, last_succesfull_retrieve, environment, stv_refresh_token, rk_refresh_token FROM sync WHERE rk_key != '' AND stv_key != ''")
	if err != nil {
		panic(err.Error()) // proper error handling instead of panic in your app
	}
	defer stmtOut.Close()
	defer dbCon.Close()

	rows, err := stmtOut.Query()
	defer rows.Close()

	result := make([]SyncTask, 0)
	for rows.Next() {
		var rkToken string
		var stvToken string
		var rkRefreshToken string
		var stvRefreshToken string
		var uid int64
		var lastSeenTime string
		var environment string

		rows.Scan(&uid, &rkToken, &stvToken, &lastSeenTime, &environment, &stvRefreshToken, &rkRefreshToken)
		unixTime, err := createUnixTimeOutOfString(lastSeenTime)
		if err != nil {
			log.Printf("Error while loading Sync tasks from database: %s", err)
			return result, err // proper error handling instead of panic in your app
		}

		sync := CreateSyncTask(rkToken, stvToken, rkRefreshToken, stvRefreshToken, unixTime, environment)
		sync.Uid = uid
		result = append(result, *sync)
	}
	return result, nil
}

func (db DbSync) FindSyncTaskByToken(token string) (*SyncTask, error) {
	dbCon, _ := sql.Open("mysql", db.ConnectionString)
	defer dbCon.Close()
	stmtOut, err := dbCon.Prepare("SELECT * FROM sync WHERE rk_key = ? OR stv_key = ? OR stv_refresh_token = ?")
	if err != nil {
		panic(err.Error()) // proper error handling instead of panic in your app
	}
	defer stmtOut.Close()

	rows, err := stmtOut.Query(token, token, token)
	defer rows.Close()

	for rows.Next() {
		var uid int64
		var rkToken string
		var stvToken string
		var lastSeen string
		var environment string
		var stv_refresh_token string
		var rk_refresh_token string

		err = rows.Scan(&uid, &rkToken, &stvToken, &lastSeen, &environment, &stv_refresh_token, &rk_refresh_token)
		if err != nil {
			log.Printf("Error while getting results from db for token %s", token)
			return nil, err
		}
		unixTime, err := createUnixTimeOutOfString(lastSeen)
		if err != nil {
			log.Printf("Error while converting timestamp from db %s", lastSeen)
			return nil, err
		}
		task := CreateSyncTask(rkToken, stvToken, rk_refresh_token, stv_refresh_token, unixTime, environment)
		task.Uid = uid
		return task, nil
	}
	return nil, nil
}

func makeDbStringHerokuCompliant(dbString string) string {
	dbStringWithoutProtocol := strings.Replace(dbString, "mysql://", "", 1)
	parts := strings.Split(dbStringWithoutProtocol, "@")
	userAndPassword := strings.Split(parts[0], ":")

	addr := strings.Split(parts[1], "/")[0]
	dbName := strings.Split(strings.Split(parts[1], "/")[1], "?")[0]

	resultString := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s", userAndPassword[0], userAndPassword[1], addr, dbName)
	return resultString
}

func createUnixTimeOutOfString(lastSeen string) (int, error) {
	timestamp, err := time.Parse("2006-01-02 15:04:05", lastSeen)

	if err != nil {
		return 0, err
	}
	return int(timestamp.Unix()), nil
}

func createStringOutOfUnixTime(t int) string {
	return time.Unix(int64(t), 0).Format("2006-01-02 15:04:05")
}
<|endoftext|>


<commit_before>package expect

import (
	. "fmt"
	"reflect"
	"testing"
)

type Have struct {
	*testing.T
	And    *Have
	actual interface{}
	assert bool
}

// Assert value to have length of the the given number
func (h *Have) Len(i int) *Have {
	msg := h.msg(Sprintf("length of %v", i))
	if l, ok := length(h.actual); ok {
		if l == i != h.assert {
			h.Error(msg)
		}
	} else {
		h.Fatal(invMsg("Array, Slice, Map or String"))
	}
	return h
}

// Assert value to have capacity of the given number
func (h *Have) Cap(i int) *Have {
	msg := h.msg(Sprint("capacity of %v", i))
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Array, reflect.Slice, reflect.Chan:
		if reflect.ValueOf(h.actual).Cap() == i != h.assert {
			h.Error(msg)
		}
	default:
		h.Fatal(invMsg("Array, Slice or Chan"))
	}
	return h
}

// Assert `key` exists on the given Map, and has optional value.
func (h *Have) Key(args ...interface{}) *Have {
	// Test also value
	testVal := len(args) > 1
	msg := Sprintf("key: %v", args[0])
	if testVal {
		msg += Sprintf(" with value: %v", args[1])
	}
	msg = h.msg(msg)
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Map:
		v := reflect.ValueOf(h.actual)
		k := v.MapIndex(reflect.ValueOf(args[0]))
		if (testVal && k.IsValid()) || k.IsValid() == h.assert {
			// Compare value
			if testVal && reflect.DeepEqual(k.Interface(), args[1]) != h.assert {
				h.Error(msg)
			}
		} else {
			h.Error(msg)
		}
	default:
		h.Fatal(invMsg("Map"))
	}
	return h
}

// Assert `keys` exists on the given Map
func (h *Have) Keys(args ...interface{}) *Have {
	msg := h.msg(Sprintf("keys: %v", args))
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Map:
		v := reflect.ValueOf(h.actual)
		for _, k := range args {
			vk := v.MapIndex(reflect.ValueOf(k))
			if vk.IsValid() != h.assert {
				h.Error(msg)
			}
		}
	default:
		h.Fatal(invMsg("Map"))
	}
	return h
}

// Assert `field` exist on the given Struct, and has optional value.
func (h *Have) Field(s string, args ...interface{}) *Have {
	// Test also value
	testVal := len(args) > 0
	msg := Sprintf("field: %v", s)
	if testVal {
		msg += Sprintf(" with value: %v", args[0])
	}
	msg = h.msg(msg)
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Struct:
		v := reflect.ValueOf(h.actual)
		f := v.FieldByName(s)
		if (testVal && f.IsValid()) || f.IsValid() == h.assert {
			// Compare value
			if testVal && reflect.DeepEqual(f.Interface(), args[0]) != h.assert {
				h.Error(msg)
			}
		} else {
			h.Error(msg)
		}
	default:
		h.Fatal(invMsg("Struct"))
	}
	return h
}

// Assert `fields` exists on the given Struct
func (h *Have) Fields(args ...string) *Have {
	msg := h.msg(Sprintf("fields: %v", args))
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Struct:
		v := reflect.ValueOf(h.actual)
		for _, f := range args {
			if v.FieldByName(f).IsValid() != h.assert {
				h.Error(msg)
			}
		}
	default:
		h.Fatal(invMsg("Struct"))
	}
	return h
}

// Assert `method` exist on the given struct/ptr
func (h *Have) Method(m string) *Have {
	msg := h.msg(Sprintf("method: %v", m))
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Struct, reflect.Ptr:
		v := reflect.ValueOf(h.actual)
		if v.MethodByName(m).IsValid() != h.assert {
			h.Error(msg)
		}
	default:
		h.Fatal(invMsg("Struct or Ptr"))
	}
	return h
}

func (h *Have) msg(s string) string {
	return errMsg("to have")(h.actual, s, h.assert)
}
<commit_msg>Use the same stack trace for Have<commit_after>package expect

import (
	. "fmt"
	"reflect"
	"testing"
)

type Have struct {
	*testing.T
	And    *Have
	actual interface{}
	assert bool
}

// Assert value to have length of the the given number
func (h *Have) Len(i int) *Have {
	msg := h.msg(Sprintf("length of %v", i))
	if l, ok := length(h.actual); ok {
		if l == i != h.assert {
			fail(h.T, 2, msg)
		}
	} else {
		h.Fatal(invMsg("Array, Slice, Map or String"))
	}
	return h
}

// Assert value to have capacity of the given number
func (h *Have) Cap(i int) *Have {
	msg := h.msg(Sprint("capacity of %v", i))
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Array, reflect.Slice, reflect.Chan:
		if reflect.ValueOf(h.actual).Cap() == i != h.assert {
			fail(h.T, 2, msg)
		}
	default:
		h.Fatal(invMsg("Array, Slice or Chan"))
	}
	return h
}

// Assert `key` exists on the given Map, and has optional value.
func (h *Have) Key(args ...interface{}) *Have {
	// Test also value
	testVal := len(args) > 1
	msg := Sprintf("key: %v", args[0])
	if testVal {
		msg += Sprintf(" with value: %v", args[1])
	}
	msg = h.msg(msg)
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Map:
		v := reflect.ValueOf(h.actual)
		k := v.MapIndex(reflect.ValueOf(args[0]))
		if (testVal && k.IsValid()) || k.IsValid() == h.assert {
			// Compare value
			if testVal && reflect.DeepEqual(k.Interface(), args[1]) != h.assert {
				fail(h.T, 2, msg)
			}
		} else {
			fail(h.T, 2, msg)
		}
	default:
		h.Fatal(invMsg("Map"))
	}
	return h
}

// Assert `keys` exists on the given Map
func (h *Have) Keys(args ...interface{}) *Have {
	msg := h.msg(Sprintf("keys: %v", args))
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Map:
		v := reflect.ValueOf(h.actual)
		for _, k := range args {
			vk := v.MapIndex(reflect.ValueOf(k))
			if vk.IsValid() != h.assert {
				fail(h.T, 2, msg)
			}
		}
	default:
		h.Fatal(invMsg("Map"))
	}
	return h
}

// Assert `field` exist on the given Struct, and has optional value.
func (h *Have) Field(s string, args ...interface{}) *Have {
	// Test also value
	testVal := len(args) > 0
	msg := Sprintf("field: %v", s)
	if testVal {
		msg += Sprintf(" with value: %v", args[0])
	}
	msg = h.msg(msg)
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Struct:
		v := reflect.ValueOf(h.actual)
		f := v.FieldByName(s)
		if (testVal && f.IsValid()) || f.IsValid() == h.assert {
			// Compare value
			if testVal && reflect.DeepEqual(f.Interface(), args[0]) != h.assert {
				fail(h.T, 2, msg)
			}
		} else {
			fail(h.T, 2, msg)
		}
	default:
		h.Fatal(invMsg("Struct"))
	}
	return h
}

// Assert `fields` exists on the given Struct
func (h *Have) Fields(args ...string) *Have {
	msg := h.msg(Sprintf("fields: %v", args))
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Struct:
		v := reflect.ValueOf(h.actual)
		for _, f := range args {
			if v.FieldByName(f).IsValid() != h.assert {
				fail(h.T, 2, msg)
			}
		}
	default:
		h.Fatal(invMsg("Struct"))
	}
	return h
}

// Assert `method` exist on the given struct/ptr
func (h *Have) Method(m string) *Have {
	msg := h.msg(Sprintf("method: %v", m))
	switch reflect.TypeOf(h.actual).Kind() {
	case reflect.Struct, reflect.Ptr:
		v := reflect.ValueOf(h.actual)
		if v.MethodByName(m).IsValid() != h.assert {
			fail(h.T, 2, msg)
		}
	default:
		h.Fatal(invMsg("Struct or Ptr"))
	}
	return h
}

func (h *Have) msg(s string) string {
	return errMsg("to have")(h.actual, s, h.assert)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"
	"text/template"

	"github.com/flynn/flynn-controller/client"
)

var cmdHelp = &Command{
	NoClient: true,
	Usage:    "help [topic]",
	Long:     `Help shows usage for a command or other topic.`,
}

func init() {
	cmdHelp.Run = runHelp // break init loop
}

func runHelp(cmd *Command, args []string, client *controller.Client) error {
	if len(args) == 0 {
		printUsage()
		return nil // not os.Exit(2); success
	}
	if len(args) != 1 {
		return errors.New("too many arguments")
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] {
			cmd.printUsage(false)
			return nil
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown help topic: %q. Run 'flynn help'.\n", args[0])
	os.Exit(2)
	return nil
}

var cmdVersion = &Command{
	Run:      runVersion,
	NoClient: true,
	Usage:    "version",
	Short:    "show flynn version",
	Long:     `Version shows the flynn client version string.`,
}

func runVersion(cmd *Command, args []string, client *controller.Client) error {
	fmt.Println(Version)
	return nil
}

var usageTemplate = template.Must(template.New("usage").Parse(`
Usage: flynn [-a app] [command] [options] [arguments]

Commands:
{{range .Commands}}{{if .Runnable}}{{if .List}}
    {{.Name | printf (print "%-" $.MaxCommandWidth "s")}}  {{.Short}}{{end}}{{end}}{{end}}

Run 'flynn help [command]' for details.
`[1:]))

func printUsage() {
	data := &struct {
		Commands        []*Command
		MaxCommandWidth int
	}{Commands: commands}

	for _, cmd := range commands {
		if len(cmd.Name()) > data.MaxCommandWidth {
			data.MaxCommandWidth = len(cmd.Name())
		}
	}

	usageTemplate.Execute(os.Stdout, data)
}

func usage() {
	printUsage()
	os.Exit(2)
}
<commit_msg>cli: Add "flynn help commands"<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"text/tabwriter"
	"text/template"

	"github.com/flynn/flynn-controller/client"
)

var cmdHelp = &Command{
	NoClient: true,
	Usage:    "help [topic]",
	Long:     `Help shows usage for a command or other topic.`,
}

func init() {
	cmdHelp.Run = runHelp // break init loop
}

func runHelp(cmd *Command, args []string, client *controller.Client) error {
	if len(args) == 0 {
		printUsage()
		return nil // not os.Exit(2); success
	}
	if len(args) != 1 {
		return errors.New("too many arguments")
	}

	if args[0] == "commands" {
		printAllUsage()
		return nil
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] {
			cmd.printUsage(false)
			return nil
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown help topic: %q. Run 'flynn help'.\n", args[0])
	os.Exit(2)
	return nil
}

var cmdVersion = &Command{
	Run:      runVersion,
	NoClient: true,
	Usage:    "version",
	Short:    "show flynn version",
	Long:     `Version shows the flynn client version string.`,
}

func runVersion(cmd *Command, args []string, client *controller.Client) error {
	fmt.Println(Version)
	return nil
}

var usageTemplate = template.Must(template.New("usage").Parse(`
Usage: flynn [-a app] [command] [options] [arguments]

Commands:
{{range .Commands}}{{if .Runnable}}{{if .List}}
    {{.Name | printf (print "%-" $.MaxCommandWidth "s")}}  {{.Short}}{{end}}{{end}}{{end}}

Run 'flynn help [command]' for details.
`[1:]))

func printUsage() {
	data := &struct {
		Commands        []*Command
		MaxCommandWidth int
	}{Commands: commands}

	for _, cmd := range commands {
		if len(cmd.Name()) > data.MaxCommandWidth {
			data.MaxCommandWidth = len(cmd.Name())
		}
	}

	usageTemplate.Execute(os.Stdout, data)
}

func printAllUsage() {
	w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0)
	defer w.Flush()

	for _, cmd := range commands {
		if cmd.Runnable() {
			fmt.Fprintf(w, "flynn %s\t%s\n", cmd.Usage, cmd.Short)
		}
	}
}

func usage() {
	printUsage()
	os.Exit(2)
}
<|endoftext|>


<commit_before>package meter

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"
	"sync"
	"time"

	"github.com/alxarch/go-meter/tcodec"
)

const (
	QueryParamEvent      = "event"
	QueryParamResolution = "res"
	QueryParamStart      = "start"
	QueryParamEnd        = "end"
	QueryParamGroup      = "group"
	QueryParamMode       = "mode"
)

func ParseQuery(q url.Values, tdec tcodec.TimeDecoder) (s QueryBuilder, err error) {
	eventNames := q[QueryParamEvent]
	delete(q, QueryParamEvent)
	if len(eventNames) == 0 {
		err = fmt.Errorf("Missing query.%s", QueryParamEvent)
		return
	}
	if _, ok := q[QueryParamResolution]; ok {
		s.Resolution = q.Get(QueryParamResolution)
		delete(q, QueryParamResolution)
	} else {
		err = fmt.Errorf("Missing query.%s", QueryParamResolution)
		return
	}
	if _, ok := q[QueryParamGroup]; ok {
		s.Group = q[QueryParamGroup]
		delete(q, QueryParamGroup)
	}

	if start, ok := q[QueryParamStart]; !ok {
		err = fmt.Errorf("Missing query.%s", QueryParamStart)
		return
	} else if s.Start, err = tdec.UnmarshalTime(start[0]); err != nil {
		err = fmt.Errorf("Invalid query.%s: %s", QueryParamStart, err)
		return
	}
	delete(q, QueryParamStart)
	if end, ok := q[QueryParamEnd]; !ok {
		err = fmt.Errorf("Missing query.%s", QueryParamEnd)
		return
	} else if s.End, err = tdec.UnmarshalTime(end[0]); err != nil {
		err = fmt.Errorf("Invalid query.%s: %s", QueryParamEnd, err)
		return
	}
	delete(q, QueryParamEnd)
	s.Query = q
	if now := time.Now(); s.End.After(now) {
		s.End = now
	}
	if s.Start.IsZero() || s.Start.After(s.End) {
		s.Start = s.End
	}
	switch q.Get(QueryParamMode) {
	case "exact":
		s.Mode = ModeExact
	case "values":
		s.Mode = ModeValues
	default:
		s.Mode = ModeScan
	}
	delete(q, QueryParamMode)
	s.Events = eventNames
	return

}

type Logger interface {
	Printf(format string, args ...interface{})
}

type Controller struct {
	DB *DB
	*Registry
	Logger        Logger
	TimeDecoder   tcodec.TimeDecoder
	FlushInterval time.Duration
	once          sync.Once
	closeCh       chan struct{}
	wg            sync.WaitGroup
}

func (c *Controller) Close() {
	if c.closeCh == nil {
		return
	}
	close(c.closeCh)
	c.wg.Wait()
}

func (c *Controller) Flush(t time.Time) {
	events := c.Registry.Events()
	errCh := make(chan error, len(events))
	c.wg.Add(1)
	defer c.wg.Done()
	for _, e := range events {
		c.wg.Add(1)
		go func(e *Event) {
			errCh <- c.DB.Gather(t, e)
			c.wg.Done()
		}(e)
	}
	c.wg.Wait()
	close(errCh)
	if c.Logger != nil {
		for _, e := range events {
			err, ok := <-errCh
			if !ok {
				break
			}
			if err != nil {
				c.Logger.Printf("Failed to sync event %s: %s", e.Describe().Name(), err)
			}
		}
	}

}
func (c *Controller) init() {
	if c.FlushInterval > 0 {
		c.closeCh = make(chan struct{})
		go c.runFlush(c.FlushInterval)
	}
}

func (c *Controller) runFlush(interval time.Duration) {
	tick := time.NewTicker(interval)
	defer tick.Stop()
	for {
		select {
		case t := <-tick.C:
			go c.Flush(t)
		case <-c.closeCh:
			return
		}
	}
}

func (c *Controller) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		q := r.URL.Query()
		qb, err := ParseQuery(q, c.TimeDecoder)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		var output interface{}
		events := c.Registry
		if events == nil {
			events = defaultRegistry
		}
		queries := qb.Queries(events)
		results, _ := c.DB.Query(queries...)
		switch qb.Mode {
		case ModeValues:
			output = results.FrequencyMap()
		default:
			output = results
		}
		w.Header().Set("Content-Type", "application/json")
		enc := json.NewEncoder(w)
		enc.Encode(output)
	case http.MethodPost:
		defer r.Body.Close()
		check, eventName := path.Split(r.URL.Path)
		if check != "/" {
			w.WriteHeader(http.StatusBadRequest)
			return
		}
		event := c.Registry.Get(eventName)
		if event == nil {
			http.NotFound(w, r)
			return
		}
		s := getSync()
		defer putSync(s)
		s.buf.Reset()
		_, err := s.buf.ReadFrom(r.Body)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		s.snapshot = s.snapshot[:0]
		if err = json.Unmarshal(s.buf.Bytes(), &s.snapshot); err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		if c.FlushInterval > 0 {
			c.once.Do(c.init)
			event.Merge(s.snapshot)
		} else {
			if err := c.DB.gather(time.Now(), event.Describe(), s.snapshot); err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		}

		w.WriteHeader(http.StatusOK)
	default:
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}

var snapshotPool sync.Pool

func getSnapshot() Snapshot {
	if x := snapshotPool.Get(); x != nil {
		return x.(Snapshot)
	}
	return make([]Counter, 0, 64)
}
func putSnapshot(s Snapshot) {
	if s == nil {
		return
	}
	snapshotPool.Put(s[:0])
}

var syncPool sync.Pool

type syncBuffer struct {
	buf      bytes.Buffer
	snapshot Snapshot
}

func getSync() *syncBuffer {
	if x := syncPool.Get(); x != nil {
		return x.(*syncBuffer)
	}
	return new(syncBuffer)
}
func putSync(s *syncBuffer) {
	if s == nil {
		return
	}
	syncPool.Put(s)
}

type Client struct {
	URL string
	*http.Client
}

func (c *Client) Batch(logger *log.Logger, events ...*Event) {
	wg := new(sync.WaitGroup)
	for _, e := range events {
		wg.Add(1)
		go func(e *Event) {
			defer wg.Done()
			if err := c.Sync(e); err != nil {
				if logger != nil {
					logger.Printf("Failed to sync event %s: %s\n", e.Describe().Name(), err)
				}
			}
		}(e)
	}
	wg.Wait()
}

func (c *Client) Run(ctx context.Context, interval time.Duration, logger *log.Logger, events ...*Event) {
	if ctx == nil {
		ctx = context.Background()
	}
	tick := time.NewTicker(interval)
	pack := time.NewTicker(time.Hour)
	defer c.Batch(logger, events...)
	for {
		select {
		case <-ctx.Done():
			pack.Stop()
			tick.Stop()
			return
		case <-tick.C:
			c.Batch(logger, events...)
		case <-pack.C:
			for _, event := range events {
				event.Pack()
			}
		}
	}
}

func (c *Client) Sync(e *Event) error {
	desc := e.Describe()
	url := path.Join(c.URL, desc.Name())

	s := getSync()
	defer putSync(s)
	s.snapshot = e.Flush(s.snapshot[:0])
	if len(s.snapshot) == 0 {
		return nil
	}
	s.buf.Reset()
	enc := json.NewEncoder(&s.buf)
	if err := enc.Encode(s.snapshot); err != nil {
		return err
	}
	client := c.Client
	if client == nil {
		client = http.DefaultClient
	}
	res, err := client.Post(url, "application/json", &s.buf)
	if err != nil {
		e.Merge(s.snapshot)
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		e.Merge(s.snapshot)
		return fmt.Errorf("Failed to sync event %s to %s: %d %s", desc.Name(), url, res.StatusCode, res.Status)
	}
	return nil
}
<commit_msg>Use *std.Logger<commit_after>package meter

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"
	"sync"
	"time"

	"github.com/alxarch/go-meter/tcodec"
)

const (
	QueryParamEvent      = "event"
	QueryParamResolution = "res"
	QueryParamStart      = "start"
	QueryParamEnd        = "end"
	QueryParamGroup      = "group"
	QueryParamMode       = "mode"
)

func ParseQuery(q url.Values, tdec tcodec.TimeDecoder) (s QueryBuilder, err error) {
	eventNames := q[QueryParamEvent]
	delete(q, QueryParamEvent)
	if len(eventNames) == 0 {
		err = fmt.Errorf("Missing query.%s", QueryParamEvent)
		return
	}
	if _, ok := q[QueryParamResolution]; ok {
		s.Resolution = q.Get(QueryParamResolution)
		delete(q, QueryParamResolution)
	} else {
		err = fmt.Errorf("Missing query.%s", QueryParamResolution)
		return
	}
	if _, ok := q[QueryParamGroup]; ok {
		s.Group = q[QueryParamGroup]
		delete(q, QueryParamGroup)
	}

	if start, ok := q[QueryParamStart]; !ok {
		err = fmt.Errorf("Missing query.%s", QueryParamStart)
		return
	} else if s.Start, err = tdec.UnmarshalTime(start[0]); err != nil {
		err = fmt.Errorf("Invalid query.%s: %s", QueryParamStart, err)
		return
	}
	delete(q, QueryParamStart)
	if end, ok := q[QueryParamEnd]; !ok {
		err = fmt.Errorf("Missing query.%s", QueryParamEnd)
		return
	} else if s.End, err = tdec.UnmarshalTime(end[0]); err != nil {
		err = fmt.Errorf("Invalid query.%s: %s", QueryParamEnd, err)
		return
	}
	delete(q, QueryParamEnd)
	s.Query = q
	if now := time.Now(); s.End.After(now) {
		s.End = now
	}
	if s.Start.IsZero() || s.Start.After(s.End) {
		s.Start = s.End
	}
	switch q.Get(QueryParamMode) {
	case "exact":
		s.Mode = ModeExact
	case "values":
		s.Mode = ModeValues
	default:
		s.Mode = ModeScan
	}
	delete(q, QueryParamMode)
	s.Events = eventNames
	return

}

type Controller struct {
	DB *DB
	*Registry
	Logger        *log.Logger
	TimeDecoder   tcodec.TimeDecoder
	FlushInterval time.Duration
	once          sync.Once
	closeCh       chan struct{}
	wg            sync.WaitGroup
}

func (c *Controller) Close() {
	if c.closeCh == nil {
		return
	}
	close(c.closeCh)
	c.wg.Wait()
}

func (c *Controller) Flush(t time.Time) {
	events := c.Registry.Events()
	errCh := make(chan error, len(events))
	c.wg.Add(1)
	defer c.wg.Done()
	for _, e := range events {
		c.wg.Add(1)
		go func(e *Event) {
			errCh <- c.DB.Gather(t, e)
			c.wg.Done()
		}(e)
	}
	c.wg.Wait()
	close(errCh)
	if c.Logger != nil {
		for _, e := range events {
			err, ok := <-errCh
			if !ok {
				break
			}
			if err != nil {
				c.Logger.Printf("Failed to sync event %s: %s\n", e.Describe().Name(), err)
			}
		}
	}

}
func (c *Controller) init() {
	if c.FlushInterval > 0 {
		c.closeCh = make(chan struct{})
		go c.runFlush(c.FlushInterval)
	}
}

func (c *Controller) runFlush(interval time.Duration) {
	tick := time.NewTicker(interval)
	defer tick.Stop()
	for {
		select {
		case t := <-tick.C:
			go c.Flush(t)
		case <-c.closeCh:
			return
		}
	}
}

func (c *Controller) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		q := r.URL.Query()
		qb, err := ParseQuery(q, c.TimeDecoder)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		var output interface{}
		events := c.Registry
		if events == nil {
			events = defaultRegistry
		}
		queries := qb.Queries(events)
		results, _ := c.DB.Query(queries...)
		switch qb.Mode {
		case ModeValues:
			output = results.FrequencyMap()
		default:
			output = results
		}
		w.Header().Set("Content-Type", "application/json")
		enc := json.NewEncoder(w)
		enc.Encode(output)
	case http.MethodPost:
		defer r.Body.Close()
		check, eventName := path.Split(r.URL.Path)
		if check != "/" {
			w.WriteHeader(http.StatusBadRequest)
			return
		}
		event := c.Registry.Get(eventName)
		if event == nil {
			http.NotFound(w, r)
			return
		}
		s := getSync()
		defer putSync(s)
		s.buf.Reset()
		_, err := s.buf.ReadFrom(r.Body)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		s.snapshot = s.snapshot[:0]
		if err = json.Unmarshal(s.buf.Bytes(), &s.snapshot); err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		if c.FlushInterval > 0 {
			c.once.Do(c.init)
			event.Merge(s.snapshot)
		} else {
			if err := c.DB.gather(time.Now(), event.Describe(), s.snapshot); err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		}

		w.WriteHeader(http.StatusOK)
	default:
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}

var snapshotPool sync.Pool

func getSnapshot() Snapshot {
	if x := snapshotPool.Get(); x != nil {
		return x.(Snapshot)
	}
	return make([]Counter, 0, 64)
}
func putSnapshot(s Snapshot) {
	if s == nil {
		return
	}
	snapshotPool.Put(s[:0])
}

var syncPool sync.Pool

type syncBuffer struct {
	buf      bytes.Buffer
	snapshot Snapshot
}

func getSync() *syncBuffer {
	if x := syncPool.Get(); x != nil {
		return x.(*syncBuffer)
	}
	return new(syncBuffer)
}
func putSync(s *syncBuffer) {
	if s == nil {
		return
	}
	syncPool.Put(s)
}

type Client struct {
	URL string
	*http.Client
}

func (c *Client) Batch(logger *log.Logger, events ...*Event) {
	wg := new(sync.WaitGroup)
	for _, e := range events {
		wg.Add(1)
		go func(e *Event) {
			defer wg.Done()
			if err := c.Sync(e); err != nil {
				if logger != nil {
					logger.Printf("Failed to sync event %s: %s\n", e.Describe().Name(), err)
				}
			}
		}(e)
	}
	wg.Wait()
}

func (c *Client) Run(ctx context.Context, interval time.Duration, logger *log.Logger, events ...*Event) {
	if ctx == nil {
		ctx = context.Background()
	}
	tick := time.NewTicker(interval)
	pack := time.NewTicker(time.Hour)
	defer c.Batch(logger, events...)
	for {
		select {
		case <-ctx.Done():
			pack.Stop()
			tick.Stop()
			return
		case <-tick.C:
			c.Batch(logger, events...)
		case <-pack.C:
			for _, event := range events {
				event.Pack()
			}
		}
	}
}

func (c *Client) Sync(e *Event) error {
	desc := e.Describe()
	url := path.Join(c.URL, desc.Name())

	s := getSync()
	defer putSync(s)
	s.snapshot = e.Flush(s.snapshot[:0])
	if len(s.snapshot) == 0 {
		return nil
	}
	s.buf.Reset()
	enc := json.NewEncoder(&s.buf)
	if err := enc.Encode(s.snapshot); err != nil {
		return err
	}
	client := c.Client
	if client == nil {
		client = http.DefaultClient
	}
	res, err := client.Post(url, "application/json", &s.buf)
	if err != nil {
		e.Merge(s.snapshot)
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		e.Merge(s.snapshot)
		return fmt.Errorf("Failed to sync event %s to %s: %d %s", desc.Name(), url, res.StatusCode, res.Status)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Eric Barkie. All rights reserved.
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.

package main

// HTTP server for accessing weather station data.

import (
	"encoding/json"
	"fmt"
	"net/http"
	//_ "net/http/pprof"
	"strconv"
	"time"
)

type httpContext serverContext

type httpLogWrapper struct {
	http.CloseNotifier
	http.Flusher
	http.ResponseWriter
	status int
}

func (l *httpLogWrapper) Write(p []byte) (int, error) {
	return l.ResponseWriter.Write(p)
}

func (l *httpLogWrapper) WriteHeader(status int) {
	l.status = status
	l.ResponseWriter.WriteHeader(status)
}

func (httpContext) logHandler(h http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		record := &httpLogWrapper{
			CloseNotifier:  w.(http.CloseNotifier),
			Flusher:        w.(http.Flusher),
			ResponseWriter: w,
			status:         http.StatusOK,
		}

		h.ServeHTTP(record, r)

		msg := fmt.Sprintf("HTTP connection from %s request %s %s response %d", r.RemoteAddr, r.Method, r.URL, record.status)
		if record.status < 299 {
			Debug.Print(msg)
		} else {
			Warn.Print(msg)
		}
	}
}

// archive is the endpoint for serving out archive records.
// GET /archive[?begin=2016-08-03T00:00:00Z][&end=2016-09-03T00:00:00Z]
func (c httpContext) archive(w http.ResponseWriter, r *http.Request) {
	// Parse and validate begin and end parameters.
	var begin, end time.Time
	var err error

	if r.URL.Query().Get("end") != "" {
		end, err = time.Parse(time.RFC3339, r.URL.Query().Get("end"))
		if err != nil {
			w.Header().Set("Warning", "Unable to parse end timestamp")
			w.WriteHeader(http.StatusBadRequest)
			return
		}
	} else {
		end = time.Now()
	}

	if r.URL.Query().Get("begin") != "" {
		begin, err = time.Parse(time.RFC3339, r.URL.Query().Get("begin"))
		if err != nil {
			w.Header().Set("Warning", "Unable to parse begin timestamp")
			w.WriteHeader(http.StatusBadRequest)
			return
		}
	} else {
		begin = end.AddDate(0, 0, -1)
	}

	if end.Before(begin) {
		w.Header().Set("Warning", "End timestamp precedes begin timestamp")
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(c.ad.Get(begin, end))
}

// loop is the endpoint for serving out loop samples.
// GET /loop[?lastSequence=#]
func (c httpContext) loop(w http.ResponseWriter, r *http.Request) {
	loops := c.lb.loops()

	// If there aren't enough samples (the server just started) or
	// there were no recent updates then send a HTTP service temporarily
	// unavailable response.
	if len(loops) < loopsMin {
		w.Header().Set("Warning", "Not enough samples yet")
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}

	if time.Since(loops[0].Update.Timestamp) > loopStaleAge {
		w.Header().Set("Warning", "Samples are too old")
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}

	// Figure out if request is for loops since a sequence or just for
	// most recent loop.
	j := json.NewEncoder(w)
	if r.URL.Query().Get("lastSequence") != "" {
		seq, _ := strconv.ParseInt(r.URL.Query().Get("lastSequence"), 10, 64)

		// There are no sequence gaps so it's simple subtraction to
		// determine the end index.  A few safeguards have to be added
		// though:
		//
		// If the requested sequence is ahead of the server then return
		// nothing.
		//
		// If the request sequence is so far back that it's been purged
		// then return everything.
		endIndex := int(loops[0].Update.Seq - seq)
		if endIndex < 1 {
			w.WriteHeader(http.StatusNoContent)
		} else {
			if endIndex > len(loops) {
				endIndex = len(loops)
			}
			w.Header().Set("Content-Type", "application/json")
			j.Encode(loops[0:endIndex])
		}
	} else {
		w.Header().Set("Content-Type", "application/json")
		j.Encode(loops[0])
	}
}

// events is the endpoint for streaming loop samples using the Server-sent
// events.
// GET /events
func (c httpContext) events(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")

	incomingEvents := c.eb.subscribe(r.RemoteAddr)
	defer c.eb.unsubscribe(incomingEvents)

	for {
		select {
		case <-w.(http.CloseNotifier).CloseNotify():
			// Client closed the connection
			return
		case e := <-incomingEvents:
			fmt.Fprintf(w, "event: %s\n", e.event)
			r, _ := json.Marshal(e.data)
			fmt.Fprintf(w, "data: %s\n\n", r)
			w.(http.Flusher).Flush()
		}
	}
}

// httpServer starts the HTTP server.  It's blocking and should be called as
// a goroutine.
func httpServer(bindAddress string, sc serverContext) {
	c := httpContext(sc)
	http.HandleFunc("/archive", c.archive)
	http.HandleFunc("/loop", c.loop)
	http.HandleFunc("/events", c.events)

	s := http.Server{
		Addr:    bindAddress + ":8080",
		Handler: c.logHandler(http.DefaultServeMux),
	}
	Info.Printf("HTTP server started on %s", s.Addr)
	err := s.ListenAndServe()
	if err != nil {
		Error.Fatalf("HTTP server error: %s", err.Error())
	}
}
<commit_msg>Bring back previous archive limit for http<commit_after>// Copyright (c) 2016-2017 Eric Barkie. All rights reserved.
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.

package main

// HTTP server for accessing weather station data.

import (
	"encoding/json"
	"fmt"
	"net/http"
	//_ "net/http/pprof"
	"strconv"
	"time"
)

type httpContext serverContext

type httpLogWrapper struct {
	http.CloseNotifier
	http.Flusher
	http.ResponseWriter
	status int
}

func (l *httpLogWrapper) Write(p []byte) (int, error) {
	return l.ResponseWriter.Write(p)
}

func (l *httpLogWrapper) WriteHeader(status int) {
	l.status = status
	l.ResponseWriter.WriteHeader(status)
}

func (httpContext) logHandler(h http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		record := &httpLogWrapper{
			CloseNotifier:  w.(http.CloseNotifier),
			Flusher:        w.(http.Flusher),
			ResponseWriter: w,
			status:         http.StatusOK,
		}

		h.ServeHTTP(record, r)

		msg := fmt.Sprintf("HTTP connection from %s request %s %s response %d", r.RemoteAddr, r.Method, r.URL, record.status)
		if record.status < 299 {
			Debug.Print(msg)
		} else {
			Warn.Print(msg)
		}
	}
}

// archive is the endpoint for serving out archive records.
// GET /archive[?begin=2016-08-03T00:00:00Z][&end=2016-09-03T00:00:00Z]
func (c httpContext) archive(w http.ResponseWriter, r *http.Request) {
	// Parse and validate begin and end parameters.
	var begin, end time.Time
	var err error

	if r.URL.Query().Get("end") != "" {
		end, err = time.Parse(time.RFC3339, r.URL.Query().Get("end"))
		if err != nil {
			w.Header().Set("Warning", "Unable to parse end timestamp")
			w.WriteHeader(http.StatusBadRequest)
			return
		}
	} else {
		end = time.Now()
	}

	if r.URL.Query().Get("begin") != "" {
		begin, err = time.Parse(time.RFC3339, r.URL.Query().Get("begin"))
		if err != nil {
			w.Header().Set("Warning", "Unable to parse begin timestamp")
			w.WriteHeader(http.StatusBadRequest)
			return
		}
	} else {
		begin = end.AddDate(0, 0, -1)
	}

	if end.Before(begin) {
		w.Header().Set("Warning", "End timestamp precedes begin timestamp")
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Large durations can be very resource intensive to marshal so
	// cap at 30 days.
	if end.Sub(begin) > (30 * (24 * time.Hour)) {
		w.Header().Set("Warning", "Duration exceeds maximum allowed")
		w.WriteHeader(http.StatusRequestEntityTooLarge)
		return
	}

	// Query archive from database and return.
	archive := c.ad.Get(begin, end)
	if len(archive) < 1 {
		w.WriteHeader(http.StatusNoContent)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(archive)
}

// loop is the endpoint for serving out loop samples.
// GET /loop[?lastSequence=#]
func (c httpContext) loop(w http.ResponseWriter, r *http.Request) {
	loops := c.lb.loops()

	// If there aren't enough samples (the server just started) or
	// there were no recent updates then send a HTTP service temporarily
	// unavailable response.
	if len(loops) < loopsMin {
		w.Header().Set("Warning", "Not enough samples yet")
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}

	if time.Since(loops[0].Update.Timestamp) > loopStaleAge {
		w.Header().Set("Warning", "Samples are too old")
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}

	// Figure out if request is for loops since a sequence or just for
	// most recent loop.
	j := json.NewEncoder(w)
	if r.URL.Query().Get("lastSequence") != "" {
		seq, _ := strconv.ParseInt(r.URL.Query().Get("lastSequence"), 10, 64)

		// There are no sequence gaps so it's simple subtraction to
		// determine the end index.  A few safeguards have to be added
		// though:
		//
		// If the requested sequence is ahead of the server then return
		// nothing.
		//
		// If the request sequence is so far back that it's been purged
		// then return everything.
		endIndex := int(loops[0].Update.Seq - seq)
		if endIndex < 1 {
			w.WriteHeader(http.StatusNoContent)
		} else {
			if endIndex > len(loops) {
				endIndex = len(loops)
			}
			w.Header().Set("Content-Type", "application/json")
			j.Encode(loops[0:endIndex])
		}
	} else {
		w.Header().Set("Content-Type", "application/json")
		j.Encode(loops[0])
	}
}

// events is the endpoint for streaming loop samples using the Server-sent
// events.
// GET /events
func (c httpContext) events(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")

	incomingEvents := c.eb.subscribe(r.RemoteAddr)
	defer c.eb.unsubscribe(incomingEvents)

	for {
		select {
		case <-w.(http.CloseNotifier).CloseNotify():
			// Client closed the connection
			return
		case e := <-incomingEvents:
			fmt.Fprintf(w, "event: %s\n", e.event)
			r, _ := json.Marshal(e.data)
			fmt.Fprintf(w, "data: %s\n\n", r)
			w.(http.Flusher).Flush()
		}
	}
}

// httpServer starts the HTTP server.  It's blocking and should be called as
// a goroutine.
func httpServer(bindAddress string, sc serverContext) {
	c := httpContext(sc)
	http.HandleFunc("/archive", c.archive)
	http.HandleFunc("/loop", c.loop)
	http.HandleFunc("/events", c.events)

	s := http.Server{
		Addr:    bindAddress + ":8080",
		Handler: c.logHandler(http.DefaultServeMux),
	}
	Info.Printf("HTTP server started on %s", s.Addr)
	err := s.ListenAndServe()
	if err != nil {
		Error.Fatalf("HTTP server error: %s", err.Error())
	}
}
<|endoftext|>


<commit_before>package htcat

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"sync"
)

const (
	_        = iota
	kB int64 = 1 << (10 * iota)
	mB
	gB
	tB
	pB
	eB
)

type HtCat struct {
	defrag

	u     *url.URL
	cl    *http.Client
	tasks chan *httpFrag

	// Protect httpFragGen with a Mutex.
	httpFragGenMu sync.Mutex
	httpFragGen
}

type HttpStatusError struct {
	error
	Status string
}

func (cat *HtCat) startup(parallelism int) {
	req := http.Request{
		Method:     "GET",
		URL:        cat.u,
		Proto:      "HTTP/1.1",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Body:       nil,
		Host:       cat.u.Host,
	}

	resp, err := cat.cl.Do(&req)
	if err != nil {
		go cat.defrag.cancel(err)
		return
	}

	// Check for non-200 OK response codes from the startup-GET.
	if resp.Status != "200 OK" {
		err = HttpStatusError{
			error: fmt.Errorf(
				"Expected HTTP Status 200, received: %q",
				resp.Status),
			Status: resp.Status}
		go cat.defrag.cancel(err)
		return
	}

	l := resp.Header.Get("Content-Length")

	// Some kinds of small or indeterminate-length files will
	// receive no parallelism.  This procedure helps prepare the
	// HtCat value for a one-HTTP-Request GET.
	noParallel := func(wtc writerToCloser) {
		f := cat.defrag.nextFragment()
		cat.defrag.setLast(cat.defrag.lastAllocated())
		f.contents = wtc
		cat.register(f)
	}

	if l == "" {
		// No Content-Length, stream without parallelism nor
		// assumptions about the length of the stream.
		go noParallel(struct {
			io.WriterTo
			io.Closer
		}{
			WriterTo: bufio.NewReader(resp.Body),
			Closer:   resp.Body,
		})
		return
	}

	length, err := strconv.ParseInt(l, 10, 64)
	if err != nil {
		// Invalid integer for Content-Length, defer reporting
		// the error until a WriteTo call is made.
		go cat.defrag.cancel(err)
		return
	}

	// Set up httpFrag generator state.
	cat.totalSize = length
	cat.targetFragSize = length / int64(parallelism)
	if cat.targetFragSize > 20*mB {
		cat.targetFragSize = 20 * mB
	}

	// Very small fragments are probably not worthwhile to start
	// up new requests for, but it in this case it was possible to
	// ascertain the size, so take advantage of that to start
	// reading in the background as eagerly as possible.
	if cat.targetFragSize < 1*mB {
		er := newEagerReader(resp.Body, cat.totalSize)
		go noParallel(er)
		go func() { er.WaitClosed() }()
		return
	}

	// None of the other special short-circuit cases have been
	// triggered, so begin preparation for full-blown parallel
	// GET.  One GET worker is started here to take advantage of
	// the already pending response (which has no determinate
	// length, so it must be limited).
	hf := cat.nextFragment()
	go func() {
		er := newEagerReader(
			struct {
				io.Reader
				io.Closer
			}{
				Reader: io.LimitReader(resp.Body, hf.size),
				Closer: resp.Body,
			},
			hf.size)

		hf.fragment.contents = er
		cat.register(hf.fragment)
		er.WaitClosed()

		// Chain into being a regular worker, having finished
		// the special start-up segment.
		cat.get()
	}()

}

func New(client *http.Client, u *url.URL, parallelism int) *HtCat {
	cat := HtCat{
		u:  u,
		cl: client,
	}

	cat.initDefrag()
	cat.startup(parallelism)

	if cat.totalSize <= 0 {
		return &cat
	}

	// Start background workers.
	//
	// "startup" starts one worker that is specially constructed
	// to deal with the first request, so back off by one to
	// prevent performing with too much parallelism.
	for i := 1; i < parallelism; i += 1 {
		go cat.get()
	}

	return &cat
}

func (cat *HtCat) nextFragment() *httpFrag {
	cat.httpFragGenMu.Lock()
	defer cat.httpFragGenMu.Unlock()

	var hf *httpFrag

	if cat.httpFragGen.hasNext() {
		f := cat.defrag.nextFragment()
		hf = cat.httpFragGen.nextFragment(f)
	} else {
		cat.defrag.setLast(cat.defrag.lastAllocated())
	}

	return hf
}

func (cat *HtCat) get() {
	for {
		hf := cat.nextFragment()
		if hf == nil {
			return
		}

		req := http.Request{
			Method:     "GET",
			URL:        cat.u,
			Proto:      "HTTP/1.1",
			ProtoMajor: 1,
			ProtoMinor: 1,
			Header:     hf.header,
			Body:       nil,
			Host:       cat.u.Host,
		}

		resp, err := cat.cl.Do(&req)
		if err != nil {
			cat.defrag.cancel(err)
		}

		// Check for non-206 Partial Content response codes from the
		// range-GET.
		if resp.Status != "206 Partial Content" {
			err = HttpStatusError{
				error: fmt.Errorf("Expected HTTP Status 206, "+
					"received: %q",
					resp.Status),
				Status: resp.Status}
			go cat.defrag.cancel(err)
			return
		}

		er := newEagerReader(resp.Body, hf.size)
		hf.fragment.contents = er
		cat.register(hf.fragment)
		er.WaitClosed()
	}
}
<commit_msg>Avoid panic when aborting after an error<commit_after>package htcat

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"sync"
)

const (
	_        = iota
	kB int64 = 1 << (10 * iota)
	mB
	gB
	tB
	pB
	eB
)

type HtCat struct {
	defrag

	u     *url.URL
	cl    *http.Client
	tasks chan *httpFrag

	// Protect httpFragGen with a Mutex.
	httpFragGenMu sync.Mutex
	httpFragGen
}

type HttpStatusError struct {
	error
	Status string
}

func (cat *HtCat) startup(parallelism int) {
	req := http.Request{
		Method:     "GET",
		URL:        cat.u,
		Proto:      "HTTP/1.1",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Body:       nil,
		Host:       cat.u.Host,
	}

	resp, err := cat.cl.Do(&req)
	if err != nil {
		go cat.defrag.cancel(err)
		return
	}

	// Check for non-200 OK response codes from the startup-GET.
	if resp.Status != "200 OK" {
		err = HttpStatusError{
			error: fmt.Errorf(
				"Expected HTTP Status 200, received: %q",
				resp.Status),
			Status: resp.Status}
		go cat.defrag.cancel(err)
		return
	}

	l := resp.Header.Get("Content-Length")

	// Some kinds of small or indeterminate-length files will
	// receive no parallelism.  This procedure helps prepare the
	// HtCat value for a one-HTTP-Request GET.
	noParallel := func(wtc writerToCloser) {
		f := cat.defrag.nextFragment()
		cat.defrag.setLast(cat.defrag.lastAllocated())
		f.contents = wtc
		cat.register(f)
	}

	if l == "" {
		// No Content-Length, stream without parallelism nor
		// assumptions about the length of the stream.
		go noParallel(struct {
			io.WriterTo
			io.Closer
		}{
			WriterTo: bufio.NewReader(resp.Body),
			Closer:   resp.Body,
		})
		return
	}

	length, err := strconv.ParseInt(l, 10, 64)
	if err != nil {
		// Invalid integer for Content-Length, defer reporting
		// the error until a WriteTo call is made.
		go cat.defrag.cancel(err)
		return
	}

	// Set up httpFrag generator state.
	cat.totalSize = length
	cat.targetFragSize = length / int64(parallelism)
	if cat.targetFragSize > 20*mB {
		cat.targetFragSize = 20 * mB
	}

	// Very small fragments are probably not worthwhile to start
	// up new requests for, but it in this case it was possible to
	// ascertain the size, so take advantage of that to start
	// reading in the background as eagerly as possible.
	if cat.targetFragSize < 1*mB {
		er := newEagerReader(resp.Body, cat.totalSize)
		go noParallel(er)
		go func() { er.WaitClosed() }()
		return
	}

	// None of the other special short-circuit cases have been
	// triggered, so begin preparation for full-blown parallel
	// GET.  One GET worker is started here to take advantage of
	// the already pending response (which has no determinate
	// length, so it must be limited).
	hf := cat.nextFragment()
	go func() {
		er := newEagerReader(
			struct {
				io.Reader
				io.Closer
			}{
				Reader: io.LimitReader(resp.Body, hf.size),
				Closer: resp.Body,
			},
			hf.size)

		hf.fragment.contents = er
		cat.register(hf.fragment)
		er.WaitClosed()

		// Chain into being a regular worker, having finished
		// the special start-up segment.
		cat.get()
	}()

}

func New(client *http.Client, u *url.URL, parallelism int) *HtCat {
	cat := HtCat{
		u:  u,
		cl: client,
	}

	cat.initDefrag()
	cat.startup(parallelism)

	if cat.totalSize <= 0 {
		return &cat
	}

	// Start background workers.
	//
	// "startup" starts one worker that is specially constructed
	// to deal with the first request, so back off by one to
	// prevent performing with too much parallelism.
	for i := 1; i < parallelism; i += 1 {
		go cat.get()
	}

	return &cat
}

func (cat *HtCat) nextFragment() *httpFrag {
	cat.httpFragGenMu.Lock()
	defer cat.httpFragGenMu.Unlock()

	var hf *httpFrag

	if cat.httpFragGen.hasNext() {
		f := cat.defrag.nextFragment()
		hf = cat.httpFragGen.nextFragment(f)
	} else {
		cat.defrag.setLast(cat.defrag.lastAllocated())
	}

	return hf
}

func (cat *HtCat) get() {
	for {
		hf := cat.nextFragment()
		if hf == nil {
			return
		}

		req := http.Request{
			Method:     "GET",
			URL:        cat.u,
			Proto:      "HTTP/1.1",
			ProtoMajor: 1,
			ProtoMinor: 1,
			Header:     hf.header,
			Body:       nil,
			Host:       cat.u.Host,
		}

		resp, err := cat.cl.Do(&req)
		if err != nil {
			cat.defrag.cancel(err)
			return
		}

		// Check for non-206 Partial Content response codes from the
		// range-GET.
		if resp.Status != "206 Partial Content" {
			err = HttpStatusError{
				error: fmt.Errorf("Expected HTTP Status 206, "+
					"received: %q",
					resp.Status),
				Status: resp.Status}
			go cat.defrag.cancel(err)
			return
		}

		er := newEagerReader(resp.Body, hf.size)
		hf.fragment.contents = er
		cat.register(hf.fragment)
		er.WaitClosed()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"github.com/minotar/minecraft"
	"net/http"
	"strconv"
	"strings"
)

type Router struct {
	Mux *mux.Router
}

type NotFoundHandler struct{}

// Handles 404 errors
func (h NotFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
	fmt.Fprintf(w, "404 not found")
}

// Converts and sanitizes the string for the avatar size.
func (r *Router) GetSize(inp string) uint {
	out64, err := strconv.ParseUint(inp, 10, 0)
	out := uint(out64)
	if err != nil {
		return DefaultSize
	} else if out > MaxSize {
		return MaxSize
	} else if out < MinSize {
		return MinSize
	}
	return out

}

// Shows only the user's skin.
func (router *Router) SkinPage(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	username := vars["username"]

	skin := fetchSkin(username)

	w.Header().Add("Content-Type", "image/png")
	w.Header().Add("X-Requested", "skin")
	w.Header().Add("X-Result", "ok")

	skin.WriteSkin(w)
}

// Shows the skin and tells the browser to attempt to download it.
func (router *Router) DownloadPage(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Content-Disposition", "attachment; filename=\"skin.png\"")
	router.SkinPage(w, r)
}

// Pull the Get<resource> method from the skin. Originally this used
// reflection, but that was slow.
func (router *Router) ResolveMethod(skin *mcSkin, resource string) func(int) error {
	stats.Served(resource)

	switch resource {
	case "Avatar":
		return skin.GetHead
	case "Helm":
		return skin.GetHelm
	case "Cube":
		return skin.GetCube
	case "Bust":
		return skin.GetBust
	case "Body":
		return skin.GetBody
	case "Armor/Bust":
		return skin.GetArmorBust
	case "Armour/Bust":
		return skin.GetArmorBust
	case "Armor/Body":
		return skin.GetArmorBody
	case "Armour/Body":
		return skin.GetArmorBody
	default:
		return skin.GetHelm
	}
}

func (router *Router) getResizeMode(ext string) string {
	switch ext {
	case ".svg":
		return "None"
	default:
		return "Normal"
	}
}

func (router *Router) writeType(ext string, skin *mcSkin, w http.ResponseWriter) {
	w.Header().Add("Cache-Control", fmt.Sprintf("public, max-age=%d", config.Server.Ttl))
	w.Header().Add("ETag", skin.Hash)
	switch ext {
	case ".svg":
		w.Header().Add("Content-Type", "image/svg+xml")
		skin.WriteSVG(w)
	default:
		w.Header().Add("Content-Type", "image/png")
		skin.WritePNG(w)
	}
}

// Binds the route and makes a handler function for the requested resource.
func (router *Router) Serve(resource string) {
	fn := func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		size := router.GetSize(vars["size"])
		skin := fetchSkin(vars["username"])
		skin.Mode = router.getResizeMode(vars["extension"])

		if r.Header.Get("If-None-Match") == skin.Skin.Hash {
			w.WriteHeader(http.StatusNotModified)
			return
		}

		err := router.ResolveMethod(skin, resource)(int(size))
		if err != nil {
			w.WriteHeader(500)
			fmt.Fprintf(w, "500 internal server error")
			return
		}
		router.writeType(vars["extension"], skin, w)
	}

	router.Mux.HandleFunc("/"+strings.ToLower(resource)+"/{username:"+minecraft.ValidUsernameRegex+"}{extension:(\\..*)?}", fn)
	router.Mux.HandleFunc("/"+strings.ToLower(resource)+"/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(\\..*)?}", fn)
}

// Binds routes to the ServerMux.
func (router *Router) Bind() {

	router.Mux.NotFoundHandler = NotFoundHandler{}

	router.Serve("Avatar")
	router.Serve("Helm")
	router.Serve("Cube")
	router.Serve("Bust")
	router.Serve("Body")
	router.Serve("Armor/Bust")
	router.Serve("Armour/Bust")
	router.Serve("Armor/Body")
	router.Serve("Armour/Body")

	router.Mux.HandleFunc("/download/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", router.DownloadPage)
	router.Mux.HandleFunc("/skin/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", router.SkinPage)

	router.Mux.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "%s", MinotarVersion)
	})

	router.Mux.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.Write(stats.ToJSON())
	})

	router.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "https://minotar.net/", 302)
	})
}

func fetchSkin(username string) *mcSkin {
	if username == "char" {
		skin, _ := minecraft.FetchSkinForChar()
		return &mcSkin{Skin: skin}
	}

	if cache.has(strings.ToLower(username)) {
		stats.HitCache()
		return &mcSkin{Processed: nil, Skin: cache.pull(strings.ToLower(username))}
	}

	skin, err := minecraft.FetchSkinFromMojang(username)
	if err != nil {
		log.Error("Failed Skin Mojang: " + username + " (" + err.Error() + ")")
		// Let's fallback to S3 and try and serve at least an old skin...
		skin, err = minecraft.FetchSkinFromS3(username)
		if err != nil {
			log.Error("Failed Skin S3: " + username + " (" + err.Error() + ")")
			// Well, looks like they don't exist after all.
			skin, _ = minecraft.FetchSkinForChar()
		}
	}

	stats.MissCache()
	cache.add(strings.ToLower(username), skin)

	return &mcSkin{Processed: nil, Skin: skin}
}
<commit_msg>Tidy up headers<commit_after>package main

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"github.com/gorilla/mux"
	"github.com/minotar/minecraft"
)

type Router struct {
	Mux *mux.Router
}

type NotFoundHandler struct{}

// Handles 404 errors
func (h NotFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNotFound)
	fmt.Fprintf(w, "404 not found")
}

// Converts and sanitizes the string for the avatar size.
func (r *Router) GetSize(inp string) uint {
	out64, err := strconv.ParseUint(inp, 10, 0)
	out := uint(out64)
	if err != nil {
		return DefaultSize
	} else if out > MaxSize {
		return MaxSize
	} else if out < MinSize {
		return MinSize
	}
	return out

}

// Shows only the user's skin.
func (router *Router) SkinPage(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	username := vars["username"]

	skin := fetchSkin(username)

	w.Header().Add("Content-Type", "image/png")

	skin.WriteSkin(w)
}

// Shows the skin and tells the browser to attempt to download it.
func (router *Router) DownloadPage(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Content-Disposition", "attachment; filename=\"skin.png\"")
	router.SkinPage(w, r)
}

// Pull the Get<resource> method from the skin. Originally this used
// reflection, but that was slow.
func (router *Router) ResolveMethod(skin *mcSkin, resource string) func(int) error {
	stats.Served(resource)

	switch resource {
	case "Avatar":
		return skin.GetHead
	case "Helm":
		return skin.GetHelm
	case "Cube":
		return skin.GetCube
	case "Bust":
		return skin.GetBust
	case "Body":
		return skin.GetBody
	case "Armor/Bust":
		return skin.GetArmorBust
	case "Armour/Bust":
		return skin.GetArmorBust
	case "Armor/Body":
		return skin.GetArmorBody
	case "Armour/Body":
		return skin.GetArmorBody
	default:
		return skin.GetHelm
	}
}

func (router *Router) getResizeMode(ext string) string {
	switch ext {
	case ".svg":
		return "None"
	default:
		return "Normal"
	}
}

func (router *Router) writeType(ext string, skin *mcSkin, w http.ResponseWriter) {
	w.Header().Add("Cache-Control", fmt.Sprintf("public, max-age=%d", config.Server.Ttl))
	w.Header().Add("ETag", skin.Hash)
	switch ext {
	case ".svg":
		w.Header().Add("Content-Type", "image/svg+xml")
		skin.WriteSVG(w)
	default:
		w.Header().Add("Content-Type", "image/png")
		skin.WritePNG(w)
	}
}

// Binds the route and makes a handler function for the requested resource.
func (router *Router) Serve(resource string) {
	fn := func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		size := router.GetSize(vars["size"])
		skin := fetchSkin(vars["username"])
		skin.Mode = router.getResizeMode(vars["extension"])

		if r.Header.Get("If-None-Match") == skin.Skin.Hash {
			w.WriteHeader(http.StatusNotModified)
			return
		}

		err := router.ResolveMethod(skin, resource)(int(size))
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintf(w, "500 internal server error")
			return
		}
		router.writeType(vars["extension"], skin, w)
	}

	router.Mux.HandleFunc("/"+strings.ToLower(resource)+"/{username:"+minecraft.ValidUsernameRegex+"}{extension:(\\..*)?}", fn)
	router.Mux.HandleFunc("/"+strings.ToLower(resource)+"/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(\\..*)?}", fn)
}

// Binds routes to the ServerMux.
func (router *Router) Bind() {

	router.Mux.NotFoundHandler = NotFoundHandler{}

	router.Serve("Avatar")
	router.Serve("Helm")
	router.Serve("Cube")
	router.Serve("Bust")
	router.Serve("Body")
	router.Serve("Armor/Bust")
	router.Serve("Armour/Bust")
	router.Serve("Armor/Body")
	router.Serve("Armour/Body")

	router.Mux.HandleFunc("/download/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", router.DownloadPage)
	router.Mux.HandleFunc("/skin/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", router.SkinPage)

	router.Mux.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "%s", MinotarVersion)
	})

	router.Mux.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.Write(stats.ToJSON())
	})

	router.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "https://minotar.net/", 302)
	})
}

func fetchSkin(username string) *mcSkin {
	if username == "char" {
		skin, _ := minecraft.FetchSkinForChar()
		return &mcSkin{Skin: skin}
	}

	if cache.has(strings.ToLower(username)) {
		stats.HitCache()
		return &mcSkin{Processed: nil, Skin: cache.pull(strings.ToLower(username))}
	}

	skin, err := minecraft.FetchSkinFromMojang(username)
	if err != nil {
		log.Error("Failed Skin Mojang: " + username + " (" + err.Error() + ")")
		// Let's fallback to S3 and try and serve at least an old skin...
		skin, err = minecraft.FetchSkinFromS3(username)
		if err != nil {
			log.Error("Failed Skin S3: " + username + " (" + err.Error() + ")")
			// Well, looks like they don't exist after all.
			skin, _ = minecraft.FetchSkinForChar()
		}
	}

	stats.MissCache()
	cache.add(strings.ToLower(username), skin)

	return &mcSkin{Processed: nil, Skin: skin}
}
<|endoftext|>


<commit_before>package util

import (
	"net/http"
	"net/http/httputil"
)

const ContentTypeJson string = "application/json"

func LogRequest(r *http.Request, body bool) {
	buff, _ := httputil.DumpRequest(r, body)
	log.Debug("Request: " + string(buff))
}

func LogResponse(r *http.Response, body bool) {
	buff, _ := httputil.DumpResponse(r, true)
	log.Debug("Response: " + string(buff))
}
<commit_msg>引数を使い忘れていたので修正<commit_after>package util

import (
	"net/http"
	"net/http/httputil"
)

const ContentTypeJson string = "application/json"

func LogRequest(r *http.Request, body bool) {
	buff, _ := httputil.DumpRequest(r, body)
	log.Debug("Request: " + string(buff))
}

func LogResponse(r *http.Response, body bool) {
	buff, _ := httputil.DumpResponse(r, body)
	log.Debug("Response: " + string(buff))
}
<|endoftext|>


<commit_before>package immortal

import (
	"log"
	"os"
	"runtime"
	"time"
)

func (self *Sup) Info(ch <-chan os.Signal, d *Daemon) {
	for {
		select {
		case <-ch:
			status := `
    Gorutines: %d
    Alloc : %d
    Total Alloc: %d
    Sys: %d
    Lookups: %d
    Mallocs: %d
    Frees: %d
    Seconds in GC: %d
    Started on: %v
    Uptime: %v
	Daemon uptime: %v
	Daemon count: %d`
			runtime.NumGoroutine()
			s := new(runtime.MemStats)
			runtime.ReadMemStats(s)
			log.Printf(status,
				runtime.NumGoroutine(),
				s.Alloc,
				s.TotalAlloc,
				s.Sys,
				s.Lookups,
				s.Mallocs,
				s.Frees,
				s.PauseTotalNs/1000000000,
				self.Start.Format(time.RFC3339),
				time.Since(self.Start),
				time.Since(d.start),
				d.count)
		}
	}
}
<commit_msg>	modified:   info.go<commit_after>package immortal

import (
	"log"
	"os"
	"runtime"
	"time"
)

func (self *Sup) Info(ch <-chan os.Signal, d *Daemon) {
	for {
		select {
		case <-ch:
			status := `
Gorutines: %d
Alloc : %d
Total Alloc: %d
Sys: %d
Lookups: %d
Mallocs: %d
Frees: %d
Seconds in GC: %d
Started on: %v
Uptime: %v
Daemon uptime: %v
Daemon count: %d`
			runtime.NumGoroutine()
			s := new(runtime.MemStats)
			runtime.ReadMemStats(s)
			log.Printf(status,
				runtime.NumGoroutine(),
				s.Alloc,
				s.TotalAlloc,
				s.Sys,
				s.Lookups,
				s.Mallocs,
				s.Frees,
				s.PauseTotalNs/1000000000,
				self.Start.Format(time.RFC3339),
				time.Since(self.Start),
				time.Since(d.start),
				d.count)
		}
	}
}
<|endoftext|>


<commit_before>package apidVerifyApiKey

import (
	"database/sql"
	"github.com/30x/apid"
	"github.com/30x/apidApigeeSync"
)

const (
	apiPath = "/verifyAPIKey"
)

var (
	log    apid.LogService
	data   apid.DataService
	events apid.EventsService
)

func init() {
	apid.RegisterPlugin(initPlugin)
}

func initPlugin(services apid.Services) error {
	log = services.Log().ForModule("apidVerifyAPIKey")
	log.Debug("start init")

	data = services.Data()
	events = services.Events()

	db, err := data.DB()
	if err != nil {
		log.Panic("Unable to access DB", err)
	}

	var count int
	row := db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='company';")
	if err := row.Scan(&count); err != nil {
		log.Panic("Unable to setup database", err)
	}
	if count == 0 {
		createTables(db)
	}

	services.API().HandleFunc(apiPath, handleRequest)

	events.Listen(apidApigeeSync.ApigeeSyncEventSelector, &handler{})
	log.Debug("end init")

	return nil
}

func createTables(db *sql.DB) {
	_, err := db.Exec("CREATE TABLE COMPANY (org varchar(255), id varchar(255), PRIMARY KEY (id, org));CREATE TABLE DEVELOPER (org varchar(255), email varchar(255), id varchar(255), sts varchar(255), username varchar(255), firstname varchar(255), lastname varchar(255), apigee_scope varchar(255), enc_password varchar(255), salt varchar(255), created_at integer, created_by varchar(255), updated_at integer, updated_by varchar(255), PRIMARY KEY (id, org));CREATE TABLE APP (org varchar(255), id varchar(255), dev_id varchar(255) null, cmp_id varchar(255) null, display_name varchar(255), apigee_scope varchar(255), type varchar(255), access_type varchar(255), cback_url varchar(255), status varchar(255), name varchar(255), app_family varchar(255), created_at integer, created_by varchar(255), updated_at integer, updated_by varchar(255), PRIMARY KEY (id, org), FOREIGN KEY (dev_id, org) references DEVELOPER (id, org) ON DELETE CASCADE);CREATE TABLE APP_CREDENTIAL (org varchar(255), id varchar(255), app_id varchar(255), cons_secret varchar(255), method_type varchar(255), status varchar(255), issued_at integer, expire_at integer, created_at integer, created_by varchar(255), updated_at integer, updated_by varchar(255), PRIMARY KEY (id, org), FOREIGN KEY (app_id, org) references app (id, org) ON DELETE CASCADE);CREATE TABLE API_PRODUCT (org varchar(255), id varchar(255), res_names varchar(255), env varchar(255), PRIMARY KEY (id, org));CREATE TABLE COMPANY_DEVELOPER (org varchar(255), dev_id varchar(255), id varchar(255), cmpny_id varchar(255), PRIMARY KEY (id, org), FOREIGN KEY (cmpny_id) references company(id) ON DELETE CASCADE, FOREIGN KEY (dev_id, org) references DEVELOPER(id, org) ON DELETE CASCADE);CREATE TABLE APP_AND_API_PRODUCT_MAPPER (org varchar(255), api_prdt_id varchar(255), app_id varchar(255), app_cred_id varchar(255), api_prdt_status varchar(255), PRIMARY KEY (org, api_prdt_id, app_id, app_cred_id), FOREIGN KEY (api_prdt_id, org) references api_product(id, org) ON DELETE CASCADE, FOREIGN KEY (app_cred_id, org) references app_credential(id, org) ON DELETE CASCADE, FOREIGN KEY (app_id, org) references app(id, org) ON DELETE CASCADE);")
	if err != nil {
		log.Panic("Unable to initialize DB", err)
	}
}
<commit_msg>Incude snapshot<commit_after>package apidVerifyApiKey

import (
	"database/sql"
	"github.com/30x/apid"
	"github.com/30x/apidApigeeSync"
)

const (
	apiPath = "/verifyAPIKey"
)

var (
	log    apid.LogService
	data   apid.DataService
	events apid.EventsService
)

func init() {
	apid.RegisterPlugin(initPlugin)
}

func initPlugin(services apid.Services) error {
	log = services.Log().ForModule("apidVerifyAPIKey")
	log.Debug("start init")

	data = services.Data()
	events = services.Events()

	db, err := data.DB()
	if err != nil {
		log.Panic("Unable to access DB", err)
	}

	var count int
	row := db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='API_PRODUCT';")
	if err := row.Scan(&count); err != nil {
		log.Panic("Unable to setup database", err)
	}
	if count == 0 {
		createTables(db)
	}

	services.API().HandleFunc(apiPath, handleRequest)

	events.Listen(apidApigeeSync.ApigeeSyncEventSelector, &handler{})
	log.Debug("end init")

	return nil
}

func createTables(db *sql.DB) {
	_, err := db.Exec(`
CREATE TABLE api_product (
    id uuid,
    tenant_id text,
    name text,
    display_name text,
    description text,
    api_resources text[],
    approval_type text,
    scopes text[],
    proxies text[],
    environments text[],
    quota text,
    quota_time_unit text,
    quota_interval int,
    created_at timestamp,
    created_by text,
    updated_at timestamp,
    updated_by text,
    PRIMARY KEY (tenant_id, id));
CREATE TABLE developer (
    id uuid,
    tenant_id text,
    username text,
    first_name text,
    last_name text,
    password text,
    email text,
    status text,
    encrypted_password text,
    salt text,
    created_at timestamp,
    created_by text,
    updated_at timestamp,
    updated_by text,
    PRIMARY KEY (tenant_id, id),
    constraint developer_email_uq unique(tenant_id, email)
);
CREATE TABLE company (
    id uuid,
    tenant_id text,
    name text,
    display_name text,
    status text,
    created_at timestamp,
    created_by text,
    updated_at timestamp,
    updated_by text,
    PRIMARY KEY (tenant_id, id),
    constraint comp_name_uq unique(tenant_id, name)
);
CREATE TABLE company_developer (
     tenant_id text,
     company_id uuid,
     developer_id uuid,
    roles text[],
    created_at timestamp,
    created_by text,
    updated_at timestamp,
    updated_by text,
    PRIMARY KEY (tenant_id, company_id,developer_id),
    FOREIGN KEY (tenant_id,company_id) references company(tenant_id,id),
    FOREIGN KEY (tenant_id,developer_id) references developer(tenant_id,id)
);
CREATE TABLE app (
    id uuid,
    tenant_id text,
    name text,
    display_name text,
    access_type text,
    callback_url text,
    status text,
    app_family text,
    company_id uuid,
    developer_id uuid,
    type app_type,
    created_at timestamp,
    created_by text,
    updated_at timestamp,
    updated_by text,
    PRIMARY KEY (tenant_id, id),
    constraint app_name_uq unique(tenant_id, name),
    FOREIGN KEY (tenant_id,company_id) references company(tenant_id,id),
    FOREIGN KEY (tenant_id,developer_id) references developer(tenant_id,id)
);
CREATE TABLE app_credential (
    id text,
    tenant_id text,
    consumer_secret text,
    app_id uuid,
    method_type text,
    status text,
    issued_at timestamp,
    expires_at timestamp,
    app_status text,
    scopes text[],
    PRIMARY KEY (tenant_id, id),
    FOREIGN KEY (tenant_id,app_id) references app(tenant_id,id)
);
CREATE TABLE app_credential_apiproduct_mapper (
    tenant_id text,
    appcred_id text,
    app_id uuid,
    apiprdt_id uuid,
    status appcred_apiprdt_status,
    PRIMARY KEY (tenant_id,appcred_id,app_id,apiprdt_id),
    FOREIGN KEY (tenant_id,appcred_id) references app_credential(tenant_id,id),
    FOREIGN KEY (tenant_id,app_id) references app(tenant_id,id)
);
CREATE TABLE attributes (
   tenant_id text,
   dev_id uuid,
   comp_id uuid,
   apiprdt_id uuid,
   app_id uuid,
   appcred_id text,
   type entity_type,
   name text ,
   value text,
   PRIMARY KEY (tenant_id,dev_id,comp_id,apiprdt_id,app_id,appcred_id,type,name),
   FOREIGN KEY (tenant_id,appcred_id) references app_credential(tenant_id,id),
   FOREIGN KEY (tenant_id,app_id) references app(tenant_id,id),
   FOREIGN KEY (tenant_id,dev_id) references developer(tenant_id,id),
   FOREIGN KEY (tenant_id,comp_id) references company(tenant_id,id),
   FOREIGN KEY (tenant_id,apiprdt_id) references api_product(tenant_id,id)
);
CREATE TABLE apidconfig (
    id uuid,
    consumer_key text,
    consumer_secret text,
    scope text[],
    app_id uuid,
    created_at timestamp,
    created_by text,
    updated_at timestamp,
    updated_by text,
    PRIMARY KEY(id),
    constraint apidconfig_key_uq unique(consumer_key),
    constraint apidconfig_appid_uq unique(app_id)
);
`)
	if err != nil {
		log.Panic("Unable to initialize DB", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	"github.com/gramework/gramework"
)

func setup(app *gramework.App) {
	app.TLSEmails = []string{
		"k@gramework.win",
	}

	app.EnableFirewall = true
	app.Settings.Firewall = gramework.FirewallSettings{
		MaxReqPerMin: 1 << 28,
		BlockTimeout: int64(15 * time.Second),
	}

	app.GET("/*banAny", app.Forbidden)
}
<commit_msg>pdd: init<commit_after>package main

import (
	"time"

	"github.com/gramework/gramework"
)

func setup(app *gramework.App) {
	app.TLSEmails = []string{
		"k@gramework.win",
	}

	app.EnableFirewall = true
	app.Settings.Firewall = gramework.FirewallSettings{
		MaxReqPerMin: 1 << 28,
		BlockTimeout: int64(15 * time.Second),
	}

	app.GET("/*any", func(ctx *gramework.Context) {
		if ctx.RouteArg("any") == "/f777d0332159.html" {
			ctx.Writef("ec3f5942dd6a")
			return
		}
		app.Forbidden(ctx)
	})
}
<|endoftext|>


<commit_before>package main

import (
    "net"
//    "golang.org/x/net/ipv4"
    "fmt"
)

type IP_Conn struct {
    pc        *net.IPConn
    version   uint8
    dst, src  string
    headerLen uint16
    //len uint16
    //id uint16
    ttl      uint8
    protocol uint8
    //checksum int
}

func NewIP_Conn(dst string) (*IP_Conn, error) {
    pc, err := net.ListenIP("ip4:17", &net.IPAddr{IP: net.ParseIP(dst)})
    if err != nil {
        fmt.Println("Failed to ListenIP")
        return nil, err
    }

    return &IP_Conn{
        pc:        pc,
        version:   4,
        headerLen: 20,
        dst:       dst,
        src:       "127.0.0.1",
        ttl:       8,
        protocol:  17,
    }, nil
}

func calcChecksum(head []byte, excludeChecksum bool) uint16 {
    totalSum := uint64(0)
    for ind, elem := range head {
        if (ind == 10 || ind == 11) && excludeChecksum { // Ignore the checksum in some situations
            continue
        }

        if ind%2 == 0 {
            totalSum += (uint64(elem) << 8)
        } else {
            totalSum += uint64(elem)
        }
    }
    fmt.Println(totalSum)

    for prefix := (totalSum >> 16); prefix != 0; prefix = (totalSum >> 16) {
//        fmt.Println(prefix)
//        fmt.Println(totalSum)
//        fmt.Println(totalSum & 0xffff)
        totalSum = uint64(totalSum & 0xffff) + prefix
    }
    fmt.Println(totalSum)

    carried := uint16(totalSum)

    return ^carried
}

func slicePacket(b []byte) (payload []byte) {
    hdrLen := int(b[0] & 0x0f) * 4
    fmt.Println(hdrLen)
    return payload[hdrLen:]
}

func (ipc *IP_Conn) ReadFrom(b []byte) (payload []byte, e error) {
    _, _, err := ipc.pc.ReadFrom(b)
    p := slicePacket(b)

    return p, err
}

func (ipc *IP_Conn) WriteTo(p []byte) error {
    totalLen := uint16(ipc.headerLen) + uint16(len(p))
    fmt.Println(totalLen)
    packet := make([]byte, ipc.headerLen)
    packet[0] = (byte)((ipc.version << 4) + (uint8)(ipc.headerLen / 4)) // Version, IHL
    packet[1] = 0
    packet[2] = (byte)(totalLen >> 8) // Total Len
    packet[3] = (byte)(totalLen)
    packet[4] = 0 // Identification (for now)
    packet[5] = 0
    packet[6] = byte(1 << 6)         // Flags: Don't fragment
    packet[7] = 0                    // Fragment Offset
    packet[8] = (byte)(ipc.ttl)      // Time to Live
    packet[9] = (byte)(ipc.protocol) // Protocol

    // Src and Dst IPs
    srcIP := net.ParseIP(ipc.src)
    fmt.Println(srcIP)
//    fmt.Println(srcIP[12])
//    fmt.Println(srcIP[13])
//    fmt.Println(srcIP[14])
//    fmt.Println(srcIP[15])
    dstIP := net.ParseIP(ipc.dst)
    fmt.Println(dstIP)
    packet[12] = srcIP[12]
    packet[13] = srcIP[13]
    packet[14] = srcIP[14]
    packet[15] = srcIP[15]
    packet[16] = dstIP[12]
    packet[17] = dstIP[13]
    packet[18] = dstIP[14]
    packet[19] = dstIP[15]

    // IPv4 header test (before checksum)
    fmt.Println(packet)

    // Checksum
    checksum := calcChecksum(packet[:20], true)
    packet[10] = byte(checksum >> 8)
    packet[11] = byte(checksum)

    // Payload
    packet = append(packet, p...)
    fmt.Println("Full Packet:  ", packet)

    dstIPAddr, err := net.ResolveIPAddr("ip", ipc.dst)
    if err != nil {
//        fmt.Println(err)
        return err
    }
    fmt.Println("Full Address: ", dstIPAddr)

    ipc.pc.WriteMsgIP(packet, nil, dstIPAddr)
    return err
}

func (ipc *IP_Conn) Close() error {
    return ipc.pc.Close()
}

/* h := &ipv4.Header{
	Version:  ipv4.Version,      // protocol version
	Len:      20,                // header length
	TOS:      0,                 // type-of-service (0 is everything normal)
	TotalLen: len(x) + 20,       // packet total length (octets)
	ID:       0,                 // identification
	Flags:    ipv4.DontFragment, // flags
	FragOff:  0,                 // fragment offset
	TTL:      8,                 // time-to-live (maximum lifespan in seconds)
	Protocol: 17,                // next protocol (17 is UDP)
	Checksum: 0,                 // checksum (apparently autocomputed)
	//Src:    net.IPv4(127, 0, 0, 1), // source address, apparently done automatically
	Dst: net.ParseIP(c.manager.ipAddress), // destination address
	//Options                         // options, extension headers
}
*/
<commit_msg>Additional error messages<commit_after>package main

import (
    "net"
//    "golang.org/x/net/ipv4"
    "fmt"
)

type IP_Conn struct {
    pc        *net.IPConn
    version   uint8
    dst, src  string
    headerLen uint16
    //len uint16
    //id uint16
    ttl      uint8
    protocol uint8
    //checksum int
}

func NewIP_Conn(dst string) (*IP_Conn, error) {
    pc, err := net.ListenIP("ip4:17", &net.IPAddr{IP: net.ParseIP(dst)})
    if err != nil {
        fmt.Println("Failed to ListenIP")
        return nil, err
    }

    return &IP_Conn{
        pc:        pc,
        version:   4,
        headerLen: 20,
        dst:       dst,
        src:       "127.0.0.1",
        ttl:       8,
        protocol:  17,
    }, nil
}

func calcChecksum(head []byte, excludeChecksum bool) uint16 {
    totalSum := uint64(0)
    for ind, elem := range head {
        if (ind == 10 || ind == 11) && excludeChecksum { // Ignore the checksum in some situations
            continue
        }

        if ind%2 == 0 {
            totalSum += (uint64(elem) << 8)
        } else {
            totalSum += uint64(elem)
        }
    }
    fmt.Println(totalSum)

    for prefix := (totalSum >> 16); prefix != 0; prefix = (totalSum >> 16) {
//        fmt.Println(prefix)
//        fmt.Println(totalSum)
//        fmt.Println(totalSum & 0xffff)
        totalSum = uint64(totalSum & 0xffff) + prefix
    }
    fmt.Println(totalSum)

    carried := uint16(totalSum)

    return ^carried
}

func slicePacket(b []byte) (payload []byte) {
    hdrLen := int(b[0] & 0x0f) * 4
    fmt.Println("HdrLen: ", hdrLen)
    return payload[hdrLen:]
}

func (ipc *IP_Conn) ReadFrom(b []byte) (payload []byte, e error) {
    n, _, err := ipc.pc.ReadFrom(b)
    b = b[:n]
    fmt.Println("Read Length: ", n)
    p := slicePacket(b)

    return p, err
}

func (ipc *IP_Conn) WriteTo(p []byte) error {
    totalLen := uint16(ipc.headerLen) + uint16(len(p))
    fmt.Println(totalLen)
    packet := make([]byte, ipc.headerLen)
    packet[0] = (byte)((ipc.version << 4) + (uint8)(ipc.headerLen / 4)) // Version, IHL
    packet[1] = 0
    packet[2] = (byte)(totalLen >> 8) // Total Len
    packet[3] = (byte)(totalLen)
    packet[4] = 0 // Identification (for now)
    packet[5] = 0
    packet[6] = byte(1 << 6)         // Flags: Don't fragment
    packet[7] = 0                    // Fragment Offset
    packet[8] = (byte)(ipc.ttl)      // Time to Live
    packet[9] = (byte)(ipc.protocol) // Protocol

    // Src and Dst IPs
    srcIP := net.ParseIP(ipc.src)
    fmt.Println(srcIP)
//    fmt.Println(srcIP[12])
//    fmt.Println(srcIP[13])
//    fmt.Println(srcIP[14])
//    fmt.Println(srcIP[15])
    dstIP := net.ParseIP(ipc.dst)
    fmt.Println(dstIP)
    packet[12] = srcIP[12]
    packet[13] = srcIP[13]
    packet[14] = srcIP[14]
    packet[15] = srcIP[15]
    packet[16] = dstIP[12]
    packet[17] = dstIP[13]
    packet[18] = dstIP[14]
    packet[19] = dstIP[15]

    // IPv4 header test (before checksum)
    fmt.Println(packet)

    // Checksum
    checksum := calcChecksum(packet[:20], true)
    packet[10] = byte(checksum >> 8)
    packet[11] = byte(checksum)

    // Payload
    packet = append(packet, p...)
    fmt.Println("Full Packet:  ", packet)

    dstIPAddr, err := net.ResolveIPAddr("ip", ipc.dst)
    if err != nil {
//        fmt.Println(err)
        return err
    }
    fmt.Println("Full Address: ", dstIPAddr)

    ipc.pc.WriteMsgIP(packet, nil, dstIPAddr)
    return err
}

func (ipc *IP_Conn) Close() error {
    return ipc.pc.Close()
}

/* h := &ipv4.Header{
	Version:  ipv4.Version,      // protocol version
	Len:      20,                // header length
	TOS:      0,                 // type-of-service (0 is everything normal)
	TotalLen: len(x) + 20,       // packet total length (octets)
	ID:       0,                 // identification
	Flags:    ipv4.DontFragment, // flags
	FragOff:  0,                 // fragment offset
	TTL:      8,                 // time-to-live (maximum lifespan in seconds)
	Protocol: 17,                // next protocol (17 is UDP)
	Checksum: 0,                 // checksum (apparently autocomputed)
	//Src:    net.IPv4(127, 0, 0, 1), // source address, apparently done automatically
	Dst: net.ParseIP(c.manager.ipAddress), // destination address
	//Options                         // options, extension headers
}
*/
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
)

var fetchers = map[string]pluginFetcher{
	"http":   fetcherFunc(fetchHTTPPlugins),
	"dns":    fetcherFunc(fetchDNSPlugins),
	"server": fetcherFunc(fetchServerTypePlugins),
}

type pluginFetcher interface {
	FetchPlugins() ([]Plugin, error)
}

type fetcherFunc func() ([]Plugin, error)

func (f fetcherFunc) FetchPlugins() ([]Plugin, error) { return f() }

func fetchHTTPPlugins() ([]Plugin, error) {
	var plugins []Plugin
	fset := token.NewFileSet()
	file := filepath.Join(goPath(), "src", directivesFile)
	f, err := parser.ParseFile(fset, file, nil, parser.ParseComments)
	if err != nil {
		return plugins, err
	}
	node, ok := f.Scope.Lookup("directives").Decl.(*ast.ValueSpec)
	if !ok {
		return plugins, fmt.Errorf("parsing error")
	}

	cmap := ast.NewCommentMap(fset, f, f.Comments)
	c := node.Values[0].(*ast.CompositeLit)
	for _, m := range c.Elts {
		if cm, ok := cmap[m]; ok {
			pkg := strings.TrimSpace(cm[len(cm)-1].Text())
			directive, err := strconv.Unquote(m.(*ast.BasicLit).Value)
			if err != nil {
				return plugins, err
			}
			// asserting that the comment word count is 1 may not be the best way
			// to confirm it is a repo path.
			if len(strings.Fields(pkg)) == 1 {
				plugin := Plugin{
					Name:    directive,
					Package: pkg,
					Type:    "http",
				}
				plugins = append(plugins, plugin)
			}
		}
	}
	return plugins, nil
}

func fetchDNSPlugins() ([]Plugin, error) {
	var plugins []Plugin
	srcDir := filepath.Join(goPath(), "src", dnsProvidersPackage)
	d, err := os.Open(srcDir)
	if err != nil {
		return plugins, err
	}
	stats, err := d.Readdir(-1)
	if err != nil {
		return plugins, err
	}
	for _, stat := range stats {
		provider := stat.Name()
		// skip hidden files
		if strings.HasPrefix(provider, ".") || !stat.IsDir() {
			continue
		}
		plugin := Plugin{
			Name:    provider,
			Package: path.Join(dnsProvidersPackage, provider),
			Type:    "dns",
		}
		plugins = append(plugins, plugin)
	}
	return plugins, nil
}

func fetchServerTypePlugins() ([]Plugin, error) {
	return []Plugin{
		{
			Type:    "server",
			Name:    "net",
			Package: "github.com/pieterlouw/caddy-net/caddynet",
		},
		{
			Type:    "server",
			Name:    "dns",
			Package: "github.com/coredns/coredns/core",
		},
	}, nil
}
<commit_msg>fix coredns import path<commit_after>package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
)

var fetchers = map[string]pluginFetcher{
	"http":   fetcherFunc(fetchHTTPPlugins),
	"dns":    fetcherFunc(fetchDNSPlugins),
	"server": fetcherFunc(fetchServerTypePlugins),
}

type pluginFetcher interface {
	FetchPlugins() ([]Plugin, error)
}

type fetcherFunc func() ([]Plugin, error)

func (f fetcherFunc) FetchPlugins() ([]Plugin, error) { return f() }

func fetchHTTPPlugins() ([]Plugin, error) {
	var plugins []Plugin
	fset := token.NewFileSet()
	file := filepath.Join(goPath(), "src", directivesFile)
	f, err := parser.ParseFile(fset, file, nil, parser.ParseComments)
	if err != nil {
		return plugins, err
	}
	node, ok := f.Scope.Lookup("directives").Decl.(*ast.ValueSpec)
	if !ok {
		return plugins, fmt.Errorf("parsing error")
	}

	cmap := ast.NewCommentMap(fset, f, f.Comments)
	c := node.Values[0].(*ast.CompositeLit)
	for _, m := range c.Elts {
		if cm, ok := cmap[m]; ok {
			pkg := strings.TrimSpace(cm[len(cm)-1].Text())
			directive, err := strconv.Unquote(m.(*ast.BasicLit).Value)
			if err != nil {
				return plugins, err
			}
			// asserting that the comment word count is 1 may not be the best way
			// to confirm it is a repo path.
			if len(strings.Fields(pkg)) == 1 {
				plugin := Plugin{
					Name:    directive,
					Package: pkg,
					Type:    "http",
				}
				plugins = append(plugins, plugin)
			}
		}
	}
	return plugins, nil
}

func fetchDNSPlugins() ([]Plugin, error) {
	var plugins []Plugin
	srcDir := filepath.Join(goPath(), "src", dnsProvidersPackage)
	d, err := os.Open(srcDir)
	if err != nil {
		return plugins, err
	}
	stats, err := d.Readdir(-1)
	if err != nil {
		return plugins, err
	}
	for _, stat := range stats {
		provider := stat.Name()
		// skip hidden files
		if strings.HasPrefix(provider, ".") || !stat.IsDir() {
			continue
		}
		plugin := Plugin{
			Name:    provider,
			Package: path.Join(dnsProvidersPackage, provider),
			Type:    "dns",
		}
		plugins = append(plugins, plugin)
	}
	return plugins, nil
}

func fetchServerTypePlugins() ([]Plugin, error) {
	return []Plugin{
		{
			Type:    "server",
			Name:    "net",
			Package: "github.com/pieterlouw/caddy-net/caddynet",
		},
		{
			Type:    "server",
			Name:    "dns",
			Package: "github.com/coredns/coredns/core/dnsserver",
		},
	}, nil
}
<|endoftext|>


<commit_before>package objecthash

import "fmt"

func commonJSON(j string) {
	fmt.Printf("%x\n", CommonJSONHash(j))
}

func ExampleCommonJSONHash_Common() {
	commonJSON(`["foo", "bar"]`)
	// Output: 32ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2
}

func ExampleCommonJSONHash_FloatAndInt() {
	commonJSON(`["foo", {"bar":["baz", null, 1.0, 1.5, 0.0001, 1000.0, 2.0, -23.1234, 2.0]}]`)
        // Integers and floats are the same in common JSON
	commonJSON(`["foo", {"bar":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]`)
	// Output:
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
}

func ExampleCommonJSONHash_KeyChange() {
	commonJSON(`["foo", {"b4r":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]`)
	// Output: 7e01f8b45da35386e4f9531ff1678147a215b8d2b1d047e690fd9ade6151e431
}

func ExampleCommonJSONHash_Unicode() {
	commonJSON(`"ԱԲաբ"`)
	// Output: 2a2a4485a4e338d8df683971956b1090d2f5d33955a81ecaad1a75125f7a316c
}

func ExampleCommonJSONHash_UnicodeNormalisation() {
	commonJSON("\"\u03d3\"")
	commonJSON("\"\u03d2\u0301\"")
	// Output:
	// f72826713a01881404f34975447bd6edcb8de40b191dc57097ebf4f5417a554d
	// f72826713a01881404f34975447bd6edcb8de40b191dc57097ebf4f5417a554d
}

func objectHash(o interface{}) {
	fmt.Printf("%x\n", ObjectHash(o))
}

func ExampleObjectHash_JSON() {
	// Same as equivalent JSON object
	o := []interface{}{`foo`, `bar`}
	objectHash(o)
	// Output: 32ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2
}

func ExampleObjectHash_JSON2() {
	// Same as equivalent _Python_ JSON object
	o := []interface{}{`foo`, map[string]interface{}{`bar`: []interface{}{`baz`, nil, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2}}}
	objectHash(o)
	// Output: 726e7ae9e3fadf8a2228bf33e505a63df8db1638fa4f21429673d387dbd1c52a
}

func ExampleObjectHash_Set() {
        o := map[string]interface{}{`thing1`: map[string]interface{}{`thing2`: Set{1, 2, `s`}}, `thing3`: 1234.567 }
	objectHash(o)
	// Output: 618cf0582d2e716a70e99c2f3079d74892fec335e3982eb926835967cb0c246c
}

func ExampleObjectHash_ComplexSet() {
	o := Set{`foo`, 23.6, Set{Set{}}, Set{Set{1}}}
	objectHash(o)
	// Output: 3773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398
}
<commit_msg>Make sure a set is a set, cryptographically.<commit_after>package objecthash

import "fmt"

func commonJSON(j string) {
	fmt.Printf("%x\n", CommonJSONHash(j))
}

func ExampleCommonJSONHash_Common() {
	commonJSON(`["foo", "bar"]`)
	// Output: 32ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2
}

func ExampleCommonJSONHash_FloatAndInt() {
	commonJSON(`["foo", {"bar":["baz", null, 1.0, 1.5, 0.0001, 1000.0, 2.0, -23.1234, 2.0]}]`)
        // Integers and floats are the same in common JSON
	commonJSON(`["foo", {"bar":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]`)
	// Output:
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
}

func ExampleCommonJSONHash_KeyChange() {
	commonJSON(`["foo", {"b4r":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]`)
	// Output: 7e01f8b45da35386e4f9531ff1678147a215b8d2b1d047e690fd9ade6151e431
}

func ExampleCommonJSONHash_Unicode() {
	commonJSON(`"ԱԲաբ"`)
	// Output: 2a2a4485a4e338d8df683971956b1090d2f5d33955a81ecaad1a75125f7a316c
}

func ExampleCommonJSONHash_UnicodeNormalisation() {
	commonJSON("\"\u03d3\"")
	commonJSON("\"\u03d2\u0301\"")
	// Output:
	// f72826713a01881404f34975447bd6edcb8de40b191dc57097ebf4f5417a554d
	// f72826713a01881404f34975447bd6edcb8de40b191dc57097ebf4f5417a554d
}

func objectHash(o interface{}) {
	fmt.Printf("%x\n", ObjectHash(o))
}

func ExampleObjectHash_JSON() {
	// Same as equivalent JSON object
	o := []interface{}{`foo`, `bar`}
	objectHash(o)
	// Output: 32ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2
}

func ExampleObjectHash_JSON2() {
	// Same as equivalent _Python_ JSON object
	o := []interface{}{`foo`, map[string]interface{}{`bar`: []interface{}{`baz`, nil, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2}}}
	objectHash(o)
	// Output: 726e7ae9e3fadf8a2228bf33e505a63df8db1638fa4f21429673d387dbd1c52a
}

func ExampleObjectHash_Set() {
        o := map[string]interface{}{`thing1`: map[string]interface{}{`thing2`: Set{1, 2, `s`}}, `thing3`: 1234.567 }
	objectHash(o)
	// Output: 618cf0582d2e716a70e99c2f3079d74892fec335e3982eb926835967cb0c246c
}

func ExampleObjectHash_ComplexSet() {
	o := Set{`foo`, 23.6, Set{Set{}}, Set{Set{1}}}
	objectHash(o)
	// Output: 3773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398
}

func ExampleObjectHash_ComplexSetRepeated() {
	o := Set{`foo`, 23.6, Set{Set{}}, Set{Set{1}}, Set{Set{}}}
	objectHash(o)
	// Output: 3773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398
}
<|endoftext|>