<commit_before>package core

import ("fmt"
		"time"
		"crypto/rand"
	        "math"
		"math/big"
		"bytes"
		"github.com/fire/go-ogre3d"
		"github.com/jmckaskill/go-capnproto")

const ORIENTATIONLOG int = 10;

type OrientationHistory struct {
	t uint64
	o ogre.Quaternion
}

type GameState struct {
	bounce float32 			// Limits of the bounce area:
	speed float32 			// Picked a speed to bounce around at startup.
	mousePressed bool 		// Go from mouse is pressed to click each time to change the control scheme.
	direction ogre.Vector2	// Direction the head is moving on the plane:
	rotation ogre.Vector3	// Rotation axis of the head:
	rotationSpeed float32  	// Rotation speed of the head in degrees:

	// use the last few frames of mouse input to build a smoothed angular velocity
	orientationIndex int
	orientationHistory[ORIENTATIONLOG] OrientationHistory
	smoothedAngular ogre.Vector3
	smoothedAngularVelocity float32 // Degree
}

func gameInit(gsockets *GameThreadSockets, gs *GameState, rs *SharedRenderState){
	fmt.Printf("Game Init.\n")
	gs.speed = randFloat32(59) + 40
	fmt.Printf("Random speed: %f\n", gs.speed)
	gs.bounce = 25.0
	angle := deg2Rad(randFloat32(359))
	gs.direction = ogre.CreateVector2FromValues(float32(math.Cos(float64(angle))), float32(math.Sin(float64(angle))))
	unitZ := ogre.CreateVector3()
	unitZ.UnitZ()
	rs.orientation = ogre.CreateQuaternion()
	rs.orientation.FromAngleAxis(0.0, unitZ)
	rs.position = ogre.CreateVector3()
	rs.position.Zero()
	gs.mousePressed = false
	gs.rotation = ogre.CreateVector3()
	gs.rotation.UnitX()
	gs.rotationSpeed = 0.0
	gs.orientationIndex = 0
	fmt.Printf("Random angle: %f\n", angle)
	// Set the input code to manipulate an object rather than look around.
	s := capn.NewBuffer(nil)
	lookAround := NewRootState(s)
	lookAround.SetConfigLookAround(true)
	lookAround.LookAround().SetManipulateObject(true)
	buf := bytes.Buffer{}
	s.WriteTo(&buf)
	gsockets.inputPush.Send(buf.Bytes(), 0)
}

func gameTick(gsockets *GameThreadSockets, gs *GameState, srs *SharedRenderState, now time.Duration){
	fmt.Printf("Game Tick.\n")

	// Get the latest mouse buttons state and orientation.
	s := capn.NewBuffer(nil)
	state := NewRootState(s)
	state.SetMouse(true)
	buf := bytes.Buffer{}
	s.WriteTo(&buf)
	gsockets.inputPush.Send(buf.Bytes(), 0)

	b, err := gsockets.inputMouseSub.Recv(0)
	if err != nil {
		fmt.Printf("%s\n", err)
	}
	s, _, err = capn.ReadFromMemoryZeroCopy(b)
	if err != nil {
		fmt.Printf("Read error %v\n", err)
		return
	}
	input := ReadRootInputMouse(s)
	orientation := ogre.CreateQuaternionFromValues(input.W(), input.X(), input.Y(), input.Z())
	buttons := input.Buttons()

	// At 16 ms tick and the last 10 orientations buffered, that's 150ms worth of orientation history.
	gs.orientationHistory[gs.orientationIndex].t = uint64(now)
	gs.orientationHistory[gs.orientationIndex].o = orientation
	gs.orientationIndex = (gs.orientationIndex + 1) % ORIENTATIONLOG

	// Oldest Orientation
	q1Index := gs.orientationIndex
	// NOTE: the problem with using the successive orientations to infer an angular speed,
	// is that if the orientation is changing fast enough, this code will 'flip' the speed around
	// e.g. this doesn't work, need to use the XY mouse data to track angular speed
	// NOTE: uncomment the following line to use the full history, notice the 'flip' happens at much lower speed
	q1Index = ( q1Index + ORIENTATIONLOG - 2) % ORIENTATIONLOG
	q1 := gs.orientationHistory[q1Index].o
	q1T := gs.orientationHistory[q1Index].t
	omega := orientation.SubtractQuaternion(q1)
	omega = omega.MultiplyScalar(2.0)
	omega = omega.UnitInverse()
	omega = omega.MultiplyScalar(float32(float64(time.Second)/float64(now - time.Duration(q1T))))
	omega.Normalise()
	// omega.ToAngleAxis(gs.smoothedAngularVelocity, gs.smoothedAngular)
}

// Create a random 32bit float from [1,max+1).
func randFloat32(max uint64) float32 {
	i := big.NewInt(0)
	r, err := rand.Int(rand.Reader, i.SetUint64(uint64(1) << 63))
	if err != nil {
			fmt.Printf("%s\n", err)
	}
	return float32(float64(r.Uint64()) / float64(1 << 63) * float64(max))
}
<commit_msg>Not using buttons yet.<commit_after>package core

import ("fmt"
		"time"
		"crypto/rand"
	        "math"
		"math/big"
		"bytes"
		"github.com/fire/go-ogre3d"
		"github.com/jmckaskill/go-capnproto")

const ORIENTATIONLOG int = 10;

type OrientationHistory struct {
	t uint64
	o ogre.Quaternion
}

type GameState struct {
	bounce float32 			// Limits of the bounce area:
	speed float32 			// Picked a speed to bounce around at startup.
	mousePressed bool 		// Go from mouse is pressed to click each time to change the control scheme.
	direction ogre.Vector2	// Direction the head is moving on the plane:
	rotation ogre.Vector3	// Rotation axis of the head:
	rotationSpeed float32  	// Rotation speed of the head in degrees:

	// use the last few frames of mouse input to build a smoothed angular velocity
	orientationIndex int
	orientationHistory[ORIENTATIONLOG] OrientationHistory
	smoothedAngular ogre.Vector3
	smoothedAngularVelocity float32 // Degree
}

func gameInit(gsockets *GameThreadSockets, gs *GameState, rs *SharedRenderState){
	fmt.Printf("Game Init.\n")
	gs.speed = randFloat32(59) + 40
	fmt.Printf("Random speed: %f\n", gs.speed)
	gs.bounce = 25.0
	angle := deg2Rad(randFloat32(359))
	gs.direction = ogre.CreateVector2FromValues(float32(math.Cos(float64(angle))), float32(math.Sin(float64(angle))))
	unitZ := ogre.CreateVector3()
	unitZ.UnitZ()
	rs.orientation = ogre.CreateQuaternion()
	rs.orientation.FromAngleAxis(0.0, unitZ)
	rs.position = ogre.CreateVector3()
	rs.position.Zero()
	gs.mousePressed = false
	gs.rotation = ogre.CreateVector3()
	gs.rotation.UnitX()
	gs.rotationSpeed = 0.0
	gs.orientationIndex = 0
	fmt.Printf("Random angle: %f\n", angle)
	// Set the input code to manipulate an object rather than look around.
	s := capn.NewBuffer(nil)
	lookAround := NewRootState(s)
	lookAround.SetConfigLookAround(true)
	lookAround.LookAround().SetManipulateObject(true)
	buf := bytes.Buffer{}
	s.WriteTo(&buf)
	gsockets.inputPush.Send(buf.Bytes(), 0)
}

func gameTick(gsockets *GameThreadSockets, gs *GameState, srs *SharedRenderState, now time.Duration){
	fmt.Printf("Game Tick.\n")

	// Get the latest mouse buttons state and orientation.
	s := capn.NewBuffer(nil)
	state := NewRootState(s)
	state.SetMouse(true)
	buf := bytes.Buffer{}
	s.WriteTo(&buf)
	gsockets.inputPush.Send(buf.Bytes(), 0)

	b, err := gsockets.inputMouseSub.Recv(0)
	if err != nil {
		fmt.Printf("%s\n", err)
	}
	s, _, err = capn.ReadFromMemoryZeroCopy(b)
	if err != nil {
		fmt.Printf("Read error %v\n", err)
		return
	}
	input := ReadRootInputMouse(s)
	orientation := ogre.CreateQuaternionFromValues(input.W(), input.X(), input.Y(), input.Z())
	//buttons := input.Buttons()

	// At 16 ms tick and the last 10 orientations buffered, that's 150ms worth of orientation history.
	gs.orientationHistory[gs.orientationIndex].t = uint64(now)
	gs.orientationHistory[gs.orientationIndex].o = orientation
	gs.orientationIndex = (gs.orientationIndex + 1) % ORIENTATIONLOG

	// Oldest Orientation
	q1Index := gs.orientationIndex
	// NOTE: the problem with using the successive orientations to infer an angular speed,
	// is that if the orientation is changing fast enough, this code will 'flip' the speed around
	// e.g. this doesn't work, need to use the XY mouse data to track angular speed
	// NOTE: uncomment the following line to use the full history, notice the 'flip' happens at much lower speed
	q1Index = ( q1Index + ORIENTATIONLOG - 2) % ORIENTATIONLOG
	q1 := gs.orientationHistory[q1Index].o
	q1T := gs.orientationHistory[q1Index].t
	omega := orientation.SubtractQuaternion(q1)
	omega = omega.MultiplyScalar(2.0)
	omega = omega.UnitInverse()
	omega = omega.MultiplyScalar(float32(float64(time.Second)/float64(now - time.Duration(q1T))))
	omega.Normalise()
	// omega.ToAngleAxis(gs.smoothedAngularVelocity, gs.smoothedAngular)
}

// Create a random 32bit float from [1,max+1).
func randFloat32(max uint64) float32 {
	i := big.NewInt(0)
	r, err := rand.Int(rand.Reader, i.SetUint64(uint64(1) << 63))
	if err != nil {
			fmt.Printf("%s\n", err)
	}
	return float32(float64(r.Uint64()) / float64(1 << 63) * float64(max))
}
<|endoftext|>


<commit_before>// Package gcfg reads "gitconfig-like" text-based configuration files with
// "name=value" pairs grouped into sections (gcfg files). Support for modifying
// and/or exporting such files may be added later.
//
// This package is a work in progress, and both the supported file format and
// the API is subject to change.
//
// The syntax is based on that used by git config:
// http://git-scm.com/docs/git-config#_syntax .
// Note that the gcfg syntax may diverge from that of git config in the future
// to a limited degree. Current differences (apart from TODOs listed below) are:
//  - gcfg files must use UTF-8 encoding (for now)
//  - include is not supported (and not planned)
//
// The package may be usable for handling some of the various "INI file" formats
// used by some programs and libraries, but achieving or maintaining
// compatibility with any of those is not a primary concern.
//
// TODO: besides more docs and tests, add support for:
//  - pointer fields
//  - subsections
//  - multi-value variables (+ internal representation)
//  - returning error context (+ numeric error codes ?)
//  - multiple readers (strings, files)
//  - escaping in strings and long(er) lines (?) (+ regexp-free parser)
//  - modifying files
//  - exporting files (+ metadata handling) (?)
//  - declare encoding (?)
//
package gcfg

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"reflect"
	"regexp"
	"strings"
)

var (
	reCmnt    = regexp.MustCompile(`^([^;#"]*)[;#].*$`)
	reCmntQ   = regexp.MustCompile(`^([^;#"]*"[^"]*"[^;#"]*)[;#].*$`)
	reBlank   = regexp.MustCompile(`^\s*$`)
	reSect    = regexp.MustCompile(`^\s*\[\s*([^\s]*)\s*\]\s*$`)
	reVar     = regexp.MustCompile(`^\s*([^"=\s]+)\s*=\s*([^"\s]*)\s*$`)
	reVarQ    = regexp.MustCompile(`^\s*([^"=\s]+)\s*=\s*"([^"\n\\]*)"\s*$`)
	reVarDflt = regexp.MustCompile(`^\s*\b(.*)\b\s*$`)
)

const (
	// Default value in case a value for a variable isn't provided.
	DefaultValue = "true"
)

type Bool bool

var boolValues = map[string]interface{}{
	"true": true, "yes": true, "on": true, "1": true,
	"false": false, "no": false, "off": false, "0": false}

func scan(state fmt.ScanState, values map[string]interface{}) (interface{}, error) {
	var rd []rune
	var r rune
	var err error
	for r, _, err = state.ReadRune(); err == nil; r, _, err = state.ReadRune() {
		rd = append(rd, r)
		part := false
		for s, v := range values {
			if strings.EqualFold(string(rd), s) {
				return v, err
			}
			if len(rd) < len(s) && strings.EqualFold(string(rd), s[:len(rd)]) {
				part = true
			}
		}
		if part == false {
			state.UnreadRune()
			return nil, errors.New("unsupported value " + string(rd))
		}
	}
	return nil, err
}

func (b *Bool) Scan(state fmt.ScanState, verb rune) error {
	v, err := scan(state, boolValues)
	switch bb := v.(type) {
	case bool:
		*b = Bool(bb)
		return err
	}
	return err
}

func unref(v reflect.Value) reflect.Value {
	for v.Type().Kind() == reflect.Ptr {
		v = v.Elem()
	}
	return v
}

func fieldFold(v reflect.Value, name string) reflect.Value {
	n := strings.Replace(name, "-", "_", -1)
	return v.FieldByNameFunc(func(fieldName string) bool {
		return strings.EqualFold(n, fieldName)
	})
}

func set(cfg interface{}, sect, name, value string) error {
	vDest := unref(reflect.ValueOf(cfg))
	vSect := unref(fieldFold(vDest, sect))
	vName := unref(fieldFold(vSect, name))
	vAddr := vName.Addr().Interface()
	switch v := vAddr.(type) {
	case *string:
		*v = value
		return nil
	case *bool:
		vAddr = (*Bool)(v)
	}
	// attempt to read an extra rune to make sure the value is consumed
	var r rune
	n, err := fmt.Sscanf(value, "%v%c", vAddr, &r)
	switch {
	case n < 1 || n == 1 && err != io.EOF:
		return fmt.Errorf("failed to parse %q as %#v: parse error %v", value,
			vName.Type(), err)
	case n > 1:
		return fmt.Errorf("failed to parse %q as %#v: extra characters", value,
			vName.Type())
	case n == 1 && err == io.EOF:
		return nil
	}
	panic("never reached")
}

// Parse reads gcfg formatted data from reader and sets the values into the
// corresponding fields in config. Config must be a pointer to a struct.
func Parse(config interface{}, reader io.Reader) error {
	r := bufio.NewReader(reader)
	sect := (*string)(nil)
	for line := 1; true; line++ {
		l, pre, err := r.ReadLine()
		if err != nil && err != io.EOF {
			return err
		} else if pre {
			return errors.New("line too long")
		}
		// exclude comments
		if c := reCmnt.FindSubmatch(l); c != nil {
			l = c[1]
		} else if c := reCmntQ.FindSubmatch(l); c != nil {
			l = c[1]
		}
		if !reBlank.Match(l) {
			// "switch" based on line contents
			if sec := reSect.FindSubmatch(l); sec != nil {
				strsec := string(sec[1])
				sect = &strsec
			} else if v, vq, vd := reVar.FindSubmatch(l),
				reVarQ.FindSubmatch(l), reVarDflt.FindSubmatch(l); //
			v != nil || vq != nil || vd != nil {
				if sect == nil {
					return errors.New("no section")
				}
				var name, value string
				if v != nil {
					name, value = string(v[1]), string(v[2])
				} else if vq != nil {
					name, value = string(vq[1]), string(vq[2])
				} else { // vd != nil
					name, value = string(vd[1]), DefaultValue
				}
				err := set(config, *sect, name, value)
				if err != nil {
					return err
				}
			} else {
				return fmt.Errorf("invalid line %q", string(l))
			}
		}
		if err == io.EOF {
			break
		}
	}
	return nil
}

// ParseString reads gcfg formatted data from str and sets the values into the
// corresponding fields in cfg. It is a wrapper for Parse(config, reader).
func ParseString(config interface{}, str string) error {
	r := strings.NewReader(str)
	return Parse(config, r)
}

// ParseFile reads gcfg formatted data from the file filename and sets the
// values into the corresponding fields in cfg. It is a wrapper for
// Parse(config, reader).
func ParseFile(config interface{}, filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()
	return Parse(config, f)
}
<commit_msg>remove unnecessary reflect calls<commit_after>// Package gcfg reads "gitconfig-like" text-based configuration files with
// "name=value" pairs grouped into sections (gcfg files). Support for modifying
// and/or exporting such files may be added later.
//
// This package is a work in progress, and both the supported file format and
// the API is subject to change.
//
// The syntax is based on that used by git config:
// http://git-scm.com/docs/git-config#_syntax .
// Note that the gcfg syntax may diverge from that of git config in the future
// to a limited degree. Current differences (apart from TODOs listed below) are:
//  - gcfg files must use UTF-8 encoding (for now)
//  - include is not supported (and not planned)
//
// The package may be usable for handling some of the various "INI file" formats
// used by some programs and libraries, but achieving or maintaining
// compatibility with any of those is not a primary concern.
//
// TODO: besides more docs and tests, add support for:
//  - pointer fields
//  - subsections
//  - multi-value variables (+ internal representation)
//  - returning error context (+ numeric error codes ?)
//  - multiple readers (strings, files)
//  - escaping in strings and long(er) lines (?) (+ regexp-free parser)
//  - modifying files
//  - exporting files (+ metadata handling) (?)
//  - declare encoding (?)
//
package gcfg

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"reflect"
	"regexp"
	"strings"
)

var (
	reCmnt    = regexp.MustCompile(`^([^;#"]*)[;#].*$`)
	reCmntQ   = regexp.MustCompile(`^([^;#"]*"[^"]*"[^;#"]*)[;#].*$`)
	reBlank   = regexp.MustCompile(`^\s*$`)
	reSect    = regexp.MustCompile(`^\s*\[\s*([^\s]*)\s*\]\s*$`)
	reVar     = regexp.MustCompile(`^\s*([^"=\s]+)\s*=\s*([^"\s]*)\s*$`)
	reVarQ    = regexp.MustCompile(`^\s*([^"=\s]+)\s*=\s*"([^"\n\\]*)"\s*$`)
	reVarDflt = regexp.MustCompile(`^\s*\b(.*)\b\s*$`)
)

const (
	// Default value in case a value for a variable isn't provided.
	DefaultValue = "true"
)

type Bool bool

var boolValues = map[string]interface{}{
	"true": true, "yes": true, "on": true, "1": true,
	"false": false, "no": false, "off": false, "0": false}

func scan(state fmt.ScanState, values map[string]interface{}) (interface{}, error) {
	var rd []rune
	var r rune
	var err error
	for r, _, err = state.ReadRune(); err == nil; r, _, err = state.ReadRune() {
		rd = append(rd, r)
		part := false
		for s, v := range values {
			if strings.EqualFold(string(rd), s) {
				return v, err
			}
			if len(rd) < len(s) && strings.EqualFold(string(rd), s[:len(rd)]) {
				part = true
			}
		}
		if part == false {
			state.UnreadRune()
			return nil, errors.New("unsupported value " + string(rd))
		}
	}
	return nil, err
}

func (b *Bool) Scan(state fmt.ScanState, verb rune) error {
	v, err := scan(state, boolValues)
	switch bb := v.(type) {
	case bool:
		*b = Bool(bb)
		return err
	}
	return err
}

func unref(v reflect.Value) reflect.Value {
	for v.Type().Kind() == reflect.Ptr {
		v = v.Elem()
	}
	return v
}

func fieldFold(v reflect.Value, name string) reflect.Value {
	n := strings.Replace(name, "-", "_", -1)
	return v.FieldByNameFunc(func(fieldName string) bool {
		return strings.EqualFold(n, fieldName)
	})
}

func set(cfg interface{}, sect, name, value string) error {
	vDest := unref(reflect.ValueOf(cfg))
	vSect := fieldFold(vDest, sect)
	vName := fieldFold(vSect, name)
	vAddr := vName.Addr().Interface()
	switch v := vAddr.(type) {
	case *string:
		*v = value
		return nil
	case *bool:
		vAddr = (*Bool)(v)
	}
	// attempt to read an extra rune to make sure the value is consumed
	var r rune
	n, err := fmt.Sscanf(value, "%v%c", vAddr, &r)
	switch {
	case n < 1 || n == 1 && err != io.EOF:
		return fmt.Errorf("failed to parse %q as %#v: parse error %v", value,
			vName.Type(), err)
	case n > 1:
		return fmt.Errorf("failed to parse %q as %#v: extra characters", value,
			vName.Type())
	case n == 1 && err == io.EOF:
		return nil
	}
	panic("never reached")
}

// Parse reads gcfg formatted data from reader and sets the values into the
// corresponding fields in config. Config must be a pointer to a struct.
func Parse(config interface{}, reader io.Reader) error {
	r := bufio.NewReader(reader)
	sect := (*string)(nil)
	for line := 1; true; line++ {
		l, pre, err := r.ReadLine()
		if err != nil && err != io.EOF {
			return err
		} else if pre {
			return errors.New("line too long")
		}
		// exclude comments
		if c := reCmnt.FindSubmatch(l); c != nil {
			l = c[1]
		} else if c := reCmntQ.FindSubmatch(l); c != nil {
			l = c[1]
		}
		if !reBlank.Match(l) {
			// "switch" based on line contents
			if sec := reSect.FindSubmatch(l); sec != nil {
				strsec := string(sec[1])
				sect = &strsec
			} else if v, vq, vd := reVar.FindSubmatch(l),
				reVarQ.FindSubmatch(l), reVarDflt.FindSubmatch(l); //
			v != nil || vq != nil || vd != nil {
				if sect == nil {
					return errors.New("no section")
				}
				var name, value string
				if v != nil {
					name, value = string(v[1]), string(v[2])
				} else if vq != nil {
					name, value = string(vq[1]), string(vq[2])
				} else { // vd != nil
					name, value = string(vd[1]), DefaultValue
				}
				err := set(config, *sect, name, value)
				if err != nil {
					return err
				}
			} else {
				return fmt.Errorf("invalid line %q", string(l))
			}
		}
		if err == io.EOF {
			break
		}
	}
	return nil
}

// ParseString reads gcfg formatted data from str and sets the values into the
// corresponding fields in cfg. It is a wrapper for Parse(config, reader).
func ParseString(config interface{}, str string) error {
	r := strings.NewReader(str)
	return Parse(config, r)
}

// ParseFile reads gcfg formatted data from the file filename and sets the
// values into the corresponding fields in cfg. It is a wrapper for
// Parse(config, reader).
func ParseFile(config interface{}, filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()
	return Parse(config, f)
}
<|endoftext|>


<commit_before>// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
// license. Its contents can be found at:
// http://creativecommons.org/publicdomain/zero/1.0/

package glfw

//#include "glue.h"
import "C"
import (
	"os"
	"unsafe"
)

func Terminate()                       { C.glfwTerminate() }
func OpenWindowHint(target, hint int)  { C.glfwOpenWindowHint(C.int(target), C.int(hint)) }
func CloseWindow()                     { C.glfwCloseWindow() }
func IconifyWindow()                   { C.glfwIconifyWindow() }
func RestoreWindow()                   { C.glfwRestoreWindow() }
func SwapBuffers()                     { C.glfwSwapBuffers() }
func WindowParam(param int) int        { return int(C.glfwGetWindowParam(C.int(param))) }
func SetSwapInterval(interval int)     { C.glfwSwapInterval(C.int(interval)) }
func SetWindowSize(width, height int)  { C.glfwSetWindowSize(C.int(width), C.int(height)) }
func SetWindowPos(x, y int)            { C.glfwSetWindowPos(C.int(x), C.int(y)) }
func SetWindowTitle(title string)      { C.glfwSetWindowTitle(C.CString(title)) }
func PollEvents()                      { C.glfwPollEvents() }
func WaitEvents()                      { C.glfwWaitEvents() }
func Key(key int) int                  { return int(C.glfwGetKey(C.int(key))) }
func MouseButton(btn int) int          { return int(C.glfwGetMouseButton(C.int(btn))) }
func SetMousePos(x, y int)             { C.glfwSetMousePos(C.int(x), C.int(y)) }
func MouseWheel() int                  { return int(C.glfwGetMouseWheel()) }
func SetMouseWheel(pos int)            { C.glfwSetMouseWheel(C.int(pos)) }
func JoystickParam(joy, param int) int { return int(C.glfwGetJoystickParam(C.int(joy), C.int(param))) }
func Time() float64                    { return float64(C.glfwGetTime()) }
func SetTime(t float64)                { C.glfwSetTime(C.double(t)) }
func Sleep(t float64)                  { C.glfwSleep(C.double(t)) }
func NumberOfProcessors() int          { return int(C.glfwGetNumberOfProcessors()) }
func Enable(token int)                 { C.glfwEnable(C.int(token)) }
func Disable(token int)                { C.glfwDisable(C.int(token)) }

func Init() (err os.Error) {
	if C.glfwInit() != 1 {
		err = os.NewError("Failed to initialize GLFW")
	}
	return
}

func OpenWindow(width, height, r, g, b, a, depth, stencil, mode int) (err os.Error) {
	if C.glfwOpenWindow(
		C.int(width), C.int(height),
		C.int(r), C.int(g), C.int(b), C.int(a),
		C.int(depth), C.int(stencil), C.int(mode),
	) != 1 {
		err = os.NewError("Failed to open window")
	}
	return
}

func WindowSize() (int, int) {
	var w, h C.int
	C.glfwGetWindowSize(&w, &h)
	return int(w), int(h)
}

func VideoModes(max int) []*VidMode {
	var vm C.GLFWvidmode

	size := unsafe.Sizeof(vm)
	ptr := (*C.GLFWvidmode)(C.malloc(C.size_t(size * max)))
	count := C.glfwGetVideoModes(ptr, C.int(max))

	if count == 0 {
		return nil
	}

	list := make([]*VidMode, count)
	for i := range list {
		p := (*C.GLFWvidmode)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + uintptr(i*size)))
		list[i] = vidModeFromPtr(p)
	}

	C.free(unsafe.Pointer(ptr))
	return list
}

func DesktopMode() *VidMode {
	var vm C.GLFWvidmode
	C.glfwGetDesktopMode(&vm)
	return vidModeFromPtr(&vm)
}

func MousePos() (int, int) {
	var cx, cy C.int
	C.glfwGetMousePos(&cx, &cy)
	return int(cx), int(cy)
}

func JoystickPos(joy int, numaxes int) float32 {
	var pos C.float
	if int(C.glfwGetJoystickPos(C.int(joy), &pos, C.int(numaxes))) != 1 {
		return 0
	}
	return float32(pos)
}

func JoystickButtons(joy, numbuttons int) []byte {
	ptr := (*_Ctype_unsignedchar)(C.malloc(C.size_t(C.int(numbuttons))))
	defer C.free(unsafe.Pointer(ptr))

	var count C.int
	if count = C.glfwGetJoystickButtons(C.int(joy), ptr, C.int(numbuttons)); count == 0 {
		return nil
	}

	b := make([]byte, count)
	copy(b, (*(*[1<<31 - 1]byte)(unsafe.Pointer(ptr)))[:count])
	return b
}

func ExtensionSupported(name string) bool {
	cs := C.CString(name)
	defer C.free(unsafe.Pointer(cs))
	return C.glfwExtensionSupported(cs) != 1
}

func ProcAddress(name string) uintptr {
	cs := C.CString(name)
	defer C.free(unsafe.Pointer(cs))
	return uintptr(C.glfwGetProcAddress(cs))
}

func GLVersion() (int, int, int) {
	var major, minor, rev C.int
	C.glfwGetGLVersion(&major, &minor, &rev)
	return int(major), int(minor), int(rev)
}

func LoadTexture2D(name string, flags int) int {
	cn := C.CString(name)
	defer C.free(unsafe.Pointer(cn))
	return int(C.glfwLoadTexture2D(cn, C.int(flags)))
}

func LoadMemoryTexture2D(data []byte, flags int) int {
	return int(C.glfwLoadMemoryTexture2D(unsafe.Pointer(&data), C.long(len(data)), C.int(flags)))
}
<commit_msg>Fix potential memory leak<commit_after>// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
// license. Its contents can be found at:
// http://creativecommons.org/publicdomain/zero/1.0/

package glfw

//#include "glue.h"
import "C"
import (
	"os"
	"unsafe"
)

func Terminate()                       { C.glfwTerminate() }
func OpenWindowHint(target, hint int)  { C.glfwOpenWindowHint(C.int(target), C.int(hint)) }
func CloseWindow()                     { C.glfwCloseWindow() }
func IconifyWindow()                   { C.glfwIconifyWindow() }
func RestoreWindow()                   { C.glfwRestoreWindow() }
func SwapBuffers()                     { C.glfwSwapBuffers() }
func WindowParam(param int) int        { return int(C.glfwGetWindowParam(C.int(param))) }
func SetSwapInterval(interval int)     { C.glfwSwapInterval(C.int(interval)) }
func SetWindowSize(width, height int)  { C.glfwSetWindowSize(C.int(width), C.int(height)) }
func SetWindowPos(x, y int)            { C.glfwSetWindowPos(C.int(x), C.int(y)) }
func SetWindowTitle(title string)      { C.glfwSetWindowTitle(C.CString(title)) }
func PollEvents()                      { C.glfwPollEvents() }
func WaitEvents()                      { C.glfwWaitEvents() }
func Key(key int) int                  { return int(C.glfwGetKey(C.int(key))) }
func MouseButton(btn int) int          { return int(C.glfwGetMouseButton(C.int(btn))) }
func SetMousePos(x, y int)             { C.glfwSetMousePos(C.int(x), C.int(y)) }
func MouseWheel() int                  { return int(C.glfwGetMouseWheel()) }
func SetMouseWheel(pos int)            { C.glfwSetMouseWheel(C.int(pos)) }
func JoystickParam(joy, param int) int { return int(C.glfwGetJoystickParam(C.int(joy), C.int(param))) }
func Time() float64                    { return float64(C.glfwGetTime()) }
func SetTime(t float64)                { C.glfwSetTime(C.double(t)) }
func Sleep(t float64)                  { C.glfwSleep(C.double(t)) }
func NumberOfProcessors() int          { return int(C.glfwGetNumberOfProcessors()) }
func Enable(token int)                 { C.glfwEnable(C.int(token)) }
func Disable(token int)                { C.glfwDisable(C.int(token)) }

func Init() (err os.Error) {
	if C.glfwInit() != 1 {
		err = os.NewError("Failed to initialize GLFW")
	}
	return
}

func OpenWindow(width, height, r, g, b, a, depth, stencil, mode int) (err os.Error) {
	if C.glfwOpenWindow(
		C.int(width), C.int(height),
		C.int(r), C.int(g), C.int(b), C.int(a),
		C.int(depth), C.int(stencil), C.int(mode),
	) != 1 {
		err = os.NewError("Failed to open window")
	}
	return
}

func WindowSize() (int, int) {
	var w, h C.int
	C.glfwGetWindowSize(&w, &h)
	return int(w), int(h)
}

func VideoModes(max int) []*VidMode {
	var vm C.GLFWvidmode

	size := unsafe.Sizeof(vm)
	ptr := (*C.GLFWvidmode)(C.malloc(C.size_t(size * max)))
	defer C.free(unsafe.Pointer(ptr))
	count := C.glfwGetVideoModes(ptr, C.int(max))

	if count == 0 {
		return nil
	}

	list := make([]*VidMode, count)
	for i := range list {
		p := (*C.GLFWvidmode)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + uintptr(i*size)))
		list[i] = vidModeFromPtr(p)
	}
	return list
}

func DesktopMode() *VidMode {
	var vm C.GLFWvidmode
	C.glfwGetDesktopMode(&vm)
	return vidModeFromPtr(&vm)
}

func MousePos() (int, int) {
	var cx, cy C.int
	C.glfwGetMousePos(&cx, &cy)
	return int(cx), int(cy)
}

func JoystickPos(joy int, numaxes int) float32 {
	var pos C.float
	if int(C.glfwGetJoystickPos(C.int(joy), &pos, C.int(numaxes))) != 1 {
		return 0
	}
	return float32(pos)
}

func JoystickButtons(joy, numbuttons int) []byte {
	ptr := (*_Ctype_unsignedchar)(C.malloc(C.size_t(C.int(numbuttons))))
	defer C.free(unsafe.Pointer(ptr))

	var count C.int
	if count = C.glfwGetJoystickButtons(C.int(joy), ptr, C.int(numbuttons)); count == 0 {
		return nil
	}

	b := make([]byte, count)
	copy(b, (*(*[1<<31 - 1]byte)(unsafe.Pointer(ptr)))[:count])
	return b
}

func ExtensionSupported(name string) bool {
	cs := C.CString(name)
	defer C.free(unsafe.Pointer(cs))
	return C.glfwExtensionSupported(cs) != 1
}

func ProcAddress(name string) uintptr {
	cs := C.CString(name)
	defer C.free(unsafe.Pointer(cs))
	return uintptr(C.glfwGetProcAddress(cs))
}

func GLVersion() (int, int, int) {
	var major, minor, rev C.int
	C.glfwGetGLVersion(&major, &minor, &rev)
	return int(major), int(minor), int(rev)
}

func LoadTexture2D(name string, flags int) int {
	cn := C.CString(name)
	defer C.free(unsafe.Pointer(cn))
	return int(C.glfwLoadTexture2D(cn, C.int(flags)))
}

func LoadMemoryTexture2D(data []byte, flags int) int {
	return int(C.glfwLoadMemoryTexture2D(unsafe.Pointer(&data), C.long(len(data)), C.int(flags)))
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"

	"golang.org/x/crypto/ssh/terminal"
)

type Editor struct {
	Reader *bufio.Reader
}

func NewEditor() *Editor {
	editor := &Editor{}
	editor.Reader = bufio.NewReader(os.Stdin)
	return editor
}

const CTRL_Q = 0x11

func (e *Editor) ReadKey() rune {
	rune, _, err := e.Reader.ReadRune()

	if err != nil {
		fmt.Print(err)
	}

	return rune
}

func (e *Editor) ProcessKeyPress() error {
	key := e.ReadKey()

	// print out the unicode value i.e. A -> 65, a -> 97
	fmt.Print(key)
	if key == CTRL_Q {
		e.Exit()
		return errors.New("quit")
	}
	return nil
}

func (e *Editor) RefreshScreen() {
	os.Stdout.Write([]byte("\x1b[2J"))   // clear screen
	os.Stdout.Write([]byte("\x1b[1;1H")) // move cursor to row 1, col 1
}

func (e *Editor) Exit() {
	os.Stdout.Write([]byte("\x1b[2J"))   // clear screen
	os.Stdout.Write([]byte("\x1b[1;1H")) // move cursor to row 1, col 1

}

func main() {

	// put the terminal into raw mode
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		panic(err)
	}
	// restore terminal however we exit
	defer terminal.Restore(0, oldState)

	e := NewEditor()
	e.RefreshScreen()
	// input loop
	for {
		err = e.ProcessKeyPress()
		if err != nil {
			break
		}
	}
}
<commit_msg>buffering before writing, welcome message<commit_after>package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"

	"golang.org/x/crypto/ssh/terminal"
)

const VERSION = "0.0.1"

type Editor struct {
	Reader *bufio.Reader

	ScreenRows int
	ScreenCols int
}

func NewEditor() *Editor {
	editor := &Editor{}
	editor.Reader = bufio.NewReader(os.Stdin)
	w, h, err := terminal.GetSize(0)
	if err != nil {
		fmt.Print(err)
	}
	editor.ScreenRows = h
	editor.ScreenCols = w
	return editor
}

const CTRL_Q = 0x11

func (e *Editor) ReadKey() rune {
	rune, _, err := e.Reader.ReadRune()

	if err != nil {
		fmt.Print(err)
	}

	return rune
}

func (e *Editor) ProcessKeyPress() error {
	key := e.ReadKey()

	// print out the unicode value i.e. A -> 65, a -> 97
	fmt.Print(key)
	if key == CTRL_Q {
		e.Exit()
		return errors.New("quit")
	}
	return nil
}

func (e *Editor) RefreshScreen() {
	buffer := make([]byte, 0)
	buffer = append(buffer, []byte("\x1b[?25l")...) // hide cursor
	buffer = append(buffer, []byte("\x1b[1;1H")...) // move cursor to row 1, col 1
	buffer = e.DrawRows(buffer)
	buffer = append(buffer, []byte("\x1b[1;1H")...) // move cursor to row 1, col 1
	buffer = append(buffer, []byte("\x1b[?25h")...) // show cursor
	os.Stdout.Write(buffer)
}

func (e *Editor) Exit() {
	buffer := make([]byte, 0)
	buffer = append(buffer, []byte("\x1b[2J")...)   // clear screen
	buffer = append(buffer, []byte("\x1b[1;1H")...) // move cursor to row 1, col 1
	os.Stdout.Write(buffer)
}

func (e *Editor) DrawRows(buffer []byte) []byte {
	for y := 1; y <= e.ScreenRows; y++ {
		if y == e.ScreenRows/3 {
			welcome := fmt.Sprintf("goed editor -- version %s", VERSION)
			padding := (e.ScreenCols - len(welcome)) / 2
			buffer = append(buffer, []byte("~")...)
			for i := 1; i <= padding; i++ {
				buffer = append(buffer, []byte(" ")...)
			}
			buffer = append(buffer, []byte(welcome)...)
		} else {
			buffer = append(buffer, []byte("~")...)
		}
		buffer = append(buffer, []byte("\x1b[K")...)
		if y < e.ScreenRows {
			buffer = append(buffer, []byte("\r\n")...)
		}
	}
	return buffer
}

func main() {

	// put the terminal into raw mode
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		panic(err)
	}
	// restore terminal however we exit
	defer terminal.Restore(0, oldState)

	e := NewEditor()
	e.RefreshScreen()
	// input loop
	for {
		err = e.ProcessKeyPress()
		if err != nil {
			break
		}
	}
}
<|endoftext|>


<commit_before>package gof1

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

const baseUrl = "http://ergast.com/api/f1/"

func GetRacesInSeason(year int) []Race {
	url := fmt.Sprintf("%s%v/schedule.json", baseUrl, year)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Println("NewRequest:", err)
		return nil
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Println("Do:", err)
		return nil
	}
	defer resp.Body.Close()

	var result F1

	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		log.Println(err)
	}

	return result.MRData.RaceTable.Races
}

// GetRacesWithResults queries the Ergast api and returns the details of every completed race in the F1 season specified
func GetRacesWithResults(year int) []Race {
	url := fmt.Sprintf("%s%v/results.json", baseUrl, year)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Println("NewRequest:", err)
		return nil
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Println("Do:", err)
		return nil
	}
	defer resp.Body.Close()

	var result F1

	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		log.Println(err)
	}

	return result.MRData.RaceTable.Races
}
<commit_msg>Add a method to retrieve all races in a season<commit_after>package gof1

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

const baseURL = "http://ergast.com/api/f1"

// GetRacesInSeason returns details of all races in the season specified.  Results are not returned.
func GetRacesInSeason(year int) []Race {
	url := fmt.Sprintf("%s/%v/schedule.json", baseURL, year)
	result := makeAPICall(url)
	return result.MRData.RaceTable.Races
}

// GetRacesWithResults queries the Ergast api and returns the details of every completed race in the F1 season specified
func GetRacesWithResults(year int) []Race {
	url := fmt.Sprintf("%s/%v/results.json?limit=1000&offset=0", baseURL, year)
	result := makeAPICall(url)
	return result.MRData.RaceTable.Races
}

// GetRaceWithResults retrieves details and results of the race specified by year and number
func GetRaceWithResults(year int, raceNumber int) Race {
	url := fmt.Sprintf("%s/%v/%v/results.json?limit=1000&offset=0", baseURL, year, raceNumber)
	result := makeAPICall(url)

	var r Race
	if len(result.MRData.RaceTable.Races) != 1 {
		return r
	}

	return result.MRData.RaceTable.Races[0]
}

func makeAPICall(url string) F1 {
	var result F1

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Println("NewRequest:", err)
		return result
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Println("Do:", err)
		return result
	}
	defer resp.Body.Close()

	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		log.Println(err)
	}

	return result
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/chadweimer/gomp/api"
	"github.com/chadweimer/gomp/models"
	"github.com/chadweimer/gomp/modules/conf"
	"github.com/phyber/negroni-gzip/gzip"
	"github.com/unrolled/render"
	"github.com/urfave/negroni"
)

func main() {
	cfg := conf.Load("conf/app.json")
	if err := cfg.Validate(); err != nil {
		log.Fatalf("[config] %s", err.Error())
	}
	model := models.New(cfg)
	renderer := render.New(render.Options{
		IndentJSON: true,

		Funcs: []template.FuncMap{map[string]interface{}{
			"ApplicationTitle": func() string { return cfg.ApplicationTitle },
			"HomeImage":        func() string { return cfg.HomeImage },
		}},
	})

	n := negroni.New()
	n.Use(negroni.NewRecovery())
	if cfg.IsDevelopment {
		n.Use(negroni.NewLogger())
	}
	n.Use(gzip.Gzip(gzip.DefaultCompression))

	apiHandler := api.NewHandler(renderer, cfg, model)
	staticHandler := newUIHandler(cfg, renderer)

	mainMux := http.NewServeMux()
	mainMux.Handle("/api/", apiHandler)
	//mainMux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(justFilesFileSystem{http.Dir("static")})))
	//mainMux.Handle("/uploads/", http.StripPrefix("/uploads/", upload.HandleS3Uploads2(cfg.UploadPath)))
	mainMux.Handle("/static/", staticHandler)
	mainMux.Handle("/uploads/", staticHandler)
	mainMux.Handle("/", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		renderer.HTML(resp, http.StatusOK, "index", nil)
	}))
	n.UseHandler(mainMux)

	// subscribe to SIGINT signals
	stopChan := make(chan os.Signal)
	signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)

	timeout := 10 * time.Second
	if cfg.IsDevelopment {
		timeout = 1 * time.Second
	}
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	log.Printf("Starting server on port :%d", cfg.Port)
	srv := &http.Server{Addr: fmt.Sprintf(":%d", cfg.Port), Handler: n}
	go srv.ListenAndServe()

	// Wait for a stop signal
	<-stopChan
	log.Print("Shutting down server...")

	// Shutdown the http server and close the database connection
	srv.Shutdown(ctx)
	model.TearDown()
}
<commit_msg>Removed compression to prove the theory<commit_after>package main

import (
	"context"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/chadweimer/gomp/api"
	"github.com/chadweimer/gomp/models"
	"github.com/chadweimer/gomp/modules/conf"
	"github.com/unrolled/render"
	"github.com/urfave/negroni"
)

func main() {
	cfg := conf.Load("conf/app.json")
	if err := cfg.Validate(); err != nil {
		log.Fatalf("[config] %s", err.Error())
	}
	model := models.New(cfg)
	renderer := render.New(render.Options{
		IndentJSON: true,

		Funcs: []template.FuncMap{map[string]interface{}{
			"ApplicationTitle": func() string { return cfg.ApplicationTitle },
			"HomeImage":        func() string { return cfg.HomeImage },
		}},
	})

	n := negroni.New()
	n.Use(negroni.NewRecovery())
	if cfg.IsDevelopment {
		n.Use(negroni.NewLogger())
	}
	//n.Use(gzip.Gzip(gzip.DefaultCompression))

	apiHandler := api.NewHandler(renderer, cfg, model)
	staticHandler := newUIHandler(cfg, renderer)

	mainMux := http.NewServeMux()
	mainMux.Handle("/api/", apiHandler)
	//mainMux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(justFilesFileSystem{http.Dir("static")})))
	//mainMux.Handle("/uploads/", http.StripPrefix("/uploads/", upload.HandleS3Uploads2(cfg.UploadPath)))
	mainMux.Handle("/static/", staticHandler)
	mainMux.Handle("/uploads/", staticHandler)
	mainMux.Handle("/", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		renderer.HTML(resp, http.StatusOK, "index", nil)
	}))
	n.UseHandler(mainMux)

	// subscribe to SIGINT signals
	stopChan := make(chan os.Signal)
	signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)

	timeout := 10 * time.Second
	if cfg.IsDevelopment {
		timeout = 1 * time.Second
	}
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	log.Printf("Starting server on port :%d", cfg.Port)
	srv := &http.Server{Addr: fmt.Sprintf(":%d", cfg.Port), Handler: n}
	go srv.ListenAndServe()

	// Wait for a stop signal
	<-stopChan
	log.Print("Shutting down server...")

	// Shutdown the http server and close the database connection
	srv.Shutdown(ctx)
	model.TearDown()
}
<|endoftext|>


<commit_before>// Gone Time Tracker -or- Where has my time gone?
package main

import (
	"bytes"
	"encoding/gob"
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"sort"
	"sync"
	"time"

	"github.com/BurntSushi/xgb"
	"github.com/BurntSushi/xgb/screensaver"
	"github.com/BurntSushi/xgb/xproto"
)

const (
	port = "127.0.0.1:8001"
	dump = "gone.gob"
	logf = "gone.log"
)

var (
	tracks = make(Tracker)
	tmpl   = template.Must(template.ParseFiles("index.html"))
	zzz    bool
	m      sync.Mutex
	logger *log.Logger
)

type Tracker map[Window]*Track

type Track struct {
	Seen  time.Time
	Spent time.Duration
}

type Window struct {
	Class string
	Name  string
}

type Xorg struct {
	X           *xgb.Conn
	root        xproto.Window
	activeAtom  *xproto.InternAtomReply
	netNameAtom *xproto.InternAtomReply
	nameAtom    *xproto.InternAtomReply
	classAtom   *xproto.InternAtomReply
}

func (t Track) String() string {
	return fmt.Sprintf("%s %s", t.Seen.Format("2006/01/02 15:04:05"), t.Spent)
}

func (w Window) String() string {
	return fmt.Sprintf("%s %s", w.Class, w.Name)
}

func (x Xorg) atom(aname string) *xproto.InternAtomReply {
	a, err := xproto.InternAtom(x.X, true, uint16(len(aname)), aname).Reply()
	if err != nil {
		log.Fatal("atom: ", err)
	}
	return a
}

func (x Xorg) property(w xproto.Window, a *xproto.InternAtomReply) (*xproto.GetPropertyReply, error) {
	return xproto.GetProperty(x.X, false, w, a.Atom,
		xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
}

func (x Xorg) active() xproto.Window {
	p, err := x.property(x.root, x.activeAtom)
	if err != nil {
		return x.root
	}
	return xproto.Window(xgb.Get32(p.Value))
}

func (x Xorg) name(w xproto.Window) (string, error) {
	name, err := x.property(w, x.netNameAtom)
	if err != nil {
		return "", err
	}
	if string(name.Value) == "" {
		name, err = x.property(w, x.nameAtom)
		if err != nil {
			return "", err
		}
		if string(name.Value) == "" {
			return "", errors.New("empty value")
		}
	}
	return string(name.Value), nil
}

func (x Xorg) class(w xproto.Window) (string, error) {
	class, err := x.property(w, x.classAtom)
	if err != nil {
		return "", err
	}
	zero := []byte{0}
	s := bytes.Split(bytes.TrimSuffix(class.Value, zero), zero)
	if l := len(s); l > 0 && len(s[l-1]) != 0 {
		return string(s[l-1]), nil
	}
	return "", errors.New("empty class")
}

func (x Xorg) window() (Window, bool) {
	id := x.active()
	/* skip invalid window id */
	if id == 0 {
		return Window{}, false
	}
	class, err := x.class(id)
	if err != nil {
		return Window{}, false
	}
	name, err := x.name(id)
	if err != nil {
		return Window{}, false
	}
	x.spy(id)
	return Window{
		Class: class,
		Name:  name,
	}, true
}

func (x Xorg) spy(w xproto.Window) {
	xproto.ChangeWindowAttributes(x.X, w, xproto.CwEventMask,
		[]uint32{xproto.EventMaskPropertyChange})
}

func (x Xorg) update(t Tracker) (current *Track) {
	if win, ok := x.window(); ok {
		m.Lock()
		if _, ok := t[win]; !ok {
			t[win] = new(Track)
		}
		t[win].Seen = time.Now()
		current = t[win]
		m.Unlock()
	}
	return
}

func connect() Xorg {
	var x Xorg
	var err error

	display := os.Getenv("DISPLAY")
	if display == "" {
		display = ":0"
	}
	x.X, err = xgb.NewConnDisplay(display)
	if err != nil {
		log.Fatal("xgb: ", err)
	}

	err = screensaver.Init(x.X)
	if err != nil {
		log.Fatal("screensaver: ", err)
	}

	setup := xproto.Setup(x.X)
	x.root = setup.DefaultScreen(x.X).Root

	drw := xproto.Drawable(x.root)
	screensaver.SelectInput(x.X, drw, screensaver.EventNotifyMask)

	x.activeAtom = x.atom("_NET_ACTIVE_WINDOW")
	x.netNameAtom = x.atom("_NET_WM_NAME")
	x.nameAtom = x.atom("WM_NAME")
	x.classAtom = x.atom("WM_CLASS")

	x.spy(x.root)

	return x
}

func (t Tracker) collect() {
	x := connect()
	defer x.X.Close()

	current := x.update(t)
	for {
		ev, everr := x.X.WaitForEvent()
		if everr != nil {
			log.Println("wait for event:", everr)
			continue
		}
		switch event := ev.(type) {
		case xproto.PropertyNotifyEvent:
			if current != nil {
				m.Lock()
				current.Spent += time.Since(current.Seen)
				m.Unlock()
			}
			current = x.update(t)
		case screensaver.NotifyEvent:
			switch event.State {
			case screensaver.StateOn:
				log.Println("away from keyboard")
				current = nil
				zzz = true
			default:
				log.Println("back to keyboard")
				zzz = false
			}
		}
	}
}

func (t Tracker) cleanup(d time.Duration) {
	m.Lock()
	for k, v := range t {
		if time.Since(v.Seen) > d {
			logger.Println(v, k)
			delete(t, k)
		}
	}
	m.Unlock()
}

func (t Tracker) reset() {
	m.Lock()
	for k, v := range t {
		logger.Println(v, k)
		delete(t, k)
	}
	m.Unlock()
}

func (t Tracker) load(fname string) {
	dump, err := os.Open(fname)
	if err != nil {
		log.Println(err)
		return
	}
	defer dump.Close()
	dec := gob.NewDecoder(dump)
	m.Lock()
	err = dec.Decode(&t)
	m.Unlock()
	if err != nil {
		log.Println(err)
	}
}

func (t Tracker) store(fname string) {
	dump, err := os.Create(fname + ".tmp")
	if err != nil {
		log.Println(err)
		return
	}
	defer dump.Close()
	enc := gob.NewEncoder(dump)
	m.Lock()
	err = enc.Encode(t)
	m.Unlock()
	if err != nil {
		log.Println(err)
	}
	os.Rename(fname+".tmp", fname)
}

type Index struct {
	Title   string
	Records Records
	Classes Records
	Total   Duration
	Zzz     bool
}

type Records []Record
type Duration time.Duration

type Record struct {
	Class string
	Name  string
	Spent Duration
	Seen  time.Time
	Odd   bool `json:"-"`
}

func (r Records) Len() int           { return len(r) }
func (r Records) Swap(i, j int)      { r[i], r[j] = r[j], r[i] }
func (r Records) Less(i, j int) bool { return r[i].Spent < r[j].Spent }

func (d Duration) String() string {
	h := int(time.Duration(d).Hours())
	m := int(time.Duration(d).Minutes()) % 60
	s := int(time.Duration(d).Seconds()) % 60
	var ret string
	if h > 0 {
		ret += fmt.Sprintf("%dh", h)
	}
	if m > 0 {
		ret += fmt.Sprintf("%dm", m)
	}
	return ret + fmt.Sprintf("%ds", s)
}
func (d Duration) Seconds() int {
	return int(time.Duration(d).Seconds())
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	var idx Index
	idx.Title = "Gone Time Tracker"
	idx.Zzz = zzz
	class := r.URL.Path[1:]

	classtotal := make(map[string]time.Duration)

	m.Lock()
	for k, v := range tracks {
		classtotal[k.Class] += v.Spent
		idx.Total += Duration(v.Spent)
		if class != "" && class != k.Class {
			continue
		}
		idx.Records = append(idx.Records, Record{
			Class: k.Class,
			Name:  k.Name,
			Spent: Duration(v.Spent)})
	}
	m.Unlock()
	for k, v := range classtotal {
		idx.Classes = append(idx.Classes, Record{Class: k, Spent: Duration(v)})
	}
	sort.Sort(sort.Reverse(idx.Classes))
	sort.Sort(sort.Reverse(idx.Records))
	for j := range idx.Records {
		idx.Records[j].Odd = j%2 == 0
	}
	err := tmpl.Execute(w, idx)
	if err != nil {
		log.Println(err)
	}
}

func dumpHandler(w http.ResponseWriter, r *http.Request) {
	var rec Records

	m.Lock()
	for k, v := range tracks {
		rec = append(rec, Record{
			Class: k.Class,
			Name:  k.Name,
			Spent: Duration(v.Spent),
			Seen:  v.Seen})
	}
	m.Unlock()

	data, err := json.MarshalIndent(rec, "", "\t")
	if err != nil {
		log.Println("dump:", err)
	}
	w.Write(data)
}

func resetHandler(w http.ResponseWriter, r *http.Request) {
	tracks.reset()
	http.Redirect(w, r, "/", http.StatusFound)
}

func main() {
	logfile, err := os.OpenFile(logf, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Fatal(err)
	}
	defer logfile.Close()
	logger = log.New(logfile, "", log.LstdFlags)

	tracks.load(dump)

	go tracks.collect()
	go func() {
		for {
			tracks.cleanup(8 * time.Hour)
			tracks.store(dump)
			time.Sleep(time.Minute)
		}
	}()
	log.Println("listen on", port)
	http.HandleFunc("/", indexHandler)
	http.HandleFunc("/gone.json", dumpHandler)
	http.HandleFunc("/reset", resetHandler)
	err = http.ListenAndServe(port, nil)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>gone: Locate files relative to the gone source directory. This makes it possible to execute gone from arbitrary working directories.<commit_after>// Gone Time Tracker -or- Where has my time gone?
package main

import (
	"bytes"
	"encoding/gob"
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"path"
	"sort"
	"sync"
	"time"

	"github.com/BurntSushi/xgb"
	"github.com/BurntSushi/xgb/screensaver"
	"github.com/BurntSushi/xgb/xproto"
	"github.com/mewkiz/pkg/goutil"
)

const (
	port = "127.0.0.1:8001"
	dump = "gone.gob"
	logf = "gone.log"
)

var (
	goneDir string
	tracks  = make(Tracker)
	tmpl    *template.Template
	zzz     bool
	m       sync.Mutex
	logger  *log.Logger
)

func init() {
	var err error
	goneDir, err = goutil.SrcDir("github.com/dim13/gone")
	if err != nil {
		log.Fatal("init: ", err)
	}
	tmpl = template.Must(template.ParseFiles(path.Join(goneDir, "index.html")))
}

type Tracker map[Window]*Track

type Track struct {
	Seen  time.Time
	Spent time.Duration
}

type Window struct {
	Class string
	Name  string
}

type Xorg struct {
	X           *xgb.Conn
	root        xproto.Window
	activeAtom  *xproto.InternAtomReply
	netNameAtom *xproto.InternAtomReply
	nameAtom    *xproto.InternAtomReply
	classAtom   *xproto.InternAtomReply
}

func (t Track) String() string {
	return fmt.Sprintf("%s %s", t.Seen.Format("2006/01/02 15:04:05"), t.Spent)
}

func (w Window) String() string {
	return fmt.Sprintf("%s %s", w.Class, w.Name)
}

func (x Xorg) atom(aname string) *xproto.InternAtomReply {
	a, err := xproto.InternAtom(x.X, true, uint16(len(aname)), aname).Reply()
	if err != nil {
		log.Fatal("atom: ", err)
	}
	return a
}

func (x Xorg) property(w xproto.Window, a *xproto.InternAtomReply) (*xproto.GetPropertyReply, error) {
	return xproto.GetProperty(x.X, false, w, a.Atom,
		xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
}

func (x Xorg) active() xproto.Window {
	p, err := x.property(x.root, x.activeAtom)
	if err != nil {
		return x.root
	}
	return xproto.Window(xgb.Get32(p.Value))
}

func (x Xorg) name(w xproto.Window) (string, error) {
	name, err := x.property(w, x.netNameAtom)
	if err != nil {
		return "", err
	}
	if string(name.Value) == "" {
		name, err = x.property(w, x.nameAtom)
		if err != nil {
			return "", err
		}
		if string(name.Value) == "" {
			return "", errors.New("empty value")
		}
	}
	return string(name.Value), nil
}

func (x Xorg) class(w xproto.Window) (string, error) {
	class, err := x.property(w, x.classAtom)
	if err != nil {
		return "", err
	}
	zero := []byte{0}
	s := bytes.Split(bytes.TrimSuffix(class.Value, zero), zero)
	if l := len(s); l > 0 && len(s[l-1]) != 0 {
		return string(s[l-1]), nil
	}
	return "", errors.New("empty class")
}

func (x Xorg) window() (Window, bool) {
	id := x.active()
	/* skip invalid window id */
	if id == 0 {
		return Window{}, false
	}
	class, err := x.class(id)
	if err != nil {
		return Window{}, false
	}
	name, err := x.name(id)
	if err != nil {
		return Window{}, false
	}
	x.spy(id)
	return Window{
		Class: class,
		Name:  name,
	}, true
}

func (x Xorg) spy(w xproto.Window) {
	xproto.ChangeWindowAttributes(x.X, w, xproto.CwEventMask,
		[]uint32{xproto.EventMaskPropertyChange})
}

func (x Xorg) update(t Tracker) (current *Track) {
	if win, ok := x.window(); ok {
		m.Lock()
		if _, ok := t[win]; !ok {
			t[win] = new(Track)
		}
		t[win].Seen = time.Now()
		current = t[win]
		m.Unlock()
	}
	return
}

func connect() Xorg {
	var x Xorg
	var err error

	display := os.Getenv("DISPLAY")
	if display == "" {
		display = ":0"
	}
	x.X, err = xgb.NewConnDisplay(display)
	if err != nil {
		log.Fatal("xgb: ", err)
	}

	err = screensaver.Init(x.X)
	if err != nil {
		log.Fatal("screensaver: ", err)
	}

	setup := xproto.Setup(x.X)
	x.root = setup.DefaultScreen(x.X).Root

	drw := xproto.Drawable(x.root)
	screensaver.SelectInput(x.X, drw, screensaver.EventNotifyMask)

	x.activeAtom = x.atom("_NET_ACTIVE_WINDOW")
	x.netNameAtom = x.atom("_NET_WM_NAME")
	x.nameAtom = x.atom("WM_NAME")
	x.classAtom = x.atom("WM_CLASS")

	x.spy(x.root)

	return x
}

func (t Tracker) collect() {
	x := connect()
	defer x.X.Close()

	current := x.update(t)
	for {
		ev, everr := x.X.WaitForEvent()
		if everr != nil {
			log.Println("wait for event:", everr)
			continue
		}
		switch event := ev.(type) {
		case xproto.PropertyNotifyEvent:
			if current != nil {
				m.Lock()
				current.Spent += time.Since(current.Seen)
				m.Unlock()
			}
			current = x.update(t)
		case screensaver.NotifyEvent:
			switch event.State {
			case screensaver.StateOn:
				log.Println("away from keyboard")
				current = nil
				zzz = true
			default:
				log.Println("back to keyboard")
				zzz = false
			}
		}
	}
}

func (t Tracker) cleanup(d time.Duration) {
	m.Lock()
	for k, v := range t {
		if time.Since(v.Seen) > d {
			logger.Println(v, k)
			delete(t, k)
		}
	}
	m.Unlock()
}

func (t Tracker) reset() {
	m.Lock()
	for k, v := range t {
		logger.Println(v, k)
		delete(t, k)
	}
	m.Unlock()
}

func (t Tracker) load(fname string) {
	dump, err := os.Open(fname)
	if err != nil {
		log.Println(err)
		return
	}
	defer dump.Close()
	dec := gob.NewDecoder(dump)
	m.Lock()
	err = dec.Decode(&t)
	m.Unlock()
	if err != nil {
		log.Println(err)
	}
}

func (t Tracker) store(fname string) {
	dump, err := os.Create(fname + ".tmp")
	if err != nil {
		log.Println(err)
		return
	}
	defer dump.Close()
	enc := gob.NewEncoder(dump)
	m.Lock()
	err = enc.Encode(t)
	m.Unlock()
	if err != nil {
		log.Println(err)
	}
	os.Rename(fname+".tmp", fname)
}

type Index struct {
	Title   string
	Records Records
	Classes Records
	Total   Duration
	Zzz     bool
}

type Records []Record
type Duration time.Duration

type Record struct {
	Class string
	Name  string
	Spent Duration
	Seen  time.Time
	Odd   bool `json:"-"`
}

func (r Records) Len() int           { return len(r) }
func (r Records) Swap(i, j int)      { r[i], r[j] = r[j], r[i] }
func (r Records) Less(i, j int) bool { return r[i].Spent < r[j].Spent }

func (d Duration) String() string {
	h := int(time.Duration(d).Hours())
	m := int(time.Duration(d).Minutes()) % 60
	s := int(time.Duration(d).Seconds()) % 60
	var ret string
	if h > 0 {
		ret += fmt.Sprintf("%dh", h)
	}
	if m > 0 {
		ret += fmt.Sprintf("%dm", m)
	}
	return ret + fmt.Sprintf("%ds", s)
}
func (d Duration) Seconds() int {
	return int(time.Duration(d).Seconds())
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	var idx Index
	idx.Title = "Gone Time Tracker"
	idx.Zzz = zzz
	class := r.URL.Path[1:]

	classtotal := make(map[string]time.Duration)

	m.Lock()
	for k, v := range tracks {
		classtotal[k.Class] += v.Spent
		idx.Total += Duration(v.Spent)
		if class != "" && class != k.Class {
			continue
		}
		idx.Records = append(idx.Records, Record{
			Class: k.Class,
			Name:  k.Name,
			Spent: Duration(v.Spent)})
	}
	m.Unlock()
	for k, v := range classtotal {
		idx.Classes = append(idx.Classes, Record{Class: k, Spent: Duration(v)})
	}
	sort.Sort(sort.Reverse(idx.Classes))
	sort.Sort(sort.Reverse(idx.Records))
	for j := range idx.Records {
		idx.Records[j].Odd = j%2 == 0
	}
	err := tmpl.Execute(w, idx)
	if err != nil {
		log.Println(err)
	}
}

func dumpHandler(w http.ResponseWriter, r *http.Request) {
	var rec Records

	m.Lock()
	for k, v := range tracks {
		rec = append(rec, Record{
			Class: k.Class,
			Name:  k.Name,
			Spent: Duration(v.Spent),
			Seen:  v.Seen})
	}
	m.Unlock()

	data, err := json.MarshalIndent(rec, "", "\t")
	if err != nil {
		log.Println("dump:", err)
	}
	w.Write(data)
}

func resetHandler(w http.ResponseWriter, r *http.Request) {
	tracks.reset()
	http.Redirect(w, r, "/", http.StatusFound)
}

func main() {
	logfile, err := os.OpenFile(path.Join(goneDir, logf), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Fatal(err)
	}
	defer logfile.Close()
	logger = log.New(logfile, "", log.LstdFlags)

	dumpPath := path.Join(goneDir, dump)
	tracks.load(dumpPath)

	go tracks.collect()
	go func() {
		for {
			tracks.cleanup(8 * time.Hour)
			tracks.store(dumpPath)
			time.Sleep(time.Minute)
		}
	}()
	log.Println("listen on", port)
	http.HandleFunc("/", indexHandler)
	http.HandleFunc("/gone.json", dumpHandler)
	http.HandleFunc("/reset", resetHandler)
	err = http.ListenAndServe(port, nil)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"log"
	"time"

	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/all"
)

func ReadDHT11(pin embd.DigitalPin) (byte, byte, error) {
	if e := pin.SetDirection(embd.Out); e != nil {
		return 0, 0, e
	}
	if e := pin.Write(embd.High); e != nil {
		return 0, 0, e
	}
	time.Sleep(500 * time.Millisecond)
	if e := pin.Write(embd.Low); e != nil {
		return 0, 0, e
	}
	time.Sleep(18 * time.Millisecond)
	if e := pin.SetDirection(embd.In); e != nil {
		return 0, 0, e
	}

	var values [5]byte

	pulses := make([]byte, (len(values)*8+1)*10)
	//started_at := time.Now()
	for i := 0; i < len(pulses); i++ {
		if pulse, e := pin.Read(); e != nil {
			return 0, 0, e
		} else {
			pulses[i] = byte(pulse)
		}
	}
	//read_time := time.Since(started_at).Seconds() * 1000000 / float64(len(pulses))

	pulse_duration := 0
	for i, j := bytes.LastIndexByte(pulses, 0), 0; i >= 0 && j < 8*len(values); i-- {
		if pulses[i] == 1 {
			pulse_duration++
		} else {
			if pulse_duration > 0 {
				value := 0
				if pulse_duration > 2 /* *read_time > 70 */ {
					value = 1
				}
				pulse_duration = 0
				values[j/8] += byte(value << byte(j%8))
				j++
			}
		}
	}

	checksum := values[4] + values[3] + values[2] + values[1]
	if checksum == values[0] {
		return values[4], values[2], nil
	}
	return 0, 0, fmt.Errorf("invalid checksum: expected %d, got %d",
		values[0], checksum)
}

func main() {
	embd.InitGPIO()
	defer embd.CloseGPIO()

	if pin, e := embd.NewDigitalPin(4); e != nil {
		log.Panic("NewDigitalPin ", e)
	} else {
		defer pin.Close()
		for {
			if h, t, e := ReadDHT11(pin); e != nil {
				fmt.Println(e)
			} else {
				fmt.Printf("%d*C, %d%%\n", t, h)
				break
			}
		}
	}
}
<commit_msg>Make DHT11 reader infinite (to test interaction)<commit_after>package main

import (
	"bytes"
	"fmt"
	"log"
	"time"

	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/all"
)

func ReadDHT11(pin embd.DigitalPin) (byte, byte, error) {
	if e := pin.SetDirection(embd.Out); e != nil {
		return 0, 0, e
	}
	if e := pin.Write(embd.High); e != nil {
		return 0, 0, e
	}
	time.Sleep(500 * time.Millisecond)
	if e := pin.Write(embd.Low); e != nil {
		return 0, 0, e
	}
	time.Sleep(18 * time.Millisecond)
	if e := pin.SetDirection(embd.In); e != nil {
		return 0, 0, e
	}

	var values [5]byte

	pulses := make([]byte, (len(values)*8+1)*10)
	//started_at := time.Now()
	for i := 0; i < len(pulses); i++ {
		if pulse, e := pin.Read(); e != nil {
			return 0, 0, e
		} else {
			pulses[i] = byte(pulse)
		}
	}
	//read_time := time.Since(started_at).Seconds() * 1000000 / float64(len(pulses))

	pulse_duration := 0
	for i, j := bytes.LastIndexByte(pulses, 0), 0; i >= 0 && j < 8*len(values); i-- {
		if pulses[i] == 1 {
			pulse_duration++
		} else {
			if pulse_duration > 0 {
				value := 0
				if pulse_duration > 2 /* *read_time > 70 */ {
					value = 1
				}
				pulse_duration = 0
				values[j/8] += byte(value << byte(j%8))
				j++
			}
		}
	}

	checksum := values[4] + values[3] + values[2] + values[1]
	if checksum == values[0] {
		return values[4], values[2], nil
	}
	return 0, 0, fmt.Errorf("invalid checksum: expected %d, got %d",
		values[0], checksum)
}

func main() {
	embd.InitGPIO()
	defer embd.CloseGPIO()

	if pin, e := embd.NewDigitalPin(4); e != nil {
		log.Panic("NewDigitalPin ", e)
	} else {
		defer pin.Close()
		for {
			if h, t, e := ReadDHT11(pin); e != nil {
				fmt.Println(e)
			} else {
				fmt.Printf("%d*C, %d%%\n", t, h)
			}
			time.Sleep(1 * time.Second)
		}
	}
}
<|endoftext|>


<commit_before>package jwt

import (
	"crypto"
	"crypto/hmac"
	"errors"
)

// Implements the HMAC-SHA family of signing methods signing methods
type SigningMethodHMAC struct {
	Name string
	Hash crypto.Hash
}

// Specific instances for HS256 and company
var (
	SigningMethodHS256  *SigningMethodHMAC
	SigningMethodHS384  *SigningMethodHMAC
	SigningMethodHS512  *SigningMethodHMAC
	ErrSignatureInvalid = errors.New("signature is invalid")
)

func init() {
	// HS256
	SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256}
	RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod {
		return SigningMethodHS256
	})

	// HS384
	SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384}
	RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod {
		return SigningMethodHS384
	})

	// HS512
	SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512}
	RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod {
		return SigningMethodHS512
	})
}

func (m *SigningMethodHMAC) Alg() string {
	return m.Name
}

func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error {
	if keyBytes, ok := key.([]byte); ok {
		var sig []byte
		var err error
		if sig, err = DecodeSegment(signature); err == nil {
			if !m.Hash.Available() {
				return ErrHashUnavailable
			}

			hasher := hmac.New(m.Hash.New, keyBytes)
			hasher.Write([]byte(signingString))

			if !hmac.Equal(sig, hasher.Sum(nil)) {
				err = ErrSignatureInvalid
			}
		}
		return err
	}

	return ErrInvalidKey
}

func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) {
	if keyBytes, ok := key.([]byte); ok {
		if !m.Hash.Available() {
			return "", ErrHashUnavailable
		}

		hasher := hmac.New(m.Hash.New, keyBytes)
		hasher.Write([]byte(signingString))

		return EncodeSegment(hasher.Sum(nil)), nil
	}

	return "", ErrInvalidKey
}
<commit_msg>added documentation for HMAC Sign method<commit_after>package jwt

import (
	"crypto"
	"crypto/hmac"
	"errors"
)

// Implements the HMAC-SHA family of signing methods signing methods
type SigningMethodHMAC struct {
	Name string
	Hash crypto.Hash
}

// Specific instances for HS256 and company
var (
	SigningMethodHS256  *SigningMethodHMAC
	SigningMethodHS384  *SigningMethodHMAC
	SigningMethodHS512  *SigningMethodHMAC
	ErrSignatureInvalid = errors.New("signature is invalid")
)

func init() {
	// HS256
	SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256}
	RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod {
		return SigningMethodHS256
	})

	// HS384
	SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384}
	RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod {
		return SigningMethodHS384
	})

	// HS512
	SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512}
	RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod {
		return SigningMethodHS512
	})
}

func (m *SigningMethodHMAC) Alg() string {
	return m.Name
}

func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error {
	if keyBytes, ok := key.([]byte); ok {
		var sig []byte
		var err error
		if sig, err = DecodeSegment(signature); err == nil {
			if !m.Hash.Available() {
				return ErrHashUnavailable
			}

			hasher := hmac.New(m.Hash.New, keyBytes)
			hasher.Write([]byte(signingString))

			if !hmac.Equal(sig, hasher.Sum(nil)) {
				err = ErrSignatureInvalid
			}
		}
		return err
	}

	return ErrInvalidKey
}

// Implements the Sign method from SigningMethod for this signing method.
// Key must be []byte
func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) {
	if keyBytes, ok := key.([]byte); ok {
		if !m.Hash.Available() {
			return "", ErrHashUnavailable
		}

		hasher := hmac.New(m.Hash.New, keyBytes)
		hasher.Write([]byte(signingString))

		return EncodeSegment(hasher.Sum(nil)), nil
	}

	return "", ErrInvalidKey
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/tls"
	"encoding/base32"
	"encoding/json"
	"errors"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/devel/dnsmapper/storeapi"
	"github.com/gorilla/handlers"
)

type ipResponse struct {
	DNS  string
	EDNS string
	HTTP string
}

var (
	uuidCh    chan string
	localNets []*net.IPNet
)

func init() {
	go uuidFactory()

	pn := []string{
		"127.0.0.0/8",
		"10.0.0.0/8",
		"172.16.0.0/12",
		"192.168.0.0/16",
		"fc00::/7",
	}
	for _, p := range pn {
		_, ipnet, err := net.ParseCIDR(p)
		if err != nil {
			panic(err)
		}
		localNets = append(localNets, ipnet)
	}
}

func uuidFactory() {
	uuidCh = make(chan string, 10)

	enc := base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")

	length := 20

	buf := make([]byte, length)
	uuid := make([]byte, enc.EncodedLen(length))

	for {
		rand.Read(buf)
		enc.Encode(uuid, buf)
		uuidCh <- string(uuid)
	}
}

func uuid() string {
	return <-uuidCh
}

func remoteIP(xff string) string {
	if len(xff) > 0 {
		ips := strings.Split(xff, ",")
		for i := len(ips) - 1; i >= 0; i-- {
			ip := strings.TrimSpace(ips[i])
			nip := net.ParseIP(ip)
			if nip != nil {
				if localNet(nip) {
					continue
				}
				return nip.String()
			}
		}
	}

	return ""
}

func jsonData(req *http.Request) (string, error) {

	ip, _, _ := net.SplitHostPort(req.RemoteAddr)
	nip := net.ParseIP(ip)

	if xff := req.Header.Get("X-Forwarded-For"); len(xff) > 0 && localNet(nip) {
		ip = remoteIP(xff)
	}

	resp := &ipResponse{HTTP: ip, DNS: ""}

	uuid := getUUIDFromDomain(req.Host)

	dns, edns, ok := getCache(uuid)

	if !ok {
		return "", errors.New("UUID not found")
	}

	resp.DNS = dns
	resp.EDNS = edns

	js, err := json.Marshal(resp)
	if err != nil {
		log.Print("JSON ERROR:", err)
		return "", err
	}

	data := storeapi.RequestData{
		TestIP:   *flagip,
		ServerIP: resp.DNS,
		ClientIP: resp.HTTP,
		EdnsNet:  resp.EDNS,
	}
	select {
	case ch <- &data:
	default:
		log.Println("dropped log data, queue full")
	}

	return string(js), nil
}

func redirectUUID(w http.ResponseWriter, req *http.Request) {
	uuid := uuid()
	host := uuid + "." + *flagdomain

	proto := "http"

	if req.TLS != nil {
		proto = "https"
	}

	http.Redirect(w, req, proto+"://"+host+req.RequestURI, 302)
	return
}

func mainServer(w http.ResponseWriter, req *http.Request) {

	if req.URL.Path == "/jsonp" || req.URL.Path == "/json" || req.URL.Path == "/none" {

		w.Header().Set("Cache-Control", "private, no-cache, no-store, must-revalidate")
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Methods", "GET")

		uuid := getUUIDFromDomain(req.Host)
		if uuid == "www" {
			redirectUUID(w, req)
			return
		}

		js, err := jsonData(req)
		if err != nil {
			log.Printf("redirecting to new uuid, err: %s", err)
			redirectUUID(w, req)
			return
		}

		if req.URL.Path == "/none" {
			w.WriteHeader(204)
			return
		}

		jsonp := req.FormValue("jsonp")
		if len(jsonp) == 0 {
			jsonp = req.FormValue("callback")
		}

		if len(jsonp) > 0 {
			w.Header().Set("Content-Type", "text/javascript")
			io.WriteString(w, jsonp+"("+js+");\n")
			return
		}

		// not jsonp
		w.Header().Set("Content-Type", "application/json")
		io.WriteString(w, js+"\n")
		return

	}

	mapperScript := `
	 (function(global){"use strict";var id=function(){var chars="0123456789abcdefghijklmnopqrstuvxyz".split("");
	 var uuid=[],rnd=Math.random,r;for(var i=0;i<17;i++){if(!uuid[i]){r=0|rnd()*16;uuid[i]=chars[i==19?r&3|8:r&15]}}
	 return uuid.join("")};
	 setTimeout(function(){(new Image).src="http://"+id()+".` +
		*flagdomain +
		`/none"},3200)})(this);
	 `

	if req.URL.Path == "/mapper.js" {
		w.Header().Set("Cache-Control", "public, max-age=86400")
		w.Header().Set("Content-Type", "text/javascript; charset=utf-8")
		w.WriteHeader(200)
		io.WriteString(w, mapperScript)
		return
	}

	if req.URL.Path == "/mapper-v6compat.js" {
		w.Header().Set("Cache-Control", "public, max-age=60")
		w.Header().Set("Content-Type", "text/javascript; charset=utf-8")
		w.WriteHeader(200)
		io.WriteString(w, mapperScript)
		io.WriteString(w, `v6 = { "version": "2", test: function(){} };`)
		return
	}

	if req.URL.Path == "/" {
		w.Header().Set("Cache-Control", "public, max-age=900")
		w.WriteHeader(200)
		io.WriteString(w, HOMEPAGE)
		return
	}

	if req.URL.Path == "/robots.txt" {
		w.Header().Set("Cache-Control", "public, max-age=604800")
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		w.WriteHeader(200)
		io.WriteString(w, "# Hi Robot!\n")
		return
	}

	if req.URL.Path == "/version" {
		io.WriteString(w, `<html><head><title>DNS Mapper `+
			VERSION+`</title><body>`+
			`Hello`+
			`</body></html>`)
		return
	}

	http.NotFound(w, req)
	return
}

func httpHandler() {
	http.HandleFunc("/", mainServer)

	if len(*flagtlskeyfile) > 0 {

		log.Printf("Starting TLS with key='%s' and cert='%s'",
			*flagtlskeyfile,
			*flagtlscrtfile,
		)

		go func() {

			tlsconfig := &tls.Config{
				ClientSessionCache: tls.NewLRUClientSessionCache(100),
				MinVersion:         tls.VersionTLS10,
				CipherSuites: []uint16{
					tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
					tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
					tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
					tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
					tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
					tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
					tls.TLS_RSA_WITH_AES_128_CBC_SHA,
					tls.TLS_RSA_WITH_AES_256_CBC_SHA,
					tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
					tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA},
			}

			tlslisten := *flagip + ":" + *flaghttpsport
			srv := &http.Server{
				Addr:         tlslisten,
				WriteTimeout: 5 * time.Second,
				ReadTimeout:  10 * time.Second,
				TLSConfig:    tlsconfig,
			}
			log.Println("Going to listen for TLS requests on port", tlslisten)
			log.Fatal(srv.ListenAndServeTLS(
				*flagtlscrtfile,
				*flagtlskeyfile,
			))

		}()
	}

	listen := *flagip + ":" + *flaghttpport
	srv := &http.Server{
		Handler:      handlers.CombinedLoggingHandler(os.Stdout, http.DefaultServeMux),
		Addr:         listen,
		WriteTimeout: 5 * time.Second,
		ReadTimeout:  5 * time.Second,
	}
	log.Println("HTTP listen on", listen)
	log.Fatal(srv.ListenAndServe())

}

func localNet(ip net.IP) bool {
	for _, n := range localNets {
		if n.Contains(ip) {
			return true
		}
	}
	return false
}
<commit_msg>Better TLS support<commit_after>package main

import (
	"crypto/rand"
	"crypto/tls"
	"encoding/base32"
	"encoding/json"
	"errors"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/devel/dnsmapper/storeapi"
	"github.com/gorilla/handlers"
)

type ipResponse struct {
	DNS  string
	EDNS string
	HTTP string
}

var (
	uuidCh    chan string
	localNets []*net.IPNet
)

func init() {
	go uuidFactory()

	pn := []string{
		"127.0.0.0/8",
		"10.0.0.0/8",
		"172.16.0.0/12",
		"192.168.0.0/16",
		"fc00::/7",
	}
	for _, p := range pn {
		_, ipnet, err := net.ParseCIDR(p)
		if err != nil {
			panic(err)
		}
		localNets = append(localNets, ipnet)
	}
}

func uuidFactory() {
	uuidCh = make(chan string, 10)

	enc := base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")

	length := 20

	buf := make([]byte, length)
	uuid := make([]byte, enc.EncodedLen(length))

	for {
		rand.Read(buf)
		enc.Encode(uuid, buf)
		uuidCh <- string(uuid)
	}
}

func uuid() string {
	return <-uuidCh
}

func remoteIP(xff string) string {
	if len(xff) > 0 {
		ips := strings.Split(xff, ",")
		for i := len(ips) - 1; i >= 0; i-- {
			ip := strings.TrimSpace(ips[i])
			nip := net.ParseIP(ip)
			if nip != nil {
				if localNet(nip) {
					continue
				}
				return nip.String()
			}
		}
	}

	return ""
}

func jsonData(req *http.Request) (string, error) {

	ip, _, _ := net.SplitHostPort(req.RemoteAddr)
	nip := net.ParseIP(ip)

	if xff := req.Header.Get("X-Forwarded-For"); len(xff) > 0 && localNet(nip) {
		ip = remoteIP(xff)
	}

	resp := &ipResponse{HTTP: ip, DNS: ""}

	uuid := getUUIDFromDomain(req.Host)

	dns, edns, ok := getCache(uuid)

	if !ok {
		return "", errors.New("UUID not found")
	}

	resp.DNS = dns
	resp.EDNS = edns

	js, err := json.Marshal(resp)
	if err != nil {
		log.Print("JSON ERROR:", err)
		return "", err
	}

	data := storeapi.RequestData{
		TestIP:   *flagip,
		ServerIP: resp.DNS,
		ClientIP: resp.HTTP,
		EdnsNet:  resp.EDNS,
	}
	select {
	case ch <- &data:
	default:
		log.Println("dropped log data, queue full")
	}

	return string(js), nil
}

func redirectUUID(w http.ResponseWriter, req *http.Request) {
	uuid := uuid()
	host := uuid + "." + *flagdomain

	proto := "http"

	if req.TLS != nil || req.Header.Get("X-Forwarded-Proto") == "https" {
		proto = "https"
	}

	http.Redirect(w, req, proto+"://"+host+req.RequestURI, 302)
	return
}

func mainServer(w http.ResponseWriter, req *http.Request) {

	if req.URL.Path == "/jsonp" || req.URL.Path == "/json" || req.URL.Path == "/none" {

		w.Header().Set("Cache-Control", "private, no-cache, no-store, must-revalidate")
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Methods", "GET")

		uuid := getUUIDFromDomain(req.Host)
		if uuid == "www" {
			redirectUUID(w, req)
			return
		}

		js, err := jsonData(req)
		if err != nil {
			log.Printf("redirecting to new uuid, err: %s", err)
			redirectUUID(w, req)
			return
		}

		if req.URL.Path == "/none" {
			w.WriteHeader(204)
			return
		}

		jsonp := req.FormValue("jsonp")
		if len(jsonp) == 0 {
			jsonp = req.FormValue("callback")
		}

		if len(jsonp) > 0 {
			w.Header().Set("Content-Type", "text/javascript")
			io.WriteString(w, jsonp+"("+js+");\n")
			return
		}

		// not jsonp
		w.Header().Set("Content-Type", "application/json")
		io.WriteString(w, js+"\n")
		return

	}

	mapperScript := `
	 (function(global){"use strict";var id=function(){var chars="0123456789abcdefghijklmnopqrstuvxyz".split("");
	 var uuid=[],rnd=Math.random,r;for(var i=0;i<17;i++){if(!uuid[i]){r=0|rnd()*16;uuid[i]=chars[i==19?r&3|8:r&15]}}
	 return uuid.join("")};
	 setTimeout(function(){(new Image).src=location.protocol+"//"+id()+".` +
		*flagdomain +
		`/none"},3200)})(this);
	 `

	if req.URL.Path == "/mapper.js" {
		w.Header().Set("Cache-Control", "public, max-age=86400")
		w.Header().Set("Content-Type", "text/javascript; charset=utf-8")
		w.WriteHeader(200)
		io.WriteString(w, mapperScript)
		return
	}

	if req.URL.Path == "/mapper-v6compat.js" {
		w.Header().Set("Cache-Control", "public, max-age=60")
		w.Header().Set("Content-Type", "text/javascript; charset=utf-8")
		w.WriteHeader(200)
		io.WriteString(w, mapperScript)
		io.WriteString(w, `v6 = { "version": "2", test: function(){} };`)
		return
	}

	if req.URL.Path == "/" {
		w.Header().Set("Cache-Control", "public, max-age=900")
		w.WriteHeader(200)
		io.WriteString(w, HOMEPAGE)
		return
	}

	if req.URL.Path == "/robots.txt" {
		w.Header().Set("Cache-Control", "public, max-age=604800")
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		w.WriteHeader(200)
		io.WriteString(w, "# Hi Robot!\n")
		return
	}

	if req.URL.Path == "/version" {
		io.WriteString(w, `<html><head><title>DNS Mapper `+
			VERSION+`</title><body>`+
			`Hello`+
			`</body></html>`)
		return
	}

	http.NotFound(w, req)
	return
}

func httpHandler() {
	http.HandleFunc("/", mainServer)

	if len(*flagtlskeyfile) > 0 {

		log.Printf("Starting TLS with key='%s' and cert='%s'",
			*flagtlskeyfile,
			*flagtlscrtfile,
		)

		go func() {

			tlsconfig := &tls.Config{
				ClientSessionCache: tls.NewLRUClientSessionCache(100),
				MinVersion:         tls.VersionTLS10,
				CipherSuites: []uint16{
					tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
					tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
					tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
					tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
					tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
					tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
					tls.TLS_RSA_WITH_AES_128_CBC_SHA,
					tls.TLS_RSA_WITH_AES_256_CBC_SHA,
					tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
					tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA},
			}

			tlslisten := *flagip + ":" + *flaghttpsport
			srv := &http.Server{
				Addr:         tlslisten,
				WriteTimeout: 5 * time.Second,
				ReadTimeout:  10 * time.Second,
				TLSConfig:    tlsconfig,
			}
			log.Println("Going to listen for TLS requests on port", tlslisten)
			log.Fatal(srv.ListenAndServeTLS(
				*flagtlscrtfile,
				*flagtlskeyfile,
			))

		}()
	}

	listen := *flagip + ":" + *flaghttpport
	srv := &http.Server{
		Handler:      handlers.CombinedLoggingHandler(os.Stdout, http.DefaultServeMux),
		Addr:         listen,
		WriteTimeout: 5 * time.Second,
		ReadTimeout:  5 * time.Second,
	}
	log.Println("HTTP listen on", listen)
	log.Fatal(srv.ListenAndServe())

}

func localNet(ip net.IP) bool {
	for _, n := range localNets {
		if n.Contains(ip) {
			return true
		}
	}
	return false
}
<|endoftext|>