<commit_before>package common

import (
	"log"

	"engo.io/ecs"
	"engo.io/engo"
	"github.com/engoengine/math"
)

// Cursor is a reference to a GLFW-cursor - to be used with the `SetCursor` method.
type Cursor uint8

const (
	CursorNone = iota
	CursorArrow
	CursorCrosshair
	CursorHand
	CursorIBeam
	CursorHResize
	CursorVResize
)

const MouseSystemPriority = 100

// Mouse is the representation of the physical mouse
type Mouse struct {
	// X is the current x position of the mouse in the game
	X float32
	// Y is the current y position of the mouse in the game
	Y float32
	// ScrollX is the current scrolled position on the x component
	ScrollX float32
	// ScrollY is the current scrolled position on the y component
	ScrollY float32
	// Action is the currently active Action
	Action engo.Action
	// Button is which button is being pressed on the mouse
	Button engo.MouseButton
	// Modifier is whether any modifier mouse buttons are being pressed
	Modifer engo.Modifier
}

// MouseComponent is the location for the MouseSystem to store its results;
// to be used / viewed by other Systems
type MouseComponent struct {
	// Clicked is true whenever the Mouse was clicked over
	// the entity space in this frame
	Clicked bool
	// Released is true whenever the left mouse button is released over the
	// entity space in this frame
	Released bool
	// Hovered is true whenever the Mouse is hovering
	// the entity space in this frame. This does not necessarily imply that
	// the mouse button was pressed down in your entity space.
	Hovered bool
	// Dragged is true whenever the entity space was clicked,
	// and then the mouse started moving (while holding)
	Dragged bool
	// RightClicked is true whenever the entity space was right-clicked
	// in this frame
	RightClicked bool
	// RightReleased is true whenever the right mouse button is released over
	// the entity space in this frame. This does not necessarily imply that
	// the mouse button was pressed down in your entity space.
	RightReleased bool
	// Enter is true whenever the Mouse entered the entity space in that frame,
	// but wasn't in that space during the previous frame
	Enter bool
	// Leave is true whenever the Mouse was in the space on the previous frame,
	// but now isn't
	Leave bool
	// Position of the mouse at any moment this is generally used
	// in conjunction with Track = true
	MouseX float32
	MouseY float32
	// Set manually this to true and your mouse component will track the mouse
	// and your entity will always be able to receive an updated mouse
	// component even if its space is not under the mouse cursor
	// WARNING: you MUST know why you want to use this because it will
	// have serious performance impacts if you have many entities with
	// a MouseComponent in tracking mode.
	// This is ideally used for a really small number of entities
	// that must really be aware of the mouse details event when the
	// mouse is not hovering them
	Track bool
	// Modifier is used to store the eventual modifiers that were pressed during
	// the same time the different click events occurred
	Modifier engo.Modifier

	// startedDragging is used internally to see if *this* is the object that is being dragged
	startedDragging bool
}

type mouseEntity struct {
	*ecs.BasicEntity
	*MouseComponent
	*SpaceComponent
	*RenderComponent
}

// MouseSystem listens for mouse events, and changes value for MouseComponent accordingly
type MouseSystem struct {
	entities []mouseEntity
	world    *ecs.World
	camera   *CameraSystem

	mouseX    float32
	mouseY    float32
	mouseDown bool
}

// Priority returns a priority higher than most, to ensure that this System runs before all others
func (m *MouseSystem) Priority() int { return MouseSystemPriority }

func (m *MouseSystem) New(w *ecs.World) {
	m.world = w

	// First check if the CameraSystem is available
	for _, system := range m.world.Systems() {
		switch sys := system.(type) {
		case *CameraSystem:
			m.camera = sys
		}
	}

	if m.camera == nil {
		log.Println("ERROR: CameraSystem not found - have you added the `RenderSystem` before the `MouseSystem`?")
		return
	}
}

// Add adds a new entity to the MouseSystem.
// * RenderComponent is only required if you're using the HUDShader on this Entity.
// * SpaceComponent is required whenever you want to know specific mouse-events on this Entity (like hover,
//   click, etc.). If you don't need those, then you can omit the SpaceComponent.
// * MouseComponent is always required.
// * BasicEntity is always required.
func (m *MouseSystem) Add(basic *ecs.BasicEntity, mouse *MouseComponent, space *SpaceComponent, render *RenderComponent) {
	m.entities = append(m.entities, mouseEntity{basic, mouse, space, render})
}

func (m *MouseSystem) Remove(basic ecs.BasicEntity) {
	var delete int = -1
	for index, entity := range m.entities {
		if entity.ID() == basic.ID() {
			delete = index
			break
		}
	}
	if delete >= 0 {
		m.entities = append(m.entities[:delete], m.entities[delete+1:]...)
	}
}

func (m *MouseSystem) Update(dt float32) {
	// Translate Mouse.X and Mouse.Y into "game coordinates"
	m.mouseX = engo.Input.Mouse.X*m.camera.z*(engo.GameWidth()/engo.CanvasWidth()) + m.camera.x - (engo.GameWidth()/2)*m.camera.z
	m.mouseY = engo.Input.Mouse.Y*m.camera.z*(engo.GameHeight()/engo.CanvasHeight()) + m.camera.y - (engo.GameHeight()/2)*m.camera.z

	// Rotate if needed
	if m.camera.angle != 0 {
		sin, cos := math.Sincos(m.camera.angle * math.Pi / 180)
		m.mouseX, m.mouseY = m.mouseX*cos+m.mouseY*sin, m.mouseY*cos-m.mouseX*sin
	}

	for _, e := range m.entities {
		// Reset all values except these
		*e.MouseComponent = MouseComponent{
			Track:           e.MouseComponent.Track,
			Hovered:         e.MouseComponent.Hovered,
			startedDragging: e.MouseComponent.startedDragging,
		}

		if e.MouseComponent.Track {
			// track mouse position so that systems that need to stay on the mouse
			// position can do it (think an RTS when placing a new building and
			// you get a ghost building following your mouse until you click to
			// place it somewhere in your world.
			e.MouseComponent.MouseX = m.mouseX
			e.MouseComponent.MouseY = m.mouseY
		}

		mx := m.mouseX
		my := m.mouseY

		if e.SpaceComponent == nil {
			continue // with other entities
		}

		if e.RenderComponent != nil {
			// Hardcoded special case for the HUD | TODO: make generic instead of hardcoding
			if e.RenderComponent.shader == HUDShader || e.RenderComponent.shader == LegacyHUDShader {
				mx = engo.Input.Mouse.X
				my = engo.Input.Mouse.Y
			}
		}

		// If the Mouse component is a tracker we always update it
		// Check if the X-value is within range
		// and if the Y-value is within range

		if e.MouseComponent.Track || e.MouseComponent.startedDragging ||
			e.SpaceComponent.Contains(engo.Point{mx, my}) {

			e.MouseComponent.Enter = !e.MouseComponent.Hovered
			e.MouseComponent.Hovered = true
			e.MouseComponent.Released = false

			if !e.MouseComponent.Track {
				// If we're tracking, we've already set these
				e.MouseComponent.MouseX = mx
				e.MouseComponent.MouseY = my
			}

			switch engo.Input.Mouse.Action {
			case engo.Press:
				switch engo.Input.Mouse.Button {
				case engo.MouseButtonLeft:
					e.MouseComponent.Clicked = true
					e.MouseComponent.startedDragging = true
				case engo.MouseButtonRight:
					e.MouseComponent.RightClicked = true
				}

				m.mouseDown = true
			case engo.Release:
				switch engo.Input.Mouse.Button {
				case engo.MouseButtonLeft:
					e.MouseComponent.Released = true
				case engo.MouseButtonRight:
					e.MouseComponent.RightReleased = true
				}
			case engo.Move:
				if m.mouseDown && e.MouseComponent.startedDragging {
					e.MouseComponent.Dragged = true
				}
			}
		} else {
			if e.MouseComponent.Hovered {
				e.MouseComponent.Leave = true
			}

			e.MouseComponent.Hovered = false
		}

		if engo.Input.Mouse.Action == engo.Release {
			// dragging stops as soon as one of the currently pressed buttons
			// is released
			e.MouseComponent.Dragged = false
			e.MouseComponent.startedDragging = false
			// mouseDown goes false as soon as one of the pressed buttons is
			// released. Effectively ending any dragging
			m.mouseDown = false
		}

		// propagate the modifiers to the mouse component so that game
		// implementers can take different decisions based on those
		e.MouseComponent.Modifier = engo.Input.Mouse.Modifer
	}
}
<commit_msg>MouseSystem now skips hidden entities (#382)<commit_after>package common

import (
	"log"

	"engo.io/ecs"
	"engo.io/engo"
	"github.com/engoengine/math"
)

// Cursor is a reference to a GLFW-cursor - to be used with the `SetCursor` method.
type Cursor uint8

const (
	CursorNone = iota
	CursorArrow
	CursorCrosshair
	CursorHand
	CursorIBeam
	CursorHResize
	CursorVResize
)

const MouseSystemPriority = 100

// Mouse is the representation of the physical mouse
type Mouse struct {
	// X is the current x position of the mouse in the game
	X float32
	// Y is the current y position of the mouse in the game
	Y float32
	// ScrollX is the current scrolled position on the x component
	ScrollX float32
	// ScrollY is the current scrolled position on the y component
	ScrollY float32
	// Action is the currently active Action
	Action engo.Action
	// Button is which button is being pressed on the mouse
	Button engo.MouseButton
	// Modifier is whether any modifier mouse buttons are being pressed
	Modifer engo.Modifier
}

// MouseComponent is the location for the MouseSystem to store its results;
// to be used / viewed by other Systems
type MouseComponent struct {
	// Clicked is true whenever the Mouse was clicked over
	// the entity space in this frame
	Clicked bool
	// Released is true whenever the left mouse button is released over the
	// entity space in this frame
	Released bool
	// Hovered is true whenever the Mouse is hovering
	// the entity space in this frame. This does not necessarily imply that
	// the mouse button was pressed down in your entity space.
	Hovered bool
	// Dragged is true whenever the entity space was clicked,
	// and then the mouse started moving (while holding)
	Dragged bool
	// RightClicked is true whenever the entity space was right-clicked
	// in this frame
	RightClicked bool
	// RightReleased is true whenever the right mouse button is released over
	// the entity space in this frame. This does not necessarily imply that
	// the mouse button was pressed down in your entity space.
	RightReleased bool
	// Enter is true whenever the Mouse entered the entity space in that frame,
	// but wasn't in that space during the previous frame
	Enter bool
	// Leave is true whenever the Mouse was in the space on the previous frame,
	// but now isn't
	Leave bool
	// Position of the mouse at any moment this is generally used
	// in conjunction with Track = true
	MouseX float32
	MouseY float32
	// Set manually this to true and your mouse component will track the mouse
	// and your entity will always be able to receive an updated mouse
	// component even if its space is not under the mouse cursor
	// WARNING: you MUST know why you want to use this because it will
	// have serious performance impacts if you have many entities with
	// a MouseComponent in tracking mode.
	// This is ideally used for a really small number of entities
	// that must really be aware of the mouse details event when the
	// mouse is not hovering them
	Track bool
	// Modifier is used to store the eventual modifiers that were pressed during
	// the same time the different click events occurred
	Modifier engo.Modifier

	// startedDragging is used internally to see if *this* is the object that is being dragged
	startedDragging bool
}

type mouseEntity struct {
	*ecs.BasicEntity
	*MouseComponent
	*SpaceComponent
	*RenderComponent
}

// MouseSystem listens for mouse events, and changes value for MouseComponent accordingly
type MouseSystem struct {
	entities []mouseEntity
	world    *ecs.World
	camera   *CameraSystem

	mouseX    float32
	mouseY    float32
	mouseDown bool
}

// Priority returns a priority higher than most, to ensure that this System runs before all others
func (m *MouseSystem) Priority() int { return MouseSystemPriority }

func (m *MouseSystem) New(w *ecs.World) {
	m.world = w

	// First check if the CameraSystem is available
	for _, system := range m.world.Systems() {
		switch sys := system.(type) {
		case *CameraSystem:
			m.camera = sys
		}
	}

	if m.camera == nil {
		log.Println("ERROR: CameraSystem not found - have you added the `RenderSystem` before the `MouseSystem`?")
		return
	}
}

// Add adds a new entity to the MouseSystem.
// * RenderComponent is only required if you're using the HUDShader on this Entity.
// * SpaceComponent is required whenever you want to know specific mouse-events on this Entity (like hover,
//   click, etc.). If you don't need those, then you can omit the SpaceComponent.
// * MouseComponent is always required.
// * BasicEntity is always required.
func (m *MouseSystem) Add(basic *ecs.BasicEntity, mouse *MouseComponent, space *SpaceComponent, render *RenderComponent) {
	m.entities = append(m.entities, mouseEntity{basic, mouse, space, render})
}

func (m *MouseSystem) Remove(basic ecs.BasicEntity) {
	var delete int = -1
	for index, entity := range m.entities {
		if entity.ID() == basic.ID() {
			delete = index
			break
		}
	}
	if delete >= 0 {
		m.entities = append(m.entities[:delete], m.entities[delete+1:]...)
	}
}

func (m *MouseSystem) Update(dt float32) {
	// Translate Mouse.X and Mouse.Y into "game coordinates"
	m.mouseX = engo.Input.Mouse.X*m.camera.z*(engo.GameWidth()/engo.CanvasWidth()) + m.camera.x - (engo.GameWidth()/2)*m.camera.z
	m.mouseY = engo.Input.Mouse.Y*m.camera.z*(engo.GameHeight()/engo.CanvasHeight()) + m.camera.y - (engo.GameHeight()/2)*m.camera.z

	// Rotate if needed
	if m.camera.angle != 0 {
		sin, cos := math.Sincos(m.camera.angle * math.Pi / 180)
		m.mouseX, m.mouseY = m.mouseX*cos+m.mouseY*sin, m.mouseY*cos-m.mouseX*sin
	}

	for _, e := range m.entities {
		// Reset all values except these
		*e.MouseComponent = MouseComponent{
			Track:           e.MouseComponent.Track,
			Hovered:         e.MouseComponent.Hovered,
			startedDragging: e.MouseComponent.startedDragging,
		}

		if e.MouseComponent.Track {
			// track mouse position so that systems that need to stay on the mouse
			// position can do it (think an RTS when placing a new building and
			// you get a ghost building following your mouse until you click to
			// place it somewhere in your world.
			e.MouseComponent.MouseX = m.mouseX
			e.MouseComponent.MouseY = m.mouseY
		}

		mx := m.mouseX
		my := m.mouseY

		if e.SpaceComponent == nil {
			continue // with other entities
		}

		if e.RenderComponent != nil {
			// Hardcoded special case for the HUD | TODO: make generic instead of hardcoding
			if e.RenderComponent.shader == HUDShader || e.RenderComponent.shader == LegacyHUDShader {
				mx = engo.Input.Mouse.X
				my = engo.Input.Mouse.Y
			}

			if e.RenderComponent.Hidden {
				continue // skip hidden components
			}
		}

		// If the Mouse component is a tracker we always update it
		// Check if the X-value is within range
		// and if the Y-value is within range

		if e.MouseComponent.Track || e.MouseComponent.startedDragging ||
			e.SpaceComponent.Contains(engo.Point{mx, my}) {

			e.MouseComponent.Enter = !e.MouseComponent.Hovered
			e.MouseComponent.Hovered = true
			e.MouseComponent.Released = false

			if !e.MouseComponent.Track {
				// If we're tracking, we've already set these
				e.MouseComponent.MouseX = mx
				e.MouseComponent.MouseY = my
			}

			switch engo.Input.Mouse.Action {
			case engo.Press:
				switch engo.Input.Mouse.Button {
				case engo.MouseButtonLeft:
					e.MouseComponent.Clicked = true
					e.MouseComponent.startedDragging = true
				case engo.MouseButtonRight:
					e.MouseComponent.RightClicked = true
				}

				m.mouseDown = true
			case engo.Release:
				switch engo.Input.Mouse.Button {
				case engo.MouseButtonLeft:
					e.MouseComponent.Released = true
				case engo.MouseButtonRight:
					e.MouseComponent.RightReleased = true
				}
			case engo.Move:
				if m.mouseDown && e.MouseComponent.startedDragging {
					e.MouseComponent.Dragged = true
				}
			}
		} else {
			if e.MouseComponent.Hovered {
				e.MouseComponent.Leave = true
			}

			e.MouseComponent.Hovered = false
		}

		if engo.Input.Mouse.Action == engo.Release {
			// dragging stops as soon as one of the currently pressed buttons
			// is released
			e.MouseComponent.Dragged = false
			e.MouseComponent.startedDragging = false
			// mouseDown goes false as soon as one of the pressed buttons is
			// released. Effectively ending any dragging
			m.mouseDown = false
		}

		// propagate the modifiers to the mouse component so that game
		// implementers can take different decisions based on those
		e.MouseComponent.Modifier = engo.Input.Mouse.Modifer
	}
}
<|endoftext|>


<commit_before>package handlers

import (
	"encoding/json"
	"github.com/didip/mcrouter-hub/libhttp"
	"github.com/didip/mcrouter-hub/payloads"
	"github.com/didip/mcrouter-hub/storage"
	"github.com/gorilla/context"
	"io/ioutil"
	"net/http"
)

func CentralGetRoot(w http.ResponseWriter, r *http.Request) {
	readOnly := context.Get(r, "readOnly").(bool)
	if readOnly {
		w.Write([]byte(`{
    paths: {
        GET: [
            "/configs"
        ]
    }
}`))

	} else {
		w.Write([]byte(`{
    paths: {
        GET: [
            "/configs"
        ],
        POST: [
            "/configs"
        ]
    }
}`))
	}

}

func CentralPostConfigs(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	store := context.Get(r, "store").(*storage.Storage)

	payloadJson, err := ioutil.ReadAll(r.Body)
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	var payload payloads.ReportConfigToCentralPayload
	err = json.Unmarshal(payloadJson, &payload)
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	store.Set("config:"+payload.Hostname, payload.Config)

	libhttp.HandleSuccessJson(w, "Config on host: "+payload.Hostname+" is saved successfully")
}

func CentralGetConfigs(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	store := context.Get(r, "store").(*storage.Storage)

	configs, err := store.ToJson("config:")
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	w.Write(configs)
}

func CentralPostStats(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	store := context.Get(r, "store").(*storage.Storage)

	payloadJson, err := ioutil.ReadAll(r.Body)
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	payload := make(map[string]interface{})
	err = json.Unmarshal(payloadJson, &payload)
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	hostname := ""
	hostnameInterface := payload["hostname"]
	if hostnameInterface != nil {
		hostname = hostnameInterface.(string)
	}

	store.Set("stats:"+hostname, payload)

	libhttp.HandleSuccessJson(w, "Stats on host: "+hostname+" is saved successfully")
}

func CentralGetStats(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	store := context.Get(r, "store").(*storage.Storage)

	stats, err := store.ToJson("stats:")
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	w.Write(stats)
}
<commit_msg>add /stats to root.<commit_after>package handlers

import (
	"encoding/json"
	"github.com/didip/mcrouter-hub/libhttp"
	"github.com/didip/mcrouter-hub/payloads"
	"github.com/didip/mcrouter-hub/storage"
	"github.com/gorilla/context"
	"io/ioutil"
	"net/http"
)

func CentralGetRoot(w http.ResponseWriter, r *http.Request) {
	readOnly := context.Get(r, "readOnly").(bool)
	if readOnly {
		w.Write([]byte(`{
    paths: {
        GET: [
            "/configs",
            "/stats"
        ]
    }
}`))

	} else {
		w.Write([]byte(`{
    paths: {
        GET: [
            "/configs",
            "/stats"
        ],
        POST: [
            "/configs",
            "/stats"
        ]
    }
}`))
	}

}

func CentralPostConfigs(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	store := context.Get(r, "store").(*storage.Storage)

	payloadJson, err := ioutil.ReadAll(r.Body)
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	var payload payloads.ReportConfigToCentralPayload
	err = json.Unmarshal(payloadJson, &payload)
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	store.Set("config:"+payload.Hostname, payload.Config)

	libhttp.HandleSuccessJson(w, "Config on host: "+payload.Hostname+" is saved successfully")
}

func CentralGetConfigs(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	store := context.Get(r, "store").(*storage.Storage)

	configs, err := store.ToJson("config:")
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	w.Write(configs)
}

func CentralPostStats(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	store := context.Get(r, "store").(*storage.Storage)

	payloadJson, err := ioutil.ReadAll(r.Body)
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	payload := make(map[string]interface{})
	err = json.Unmarshal(payloadJson, &payload)
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	hostname := ""
	hostnameInterface := payload["hostname"]
	if hostnameInterface != nil {
		hostname = hostnameInterface.(string)
	}

	store.Set("stats:"+hostname, payload)

	libhttp.HandleSuccessJson(w, "Stats on host: "+hostname+" is saved successfully")
}

func CentralGetStats(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	store := context.Get(r, "store").(*storage.Storage)

	stats, err := store.ToJson("stats:")
	if err != nil {
		libhttp.HandleErrorJson(w, err)
		return
	}

	w.Write(stats)
}
<|endoftext|>


<commit_before>// +build windows

package main

import (
	"context"
	"flag"
	"fmt"
	"time"

	"gopkg.in/dfsr.v0/config"
	"gopkg.in/dfsr.v0/monitor"
	"gopkg.in/dfsr.v0/monitor/consumer/stathatconsumer"

	"golang.org/x/sys/windows/svc"
	"golang.org/x/sys/windows/svc/debug"
	"golang.org/x/sys/windows/svc/eventlog"
)

var elog debug.Log

type dfsrmonitor struct{}

const acceptedCmds = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue

func (m *dfsrmonitor) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
	changes <- svc.Status{State: svc.StartPending}

	// TODO: Move all of this initialization code into its own goroutine with a context for cancellation

	// Step 1: Parse settings
	settings := environment.Settings
	if !environment.IsInteractive {
		elog.Info(1, fmt.Sprintf("Service Args: %v", args))
		settings.Parse(args[1:], flag.ExitOnError)
		elog.Info(1, fmt.Sprintf("Service Settings: %+v", settings))
	}

	// Step 2: Create and start configuration monitor
	elog.Info(EventInitProgress, "Creating configuration monitor.")
	cfg := config.NewDomainMonitor(settings.Domain, settings.ConfigPollingInterval)
	if err := cfg.Start(); err != nil {
		elog.Error(EventInitFailure, fmt.Sprintf("Configuration initialization failure: %v", err))
		return true, ErrConfigInitFailure
	}
	defer cfg.Close()

	cfg.Update()
	if err := cfg.WaitReady(); err != nil { // TODO: Support some sort of timeout
		elog.Error(EventInitFailure, fmt.Sprintf("Configuration initialization failure: %v", err))
		return true, ErrConfigInitFailure
	}

	// Step 3: Create backlog monitor
	elog.Info(EventInitProgress, "Creating backlog monitor.")
	mon := monitor.New(cfg, settings.BacklogPollingInterval, settings.VectorCacheDuration, settings.Limit)
	monChan := mon.Listen(16)

	// Step 4: Create backlog consumers
	if settings.StatHatKey != "" {
		stathatconsumer.New(settings.StatHatKey, settings.StatHatFormat, mon.Listen(16))
	}

	// Step 5: Start backlog monitor
	if err := mon.Start(); err != nil {
		elog.Error(EventInitFailure, fmt.Sprintf("Monitor initialization failure: %v", err))
		return true, 1
	}
	defer mon.Close()

	elog.Info(EventInitComplete, "Initialization complete.")

	changes <- svc.Status{State: svc.Running, Accepts: acceptedCmds}

	mon.Update() // Kick off an initial poll right away

	for {
		select {
		case update, running := <-monChan:
			if !running {
				return
			}
			go watchUpdate(update)
		case c := <-r:
			switch c.Cmd {
			case svc.Interrogate:
				changes <- c.CurrentStatus
				// Testing deadlock from https://code.google.com/p/winsvc/issues/detail?id=4
				time.Sleep(100 * time.Millisecond)
				changes <- c.CurrentStatus
			case svc.Stop, svc.Shutdown:
				changes <- svc.Status{State: svc.StopPending}
				elog.Info(1, "Received stop command. Stopping service.")
				go func() {
					mon.Close()
					elog.Info(1, "Service stopped.")
				}()
			case svc.Pause:
				changes <- svc.Status{State: svc.Paused, Accepts: acceptedCmds}
				elog.Info(1, "Received pause command. Pausing service.")
				go func() {
					mon.Stop()
					elog.Info(1, "Service paused.")
				}()
			case svc.Continue:
				changes <- svc.Status{State: svc.Running, Accepts: acceptedCmds}
				//elog.Info(1, "Continued")
				elog.Info(1, "Received continue command. Unpausing service.")
				go func() {
					mon.Start()
					elog.Info(1, "Service unpaused.")
				}()
			default:
				elog.Error(1, fmt.Sprintf("Unexpected control request #%d", c))
			}
		}
	}
}

func runService(env *Environment) {
	var err error
	if env.IsDebug {
		elog = debug.New(env.ServiceName)
	} else {
		elog, err = eventlog.Open(env.ServiceName)
		if err != nil {
			return
		}
	}
	defer elog.Close()

	elog.Info(1, fmt.Sprintf("Starting %s service.", env.ServiceName))
	run := svc.Run
	if env.IsDebug {
		run = debug.Run
	}
	err = run(env.ServiceName, &dfsrmonitor{})
	if err != nil {
		elog.Error(1, fmt.Sprintf("Failed to start %s service: %v", env.ServiceName, err))
		return
	}
	elog.Info(1, fmt.Sprintf("Stopped %s service.", env.ServiceName))
}

func watchUpdate(update *monitor.Update) {
	elog.Info(1, fmt.Sprintf("Polling started at %v", update.Start()))
	for backlog := range update.Listen() {
		if backlog.Err != nil {
			if !isCancellationErr(backlog.Err) {
				elog.Warning(1, fmt.Sprintf("[%s] Backlog from %s to %s: %v", backlog.Group.Name, backlog.From, backlog.To, backlog.Err))
			}
			continue
		}
		if !backlog.IsZero() {
			elog.Info(1, fmt.Sprintf("[%s] Backlog from %s to %s: %v", backlog.Group.Name, backlog.From, backlog.To, backlog.Sum()))
		}
	}
	elog.Info(1, fmt.Sprintf("Polling finished at %v. Total wall time: %v", update.End(), update.Duration()))
}

func isCancellationErr(err error) bool {
	switch err {
	case context.Canceled, context.DeadlineExceeded:
		return true
	default:
		return false
	}
}
<commit_msg>Added backlog counts to dfsrmonitor log entries<commit_after>// +build windows

package main

import (
	"context"
	"flag"
	"fmt"
	"strconv"
	"time"

	"gopkg.in/dfsr.v0/config"
	"gopkg.in/dfsr.v0/monitor"
	"gopkg.in/dfsr.v0/monitor/consumer/stathatconsumer"

	"golang.org/x/sys/windows/svc"
	"golang.org/x/sys/windows/svc/debug"
	"golang.org/x/sys/windows/svc/eventlog"
)

var elog debug.Log

type dfsrmonitor struct{}

const acceptedCmds = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue

const updateChanSize = 16

func (m *dfsrmonitor) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
	changes <- svc.Status{State: svc.StartPending}

	// TODO: Move all of this initialization code into its own goroutine with a context for cancellation

	// Step 1: Parse settings
	settings := environment.Settings
	if !environment.IsInteractive {
		elog.Info(1, fmt.Sprintf("Service Args: %v", args))
		settings.Parse(args[1:], flag.ExitOnError)
		elog.Info(1, fmt.Sprintf("Service Settings: %+v", settings))
	}

	// Step 2: Create and start configuration monitor
	elog.Info(EventInitProgress, "Creating configuration monitor.")
	cfg := config.NewDomainMonitor(settings.Domain, settings.ConfigPollingInterval)
	if err := cfg.Start(); err != nil {
		elog.Error(EventInitFailure, fmt.Sprintf("Configuration initialization failure: %v", err))
		return true, ErrConfigInitFailure
	}
	defer cfg.Close()

	cfg.Update()
	if err := cfg.WaitReady(); err != nil { // TODO: Support some sort of timeout
		elog.Error(EventInitFailure, fmt.Sprintf("Configuration initialization failure: %v", err))
		return true, ErrConfigInitFailure
	}

	// Step 3: Create backlog monitor
	elog.Info(EventInitProgress, "Creating backlog monitor.")
	mon := monitor.New(cfg, settings.BacklogPollingInterval, settings.VectorCacheDuration, settings.Limit)
	monChan := mon.Listen(updateChanSize)

	// Step 4: Create backlog consumers
	if settings.StatHatKey != "" {
		stathatconsumer.New(settings.StatHatKey, settings.StatHatFormat, mon.Listen(updateChanSize))
	}

	// Step 5: Start backlog monitor
	if err := mon.Start(); err != nil {
		elog.Error(EventInitFailure, fmt.Sprintf("Monitor initialization failure: %v", err))
		return true, 1
	}
	defer mon.Close()

	elog.Info(EventInitComplete, "Initialization complete.")

	changes <- svc.Status{State: svc.Running, Accepts: acceptedCmds}

	mon.Update() // Kick off an initial poll right away

	for {
		select {
		case update, running := <-monChan:
			if !running {
				return
			}
			go watchUpdate(update)
		case c := <-r:
			switch c.Cmd {
			case svc.Interrogate:
				changes <- c.CurrentStatus
				// Testing deadlock from https://code.google.com/p/winsvc/issues/detail?id=4
				time.Sleep(100 * time.Millisecond)
				changes <- c.CurrentStatus
			case svc.Stop, svc.Shutdown:
				changes <- svc.Status{State: svc.StopPending}
				elog.Info(1, "Received stop command. Stopping service.")
				go func() {
					mon.Close()
					elog.Info(1, "Service stopped.")
				}()
			case svc.Pause:
				changes <- svc.Status{State: svc.Paused, Accepts: acceptedCmds}
				elog.Info(1, "Received pause command. Pausing service.")
				go func() {
					mon.Stop()
					elog.Info(1, "Service paused.")
				}()
			case svc.Continue:
				changes <- svc.Status{State: svc.Running, Accepts: acceptedCmds}
				//elog.Info(1, "Continued")
				elog.Info(1, "Received continue command. Unpausing service.")
				go func() {
					mon.Start()
					elog.Info(1, "Service unpaused.")
				}()
			default:
				elog.Error(1, fmt.Sprintf("Unexpected control request #%d", c))
			}
		}
	}
}

func runService(env *Environment) {
	var err error
	if env.IsDebug {
		elog = debug.New(env.ServiceName)
	} else {
		elog, err = eventlog.Open(env.ServiceName)
		if err != nil {
			return
		}
	}
	defer elog.Close()

	elog.Info(1, fmt.Sprintf("Starting %s service.", env.ServiceName))
	run := svc.Run
	if env.IsDebug {
		run = debug.Run
	}
	err = run(env.ServiceName, &dfsrmonitor{})
	if err != nil {
		elog.Error(1, fmt.Sprintf("Failed to start %s service: %v", env.ServiceName, err))
		return
	}
	elog.Info(1, fmt.Sprintf("Stopped %s service.", env.ServiceName))
}

func watchUpdate(update *monitor.Update) {
	var (
		i, size = 0, update.Size()
		len     = len(strconv.Itoa(size))
	)

	elog.Info(1, fmt.Sprintf("Polling started at %v", update.Start()))
	for backlog := range update.Listen() {
		i++
		if backlog.Err != nil {
			if !isCancellationErr(backlog.Err) {
				elog.Warning(1, fmt.Sprintf("[%*d/%*d] %s backlog from %s to %s: %v", len, i, len, size, backlog.Group.Name, backlog.From, backlog.To, backlog.Err))
			}
			continue
		}
		if !backlog.IsZero() {
			elog.Info(1, fmt.Sprintf("[%*d/%*d] %s backlog from %s to %s: %v", len, i, len, size, backlog.Group.Name, backlog.From, backlog.To, backlog.Sum()))
		}
	}
	elog.Info(1, fmt.Sprintf("Polling finished at %v. Total wall time: %v", update.End(), update.Duration()))
}

func isCancellationErr(err error) bool {
	switch err {
	case context.Canceled, context.DeadlineExceeded:
		return true
	default:
		return false
	}
}
<|endoftext|>


<commit_before>package common

import (
	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netns"
	"net"
	"runtime"
	"strings"
)

// Assert test is true, panic otherwise
func Assert(test bool) {
	if !test {
		panic("Assertion failure")
	}
}

func ErrorMessages(errors []error) string {
	var result []string
	for _, err := range errors {
		result = append(result, err.Error())
	}
	return strings.Join(result, "\n")
}

func WithNetNS(ns netns.NsHandle, work func() error) error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	oldNs, err := netns.Get()
	if err == nil {
		defer oldNs.Close()

		err = netns.Set(ns)
		if err == nil {
			defer netns.Set(oldNs)

			err = work()
		}
	}

	return err
}

type NetDev struct {
	MAC   net.HardwareAddr
	CIDRs []*net.IPNet
}

// Search the network namespace of a process for interfaces matching a predicate
func FindNetDevs(processID int, match func(string) bool) ([]NetDev, error) {
	var netDevs []NetDev

	ns, err := netns.GetFromPid(processID)
	if err != nil {
		return nil, err
	}
	defer ns.Close()

	err = WithNetNS(ns, func() error {
		links, err := netlink.LinkList()
		if err != nil {
			return err
		}
		for _, link := range links {
			if match(link.Attrs().Name) {
				addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
				if err != nil {
					return err
				}

				netDev := NetDev{MAC: link.Attrs().HardwareAddr}
				for _, addr := range addrs {
					netDev.CIDRs = append(netDev.CIDRs, addr.IPNet)
				}
				netDevs = append(netDevs, netDev)
			}
		}
		return nil
	})

	return netDevs, err
}

// Lookup the weave interface of a container
func GetWeaveNetDevs(processID int) ([]NetDev, error) {
	return FindNetDevs(processID, func(name string) bool {
		return strings.HasPrefix(name, "ethwe")
	})
}

// Get the weave bridge interface
func GetBridgeNetDev(bridgeName string) ([]NetDev, error) {
	return FindNetDevs(1, func(name string) bool {
		return name == bridgeName
	})
}
<commit_msg>Refactor FindNetDevs so we can get the link, and re-use parts of the function<commit_after>package common

import (
	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netns"
	"net"
	"runtime"
	"strings"
)

// Assert test is true, panic otherwise
func Assert(test bool) {
	if !test {
		panic("Assertion failure")
	}
}

func ErrorMessages(errors []error) string {
	var result []string
	for _, err := range errors {
		result = append(result, err.Error())
	}
	return strings.Join(result, "\n")
}

func WithNetNS(ns netns.NsHandle, work func() error) error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	oldNs, err := netns.Get()
	if err == nil {
		defer oldNs.Close()

		err = netns.Set(ns)
		if err == nil {
			defer netns.Set(oldNs)

			err = work()
		}
	}

	return err
}

type NetDev struct {
	MAC   net.HardwareAddr
	CIDRs []*net.IPNet
}

// Search the network namespace of a process for interfaces matching a predicate
func FindNetDevs(processID int, match func(link netlink.Link) bool) ([]NetDev, error) {
	var netDevs []NetDev

	ns, err := netns.GetFromPid(processID)
	if err != nil {
		return nil, err
	}
	defer ns.Close()

	err = WithNetNS(ns, func() error {
		return forEachLink(func(link netlink.Link) error {
			if match(link) {
				netDev, err := linkToNetDev(link)
				if err != nil {
					return err
				}
				netDevs = append(netDevs, *netDev)
			}
			return nil
		})
	})

	return netDevs, err
}

func forEachLink(f func(netlink.Link) error) error {
	links, err := netlink.LinkList()
	if err != nil {
		return err
	}
	for _, link := range links {
		if err := f(link); err != nil {
			return err
		}
	}
	return nil
}

func linkToNetDev(link netlink.Link) (*NetDev, error) {
	addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
	if err != nil {
		return nil, err
	}

	netDev := &NetDev{MAC: link.Attrs().HardwareAddr}
	for _, addr := range addrs {
		netDev.CIDRs = append(netDev.CIDRs, addr.IPNet)
	}
	return netDev, nil
}

// Lookup the weave interface of a container
func GetWeaveNetDevs(processID int) ([]NetDev, error) {
	return FindNetDevs(processID, func(link netlink.Link) bool {
		return strings.HasPrefix(link.Attrs().Name, "ethwe")
	})
}

// Get the weave bridge interface
func GetBridgeNetDev(bridgeName string) ([]NetDev, error) {
	return FindNetDevs(1, func(link netlink.Link) bool {
		return link.Attrs().Name == bridgeName
	})
}
<|endoftext|>


<commit_before>package common

import (
	mesos "github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	"sort"
)

// The new value for the resource, the ask, and whether or not the ask was accomodated - the ask may be nil if it wasn't accomodated
type ResourceAsker (func([]*mesos.Resource) ([]*mesos.Resource, *mesos.Resource, bool))

func AskForScalar(resourceName string, askSize float64) ResourceAsker {
	return func(resources []*mesos.Resource) ([]*mesos.Resource, *mesos.Resource, bool) {
		newResources := make([]*mesos.Resource, len(resources))
		copy(newResources, resources)
		for idx, resource := range resources {
			if resource.GetName() == resourceName && askSize <= resource.GetScalar().GetValue() {
				newResources[idx] = util.NewScalarResource(resourceName, resource.GetScalar().GetValue()-askSize)
				ask := util.NewScalarResource(resourceName, askSize)
				return newResources, ask, true
			}
		}
		return newResources, nil, false
	}
}
func AskForCPU(cpuAsk float64) ResourceAsker {
	return AskForScalar("cpus", cpuAsk)
}

func AskForMemory(memory float64) ResourceAsker {
	return AskForScalar("mem", memory)

}

type intarray []int64

func (a intarray) Len() int           { return len(a) }
func (a intarray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a intarray) Less(i, j int) bool { return a[i] < a[j] }

// We assume the input is sorted
func arrayToRanges(ports []int64) []*mesos.Value_Range {
	sort.Sort(intarray(ports))
	if len(ports) == 0 {
		return []*mesos.Value_Range{}
	}
	fakeret := [][]int64{[]int64{ports[0], ports[0]}}
	for _, val := range ports {
		if val > fakeret[len(fakeret)-1][1]+1 {
			fakeret = append(fakeret, []int64{val, val})
		} else {
			fakeret[len(fakeret)-1][1] = val
		}
	}
	ret := make([]*mesos.Value_Range, len(fakeret))
	for idx := range fakeret {
		ret[idx] = util.NewValueRange(uint64(fakeret[idx][0]), uint64(fakeret[idx][1]))
	}
	return ret
}
func rangesToArray(ranges []*mesos.Value_Range) []int64 {
	array := make([]int64, 0)
	for _, mesosRange := range ranges {
		temp := make([]int64, mesosRange.GetEnd()-mesosRange.GetBegin()+1)
		idx := 0
		for i := mesosRange.GetBegin(); i <= mesosRange.GetEnd(); i++ {
			temp[idx] = int64(i)
			idx++
		}
		array = append(array, temp...)
	}
	return array
}

func AskForPorts(portCount int) ResourceAsker {
	ret := func(resources []*mesos.Resource) ([]*mesos.Resource, *mesos.Resource, bool) {
		newResources := make([]*mesos.Resource, len(resources))
		copy(newResources, resources)
		for idx, resource := range resources {
			if resource.GetName() == "ports" {
				ports := rangesToArray(resource.GetRanges().GetRange())
				// Now we have to see if there are N ports
				if len(ports) >= portCount {
					takingPorts := ports[:portCount]
					leavingPorts := ports[portCount:]
					newResources[idx] = util.NewRangesResource("ports", arrayToRanges(leavingPorts))
					ask := util.NewRangesResource("ports", arrayToRanges(takingPorts))
					return newResources, ask, true
				}
			}
		}
		return resources, nil, false
	}
	return ret
}
<commit_msg>Add disk to resource askers<commit_after>package common

import (
	mesos "github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	"sort"
)

// The new value for the resource, the ask, and whether or not the ask was accomodated - the ask may be nil if it wasn't accomodated
type ResourceAsker (func([]*mesos.Resource) ([]*mesos.Resource, *mesos.Resource, bool))

func AskForScalar(resourceName string, askSize float64) ResourceAsker {
	return func(resources []*mesos.Resource) ([]*mesos.Resource, *mesos.Resource, bool) {
		newResources := make([]*mesos.Resource, len(resources))
		copy(newResources, resources)
		for idx, resource := range resources {
			if resource.GetName() == resourceName && askSize <= resource.GetScalar().GetValue() {
				newResources[idx] = util.NewScalarResource(resourceName, resource.GetScalar().GetValue()-askSize)
				ask := util.NewScalarResource(resourceName, askSize)
				return newResources, ask, true
			}
		}
		return newResources, nil, false
	}
}
func AskForCPU(cpuAsk float64) ResourceAsker {
	return AskForScalar("cpus", cpuAsk)
}

func AskForMemory(memory float64) ResourceAsker {
	return AskForScalar("mem", memory)

}

func AskForDisk(disk float64) ResourceAsker {
	return AskForScalar("disk", disk)

}

type intarray []int64

func (a intarray) Len() int           { return len(a) }
func (a intarray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a intarray) Less(i, j int) bool { return a[i] < a[j] }

// We assume the input is sorted
func arrayToRanges(ports []int64) []*mesos.Value_Range {
	sort.Sort(intarray(ports))
	if len(ports) == 0 {
		return []*mesos.Value_Range{}
	}
	fakeret := [][]int64{[]int64{ports[0], ports[0]}}
	for _, val := range ports {
		if val > fakeret[len(fakeret)-1][1]+1 {
			fakeret = append(fakeret, []int64{val, val})
		} else {
			fakeret[len(fakeret)-1][1] = val
		}
	}
	ret := make([]*mesos.Value_Range, len(fakeret))
	for idx := range fakeret {
		ret[idx] = util.NewValueRange(uint64(fakeret[idx][0]), uint64(fakeret[idx][1]))
	}
	return ret
}
func rangesToArray(ranges []*mesos.Value_Range) []int64 {
	array := make([]int64, 0)
	for _, mesosRange := range ranges {
		temp := make([]int64, mesosRange.GetEnd()-mesosRange.GetBegin()+1)
		idx := 0
		for i := mesosRange.GetBegin(); i <= mesosRange.GetEnd(); i++ {
			temp[idx] = int64(i)
			idx++
		}
		array = append(array, temp...)
	}
	return array
}

func AskForPorts(portCount int) ResourceAsker {
	ret := func(resources []*mesos.Resource) ([]*mesos.Resource, *mesos.Resource, bool) {
		newResources := make([]*mesos.Resource, len(resources))
		copy(newResources, resources)
		for idx, resource := range resources {
			if resource.GetName() == "ports" {
				ports := rangesToArray(resource.GetRanges().GetRange())
				// Now we have to see if there are N ports
				if len(ports) >= portCount {
					takingPorts := ports[:portCount]
					leavingPorts := ports[portCount:]
					newResources[idx] = util.NewRangesResource("ports", arrayToRanges(leavingPorts))
					ask := util.NewRangesResource("ports", arrayToRanges(takingPorts))
					return newResources, ask, true
				}
			}
		}
		return resources, nil, false
	}
	return ret
}
<|endoftext|>


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

package w32

import (
	"errors"
	"syscall"
	"unsafe"
)

var (
	modkernel32 = syscall.NewLazyDLL("ntdll.dll")

	procNtAlpcCreatePort = modadvapi32.NewProc("NtAlpcCreatePort")
)

func newUnicodeString(s string) (us UNICODE_STRING, e error) {
	ustr, err := syscall.UTF16FromString(s)
	if err != nil {
		e = err
		return
	}
	us.Length = len(ustr)
	us.MaximumLength = len(ustr)
	us.Buffer = unsafe.Pointer(&ustr[0])
	return
}

// (this is a macro)
// VOID InitializeObjectAttributes(
//   [out]           POBJECT_ATTRIBUTES InitializedAttributes,
//   [in]            PUNICODE_STRING ObjectName,
//   [in]            ULONG Attributes,
//   [in]            HANDLE RootDirectory,
//   [in, optional]  PSECURITY_DESCRIPTOR SecurityDescriptor
// )
func NewObjectAttributes(
	name string,
	attributes uint32,
	rootDir HANDLE,
	pSecurityDescriptor *SECURITY_DESCRIPTOR,
) (objectAttributes OBJECT_ATTRIBUTES, e error) {

	unicodeString, err := newUnicodeString(name)
	if err != nil {
		e = err
		return
	}

	objectAttributes = OBJECT_ATTRIBUTES{
		RootDirectory:      rootDir,
		ObjectName:         &unicodeString,
		Attributes:         attributes,
		SecurityDescriptor: pSecurityDescriptor,
	}
	return
}

// # NTSTATUS
// # NtAlpcCreatePort(
// #   __out PHANDLE PortHandle,
// #   __in POBJECT_ATTRIBUTES ObjectAttributes,
// #   __in_opt PALPC_PORT_ATTRIBUTES PortAttributes
// #   );
func NtAlpcCreatePort(pObjectAttributes *OBJECT_ATTRIBUTES, pPortAttributes *ALPC_PORT_ATTRIBUTES) (hPort HANDLE, e error) {

	pHandle := &hPort
	ret, _, _ := procNtAlpcCreatePort.Call(
		uintptr(unsafe.Pointer(pHandle)),
		uintptr(unsafe.Pointer(pObjectAttributes)),
		uintptr(unsafe.Pointer(pPortAttributes)),
	)
	if ret != ERROR_SUCCESS {
		return hPort, errors.New(ret)
	}

	return
}
<commit_msg>bugfix<commit_after>// Copyright 2010-2012 The W32 Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package w32

import (
	"errors"
	"syscall"
	"unsafe"
)

var (
	modntdll = syscall.NewLazyDLL("ntdll.dll")

	procNtAlpcCreatePort = modntdll.NewProc("NtAlpcCreatePort")
)

func newUnicodeString(s string) (us UNICODE_STRING, e error) {
	ustr, err := syscall.UTF16FromString(s)
	if err != nil {
		e = err
		return
	}
	us.Length = len(ustr)
	us.MaximumLength = len(ustr)
	us.Buffer = unsafe.Pointer(&ustr[0])
	return
}

// (this is a macro)
// VOID InitializeObjectAttributes(
//   [out]           POBJECT_ATTRIBUTES InitializedAttributes,
//   [in]            PUNICODE_STRING ObjectName,
//   [in]            ULONG Attributes,
//   [in]            HANDLE RootDirectory,
//   [in, optional]  PSECURITY_DESCRIPTOR SecurityDescriptor
// )
func NewObjectAttributes(
	name string,
	attributes uint32,
	rootDir HANDLE,
	pSecurityDescriptor *SECURITY_DESCRIPTOR,
) (objectAttributes OBJECT_ATTRIBUTES, e error) {

	unicodeString, err := newUnicodeString(name)
	if err != nil {
		e = err
		return
	}

	objectAttributes = OBJECT_ATTRIBUTES{
		RootDirectory:      rootDir,
		ObjectName:         &unicodeString,
		Attributes:         attributes,
		SecurityDescriptor: pSecurityDescriptor,
	}
	return
}

// # NTSTATUS
// # NtAlpcCreatePort(
// #   __out PHANDLE PortHandle,
// #   __in POBJECT_ATTRIBUTES ObjectAttributes,
// #   __in_opt PALPC_PORT_ATTRIBUTES PortAttributes
// #   );
func NtAlpcCreatePort(pObjectAttributes *OBJECT_ATTRIBUTES, pPortAttributes *ALPC_PORT_ATTRIBUTES) (hPort HANDLE, e error) {

	pHandle := &hPort
	ret, _, _ := procNtAlpcCreatePort.Call(
		uintptr(unsafe.Pointer(pHandle)),
		uintptr(unsafe.Pointer(pObjectAttributes)),
		uintptr(unsafe.Pointer(pPortAttributes)),
	)
	if ret != ERROR_SUCCESS {
		return hPort, errors.New(ret)
	}

	return
}
<|endoftext|>


<commit_before>package api

import (
	"testing"
	"math/rand"
	"io/ioutil"
	"os"
)

func TestTriggers(t *testing.T) {
	var err error

	err = triggerNewTagHandler("/bin/echo", "tag")
	if err != nil {
		t.Fatal(err)
	}

	err = triggerUploadedFileHandler("/bin/echo", "tag", "filename")
	if err != nil {
		t.Fatal(err)
	}

	err = triggerExpiredTagHandler("/bin/echo", "tag")
	if err != nil {
		t.Fatal(err)
	}
}

func TestSha256Sum(t *testing.T) {
	file, err := ioutil.TempFile(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}

	defer os.Remove(file.Name())
	file.WriteString("some content")
	file.Sync()
	checksum, err := sha256sum(file.Name())
	if err != nil {
		t.Fatal(err)
	}

	if checksum != "290f493c44f5d63d06b374d0a5abd292fae38b92cab2fae5efefe1b0e9347f56" {
		t.Fatal("Invalid checksum", checksum)
	}
}

func TestIsDir(t *testing.T) {
	if isDir("/etc") == false {
		t.Fatal("Unable to detect /etc as a directory")
	}

	if isDir("/unknowndirectory") != false {
		t.Fatal("Non existing path should not be a directory")
	}

	file, err := ioutil.TempFile(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(file.Name())
	if isDir(file.Name()) != false {
		t.Fatal("File", file.Name(), "is not a directory")
	}
}

func TestRandomString(t *testing.T) {
	rand.Seed(1)
	str := randomString(16)
	if str != "fpllngzieyoh43e0" {
		t.Fatal("Random string from known seed is not", str)
	}
}

func TestSanitizeFilename(t *testing.T) {
	var str string
	str = sanitizeFilename("foo")
	if str != "foo" {
		t.Fatal("Sanitizing failed:", str)
	}

	str = sanitizeFilename(" foo!\"#$%&()= ")
	if str != "foo________=" {
		t.Fatal("Sanitizing failed:", str)
	}

	str = sanitizeFilename("/foo/bar/baz")
	if str != "baz" {
		t.Fatal("Sanitizing failed:", str)
	}
}

func TestValidTag(t *testing.T) {
	if validTag("s") == true {
		t.Fatal("Too short tag")
	}

	if validTag("s ") == true {
		t.Fatal("Tag contains whitespace")
	}

	if validTag("/foo/bar") == true {
		t.Fatal("Tag contains invalid characters")
	}

	if validTag("../foo") == true {
		t.Fatal("Tag contains invalid characters")
	}
}

func TestEnsureDirectoryExists(t *testing.T) {
	// Use TempDir to figure out the path to a valid directory
	dir, err := ioutil.TempDir(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}
	// Remove the directory and keep the path
	err = os.Remove(dir)
	if err != nil {
		t.Fatal(err)
	}

	// Try to create the directory using our function
	err = ensureDirectoryExists(dir)
	if err != nil {
		t.Fatal("This directory cannot be created:", err)
	}
}

func TestWriteToFile(t *testing.T) {
	file, err := ioutil.TempFile(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}
	os.Remove(file.Name())

	//nBytes, err := writeToFile(file.Name(), content)
	//if err != nil {
	//	t.Fatal(err)
	//}
	//if nBytes != 6 {
	//	t.Fatal("The amount of bytes was unexpected:", nBytes)
	//}

}

func TestDetectMIME(t *testing.T) {
	var mime string
	var err error

	mime, err = detectMIME("testing/image.png")
	if err != nil {
		t.Fatal(err)
	}
	if mime != "image/png" {
		t.Fatal("Unable to detect mime type:", mime)
	}

	mime, err = detectMIME("testing/image.jpg")
	if err != nil {
		t.Fatal(err)
	}
	if mime != "image/jpeg" {
		t.Fatal("Unable to detect mime type:", mime)
	}

	mime, err = detectMIME("testing/image.gif")
	if err != nil {
		t.Fatal(err)
	}
	if mime != "image/gif" {
		t.Fatal("Unable to detect mime type:", mime)
	}
}
<commit_msg>Add more tests<commit_after>package api

import (
	"testing"
	"math/rand"
	"io/ioutil"
	"os"
)

func TestTriggers(t *testing.T) {
	var err error

	err = triggerNewTagHandler("/bin/echo", "tag")
	if err != nil {
		t.Fatal(err)
	}

	err = triggerUploadedFileHandler("/bin/echo", "tag", "filename")
	if err != nil {
		t.Fatal(err)
	}

	err = triggerExpiredTagHandler("/bin/echo", "tag")
	if err != nil {
		t.Fatal(err)
	}

	err = triggerNewTagHandler("unknowncommand", "tag")
	if err == nil {
		t.Fatal("This should fail")
	}

	err = triggerUploadedFileHandler("unknowncommand", "tag", "filename")
	if err == nil {
		t.Fatal("This should fail")
	}

	err = triggerExpiredTagHandler("unknowncommand", "tag")
	if err == nil {
		t.Fatal("This should fail")
	}
}

func TestSha256Sum(t *testing.T) {
	file, err := ioutil.TempFile(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}

	defer os.Remove(file.Name())
	file.WriteString("some content")
	file.Sync()
	checksum, err := sha256sum(file.Name())
	if err != nil {
		t.Fatal(err)
	}

	if checksum != "290f493c44f5d63d06b374d0a5abd292fae38b92cab2fae5efefe1b0e9347f56" {
		t.Fatal("Invalid checksum", checksum)
	}

	checksum, err = sha256sum("unknownfile")
	if err == nil {
		t.Fatal("This should fail")
	}
}

func TestIsDir(t *testing.T) {
	dir, err := ioutil.TempDir(os.TempDir(), "prefix")
	defer os.Remove(dir)
	if err != nil {
		t.Fatal(err)
	}
	if isDir(dir) != true {
		t.Fatal("Unable to detect " + dir + " as a directory")
	}

	if isDir("/unknowndirectory") != false {
		t.Fatal("Non existing path should not be a directory")
	}

	file, err := ioutil.TempFile(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(file.Name())
	if isDir(file.Name()) != false {
		t.Fatal("File", file.Name(), "is not a directory")
	}
}

func TestRandomString(t *testing.T) {
	rand.Seed(1)
	str := randomString(16)
	if str != "fpllngzieyoh43e0" {
		t.Fatal("Random string from known seed is not", str)
	}
}

func TestSanitizeFilename(t *testing.T) {
	var str string
	str = sanitizeFilename("foo")
	if str != "foo" {
		t.Fatal("Sanitizing failed:", str)
	}

	str = sanitizeFilename(" foo!\"#$%&()= ")
	if str != "foo________=" {
		t.Fatal("Sanitizing failed:", str)
	}

	str = sanitizeFilename("/foo/bar/baz")
	if str != "baz" {
		t.Fatal("Sanitizing failed:", str)
	}
}

func TestValidTag(t *testing.T) {
	if validTag("s") == true {
		t.Fatal("Too short tag")
	}

	if validTag("s ") == true {
		t.Fatal("Tag contains whitespace")
	}

	if validTag("/foo/bar") == true {
		t.Fatal("Tag contains invalid characters")
	}

	if validTag("../foo") == true {
		t.Fatal("Tag contains invalid characters")
	}

	if validTag("abcdefghijklmnop") == false {
		t.Fatal("This tag is valid")
	}
}

func TestEnsureDirectoryExists(t *testing.T) {
	// Use TempDir to figure out the path to a valid directory
	dir, err := ioutil.TempDir(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}
	// Remove the directory and keep the path
	err = os.Remove(dir)
	if err != nil {
		t.Fatal(err)
	}

	// Try to create the directory using our function
	err = ensureDirectoryExists(dir)
	if err != nil {
		t.Fatal("This directory cannot be created:", err)
	}

	// Ensure that the directory is created
	err = ensureDirectoryExists(dir)
	if err != nil {
		t.Fatal("This directory wasn't created:", err)
	}

	// Remove the directory to clean up
	err = os.Remove(dir)
	if err != nil {
		t.Fatal(err)
	}
}

func TestWriteToFile(t *testing.T) {
	from_file, err := ioutil.TempFile(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(from_file.Name())
	from_file.WriteString("some content")
	from_file.Sync()
	from_file.Seek(0, 0)

	to_file, err := ioutil.TempFile(os.TempDir(), "prefix")
	if err != nil {
		t.Fatal(err)
	}
	os.Remove(to_file.Name())

	nBytes, err := writeToFile(to_file.Name(), from_file)
	if err != nil {
		t.Fatal(err)
	}
	if nBytes != 12 {
		t.Fatal("The amount of bytes was unexpected:", nBytes)
	}
}

func TestDetectMIME(t *testing.T) {
	var mime string
	var err error

	mime, err = detectMIME("testing/image.png")
	if err != nil {
		t.Fatal(err)
	}
	if mime != "image/png" {
		t.Fatal("Unable to detect mime type:", mime)
	}

	mime, err = detectMIME("testing/image.jpg")
	if err != nil {
		t.Fatal(err)
	}
	if mime != "image/jpeg" {
		t.Fatal("Unable to detect mime type:", mime)
	}

	mime, err = detectMIME("testing/image.gif")
	if err != nil {
		t.Fatal(err)
	}
	if mime != "image/gif" {
		t.Fatal("Unable to detect mime type:", mime)
	}
}
<|endoftext|>


<commit_before>package auth

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"strings"

	"github.com/micro/go-micro/v2/api/resolver"
	"github.com/micro/go-micro/v2/api/server"
	"github.com/micro/go-micro/v2/auth"
	"github.com/micro/go-micro/v2/logger"
	"github.com/micro/go-micro/v2/util/ctx"
	inauth "github.com/micro/micro/v2/internal/auth"
	"github.com/micro/micro/v2/internal/namespace"
)

// Wrapper wraps a handler and authenticates requests
func Wrapper(r resolver.Resolver, prefix string) server.Wrapper {
	return func(h http.Handler) http.Handler {
		return authWrapper{
			handler:       h,
			resolver:      r,
			servicePrefix: prefix,
			auth:          auth.DefaultAuth,
		}
	}
}

type authWrapper struct {
	handler       http.Handler
	auth          auth.Auth
	resolver      resolver.Resolver
	servicePrefix string
}

func (a authWrapper) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// Determine the name of the service being requested
	endpoint, err := a.resolver.Resolve(req)
	if err == resolver.ErrInvalidPath || err == resolver.ErrNotFound {
		// a file not served by the resolver has been requested (e.g. favicon.ico)
		endpoint = &resolver.Endpoint{Path: req.URL.Path, Domain: namespace.DefaultNamespace}
	} else if err != nil {
		logger.Error(err)
		http.Error(w, err.Error(), 500)
		return
	} else {
		// set the endpoint in the context so it can be used to resolve
		// the request later
		ctx := context.WithValue(req.Context(), resolver.Endpoint{}, endpoint)
		*req = *req.Clone(ctx)
	}

	// Determine the namespace and set it in the header
	ns := req.Header.Get(namespace.NamespaceKey)
	if len(ns) == 0 {
		ns = endpoint.Domain
		req.Header.Set(namespace.NamespaceKey, ns)
	}

	// Set the metadata so we can access it in micro api / web
	req = req.WithContext(ctx.FromRequest(req))

	// Extract the token from the request
	var token string
	if header := req.Header.Get("Authorization"); len(header) > 0 {
		// Extract the auth token from the request
		if strings.HasPrefix(header, auth.BearerScheme) {
			token = header[len(auth.BearerScheme):]
		}
	} else {
		// Get the token out the cookies if not provided in headers
		if c, err := req.Cookie("micro-token"); err == nil && c != nil {
			token = strings.TrimPrefix(c.Value, inauth.TokenCookieName+"=")
			req.Header.Set("Authorization", auth.BearerScheme+token)
		}
	}

	// Get the account using the token, some are unauthenticated, so the lack of an
	// account doesn't necesserially mean a forbidden request
	acc, _ := a.auth.Inspect(token)

	// Ensure the accounts issuer matches the namespace being requested
	if acc != nil && len(acc.Issuer) > 0 && acc.Issuer != ns {
		http.Error(w, "Account not issued by "+ns, 403)
		return
	}

	// construct the resource name, e.g. home => go.micro.web.home
	resName := a.servicePrefix + "." + endpoint.Name

	// determine the resource path. there is an inconsistency in how resolvers
	// use method, some use it as Users.ReadUser (the rpc method), and others
	// use it as the HTTP method, e.g GET. TODO: Refactor this to make it consistent.
	resEndpoint := endpoint.Path
	if len(endpoint.Path) == 0 {
		resEndpoint = endpoint.Method
	}

	// Perform the verification check to see if the account has access to
	// the resource they're requesting
	res := &auth.Resource{Type: "service", Name: resName, Endpoint: resEndpoint}
	if err := a.auth.Verify(acc, res, auth.VerifyContext(req.Context())); err == nil {
		// The account has the necessary permissions to access the resource
		a.handler.ServeHTTP(w, req)
		return
	}

	// The account is set, but they don't have enough permissions, hence
	// we return a forbidden error.
	if acc != nil {
		http.Error(w, "Forbidden request", 403)
		return
	}

	// If there is no auth login url set, 401
	loginURL := a.auth.Options().LoginURL
	if loginURL == "" {
		http.Error(w, "unauthorized request", 401)
		return
	}

	// Redirect to the login path
	params := url.Values{"redirect_to": {req.URL.String()}}
	loginWithRedirect := fmt.Sprintf("%v?%v", loginURL, params.Encode())
	http.Redirect(w, req, loginWithRedirect, http.StatusTemporaryRedirect)
}
<commit_msg>client/api/auth: fix mutli-tenancy account issuer bug<commit_after>package auth

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"strings"

	"github.com/micro/go-micro/v2/api/resolver"
	"github.com/micro/go-micro/v2/api/resolver/subdomain"
	"github.com/micro/go-micro/v2/api/server"
	"github.com/micro/go-micro/v2/auth"
	"github.com/micro/go-micro/v2/logger"
	"github.com/micro/go-micro/v2/util/ctx"
	inauth "github.com/micro/micro/v2/internal/auth"
	"github.com/micro/micro/v2/internal/namespace"
)

// Wrapper wraps a handler and authenticates requests
func Wrapper(r resolver.Resolver, prefix string) server.Wrapper {
	return func(h http.Handler) http.Handler {
		return authWrapper{
			handler:       h,
			resolver:      r,
			servicePrefix: prefix,
			auth:          auth.DefaultAuth,
		}
	}
}

type authWrapper struct {
	handler       http.Handler
	auth          auth.Auth
	resolver      resolver.Resolver
	servicePrefix string
}

func (a authWrapper) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// Determine the name of the service being requested
	endpoint, err := a.resolver.Resolve(req)
	if err == resolver.ErrInvalidPath || err == resolver.ErrNotFound {
		// a file not served by the resolver has been requested (e.g. favicon.ico)
		endpoint = &resolver.Endpoint{Path: req.URL.Path}
	} else if err != nil {
		logger.Error(err)
		http.Error(w, err.Error(), 500)
		return
	} else {
		// set the endpoint in the context so it can be used to resolve
		// the request later
		ctx := context.WithValue(req.Context(), resolver.Endpoint{}, endpoint)
		*req = *req.Clone(ctx)
	}

	// If an error occured looking up the route, the domain isn't returned. TODO: Find a better way
	// of resolving network for non-standard requests, e.g. "/rpc".
	if r, ok := a.resolver.(*subdomain.Resolver); ok && len(endpoint.Domain) == 0 {
		endpoint.Domain = r.Domain(req)
	}

	// Determine the namespace and set it in the header
	ns := req.Header.Get(namespace.NamespaceKey)
	if len(ns) == 0 {
		ns = endpoint.Domain
		req.Header.Set(namespace.NamespaceKey, ns)
	}

	// Set the metadata so we can access it in micro api / web
	req = req.WithContext(ctx.FromRequest(req))

	// Extract the token from the request
	var token string
	if header := req.Header.Get("Authorization"); len(header) > 0 {
		// Extract the auth token from the request
		if strings.HasPrefix(header, auth.BearerScheme) {
			token = header[len(auth.BearerScheme):]
		}
	} else {
		// Get the token out the cookies if not provided in headers
		if c, err := req.Cookie("micro-token"); err == nil && c != nil {
			token = strings.TrimPrefix(c.Value, inauth.TokenCookieName+"=")
			req.Header.Set("Authorization", auth.BearerScheme+token)
		}
	}

	// Get the account using the token, some are unauthenticated, so the lack of an
	// account doesn't necesserially mean a forbidden request
	acc, _ := a.auth.Inspect(token)

	// Ensure accounts only issued by the namesace are valid
	if acc != nil && acc.Issuer != ns {
		acc = nil
	}

	// construct the resource name, e.g. home => go.micro.web.home
	resName := a.servicePrefix + "." + endpoint.Name

	// determine the resource path. there is an inconsistency in how resolvers
	// use method, some use it as Users.ReadUser (the rpc method), and others
	// use it as the HTTP method, e.g GET. TODO: Refactor this to make it consistent.
	resEndpoint := endpoint.Path
	if len(endpoint.Path) == 0 {
		resEndpoint = endpoint.Method
	}

	// Perform the verification check to see if the account has access to
	// the resource they're requesting
	res := &auth.Resource{Type: "service", Name: resName, Endpoint: resEndpoint}
	if err := a.auth.Verify(acc, res, auth.VerifyContext(req.Context())); err == nil {
		// The account has the necessary permissions to access the resource
		a.handler.ServeHTTP(w, req)
		return
	}

	// The account is set, but they don't have enough permissions, hence
	// we return a forbidden error.
	if acc != nil {
		http.Error(w, "Forbidden request", 403)
		return
	}

	// If there is no auth login url set, 401
	loginURL := a.auth.Options().LoginURL
	if loginURL == "" {
		http.Error(w, "unauthorized request", 401)
		return
	}

	// Redirect to the login path
	params := url.Values{"redirect_to": {req.URL.String()}}
	loginWithRedirect := fmt.Sprintf("%v?%v", loginURL, params.Encode())
	http.Redirect(w, req, loginWithRedirect, http.StatusTemporaryRedirect)
}
<|endoftext|>


<commit_before>package shared

import (
	"fmt"
	"runtime"
)

type Logger interface {
	Debug(msg string, ctx ...interface{})
	Info(msg string, ctx ...interface{})
	Warn(msg string, ctx ...interface{})
	Error(msg string, ctx ...interface{})
	Crit(msg string, ctx ...interface{})
}

var Log Logger

type nullLogger struct{}

func (nl nullLogger) Debug(msg string, ctx ...interface{}) {}
func (nl nullLogger) Info(msg string, ctx ...interface{})  {}
func (nl nullLogger) Warn(msg string, ctx ...interface{})  {}
func (nl nullLogger) Error(msg string, ctx ...interface{}) {}
func (nl nullLogger) Crit(msg string, ctx ...interface{})  {}

func init() {
	Log = nullLogger{}
}

// Logf sends to the logger registered via SetLogger the string resulting
// from running format and args through Sprintf.
func Logf(format string, args ...interface{}) {
	if Log != nil {
		Log.Info(fmt.Sprintf(format, args...))
	}
}

// Debugf sends to the logger registered via SetLogger the string resulting
// from running format and args through Sprintf, but only if debugging was
// enabled via SetDebug.
func Debugf(format string, args ...interface{}) {
	if Log != nil {
		Log.Debug(fmt.Sprintf(format, args...))
	}
}

func PrintStack() {
	buf := make([]byte, 1<<16)
	runtime.Stack(buf, true)
	Debugf("%s", buf)
}
<commit_msg>log: add wrappers for log functions<commit_after>package shared

import (
	"fmt"
	log "gopkg.in/inconshreveable/log15.v2"
	"runtime"
)

type Logger interface {
	Debug(msg string, ctx ...interface{})
	Info(msg string, ctx ...interface{})
	Warn(msg string, ctx ...interface{})
	Error(msg string, ctx ...interface{})
	Crit(msg string, ctx ...interface{})
}

var Log Logger

type nullLogger struct{}

func (nl nullLogger) Debug(msg string, ctx ...interface{}) {}
func (nl nullLogger) Info(msg string, ctx ...interface{})  {}
func (nl nullLogger) Warn(msg string, ctx ...interface{})  {}
func (nl nullLogger) Error(msg string, ctx ...interface{}) {}
func (nl nullLogger) Crit(msg string, ctx ...interface{})  {}

func init() {
	Log = nullLogger{}
}

// Wrapper function for functions in the Logger interface.
func LogDebug(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Warn(msg, log.Ctx(ctx))
	}
}

func LogInfo(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Info(msg, log.Ctx(ctx))
	}
}

func LogWarn(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Warn(msg, log.Ctx(ctx))
	}
}

func LogError(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Error(msg, log.Ctx(ctx))
	}
}

func LogCrit(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Crit(msg, log.Ctx(ctx))
	}
}

// Logf sends to the logger registered via SetLogger the string resulting
// from running format and args through Sprintf.
func Logf(format string, args ...interface{}) {
	if Log != nil {
		Log.Info(fmt.Sprintf(format, args...))
	}
}

// Debugf sends to the logger registered via SetLogger the string resulting
// from running format and args through Sprintf, but only if debugging was
// enabled via SetDebug.
func Debugf(format string, args ...interface{}) {
	if Log != nil {
		Log.Debug(fmt.Sprintf(format, args...))
	}
}

func PrintStack() {
	buf := make([]byte, 1<<16)
	runtime.Stack(buf, true)
	Debugf("%s", buf)
}
<|endoftext|>


<commit_before>package shell

import (
	"context"
	"fmt"
	"io"
	"os"
	"os/signal"
)

// Stream is the inteface which can read command-line
type Stream interface {
	ReadLine(context.Context) (context.Context, string, error)
}

func (ses *session) push(lines []string) {
	if lines != nil && len(lines) >= 1 {
		ses.unreadline = append(ses.unreadline, lines...)
	}
}

func (ses *session) pop() (string, bool) {
	if ses.unreadline == nil || len(ses.unreadline) <= 0 {
		return "", false
	}
	line := ses.unreadline[0]
	if len(ses.unreadline) >= 2 {
		ses.unreadline = ses.unreadline[1:]
	} else {
		ses.unreadline = nil
	}
	return line, true
}

// ReadCommand reads completed one command from `stream`.
func (sh *Shell) ReadCommand(ctx context.Context, stream Stream) (context.Context, string, error) {
	var line string
	var err error

	line, ok := sh.pop()
	if !ok {
		ctx, line, err = stream.ReadLine(ctx)
		if err != nil {
			return ctx, line, err
		}

		texts := splitToStatement(line)
		line = texts[0]
		sh.push(texts[1:])
	}
	return ctx, line, nil
}

type streamIDT struct{}

// StreamID is the key-object to find the last stream in the context object.
var StreamID streamIDT

// Loop executes commands from `stream` until any errors are found.
func (sh *Shell) Loop(ctx0 context.Context, stream Stream) (int, error) {
	sigint := make(chan os.Signal, 1)
	defer close(sigint)
	quit := make(chan struct{}, 1)
	defer close(quit)

	for {
		ctx, cancel := context.WithCancel(ctx0)
		ctx = context.WithValue(ctx, StreamID, stream)

		ctx, line, err := sh.ReadCommand(ctx, stream)
		if err != nil {
			cancel()
			if err == io.EOF {
				return 0, err
			}
			return 1, err
		}
		signal.Notify(sigint, os.Interrupt)

		go func(sigint_ chan os.Signal, quit_ chan struct{}, cancel_ func()) {
			for {
				select {
				case <-sigint_:
					cancel_()
					<-quit
					return
				case <-quit:
					cancel_()
					return
				}
			}
		}(sigint, quit, cancel)
		rc, err := sh.Interpret(ctx, line)
		signal.Stop(sigint)
		quit <- struct{}{}

		if err != nil {
			if err == io.EOF {
				return rc, err
			}
			if err1, ok := err.(AlreadyReportedError); ok {
				if err1.Err == io.EOF {
					return rc, err
				}
			} else {
				fmt.Fprintln(os.Stderr, err)
			}
		}
	}
}

// ForEver executes commands from `stream` until EOF are found.
func (sh *Shell) ForEver(ctx context.Context, stream Stream) {
	for {
		_, err := sh.Loop(ctx, stream)
		if err == io.EOF {
			return
		}
		if err != nil {
			fmt.Println(err.Error())
		}
	}
}
<commit_msg>Reduce Ctrl-C cancel duration to avoid unexpected cancel<commit_after>package shell

import (
	"context"
	"fmt"
	"io"
	"os"
	"os/signal"
)

// Stream is the inteface which can read command-line
type Stream interface {
	ReadLine(context.Context) (context.Context, string, error)
}

func (ses *session) push(lines []string) {
	if lines != nil && len(lines) >= 1 {
		ses.unreadline = append(ses.unreadline, lines...)
	}
}

func (ses *session) pop() (string, bool) {
	if ses.unreadline == nil || len(ses.unreadline) <= 0 {
		return "", false
	}
	line := ses.unreadline[0]
	if len(ses.unreadline) >= 2 {
		ses.unreadline = ses.unreadline[1:]
	} else {
		ses.unreadline = nil
	}
	return line, true
}

// ReadCommand reads completed one command from `stream`.
func (sh *Shell) ReadCommand(ctx context.Context, stream Stream) (context.Context, string, error) {
	var line string
	var err error

	line, ok := sh.pop()
	if !ok {
		ctx, line, err = stream.ReadLine(ctx)
		if err != nil {
			return ctx, line, err
		}

		texts := splitToStatement(line)
		line = texts[0]
		sh.push(texts[1:])
	}
	return ctx, line, nil
}

type streamIDT struct{}

// StreamID is the key-object to find the last stream in the context object.
var StreamID streamIDT

// Loop executes commands from `stream` until any errors are found.
func (sh *Shell) Loop(ctx0 context.Context, stream Stream) (int, error) {
	for {
		ctx, cancel := context.WithCancel(ctx0)
		ctx = context.WithValue(ctx, StreamID, stream)

		ctx, line, err := sh.ReadCommand(ctx, stream)
		if err != nil {
			cancel()
			if err == io.EOF {
				return 0, err
			}
			return 1, err
		}

		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, os.Interrupt)
		quit := make(chan struct{}, 1)

		go func(sigint_ chan os.Signal, quit_ chan struct{}, cancel_ func()) {
			for {
				select {
				case <-sigint_:
					cancel_()
					<-quit
					return
				case <-quit:
					cancel_()
					return
				}
			}
		}(sigint, quit, cancel)
		rc, err := sh.Interpret(ctx, line)
		signal.Stop(sigint)

		quit <- struct{}{}
		close(quit)
		close(sigint)

		if err != nil {
			if err == io.EOF {
				return rc, err
			}
			if err1, ok := err.(AlreadyReportedError); ok {
				if err1.Err == io.EOF {
					return rc, err
				}
			} else {
				fmt.Fprintln(os.Stderr, err)
			}
		}
	}
}

// ForEver executes commands from `stream` until EOF are found.
func (sh *Shell) ForEver(ctx context.Context, stream Stream) {
	for {
		_, err := sh.Loop(ctx, stream)
		if err == io.EOF {
			return
		}
		if err != nil {
			fmt.Println(err.Error())
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"testing"

	"github.com/bradfitz/webfist"
)

type DummyStorage struct{}

func (DummyStorage) PutEmail(*webfist.EmailAddr, *webfist.Email) error {
	return nil
}

func (DummyStorage) Emails(*webfist.EmailAddr) ([]*webfist.Email, error) {
	files := []string{
		"gmail_dkim.txt",
	}
	var res []*webfist.Email
	for _, file := range files {
		full := filepath.Join("../testdata", file)
		all, err := ioutil.ReadFile(full)
		if err != nil {
			return nil, err
		}
		e, err := webfist.NewEmail(all)
		if err != nil {
			return nil, err
		}
		res = append(res, e)
	}
	return res, nil
}

func (DummyStorage) StatEncryptedEmail(addrKey, encSHA1 string) (size int, err error) {
	panic("Not implemented")
}

func (DummyStorage) EncryptedEmail(addrKey, sha1 string) ([]byte, error) {
	panic("Not implemented")
}

func (DummyStorage) PutEncryptedEmail(addrKey, encSHA1 string, data []byte) error {
	panic("Not implemented")
}

func (DummyStorage) RecentMeta() ([]*RecentMeta, error) {
	panic("Not implemented")
}

var (
	testServer *server
)

func init() {
	storage := &DummyStorage{}
	testServer = &server{
		storage: storage,
		lookup:  NewLookup(storage),
	}
}

func TestEmailLookup(t *testing.T) {
	req, _ := http.NewRequest("GET", "http://example.com/foo?resource=acct:myname@example.com", nil)
	resp := httptest.NewRecorder()
	testServer.Lookup(resp, req)
	body := resp.Body.String()
	wants := `{"subject":"myname@example.com","links":[{"rel":"http://webfist.org/spec/rel","href":"http://www.example.com/foo/bar/baz.json","properties":{"http://webfist.org/spec/proof":"http://webfist.org/webfist/proof/9239956c3d0668d7d0009ef14228bfbbc43dfd10-3a3202736e2f25cae0f5acfb011b6436eb28e27d"}}]}`
	if body != wants {
		t.Fatalf("Body = %q; want %q", body, wants)
	}
}
<commit_msg>Fix the lookup test<commit_after>package main

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"testing"

	"github.com/bradfitz/webfist"
)

type DummyStorage struct{}

func (DummyStorage) PutEmail(*webfist.EmailAddr, *webfist.Email) error {
	return nil
}

func (DummyStorage) Emails(*webfist.EmailAddr) ([]*webfist.Email, error) {
	files := []string{
		"gmail_dkim.txt",
	}
	var res []*webfist.Email
	for _, file := range files {
		full := filepath.Join("../testdata", file)
		all, err := ioutil.ReadFile(full)
		if err != nil {
			return nil, err
		}
		e, err := webfist.NewEmail(all)
		if err != nil {
			return nil, err
		}
		res = append(res, e)
	}
	return res, nil
}

func (DummyStorage) StatEncryptedEmail(addrKey, encSHA1 string) (size int, err error) {
	panic("Not implemented")
}

func (DummyStorage) EncryptedEmail(addrKey, sha1 string) ([]byte, error) {
	panic("Not implemented")
}

func (DummyStorage) PutEncryptedEmail(addrKey, encSHA1 string, data []byte) error {
	panic("Not implemented")
}

func (DummyStorage) RecentMeta() ([]*webfist.RecentMeta, error) {
	panic("Not implemented")
}

var (
	testServer *server
)

func init() {
	storage := &DummyStorage{}
	testServer = &server{
		storage: storage,
		lookup:  NewLookup(storage),
	}
}

func TestEmailLookup(t *testing.T) {
	req, _ := http.NewRequest("GET", "http://example.com/foo?resource=acct:myname@example.com", nil)
	resp := httptest.NewRecorder()
	testServer.Lookup(resp, req)
	body := resp.Body.String()
	wants := `{"subject":"myname@example.com","links":[{"rel":"http://webfist.org/spec/rel","href":"http://www.example.com/foo/bar/baz.json","properties":{"http://webfist.org/spec/proof":"http://webfist.org/webfist/proof/9239956c3d0668d7d0009ef14228bfbbc43dfd10-3a3202736e2f25cae0f5acfb011b6436eb28e27d?decrypt=myname%40example.com"}}]}`
	if body != wants {
		t.Fatalf("Body = %q; want %q", body, wants)
	}
}
<|endoftext|>


<commit_before>package ebay

type GetOrdersRequest struct {
	Xmlns string `xml:"xmlns,attr"`

	RequesterCredentials RequesterCredentials `xml:"RequesterCredentials"`

	CreateTimeFrom       string
	CreateTimeTo         string
	IncludeFinalValueFee string
	//  ListingType          string
	//  ModTimeFrom string
	//	ModTimeTo            string
	//	NumberOfDays         string
	OrderRole   string
	OrderStatus string
	//	SortingOrder         string
	DetailLevel string
	//	ErrorLanguage        string
	//	MessageID            string
	//	OutputSelector       string
	Version string
	//	WarningLevel         string
	//	Pagination
	//	OrderIDArray
}

type GetOrdersRequestResponse struct {
	Xmlns                    string `xml:"xmlns,attr"`
	Timestamp                string
	Ack                      string
	Build                    string
	Errors                   Errors
	HasMoreOrders            bool
	ReturnedOrderCountActual int
	CorrelationID            string
	HardExpirationWarning    string

	Pagination
	OrderArray OrderArray
}

type Pagination struct {
	EntriesPerPage       string
	OrdersPerPage        string
	PageNumber           string
	TotalNumberOfEntries int
	TotalNumberOfPages   int
}

type OrderIDArray struct {
	OrderID     string
	BuyerUserID string
}

type OrderArray struct {
	Order Order
}

type Order struct {
	BuyerCheckoutMessage string
	AmountSaved          string
	BuyerPackageEnclosure
	BuyerTaxIdentifier
	BuyerUserID string
	CancelDetail
	CancelReasonDetails string
	CancelStatus        string
	CheckoutStatus
	ContainseBayPlusTransaction bool
	CreatedTime                 string
	CreatingUserRole            string
	EIASToken                   string
	ExtendedOrderID             string
	ExternalTransaction
	IntegratedMerchantCreditCardEnabled string
	IsMultiLegShipping                  string
	LogisticsPlanType                   string
	MonetaryDetails
	OrderID     string
	OrderStatus string
	PaidTime    string
}
type RequiredSellerActionArray struct {
	RequiredSellerAction
}
type PaymentHoldDetails struct {
	ExpectedReleaseDate
	NumOfReqSellerActions
	PaymentHoldReason
	RequiredSellerActionArray
}
type ShipToAddress struct {
	AddressAttribute  string
	AddressID         string
	AddressOwner      string
	CityName          string
	Country           string
	CountryName       string
	ExternalAddressID string
	Name              string
	Phone             string
	PostalCode        string
	ReferenceID       string
	StateOrProvince   string
	Street1           string
	Street2           string
}
type SellerShipmentToLogisticsProvider struct {
	ShippingServiceDetails
	ShipToAddress
}
type ShippingServiceDetails struct {
	ShippingService   string
	TotalShippingCost string
}
type MultiLegShippingDetails struct {
	SellerShipmentToLogisticsProvider
	ShippingTimeMax int
	ShippingTimeMin int
	ShipToAddress
}
type MonetaryDetails struct {
	Payments
	Refunds
}

type Payments struct {
	Payment
}

type Refunds struct {
	Refund
}
type Refund struct {
	FeeOrCreditAmount string
	ReferenceID       string
	RefundAmount      string
	RefundStatus      string
	RefundTime        string
	RefundTo          string
	RefundType        string
}

type Payment struct {
	FeeOrCreditAmount  string
	Payee              string
	Payer              string
	PaymentAmount      string
	PaymentReferenceID string
	PaymentStatus      string
	PaymentTime        string
	ReferenceID        string
}

type ExternalTransaction struct {
	ExternalTransactionID     string
	ExternalTransactionStatus string
	ExternalTransactionTime   string
	FeeOrCreditAmount         string
	PaymentOrRefundAmount     string
}
type BuyerPackageEnclosure struct {
	BuyerPackageEnclosureType string
}

type BuyerTaxIdentifier struct {
	Attribute string
	ID        string
	Type      string
}

type CancelDetail struct {
	CancelCompleteDate  string
	CancelIntiationDate string
	CancelIntiator      string
	CancelReason        string
	CancelReasonDetails string
}

type CheckoutStatus struct{}

func (p *Pagination) Setpagination(entriesperpage, pagenumber string) {
	p.EntriesPerPage = entriesperpage
	p.PageNumber = pagenumber
}

func (o *OrderIDArray) GetOrderId(orderid string) {
	o.OrderID = orderid

}
<commit_msg>more work on structs<commit_after>package ebay

type GetOrdersRequest struct {
	Xmlns string `xml:"xmlns,attr"`

	RequesterCredentials RequesterCredentials `xml:"RequesterCredentials"`

	CreateTimeFrom       string
	CreateTimeTo         string
	IncludeFinalValueFee string
	//  ListingType          string
	//  ModTimeFrom string
	//	ModTimeTo            string
	//	NumberOfDays         string
	OrderRole   string
	OrderStatus string
	//	SortingOrder         string
	DetailLevel string
	//	ErrorLanguage        string
	//	MessageID            string
	//	OutputSelector       string
	Version string
	//	WarningLevel         string
	//	Pagination
	//	OrderIDArray
}

type GetOrdersRequestResponse struct {
	Xmlns                    string `xml:"xmlns,attr"`
	Timestamp                string
	Ack                      string
	Build                    string
	Errors                   Errors
	HasMoreOrders            bool
	ReturnedOrderCountActual int
	CorrelationID            string
	HardExpirationWarning    string

	Pagination
	OrderArray OrderArray
}

type Pagination struct {
	EntriesPerPage       string
	OrdersPerPage        string
	PageNumber           string
	TotalNumberOfEntries int
	TotalNumberOfPages   int
}

type OrderIDArray struct {
	OrderID     string
	BuyerUserID string
}

type OrderArray struct {
	Order Order
}
type PickupOptions struct {
	PickupMethod   string
	PickupPriority string
}

type Order struct {
	BuyerCheckoutMessage string
	AmountSaved          string
	BuyerPackageEnclosure
	BuyerTaxIdentifier
	BuyerUserID string
	CancelDetail
	CancelReasonDetails string
	CancelStatus        string
	CheckoutStatus
	ContainseBayPlusTransaction bool
	CreatedTime                 string
	CreatingUserRole            string
	EIASToken                   string
	ExtendedOrderID             string
	ExternalTransaction
	IntegratedMerchantCreditCardEnabled string
	IsMultiLegShipping                  string
	LogisticsPlanType                   string
	MonetaryDetails
	OrderID     string
	OrderStatus string
	PaidTime    string
	PaymentHoldDetails
	PaymentHoldStatus string
	PaymentMethods    string
	PickupDetails
}
type PickupMethodSelected struct{}
type PickupDetails struct {
	PickupOptions
}

type RequiredSellerActionArray struct {
	RequiredSellerAction
}
type PaymentHoldDetails struct {
	ExpectedReleaseDate   string
	NumOfReqSellerActions string
	PaymentHoldReason     string
	RequiredSellerActionArray
}
type ShipToAddress struct {
	AddressAttribute  string
	AddressID         string
	AddressOwner      string
	CityName          string
	Country           string
	CountryName       string
	ExternalAddressID string
	Name              string
	Phone             string
	PostalCode        string
	ReferenceID       string
	StateOrProvince   string
	Street1           string
	Street2           string
}
type SellerShipmentToLogisticsProvider struct {
	ShippingServiceDetails
	ShipToAddress
}
type ShippingServiceDetails struct {
	ShippingService   string
	TotalShippingCost string
}
type MultiLegShippingDetails struct {
	SellerShipmentToLogisticsProvider
	ShippingTimeMax int
	ShippingTimeMin int
	ShipToAddress
}
type MonetaryDetails struct {
	Payments
	Refunds
}

type Payments struct {
	Payment
}

type Refunds struct {
	Refund
}
type Refund struct {
	FeeOrCreditAmount string
	ReferenceID       string
	RefundAmount      string
	RefundStatus      string
	RefundTime        string
	RefundTo          string
	RefundType        string
}

type Payment struct {
	FeeOrCreditAmount  string
	Payee              string
	Payer              string
	PaymentAmount      string
	PaymentReferenceID string
	PaymentStatus      string
	PaymentTime        string
	ReferenceID        string
}

type ExternalTransaction struct {
	ExternalTransactionID     string
	ExternalTransactionStatus string
	ExternalTransactionTime   string
	FeeOrCreditAmount         string
	PaymentOrRefundAmount     string
}
type BuyerPackageEnclosure struct {
	BuyerPackageEnclosureType string
}

type BuyerTaxIdentifier struct {
	Attribute string
	ID        string
	Type      string
}

type CancelDetail struct {
	CancelCompleteDate  string
	CancelIntiationDate string
	CancelIntiator      string
	CancelReason        string
	CancelReasonDetails string
}

type CheckoutStatus struct{}

func (p *Pagination) Setpagination(entriesperpage, pagenumber string) {
	p.EntriesPerPage = entriesperpage
	p.PageNumber = pagenumber
}

func (o *OrderIDArray) GetOrderId(orderid string) {
	o.OrderID = orderid

}
<|endoftext|>