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

package sqlite

/*
#include <sqlite3.h>
#include <stdlib.h>

// cgo doesn't support varargs
static inline int my_db_config(sqlite3 *db, int op, int v, int *ok) {
	return sqlite3_db_config(db, op, v, ok);
}

static inline int goSqlite3ConfigThreadMode(int mode) {
	return sqlite3_config(mode);
}

static inline int goSqlite3Config(int op, int mode) {
	return sqlite3_config(op, mode);
}
*/
import "C"

import "unsafe"

// ThreadingMode enumerates SQLite threading mode
// See ConfigThreadingMode
type ThreadingMode int32

// SQLite threading modes
const (
	SingleThread ThreadingMode = C.SQLITE_CONFIG_SINGLETHREAD
	MultiThread  ThreadingMode = C.SQLITE_CONFIG_MULTITHREAD
	Serialized   ThreadingMode = C.SQLITE_CONFIG_SERIALIZED
)

// ConfigThreadingMode alters threading mode.
// (See sqlite3_config(SQLITE_CONFIG_SINGLETHREAD|SQLITE_CONFIG_MULTITHREAD|SQLITE_CONFIG_SERIALIZED): http://sqlite.org/c3ref/config.html)
func ConfigThreadingMode(mode ThreadingMode) error {
	rv := C.goSqlite3ConfigThreadMode(C.int(mode))
	if rv == C.SQLITE_OK {
		return nil
	}
	return Errno(rv)
}

// ConfigMemStatus enables or disables the collection of memory allocation statistics.
// (See sqlite3_config(SQLITE_CONFIG_MEMSTATUS): http://sqlite.org/c3ref/config.html)
func ConfigMemStatus(b bool) error {
	rv := C.goSqlite3Config(C.SQLITE_CONFIG_MEMSTATUS, btocint(b))
	if rv == C.SQLITE_OK {
		return nil
	}
	return Errno(rv)
}

// ConfigURI enables or disables URI handling.
// (See sqlite3_config(SQLITE_CONFIG_URI): http://sqlite.org/c3ref/config.html)
func ConfigURI(b bool) error {
	rv := C.goSqlite3Config(C.SQLITE_CONFIG_URI, btocint(b))
	if rv == C.SQLITE_OK {
		return nil
	}
	return Errno(rv)
}

// EnableSharedCache enables or disables shared pager cache
// (See http://sqlite.org/c3ref/enable_shared_cache.html)
func EnableSharedCache(b bool) error {
	rv := C.sqlite3_enable_shared_cache(btocint(b))
	if rv == C.SQLITE_OK {
		return nil
	}
	return Errno(rv)
}

// EnableFKey enables or disables the enforcement of foreign key constraints.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, b).
// Another way is PRAGMA foreign_keys = boolean;
//
// (See http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html)
func (c *Conn) EnableFKey(b bool) (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_ENABLE_FKEY, btocint(b))
}

// IsFKeyEnabled reports if the enforcement of foreign key constraints is enabled or not.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, -1).
// Another way is PRAGMA foreign_keys;
//
// (See http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html)
func (c *Conn) IsFKeyEnabled() (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_ENABLE_FKEY, -1)
}

// EnableTriggers enables or disables triggers.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_TRIGGER, b).
//
// (See http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html)
func (c *Conn) EnableTriggers(b bool) (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_ENABLE_TRIGGER, btocint(b))
}

// AreTriggersEnabled checks if triggers are enabled.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_TRIGGER, -1)
//
// (See http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html)
func (c *Conn) AreTriggersEnabled() (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_ENABLE_TRIGGER, -1)
}

func (c *Conn) queryOrSetEnableDbConfig(key, i C.int) (bool, error) {
	var ok C.int
	rv := C.my_db_config(c.db, key, i, &ok)
	if rv == C.SQLITE_OK {
		return ok == 1, nil
	}
	return false, c.error(rv)
}

// EnableExtendedResultCodes enables or disables the extended result codes feature of SQLite.
// (See http://sqlite.org/c3ref/extended_result_codes.html)
func (c *Conn) EnableExtendedResultCodes(b bool) error {
	return c.error(C.sqlite3_extended_result_codes(c.db, btocint(b)), "Conn.EnableExtendedResultCodes")
}

// CompileOptionUsed returns false or true indicating whether the specified option was defined at compile time.
// (See http://sqlite.org/c3ref/compileoption_get.html)
func CompileOptionUsed(optName string) bool {
	cOptName := C.CString(optName)
	defer C.free(unsafe.Pointer(cOptName))
	return C.sqlite3_compileoption_used(cOptName) == 1
}
<commit_msg>Add EnableDefensive() function for database connections<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlite

/*
#include <sqlite3.h>
#include <stdlib.h>

// cgo doesn't support varargs
static inline int my_db_config(sqlite3 *db, int op, int v, int *ok) {
	return sqlite3_db_config(db, op, v, ok);
}

static inline int goSqlite3ConfigThreadMode(int mode) {
	return sqlite3_config(mode);
}

static inline int goSqlite3Config(int op, int mode) {
	return sqlite3_config(op, mode);
}
*/
import "C"

import "unsafe"

// ThreadingMode enumerates SQLite threading mode
// See ConfigThreadingMode
type ThreadingMode int32

// SQLite threading modes
const (
	SingleThread ThreadingMode = C.SQLITE_CONFIG_SINGLETHREAD
	MultiThread  ThreadingMode = C.SQLITE_CONFIG_MULTITHREAD
	Serialized   ThreadingMode = C.SQLITE_CONFIG_SERIALIZED
)

// ConfigThreadingMode alters threading mode.
// (See sqlite3_config(SQLITE_CONFIG_SINGLETHREAD|SQLITE_CONFIG_MULTITHREAD|SQLITE_CONFIG_SERIALIZED): http://sqlite.org/c3ref/config.html)
func ConfigThreadingMode(mode ThreadingMode) error {
	rv := C.goSqlite3ConfigThreadMode(C.int(mode))
	if rv == C.SQLITE_OK {
		return nil
	}
	return Errno(rv)
}

// ConfigMemStatus enables or disables the collection of memory allocation statistics.
// (See sqlite3_config(SQLITE_CONFIG_MEMSTATUS): http://sqlite.org/c3ref/config.html)
func ConfigMemStatus(b bool) error {
	rv := C.goSqlite3Config(C.SQLITE_CONFIG_MEMSTATUS, btocint(b))
	if rv == C.SQLITE_OK {
		return nil
	}
	return Errno(rv)
}

// ConfigURI enables or disables URI handling.
// (See sqlite3_config(SQLITE_CONFIG_URI): http://sqlite.org/c3ref/config.html)
func ConfigURI(b bool) error {
	rv := C.goSqlite3Config(C.SQLITE_CONFIG_URI, btocint(b))
	if rv == C.SQLITE_OK {
		return nil
	}
	return Errno(rv)
}

// EnableSharedCache enables or disables shared pager cache
// (See http://sqlite.org/c3ref/enable_shared_cache.html)
func EnableSharedCache(b bool) error {
	rv := C.sqlite3_enable_shared_cache(btocint(b))
	if rv == C.SQLITE_OK {
		return nil
	}
	return Errno(rv)
}

/* Database Connection Configuration Options
//   https://www.sqlite.org/c3ref/c_dbconfig_defensive.html
 */

// EnableFKey enables or disables the enforcement of foreign key constraints.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, b).
// Another way is PRAGMA foreign_keys = boolean;
//
// (See https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigenablefkey)
func (c *Conn) EnableFKey(b bool) (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_ENABLE_FKEY, btocint(b))
}

// IsFKeyEnabled reports if the enforcement of foreign key constraints is enabled or not.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, -1).
// Another way is PRAGMA foreign_keys;
//
// (See https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigenablefkey)
func (c *Conn) IsFKeyEnabled() (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_ENABLE_FKEY, -1)
}

// EnableTriggers enables or disables triggers.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_TRIGGER, b).
//
// (See https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigenabletrigger)
func (c *Conn) EnableTriggers(b bool) (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_ENABLE_TRIGGER, btocint(b))
}

// AreTriggersEnabled checks if triggers are enabled.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_TRIGGER, -1)
//
// (See https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigenabletrigger)
func (c *Conn) AreTriggersEnabled() (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_ENABLE_TRIGGER, -1)
}

// EnableDefensive enables defensive mode for the database connection.
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1).
//
// (See https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigdefensive)
func (c *Conn) EnableDefensive() (bool, error) {
	return c.queryOrSetEnableDbConfig(C.SQLITE_DBCONFIG_DEFENSIVE, 1)
}

func (c *Conn) queryOrSetEnableDbConfig(key, i C.int) (bool, error) {
	var ok C.int
	rv := C.my_db_config(c.db, key, i, &ok)
	if rv == C.SQLITE_OK {
		return ok == 1, nil
	}
	return false, c.error(rv)
}

// EnableExtendedResultCodes enables or disables the extended result codes feature of SQLite.
// (See http://sqlite.org/c3ref/extended_result_codes.html)
func (c *Conn) EnableExtendedResultCodes(b bool) error {
	return c.error(C.sqlite3_extended_result_codes(c.db, btocint(b)), "Conn.EnableExtendedResultCodes")
}

// CompileOptionUsed returns false or true indicating whether the specified option was defined at compile time.
// (See http://sqlite.org/c3ref/compileoption_get.html)
func CompileOptionUsed(optName string) bool {
	cOptName := C.CString(optName)
	defer C.free(unsafe.Pointer(cOptName))
	return C.sqlite3_compileoption_used(cOptName) == 1
}
<|endoftext|>


<commit_before>package changes

import (
	"encoding/json"
	"os"
	"time"

	"github.com/omniscale/imposm3/config"
	"github.com/pkg/errors"
)

type Config struct {
	Connection string   `json:"connection"`
	Schemas    Schemas  `json:"schemas"`
	LimitTo    *LimitTo `json:"changes_bbox"`
	DiffDir    string   `json:"diffdir"`
	ChangesDir string   `json:"changesdir"`

	DiffFromDiffDir   bool                   `json:"replication_from_diffdir"`
	DiffUrl           string                 `json:"replication_url"`
	DiffInterval      config.MinutesInterval `json:"replication_interval"`
	ChangesetUrl      string                 `json:"changeset_url"`
	ChangesetInterval config.MinutesInterval `json:"changeset_interval"`
	InitialHistory    config.MinutesInterval `json:"initial_history"`
}

type Schemas struct {
	Changes string `json:"changes"`
}

func LoadConfig(filename string) (*Config, error) {
	conf := &Config{
		InitialHistory:    config.MinutesInterval{Duration: time.Hour},
		DiffUrl:           "http://planet.openstreetmap.org/replication/minute/",
		DiffInterval:      config.MinutesInterval{Duration: time.Minute},
		ChangesetUrl:      "http://planet.openstreetmap.org/replication/changesets/",
		ChangesetInterval: config.MinutesInterval{Duration: time.Minute},
		Schemas:           Schemas{Changes: "changes"},
	}

	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	decoder := json.NewDecoder(f)

	err = decoder.Decode(&conf)
	if err != nil {
		return nil, err
	}
	if conf.Connection == "" {
		return nil, errors.New("missing connection option")
	}

	if conf.DiffDir == "" {
		return nil, errors.New("missing diffdir option")
	}

	if conf.ChangesDir == "" {
		return nil, errors.New("missing changesdir option")
	}

	return conf, nil
}
<commit_msg>conf: use https urls<commit_after>package changes

import (
	"encoding/json"
	"os"
	"time"

	"github.com/omniscale/imposm3/config"
	"github.com/pkg/errors"
)

type Config struct {
	Connection string   `json:"connection"`
	Schemas    Schemas  `json:"schemas"`
	LimitTo    *LimitTo `json:"changes_bbox"`
	DiffDir    string   `json:"diffdir"`
	ChangesDir string   `json:"changesdir"`

	DiffFromDiffDir   bool                   `json:"replication_from_diffdir"`
	DiffUrl           string                 `json:"replication_url"`
	DiffInterval      config.MinutesInterval `json:"replication_interval"`
	ChangesetUrl      string                 `json:"changeset_url"`
	ChangesetInterval config.MinutesInterval `json:"changeset_interval"`
	InitialHistory    config.MinutesInterval `json:"initial_history"`
}

type Schemas struct {
	Changes string `json:"changes"`
}

func LoadConfig(filename string) (*Config, error) {
	conf := &Config{
		InitialHistory:    config.MinutesInterval{Duration: time.Hour},
		DiffUrl:           "https://planet.openstreetmap.org/replication/minute/",
		DiffInterval:      config.MinutesInterval{Duration: time.Minute},
		ChangesetUrl:      "https://planet.openstreetmap.org/replication/changesets/",
		ChangesetInterval: config.MinutesInterval{Duration: time.Minute},
		Schemas:           Schemas{Changes: "changes"},
	}

	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	decoder := json.NewDecoder(f)

	err = decoder.Decode(&conf)
	if err != nil {
		return nil, err
	}

	if conf.Connection == "" {
		return nil, errors.New("missing connection option")
	}

	if conf.DiffDir == "" {
		return nil, errors.New("missing diffdir option")
	}

	if conf.ChangesDir == "" {
		return nil, errors.New("missing changesdir option")
	}

	return conf, nil
}
<|endoftext|>


<commit_before>// GameServer: main gameserver struct and functions
// does not know or care about where Packets come from,
// they just arrive on our In port.
package main

import (
	"github.com/mischief/goland/game"
	"github.com/mischief/goland/game/gnet"
	"github.com/mischief/goland/game/gutil"
	"github.com/trustmaster/goflow"
	"image"
	"log"
	"net"
)

type GameServer struct {
	flow.Graph // graph for our procs; see goflow

	Listener   net.Listener       // acceptor of client connections
	PacketChan chan *ClientPacket // channel where clients packets arrive

	*game.DefaultSubject //

	Sessions map[int64]*WorldSession //client list

	Objects game.GameObjectMap
	//Objects []*game.GameObject
	Map *game.MapChunk

	Parameters *gutil.LuaParMap
}

func NewGameServer(params *gutil.LuaParMap) *GameServer {

	// flow network setup
	gs := new(GameServer)
	gs.Parameters = params
	gs.InitGraphState()

	// add nodes
	gs.Add(NewPacketRouter(gs), "router")
	gs.Add(new(PacketLogger), "logger")

	// connect processes
	gs.Connect("router", "Log", "logger", "In", make(chan *ClientPacket))

	// map external ports
	gs.MapInPort("In", "router", "In")

	gs.PacketChan = make(chan *ClientPacket, 5)
	gs.SetInPort("In", gs.PacketChan)

	// observers setup
	gs.DefaultSubject = game.NewDefaultSubject()

	// objects setup
	gs.Objects = game.NewGameObjectMap()

	return gs
}

func (gs *GameServer) Run() {
	gs.Start()

	for {
		conn, err := gs.Listener.Accept()
		if err != nil {
			log.Println("GameServer: acceptor: ", err)
			continue
		}

		ws := NewWorldSession(gs, conn)
		gs.Attach(ws)

		log.Printf("New World Session: %s", ws)

		go ws.ReceiveProc()
	}

	gs.End()
}

func (gs *GameServer) Start() {
	var err error

	// load assets
	log.Print("GameServer: Loading assets")
	gs.LoadAssets()

	// setup tcp listener
	log.Printf("Starting listener")

	dialstr := ":61507"
	if dialstr, ok := gs.Parameters.Get("listener"); !ok {
		log.Println("GameServer: 'listen' not found in config. defaulting to ", dialstr)
	}

	if gs.Listener, err = net.Listen("tcp", dialstr); err != nil {
		log.Fatalf("GameServer: %s", err)
	}

	// setup goflow network
	log.Print("GameServer: Starting flow")

	flow.RunNet(gs)

}

func (gs *GameServer) End() {
}

func (gs *GameServer) LoadAssets() {
	mapfile, ok := gs.Parameters.Get("map")
	if !ok {
		log.Fatal("No map file specified")
	}

	log.Printf("Loading map chunk file: %s", mapfile)
	if gs.Map = game.MapChunkFromFile(mapfile); gs.Map == nil {
		log.Fatal("Can't open map chunk file")
	}

}

func (gs *GameServer) SendPacketAll(pk *gnet.Packet) {
	for s := gs.DefaultSubject.Observers.Front(); s != nil; s = s.Next() {
		s.Value.(*WorldSession).SendPacket(pk)
	}
}

func (gs *GameServer) HandlePacket(cp *ClientPacket) {

	switch cp.Tag {
	case "Tchat":
		// broadcast chat

	case "Taction":
		// handle movement
		gs.HandleActionPacket(cp)

	case "Tconnect":
		// make new player for client
		newpl := game.NewPlayer()
		newpl.SetPos(image.Pt(256/2, 256/2))

		cp.Client.Player = newpl

		gs.Objects.Add(newpl.GameObject)

		gs.SendPacketAll(gnet.NewPacket("Rnewobject", newpl.GameObject))

		// tell client about all other objects
		for _, o := range gs.Objects {
			cp.Reply(gnet.NewPacket("Rnewobject", o))
		}

	case "Tdisconnect":
		// notify clients this player went away
		gs.Objects.RemoveObject(cp.Client.Player.GameObject)
		gs.SendPacketAll(gnet.NewPacket("Rdelobject", cp.Client.Player.GameObject))

	case "Tgetplayer":
		if cp.Client.Player != nil {
			cp.Reply(gnet.NewPacket("Rgetplayer", cp.Client.Player.ID))
		} else {
			cp.Reply(gnet.NewPacket("error", "nil Player in WorldSession"))
		}

	case "Tloadmap":
		cp.Reply(gnet.NewPacket("Rloadmap", gs.Map))

	default:
		log.Printf("GameServer: HandlePacket: unknown packet type %s", cp.Tag)
	}
}

func (gs *GameServer) HandleActionPacket(cp *ClientPacket) {
	dir := cp.Data.(game.Direction)
	newpos := cp.Client.Player.GetPos().Add(game.DirTable[dir])
	//if gs.Map.CheckCollision(cp.Client.Player, newpos) {
	if gs.Map.CheckCollision(nil, newpos) {
		cp.Client.Player.SetPos(newpos)

		gs.SendPacketAll(gnet.NewPacket("Raction", cp.Client.Player))
	}
}
<commit_msg>cleanup server logging and comment what packets do. also collide with game objects not just walls<commit_after>// GameServer: main gameserver struct and functions
// does not know or care about where Packets come from,
// they just arrive on our In port.
package main

import (
	"fmt"
	"github.com/mischief/goland/game"
	"github.com/mischief/goland/game/gnet"
	"github.com/mischief/goland/game/gutil"
	"github.com/trustmaster/goflow"
	"image"
	"log"
	"net"
)

type GameServer struct {
	flow.Graph // graph for our procs; see goflow

	Listener   net.Listener       // acceptor of client connections
	PacketChan chan *ClientPacket // channel where clients packets arrive

	*game.DefaultSubject //

	Sessions map[int64]*WorldSession //client list

	Objects game.GameObjectMap
	//Objects []*game.GameObject
	Map *game.MapChunk

	Parameters *gutil.LuaParMap
}

func NewGameServer(params *gutil.LuaParMap) *GameServer {

	// flow network setup
	gs := new(GameServer)
	gs.Parameters = params
	gs.InitGraphState()

	// add nodes
	gs.Add(NewPacketRouter(gs), "router")
	gs.Add(new(PacketLogger), "logger")

	// connect processes
	gs.Connect("router", "Log", "logger", "In", make(chan *ClientPacket))

	// map external ports
	gs.MapInPort("In", "router", "In")

	gs.PacketChan = make(chan *ClientPacket, 5)
	gs.SetInPort("In", gs.PacketChan)

	// observers setup
	gs.DefaultSubject = game.NewDefaultSubject()

	// objects setup
	gs.Objects = game.NewGameObjectMap()

	return gs
}

func (gs *GameServer) Run() {
	gs.Start()

	for {
		conn, err := gs.Listener.Accept()
		if err != nil {
			log.Println("GameServer: acceptor: ", err)
			continue
		}

		ws := NewWorldSession(gs, conn)
		gs.Attach(ws)

		log.Printf("New World Session: %s", ws)

		go ws.ReceiveProc()
	}

	gs.End()
}

func (gs *GameServer) Start() {
	var err error

	// load assets
	log.Print("GameServer: Loading assets")
	gs.LoadAssets()

	// setup tcp listener
	log.Printf("GameServer: Starting listener")

	dialstr := ":61507"
	if dialstr, ok := gs.Parameters.Get("listener"); !ok {
		log.Println("GameServer: 'listen' not found in config. defaulting to ", dialstr)
	}

	if gs.Listener, err = net.Listen("tcp", dialstr); err != nil {
		log.Fatalf("GameServer: %s", err)
	}

	// setup goflow network
	log.Print("GameServer: Starting flow")

	flow.RunNet(gs)

}

func (gs *GameServer) End() {
}

func (gs *GameServer) LoadAssets() {
	mapfile, ok := gs.Parameters.Get("map")
	if !ok {
		log.Fatal("GameServer: LoadAssets: No map file specified")
	}

	log.Printf("GameServer: LoadAssets: Loading map chunk file: %s", mapfile)
	if gs.Map = game.MapChunkFromFile(mapfile); gs.Map == nil {
		log.Fatal("GameServer: LoadAssets: Can't open map chunk file")
	}

}

func (gs *GameServer) SendPacketAll(pk *gnet.Packet) {
	for s := gs.DefaultSubject.Observers.Front(); s != nil; s = s.Next() {
		s.Value.(*WorldSession).SendPacket(pk)
	}
}

func (gs *GameServer) HandlePacket(cp *ClientPacket) {

	switch cp.Tag {

	// Tchat: chat message from a client
	case "Tchat":
		// broadcast chat

		// Taction: movement request
	case "Taction":
		gs.HandleActionPacket(cp)

	case "Tconnect":
		// make new player for client
		newpl := game.NewPlayer()
		newpl.SetPos(image.Pt(256/2, 256/2))

		cp.Client.Player = newpl

		gs.Objects.Add(newpl.GameObject)

		gs.SendPacketAll(gnet.NewPacket("Rnewobject", newpl.GameObject))

		// tell client about all other objects
		for _, o := range gs.Objects {
			cp.Reply(gnet.NewPacket("Rnewobject", o))
		}

	case "Tdisconnect":
		// notify clients this player went away
		gs.Objects.RemoveObject(cp.Client.Player.GameObject)
		gs.SendPacketAll(gnet.NewPacket("Rdelobject", cp.Client.Player.GameObject))

	case "Tgetplayer":
		if cp.Client.Player != nil {
			cp.Reply(gnet.NewPacket("Rgetplayer", cp.Client.Player.ID))
		} else {
			cp.Reply(gnet.NewPacket("error", "nil Player in WorldSession"))
		}

	case "Tloadmap":
		cp.Reply(gnet.NewPacket("Rloadmap", gs.Map))

	default:
		log.Printf("GameServer: HandlePacket: unknown packet type %s", cp.Tag)
	}
}

// handle a Taction packet
func (gs *GameServer) HandleActionPacket(cp *ClientPacket) {
	dir := cp.Data.(game.Direction)
	newpos := cp.Client.Player.GetPos().Add(game.DirTable[dir])
	valid := false

	// check terrain collision
	//if gs.Map.CheckCollision(cp.Client.Player, newpos) {
	if gs.Map.CheckCollision(nil, newpos) {
		valid = true
	} else {
		cp.Reply(gnet.NewPacket("Rchat", "Ouch! You bump into a wall."))
	}

	// check gameobject collision
	for _, o := range gs.Objects {
		if o.GetPos() == newpos {
			valid = false
			break
		}
	}

	if valid {
		cp.Client.Player.SetPos(newpos)
	}

	gs.SendPacketAll(gnet.NewPacket("Raction", cp.Client.Player))
}
<|endoftext|>


<commit_before>//Package server implements the http frontend
package server

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

	"github.com/golang/protobuf/proto"
	"github.com/terranodo/tegola"
	"github.com/terranodo/tegola/basic"
	"github.com/terranodo/tegola/mvt"
	"github.com/terranodo/tegola/provider/postgis"
)

const (
	//MaxTileSize is	500k
	MaxTileSize = 500000
	//MaxZoom is the suggested max by Slippy Map Tilenames spec
	MaxZoom = 18
)

//	creates a debug layer with z/x/y encoded as a point
func debugLayer(tile tegola.Tile) *mvt.Layer {
	//	create a line
	line1 := &basic.Line{
		basic.Point{0, 0},
		basic.Point{4096, 0},
		basic.Point{4096, 4096},
		basic.Point{0, 4096},
		basic.Point{0, 0},
	}

	//	tile outlines
	outline := mvt.Feature{
		Tags: map[string]interface{}{
			"type": "debug_outline",
		},
		Geometry: line1,
	}

	//	middle of tile
	point1 := &basic.Point{2048, 2048}

	//	new feature
	zxy := mvt.Feature{
		Tags: map[string]interface{}{
			"type":    "debug_text",
			"name_en": fmt.Sprintf("Z:%v, X:%v, Y:%v", tile.Z, tile.X, tile.Y),
		},
		Geometry: point1,
	}

	layer := mvt.Layer{
		Name: "debug",
	}

	layer.AddFeatures(zxy, outline)

	return &layer
}

var postgisProvider *postgis.Provider

//	URI scheme: /maps/:map_id/:z/:x/:y
//		map_id - id in the config file with an accompanying data source
//		z, x, y - tile coordinates as described in the Slippy Map Tilenames specification
//			z - zoom level
//			x - row
//			y - column
func handleZXY(w http.ResponseWriter, r *http.Request) {
	//	check http verb
	switch r.Method {
	//	preflight check for CORS request
	case "OPTIONS":
		//	TODO: how configurable do we want the CORS policy to be?
		//	set CORS header
		w.Header().Add("Access-Control-Allow-Origin", "*")

		//	options call does not have a body
		w.Write(nil)
		return
	//	tile request
	case "GET":
		//	pop off URI prefix
		uri := r.URL.Path[len("/maps/"):]

		//	break apart our URI
		uriParts := strings.Split(uri, "/")

		//	check that we have the correct number of arguments in our URI
		if len(uriParts) != 4 {
			http.Error(w, "uri requires four params: /:map_id/:z/:x/:y", http.StatusBadRequest)
			return
		}

		//	lookup our map layers
		layers, ok := maps[uriParts[0]]
		if !ok {
			http.Error(w, "no map configured: "+uriParts[0], http.StatusBadRequest)
			return
		}

		//	trim the "y" param in the url in case it has an extension
		yparts := strings.Split(uriParts[3], ".")
		uriParts[3] = yparts[0]

		//	parse our URL vals to ints
		z, err := strconv.Atoi(uriParts[1])
		if err != nil {
			http.Error(w, "invalid z value: "+uriParts[1], http.StatusBadRequest)
			return
		}

		x, err := strconv.Atoi(uriParts[2])
		if err != nil {
			http.Error(w, "invalid x value: "+uriParts[2], http.StatusBadRequest)
			return
		}

		y, err := strconv.Atoi(uriParts[3])
		if err != nil {
			http.Error(w, "invalid y value: "+uriParts[3], http.StatusBadRequest)
			return
		}

		//	new tile
		tile := tegola.Tile{
			Z: z,
			X: x,
			Y: y,
		}

		//	generate a tile
		var mvtTile mvt.Tile
		var pbyte []byte

		//	check that our request is below max zoom
		if tile.Z < MaxZoom {
			//	iterate our layers and fetch data from their providers
			for i := range layers {
				mvtLayer, err := layers[i].Provider.MVTLayer(layers[i].Name, tile)
				if err != nil {
					http.Error(w, fmt.Sprintf("Error Getting MVTLayer: %v", err.Error()), http.StatusBadRequest)
					return
				}
				//	add layers
				mvtTile.AddLayers(mvtLayer)
			}
			/*
				//	fetch requested layer from our data provider
				mvtLayer, err := postgisProvider.MVTLayer("landuse", tile)
				if err != nil {
					http.Error(w, fmt.Sprintf("Error Getting MVTLayer: %v", err.Error()), http.StatusBadRequest)
					return
				}
			*/
		}
		//	TODO: make debugging a config toggle
		//	add debug layer
		debugLayer := debugLayer(tile)
		mvtTile.AddLayers(debugLayer)

		//	generate our vector tile
		vtile, err := mvtTile.VTile(tile.Extent())
		if err != nil {
			http.Error(w, fmt.Sprintf("Error Getting VTile: %v", err.Error()), http.StatusBadRequest)
			return
		}

		//	marshal our tile into a protocol buffer
		pbyte, err = proto.Marshal(vtile)
		if err != nil {
			http.Error(w, "error marshalling tile", http.StatusInternalServerError)
			return
		}

		//	check for tile size warnings
		if len(pbyte) > MaxTileSize {
			log.Printf("tile is rather large - %v", len(pbyte))
		}

		//	TODO: how configurable do we want the CORS policy to be?
		//	set CORS header
		w.Header().Add("Access-Control-Allow-Origin", "*")

		//	mimetype for protocol buffers
		w.Header().Add("Content-Type", "application/x-protobuf")

		w.Write(pbyte)

	default:
		http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
		return
	}
}
<commit_msg>fixed merge conflict<commit_after>//Package server implements the http frontend
package server

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

	"github.com/golang/protobuf/proto"
	"github.com/terranodo/tegola"
	"github.com/terranodo/tegola/basic"
	"github.com/terranodo/tegola/mvt"
	"github.com/terranodo/tegola/provider/postgis"
)

const (
	//MaxTileSize is	500k
	MaxTileSize = 500000
	//MaxZoom is the suggested max by Slippy Map Tilenames spec
	MaxZoom = 18
)

//	creates a debug layer with z/x/y encoded as a point
func debugLayer(tile tegola.Tile) *mvt.Layer {

	ext := tile.Extent()
	layer := mvt.Layer{
		Name: "debug",
	}

	//	create a line
	line1 := &basic.Line{
		basic.Point{ext.Minx, ext.Miny},
		basic.Point{ext.Maxx, ext.Miny},
		basic.Point{ext.Maxx, ext.Maxy},
		basic.Point{ext.Minx, ext.Maxy},
	}

	//	tile outlines
	outline := mvt.Feature{
		Tags: map[string]interface{}{
			"type": "debug_outline",
		},
		Geometry: line1,
	}

	//	middle of tile
	point1 := &basic.Point{ext.Minx + ((ext.Maxx - ext.Minx) / 2), ext.Miny + ((ext.Maxy - ext.Miny) / 2)}

	//	new feature
	zxy := mvt.Feature{
		Tags: map[string]interface{}{
			"type":    "debug_text",
			"name_en": fmt.Sprintf("Z:%v, X:%v, Y:%v", tile.Z, tile.X, tile.Y),
		},
		Geometry: point1,
	}

	layer.AddFeatures(zxy, outline)

	return &layer
}

var postgisProvider *postgis.Provider

//	URI scheme: /maps/:map_id/:z/:x/:y
//		map_id - id in the config file with an accompanying data source
//		z, x, y - tile coordinates as described in the Slippy Map Tilenames specification
//			z - zoom level
//			x - row
//			y - column
func handleZXY(w http.ResponseWriter, r *http.Request) {
	//	check http verb
	switch r.Method {
	//	preflight check for CORS request
	case "OPTIONS":
		//	TODO: how configurable do we want the CORS policy to be?
		//	set CORS header
		w.Header().Add("Access-Control-Allow-Origin", "*")

		//	options call does not have a body
		w.Write(nil)
		return
	//	tile request
	case "GET":
		//	pop off URI prefix
		uri := r.URL.Path[len("/maps/"):]

		//	break apart our URI
		uriParts := strings.Split(uri, "/")

		//	check that we have the correct number of arguments in our URI
		if len(uriParts) != 4 {
			http.Error(w, "uri requires four params: /:map_id/:z/:x/:y", http.StatusBadRequest)
			return
		}

		//	lookup our map layers
		layers, ok := maps[uriParts[0]]
		if !ok {
			http.Error(w, "no map configured: "+uriParts[0], http.StatusBadRequest)
			return
		}

		//	trim the "y" param in the url in case it has an extension
		yparts := strings.Split(uriParts[3], ".")
		uriParts[3] = yparts[0]

		//	parse our URL vals to ints
		z, err := strconv.Atoi(uriParts[1])
		if err != nil {
			http.Error(w, "invalid z value: "+uriParts[1], http.StatusBadRequest)
			return
		}

		x, err := strconv.Atoi(uriParts[2])
		if err != nil {
			http.Error(w, "invalid x value: "+uriParts[2], http.StatusBadRequest)
			return
		}

		y, err := strconv.Atoi(uriParts[3])
		if err != nil {
			http.Error(w, "invalid y value: "+uriParts[3], http.StatusBadRequest)
			return
		}

		//	new tile
		tile := tegola.Tile{
			Z: z,
			X: x,
			Y: y,
		}

		//	generate a tile
		var mvtTile mvt.Tile
		var pbyte []byte

		//	check that our request is below max zoom
		if tile.Z < MaxZoom {
			//	iterate our layers and fetch data from their providers
			for i := range layers {
				mvtLayer, err := layers[i].Provider.MVTLayer(layers[i].Name, tile)
				if err != nil {
					http.Error(w, fmt.Sprintf("Error Getting MVTLayer: %v", err.Error()), http.StatusBadRequest)
					return
				}
				//	add layers
				mvtTile.AddLayers(mvtLayer)
			}
			/*
				//	fetch requested layer from our data provider
				mvtLayer, err := postgisProvider.MVTLayer("landuse", tile)
				if err != nil {
					http.Error(w, fmt.Sprintf("Error Getting MVTLayer: %v", err.Error()), http.StatusBadRequest)
					return
				}
			*/

			//	add layers
			mvtTile.AddLayers(mvtLayer)
		}
		//	TODO: make debugging a config toggle
		//	add debug layer
		debugLayer := debugLayer(tile)
		mvtTile.AddLayers(debugLayer)

		//	generate our vector tile
		vtile, err := mvtTile.VTile(tile.Extent())
		if err != nil {
			http.Error(w, fmt.Sprintf("Error Getting VTile: %v", err.Error()), http.StatusBadRequest)
			return
		}

		//	marshal our tile into a protocol buffer
		pbyte, err = proto.Marshal(vtile)
		if err != nil {
			http.Error(w, "error marshalling tile", http.StatusInternalServerError)
			return
		}

		//	check for tile size warnings
		if len(pbyte) > MaxTileSize {
			log.Printf("tile is rather large - %v", len(pbyte))
		}

		//	TODO: how configurable do we want the CORS policy to be?
		//	set CORS header
		w.Header().Add("Access-Control-Allow-Origin", "*")

		//	mimetype for protocol buffers
		w.Header().Add("Content-Type", "application/x-protobuf")

		w.Write(pbyte)

	default:
		http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "os"
  "os/exec"
  "log"
  "strings"
  "github.com/fatih/color"
  "encoding/json"
  "errors"
  "time"
  "regexp"
  "net/http"
  "net/url"
  "io/ioutil"
  fp "path/filepath"
)

const (
  INDENT = "   "
  ARROW = "-> "

  SCAFFOLD_REPO = "https://github.com/hotrodup/engine"
  CONFIG_FILE = ".hotrod.yml"
  GRANDSTAND_URL = "http://htrd.io"
)

func checkUnique(name string) error {
  fi, err := os.Stat(name)
  switch {
    case err != nil:
      return nil
    case fi.IsDir():
      return errors.New("Project already exists")
    default:
      return errors.New("Project directory can not be created")
  }
}

func checkDeps() error {
  _, err := exec.LookPath("git")
  _, err2 := exec.LookPath("gcloud")
  if err != nil || err2 != nil {
    return err
  }
  return nil
}

func checkAuth() error {
  out, err := exec.Command("gcloud", "auth", "list").CombinedOutput()
  if err != nil {
    log.Fatal(err)
  }
  if strings.Contains(string(out[:]), "No credentialed accounts") {
    return errors.New("No credentialed accounts")
  }
  return nil
}

func checkProject() (string, error) {
  out, err := exec.Command("gcloud", "config", "list", "project").CombinedOutput()
  if err != nil {
    log.Fatal(err)
  }
  if strings.Contains(string(out[:]), "(unset)") {
    return "", errors.New("Project unset")
  }
  project := strings.Trim(strings.Split(string(out[:]), "=")[1], " \n")
  return project, nil
}

func execCustom(name string, arg ...string) (string, error) {
  done := make(chan string)
  go func(){
    out, err := exec.Command(name, arg...).CombinedOutput()
    if err != nil {
      done <- ""
    }
    done <- string(out[:])
  }()
  c := time.Tick(1 * time.Second)
  fmt.Print(INDENT)
  for {
    select {
      case _ = <-c:
        fmt.Print(".")
      case output := <-done:
        fmt.Print("\n")
        if output == "" {
          return "", errors.New("Could not execute command.")
        }
        return output, nil
    }
  }
}

func findIP(input string) string {
  numBlock := "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])"
  regexPattern := numBlock + "\\." + numBlock + "\\." + numBlock + "\\." + numBlock
  regEx := regexp.MustCompile(regexPattern)
  ips := regEx.FindAllString(input, -1)
  return ips[len(ips)-1]
}

func createInstance(name string) (string, error) {
  err := ioutil.WriteFile("hotrod-containers.yaml", []byte(containers), 0777)
  out, err := execCustom(
    "gcloud", "compute", "instances", "create", "hotrod-" + name,
    "--image", "container-vm-v20140929",
    "--image-project", "google-containers",
    "--metadata-from-file", "google-container-manifest=hotrod-containers.yaml",
    "--zone", "us-central1-a",
    "--machine-type", "f1-micro")
  os.Remove("hotrod-containers.yaml")
  if err != nil {
    return "", err
  }
  return findIP(out), nil
}

func configureFirewall() error {
  _, _ = execCustom(
    "gcloud", "compute", "firewall-rules", "create", "allow-http",
    "--description", "Incoming http allowed",
    "--allow", "tcp:80")
  _, _ = execCustom(
    "gcloud", "compute", "firewall-rules", "create", "allow-other",
    "--description", "Incoming src files allowed",
    "--allow", "tcp:8888")
  return nil
}

func waitForContainers(ip string) {
  engineUp := make(chan bool)
  go func(){
    for {
      resp, err := http.Get("http://"+ip)
      if err != nil {
        continue
      }
      if resp.StatusCode == http.StatusOK {
        engineUp <- true
        return
      }
      time.Sleep(2 * time.Second)
    }
  }()
  fuelerUp := make(chan bool)
  go func() {
    for {
      resp, err := http.Get("http://"+ip+":8888")
      if err != nil {
        continue
      }
      if resp.StatusCode == http.StatusOK {
        fuelerUp <- true
        return
      }
      time.Sleep(2 * time.Second)
    }
  }()
  c := time.Tick(2 * time.Second)
  fmt.Print(INDENT)
  containersUp := 0
  for {
    select {
      case _ = <-c:
        fmt.Print(".")
      case _ = <-fuelerUp:
        containersUp += 1
      case _ = <-engineUp:
        containersUp += 1
    }
    if containersUp == 2 {
      fmt.Print("\n")
      return
    }
  }
}

type App struct {
  IP  string
  Name string
  Runtime string
  Slug string
  Date    time.Time
}

func getURL(ip, name string) (string, error) {
  resp, err := http.PostForm(GRANDSTAND_URL + "/create",
    url.Values{"ip": {ip}, "name": {name}, "runtime": {"node"}})
    if err != nil {
      return "", err
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
      return "", err
    }
    var app App
    err = json.Unmarshal(body, &app)
    if err != nil {
      return "", err
    }
    return GRANDSTAND_URL + "/" + app.Slug, nil
}

func copySource(name, ip, url string) error {
  err := exec.Command(
    "git","clone", SCAFFOLD_REPO, name).Run()
  if err != nil {
    return err
  }
  err = exec.Command(
    "rm", "-rf", name + "/.git").Run()
  if err != nil {
    return err
  }
  err = exec.Command(
    "rm", name + "/Dockerfile").Run()
  if err != nil {
    return err
  }

  err = ioutil.WriteFile(fp.Join(name, CONFIG_FILE), []byte(fmt.Sprintf(hotrodConfig, name, ip, url)), 0777)
  if err != nil {
    return err
  }

  return nil
}

func create(name string) {

  fmt.Println(CHECKERED_FLAG, color.YellowString("Creating new project"), color.GreenString(name))

  err := checkUnique(name)
  if err != nil {
    fmt.Println(INDENT, color.RedString("Can't create directory"), name)
    fmt.Println(INDENT, color.RedString("Choose a unique project name"))
    return
  }

  err = checkDeps()
  if err != nil {
    fmt.Println(INDENT, color.RedString("Hot Rod requires `git` and `gcloud`"))
    fmt.Println(INDENT, color.RedString("Make sure both dependencies are on the $PATH"))
    return
  }
  err = checkAuth()
  if err != nil {
    fmt.Println(INDENT, color.RedString("Hot Rod requires an credentialed `gcloud` account"))
    fmt.Println(INDENT, color.RedString("Run `gcloud auth login`"))
    return
  }
  project, err := checkProject()
  if err != nil {
    fmt.Println(INDENT, color.RedString("Hot Rod requires an active `gcloud` project"))
    fmt.Println(INDENT, color.RedString("Create a project at"), "https://console.developers.google.com/project")
    fmt.Println(INDENT, color.RedString("and set it as default with `gcloud config set project <PROJECT>"))
    return
  }

  fmt.Println(ARROW, "Spinning up an instance")
  ip, err := createInstance(name)
  if err != nil {
    fmt.Println(INDENT, color.RedString("Hot Rod failed to create an instance"))
    fmt.Println(INDENT, color.RedString("Please enable billing and turn on the Compute API"))
    fmt.Println(INDENT, color.RedString("at"), fmt.Sprintf("https://console.developers.google.com/project/%s/apiui/api", project))
    return
  }

  url, err := getURL(ip, name)
  if err != nil {
    fmt.Println(INDENT, color.RedString("Failed to create a preview URL at"), "http://htrd.io")
  }

  done := make(chan bool)
  go func() {
    err := copySource(name, ip, url)
    if err != nil {
      done <- false
    }
    done <- true
  }()

  fmt.Println(ARROW, "Opening ports for traffic")
  err = configureFirewall()
  if err != nil {
    fmt.Println(INDENT, color.RedString("Opening ports failed"))
    fmt.Println(INDENT, color.RedString("Please try again later"))
    return
  }

  fmt.Println(ARROW, "Starting containers")
  waitForContainers(ip)

  d := <-done
  if !d {
    fmt.Println(INDENT, color.RedString("Hot Rod failed to create the source directory"))
    fmt.Println(INDENT, color.RedString("Check folder permissions"))
  }

  fmt.Println(ARROW, "Done")
  fmt.Println(ARROW, "Preview app at", color.GreenString(url))
  fmt.Println(RED_CAR, color.YellowString("Now `cd "+name+"` and run `hotrod up`"))

}

const containers = `
version: v1beta2
containers:
  - name: engine
    image: hotrod/engine
    ports:
      - name: http
        hostPort: 80
        containerPort: 8080
    volumeMounts:
      - name: app
        mountPath: /app
    env:
      - name: PORT
        value: 8080
  - name: fueler
    image: hotrod/fueler
    ports:
      - name: upload
        hostPort: 8888
        containerPort: 8888
    volumeMounts:
      - name: app
        mountPath: /app
volumes:
  - name: app
`

const hotrodConfig = `
name: %s
ip: %s
url: %s
`
<commit_msg>add burnout<commit_after>package main

import (
  "fmt"
  "os"
  "os/exec"
  "log"
  "strings"
  "github.com/fatih/color"
  "encoding/json"
  "errors"
  "time"
  "regexp"
  "net/http"
  "net/url"
  "io/ioutil"
  fp "path/filepath"
)

const (
  INDENT = "   "
  ARROW = "-> "

  SCAFFOLD_REPO = "https://github.com/hotrodup/engine"
  CONFIG_FILE = ".hotrod.yml"
  GRANDSTAND_URL = "http://htrd.io"
)

func checkUnique(name string) error {
  fi, err := os.Stat(name)
  switch {
    case err != nil:
      return nil
    case fi.IsDir():
      return errors.New("Project already exists")
    default:
      return errors.New("Project directory can not be created")
  }
}

func checkDeps() error {
  _, err := exec.LookPath("git")
  _, err2 := exec.LookPath("gcloud")
  if err != nil || err2 != nil {
    return err
  }
  return nil
}

func checkAuth() error {
  out, err := exec.Command("gcloud", "auth", "list").CombinedOutput()
  if err != nil {
    log.Fatal(err)
  }
  if strings.Contains(string(out[:]), "No credentialed accounts") {
    return errors.New("No credentialed accounts")
  }
  return nil
}

func checkProject() (string, error) {
  out, err := exec.Command("gcloud", "config", "list", "project").CombinedOutput()
  if err != nil {
    log.Fatal(err)
  }
  if strings.Contains(string(out[:]), "(unset)") {
    return "", errors.New("Project unset")
  }
  project := strings.Trim(strings.Split(string(out[:]), "=")[1], " \n")
  return project, nil
}

func execCustom(name string, arg ...string) (string, error) {
  done := make(chan string)
  go func(){
    out, err := exec.Command(name, arg...).CombinedOutput()
    if err != nil {
      done <- ""
    }
    done <- string(out[:])
  }()
  c := time.Tick(1 * time.Second)
  fmt.Print(INDENT)
  for {
    select {
      case _ = <-c:
        fmt.Print(".")
      case output := <-done:
        fmt.Print("\n")
        if output == "" {
          return "", errors.New("Could not execute command.")
        }
        return output, nil
    }
  }
}

func findIP(input string) string {
  numBlock := "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])"
  regexPattern := numBlock + "\\." + numBlock + "\\." + numBlock + "\\." + numBlock
  regEx := regexp.MustCompile(regexPattern)
  ips := regEx.FindAllString(input, -1)
  return ips[len(ips)-1]
}

func createInstance(name string) (string, error) {
  err := ioutil.WriteFile("hotrod-containers.yaml", []byte(containers), 0777)
  out, err := execCustom(
    "gcloud", "compute", "instances", "create", "hotrod-" + name,
    "--image", "container-vm-v20140929",
    "--image-project", "google-containers",
    "--metadata-from-file", "google-container-manifest=hotrod-containers.yaml",
    "--zone", "us-central1-a",
    "--machine-type", "f1-micro")
  os.Remove("hotrod-containers.yaml")
  if err != nil {
    return "", err
  }
  return findIP(out), nil
}

func configureFirewall() error {
  _, _ = execCustom(
    "gcloud", "compute", "firewall-rules", "create", "allow-http",
    "--description", "Incoming http allowed",
    "--allow", "tcp:80")
  _, _ = execCustom(
    "gcloud", "compute", "firewall-rules", "create", "allow-other",
    "--description", "Incoming src files allowed",
    "--allow", "tcp:8888")
  _, _ = execCustom(
    "gcloud", "compute", "firewall-rules", "create", "allow-ws",
    "--description", "Incoming src files allowed",
    "--allow", "tcp:8585")
  return nil
}

func waitForContainers(ip string) {
  engineUp := make(chan bool)
  go func(){
    for {
      resp, err := http.Get("http://"+ip)
      if err != nil {
        continue
      }
      if resp.StatusCode == http.StatusOK {
        engineUp <- true
        return
      }
      time.Sleep(2 * time.Second)
    }
  }()
  fuelerUp := make(chan bool)
  go func() {
    for {
      resp, err := http.Get("http://"+ip+":8888")
      if err != nil {
        continue
      }
      if resp.StatusCode == http.StatusOK {
        fuelerUp <- true
        return
      }
      time.Sleep(2 * time.Second)
    }
  }()
  burnoutUp := make(chan bool)
  go func() {
    for {
      resp, err := http.Get("http://"+ip+":8585")
      if err != nil {
        continue
      }
      if resp.StatusCode == http.StatusOK {
        burnoutUp <- true
        return
      }
      time.Sleep(2 * time.Second)
    }
  }()
  c := time.Tick(2 * time.Second)
  fmt.Print(INDENT)
  containersUp := 0
  for {
    select {
      case _ = <-c:
        fmt.Print(".")
      case _ = <-fuelerUp:
        containersUp += 1
      case _ = <-engineUp:
        containersUp += 1
      case _ = <-burnoutUp:
        containersUp += 1
    }
    if containersUp == 3 {
      fmt.Print("\n")
      return
    }
  }
}

type App struct {
  IP  string
  Name string
  Runtime string
  Slug string
  Date    time.Time
}

func getURL(ip, name string) (string, error) {
  resp, err := http.PostForm(GRANDSTAND_URL + "/create",
    url.Values{"ip": {ip}, "name": {name}, "runtime": {"node"}})
    if err != nil {
      return "", err
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
      return "", err
    }
    var app App
    err = json.Unmarshal(body, &app)
    if err != nil {
      return "", err
    }
    return GRANDSTAND_URL + "/" + app.Slug, nil
}

func copySource(name, ip, url string) error {
  err := exec.Command(
    "git","clone", SCAFFOLD_REPO, name).Run()
  if err != nil {
    return err
  }
  err = exec.Command(
    "rm", "-rf", name + "/.git").Run()
  if err != nil {
    return err
  }
  err = exec.Command(
    "rm", name + "/Dockerfile").Run()
  if err != nil {
    return err
  }

  err = ioutil.WriteFile(fp.Join(name, CONFIG_FILE), []byte(fmt.Sprintf(hotrodConfig, name, ip, url)), 0777)
  if err != nil {
    return err
  }

  return nil
}

func create(name string) {

  fmt.Println(CHECKERED_FLAG, color.YellowString("Creating new project"), color.GreenString(name))

  err := checkUnique(name)
  if err != nil {
    fmt.Println(INDENT, color.RedString("Can't create directory"), name)
    fmt.Println(INDENT, color.RedString("Choose a unique project name"))
    return
  }

  err = checkDeps()
  if err != nil {
    fmt.Println(INDENT, color.RedString("Hot Rod requires `git` and `gcloud`"))
    fmt.Println(INDENT, color.RedString("Make sure both dependencies are on the $PATH"))
    return
  }
  err = checkAuth()
  if err != nil {
    fmt.Println(INDENT, color.RedString("Hot Rod requires an credentialed `gcloud` account"))
    fmt.Println(INDENT, color.RedString("Run `gcloud auth login`"))
    return
  }
  project, err := checkProject()
  if err != nil {
    fmt.Println(INDENT, color.RedString("Hot Rod requires an active `gcloud` project"))
    fmt.Println(INDENT, color.RedString("Create a project at"), "https://console.developers.google.com/project")
    fmt.Println(INDENT, color.RedString("and set it as default with `gcloud config set project <PROJECT>"))
    return
  }

  fmt.Println(ARROW, "Spinning up a new instance")
  ip, err := createInstance(name)
  if err != nil {
    fmt.Println(INDENT, color.RedString("Hot Rod failed to create a new instance"))
    fmt.Println(INDENT, color.RedString("Please enable billing and turn on the Compute API"))
    fmt.Println(INDENT, color.RedString("at"), fmt.Sprintf("https://console.developers.google.com/project/%s/apiui/api", project))
    return
  }

  url, err := getURL(ip, name)
  if err != nil {
    fmt.Println(INDENT, color.RedString("Failed to create a preview URL at"), "http://htrd.io")
  }

  done := make(chan bool)
  go func() {
    err := copySource(name, ip, url)
    if err != nil {
      done <- false
    }
    done <- true
  }()

  fmt.Println(ARROW, "Opening ports for traffic")
  err = configureFirewall()
  if err != nil {
    fmt.Println(INDENT, color.RedString("Opening ports failed"))
    fmt.Println(INDENT, color.RedString("Please try again later"))
    return
  }

  fmt.Println(ARROW, "Starting containers")
  waitForContainers(ip)

  d := <-done
  if !d {
    fmt.Println(INDENT, color.RedString("Hot Rod failed to create the source directory"))
    fmt.Println(INDENT, color.RedString("Check folder permissions"))
  }

  fmt.Println(ARROW, "Done")
  fmt.Println(ARROW, "Preview app at", color.GreenString(url))
  fmt.Println(RED_CAR, color.YellowString("Now `cd "+name+"` and run `hotrod up`"))

}

const containers = `
version: v1beta2
containers:
  - name: engine
    image: hotrod/engine
    ports:
      - name: http
        hostPort: 80
        containerPort: 8080
    volumeMounts:
      - name: app
        mountPath: /app
    env:
      - name: PORT
        value: 8080
  - name: fueler
    image: hotrod/fueler
    ports:
      - name: upload
        hostPort: 8888
        containerPort: 8888
    volumeMounts:
      - name: app
        mountPath: /app
  - name: burnout
    image: hotrod/burnout
    ports:
      - name: ping
        hostPort: 8585
        containerPort: 8585
    volumeMounts:
      - name: app
        mountPath: /app
volumes:
  - name: app
`

const hotrodConfig = `
name: %s
ip: %s
url: %s
`
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file

package services

import (
	"bufio"
	"crypto/tls"
	"github.com/bitmark-inc/bitmark-webgui/configuration"
	"github.com/bitmark-inc/bitmark-webgui/fault"
	"github.com/bitmark-inc/bitmark-webgui/structs"
	"github.com/bitmark-inc/bitmark-webgui/utils"
	"github.com/bitmark-inc/bitmarkd/rpc"
	"github.com/bitmark-inc/logger"
	"net"
	netrpc "net/rpc"
	"os"
	"os/exec"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

type Bitmarkd struct {
	sync.RWMutex
	initialised bool
	log         *logger.L
	configFile  string
	process     *os.Process
	running     bool
	ModeStart   chan bool
}

func (bitmarkd *Bitmarkd) Initialise(configFile string) error {
	bitmarkd.Lock()
	defer bitmarkd.Unlock()

	if bitmarkd.initialised {
		return fault.ErrAlreadyInitialised
	}

	bitmarkd.configFile = configFile

	bitmarkd.log = logger.New("service-bitmarkd")
	if nil == bitmarkd.log {
		return fault.ErrInvalidLoggerChannel
	}

	bitmarkd.running = false
	bitmarkd.ModeStart = make(chan bool, 1)

	// all data initialised
	bitmarkd.initialised = true
	return nil
}

func (bitmarkd *Bitmarkd) Finalise() error {
	bitmarkd.Lock()
	defer bitmarkd.Unlock()

	if !bitmarkd.initialised {
		return fault.ErrNotInitialised
	}

	bitmarkd.initialised = false
	return nil
}

func (bitmarkd *Bitmarkd) IsRunning() bool {
	return bitmarkd.running
}

func (bitmarkd *Bitmarkd) Setup(bitmarkConfigFile, chain string, webguiConfigFile string, webguiConfig *configuration.Configuration) error {
	if bitmarkd.running {
		return fault.ErrBitmarkdIsRunning
	}

	bitmarkd.configFile = bitmarkConfigFile
	webguiConfig.BitmarkConfigFile = bitmarkConfigFile

	err := EnsureFile(bitmarkConfigFile)
	if err != nil {
		return err
	}

	if bitmarkConfigs, err := structs.NewBitmarkdConfiguration(bitmarkConfigFile); nil != err {
		return err
	} else {
		bitmarkConfigs.Chain = chain
		bitmarkConfigs.SaveToJson(bitmarkConfigFile)
	}

	cmd := exec.Command("bitmarkd", "--config-file="+bitmarkConfigFile, "gen-peer-identity")
	_ = cmd.Run()

	cmd = exec.Command("bitmarkd", "--config-file="+bitmarkConfigFile, "gen-rpc-cert")
	_ = cmd.Run()

	return configuration.UpdateConfiguration(webguiConfigFile, webguiConfig)
}

func (bitmarkd *Bitmarkd) Run(args interface{}, shutdown <-chan struct{}) {
loop:
	for {
		select {

		case <-shutdown:
			break loop
		case start := <-bitmarkd.ModeStart:
			if start {
				bitmarkd.startBitmarkd()
			} else {
				bitmarkd.stopBitmarkd()
			}
		}

	}
	close(bitmarkd.ModeStart)
}

func (bitmarkd *Bitmarkd) startBitmarkd() error {
	if bitmarkd.running {
		bitmarkd.log.Errorf("Start bitmarkd failed: %v", fault.ErrBitmarkdIsRunning)
		return fault.ErrBitmarkdIsRunning
	}

	// Check bitmarkConfigFile exists
	bitmarkd.log.Infof("bitmark config file: %s\n", bitmarkd.configFile)
	if !utils.EnsureFileExists(bitmarkd.configFile) {
		bitmarkd.log.Errorf("Start bitmarkd failed: %v", fault.ErrNotFoundConfigFile)
		return fault.ErrNotFoundConfigFile
	}

	bitmarkd.running = true
	stopped := make(chan bool, 1)

	go func() {
		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
		select {
		case <-stopped:
			return
		case <-ch:
			bitmarkd.stopBitmarkd()
		}
	}()

	go func() {
		for bitmarkd.running {
			// start bitmarkd as sub process
			cmd := exec.Command("bitmarkd", "--config-file="+bitmarkd.configFile)
			// start bitmarkd as sub process
			stderr, err := cmd.StderrPipe()
			if err != nil {
				bitmarkd.log.Errorf("Error: %v", err)
				continue
			}
			stdout, err := cmd.StdoutPipe()
			if err != nil {
				bitmarkd.log.Errorf("Error: %v", err)
				continue
			}
			if err := cmd.Start(); nil != err {
				continue
			}

			bitmarkd.process = cmd.Process
			bitmarkd.log.Infof("process id: %d", cmd.Process.Pid)
			stdeReader := bufio.NewReader(stderr)
			stdoReader := bufio.NewReader(stdout)

			go func() {
				for {
					stde, err := stdeReader.ReadString('\n')
					bitmarkd.log.Errorf("bitmarkd stderr: %q", stde)
					if nil != err {
						bitmarkd.log.Errorf("Error: %v", err)
						return
					}
				}
			}()

			go func() {
				for {
					stdo, err := stdoReader.ReadString('\n')
					bitmarkd.log.Infof("bitmarkd stdout: %q", stdo)
					if nil != err {
						bitmarkd.log.Errorf("Error: %v", err)
						return
					}
				}
			}()

			if err := cmd.Wait(); nil != err {
				if bitmarkd.running {
					bitmarkd.log.Errorf("bitmarkd has terminated unexpectedly. failed: %v", err)
					bitmarkd.log.Errorf("bitmarkd will be restarted in 1 second...")
					time.Sleep(time.Second)
				}
				bitmarkd.process = nil
				stopped <- true
			}
		}
	}()

	// wait for 1 second if cmd has no error then return nil
	time.Sleep(time.Second * 1)
	return nil

}

func (bitmarkd *Bitmarkd) stopBitmarkd() error {
	if !bitmarkd.running {
		bitmarkd.log.Errorf("Stop bitmarkd failed: %v", fault.ErrBitmarkdIsNotRunning)
		return fault.ErrBitmarkdIsNotRunning
	}
	bitmarkd.running = false

	// if err := bitmarkd.process.Signal(os.Interrupt); nil != err {
	// bitmarkd.log.Errorf("Send interrupt to bitmarkd failed: %v", err)
	if err := bitmarkd.process.Signal(os.Kill); nil != err {
		bitmarkd.log.Errorf("Send kill to bitmarkd failed: %v", err)
		return err
	}
	// }

	bitmarkd.log.Infof("Stop bitmarkd. PID: %d", bitmarkd.process.Pid)
	bitmarkd.process = nil
	return nil
}

func (bitmarkd *Bitmarkd) GetInfo(client *netrpc.Client) (*rpc.InfoReply, error) {

	var reply rpc.InfoReply
	if err := client.Call("Node.Info", rpc.InfoArguments{}, &reply); err != nil {
		bitmarkd.log.Errorf("Node.Info error: %v\n", err)
		return nil, fault.ErrNodeInfoRequestFail
	}

	return &reply, nil
}

// connect to bitmarkd RPC
func (bitmarkd *Bitmarkd) Connect(connect string) (net.Conn, error) {

	tlsConfig := &tls.Config{
		InsecureSkipVerify: true,
	}

	conn, err := tls.Dial("tcp", connect, tlsConfig)
	if nil != err {
		return nil, err
	}

	return conn, nil
}
<commit_msg>Fix bugs in bitmarkd service<commit_after>// Copyright (c) 2014-2015 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file

package services

import (
	"bufio"
	"crypto/tls"
	"github.com/bitmark-inc/bitmark-webgui/configuration"
	"github.com/bitmark-inc/bitmark-webgui/fault"
	"github.com/bitmark-inc/bitmark-webgui/structs"
	"github.com/bitmark-inc/bitmark-webgui/utils"
	"github.com/bitmark-inc/bitmarkd/rpc"
	"github.com/bitmark-inc/logger"
	"net"
	netrpc "net/rpc"
	"os"
	"os/exec"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

type Bitmarkd struct {
	sync.RWMutex
	initialised bool
	log         *logger.L
	configFile  string
	process     *os.Process
	running     bool
	ModeStart   chan bool
}

func (bitmarkd *Bitmarkd) Initialise(configFile string) error {
	bitmarkd.Lock()
	defer bitmarkd.Unlock()

	if bitmarkd.initialised {
		return fault.ErrAlreadyInitialised
	}

	bitmarkd.configFile = configFile

	bitmarkd.log = logger.New("service-bitmarkd")
	if nil == bitmarkd.log {
		return fault.ErrInvalidLoggerChannel
	}

	bitmarkd.running = false
	bitmarkd.ModeStart = make(chan bool, 1)

	// all data initialised
	bitmarkd.initialised = true
	return nil
}

func (bitmarkd *Bitmarkd) Finalise() error {
	bitmarkd.Lock()
	defer bitmarkd.Unlock()

	if !bitmarkd.initialised {
		return fault.ErrNotInitialised
	}

	bitmarkd.initialised = false
	return nil
}

func (bitmarkd *Bitmarkd) IsRunning() bool {
	return bitmarkd.running
}

func (bitmarkd *Bitmarkd) Setup(bitmarkConfigFile, chain string, webguiConfigFile string, webguiConfig *configuration.Configuration) error {
	if bitmarkd.running {
		return fault.ErrBitmarkdIsRunning
	}

	bitmarkd.configFile = bitmarkConfigFile
	webguiConfig.BitmarkConfigFile = bitmarkConfigFile

	err := EnsureFile(bitmarkConfigFile)
	if err != nil {
		return err
	}

	if bitmarkConfigs, err := structs.NewBitmarkdConfiguration(bitmarkConfigFile); nil != err {
		return err
	} else {
		bitmarkConfigs.Chain = chain
		bitmarkConfigs.SaveToJson(bitmarkConfigFile)
	}

	cmd := exec.Command("bitmarkd", "--config-file="+bitmarkConfigFile, "gen-peer-identity")
	_ = cmd.Run()

	cmd = exec.Command("bitmarkd", "--config-file="+bitmarkConfigFile, "gen-rpc-cert")
	_ = cmd.Run()

	return configuration.UpdateConfiguration(webguiConfigFile, webguiConfig)
}

func (bitmarkd *Bitmarkd) Run(args interface{}, shutdown <-chan struct{}) {
loop:
	for {
		select {

		case <-shutdown:
			break loop
		case start := <-bitmarkd.ModeStart:
			if start {
				bitmarkd.startBitmarkd()
			} else {
				bitmarkd.stopBitmarkd()
			}
		}

	}
	close(bitmarkd.ModeStart)
}

func (bitmarkd *Bitmarkd) startBitmarkd() error {
	if bitmarkd.running {
		bitmarkd.log.Errorf("Start bitmarkd failed: %v", fault.ErrBitmarkdIsRunning)
		return fault.ErrBitmarkdIsRunning
	}

	// Check bitmarkConfigFile exists
	bitmarkd.log.Infof("bitmark config file: %s\n", bitmarkd.configFile)
	if !utils.EnsureFileExists(bitmarkd.configFile) {
		bitmarkd.log.Errorf("Start bitmarkd failed: %v", fault.ErrNotFoundConfigFile)
		return fault.ErrNotFoundConfigFile
	}

	bitmarkd.running = true
	stopped := make(chan bool, 1)

	go func() {
		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
		select {
		case <-stopped:
			return
		case <-ch:
			bitmarkd.stopBitmarkd()
		}
	}()

	go func() {
		defer func() {
			stopped <- true
		}()
		for bitmarkd.running {
			// start bitmarkd as sub process
			cmd := exec.Command("bitmarkd", "--config-file="+bitmarkd.configFile)
			// start bitmarkd as sub process
			stderr, err := cmd.StderrPipe()
			if err != nil {
				bitmarkd.log.Errorf("Error: %v", err)
				continue
			}
			stdout, err := cmd.StdoutPipe()
			if err != nil {
				bitmarkd.log.Errorf("Error: %v", err)
				continue
			}
			if err := cmd.Start(); nil != err {
				continue
			}

			bitmarkd.process = cmd.Process
			bitmarkd.log.Infof("process id: %d", cmd.Process.Pid)
			stdeReader := bufio.NewReader(stderr)
			stdoReader := bufio.NewReader(stdout)

			go func() {
				for {
					stde, err := stdeReader.ReadString('\n')
					bitmarkd.log.Errorf("bitmarkd stderr: %q", stde)
					if nil != err {
						bitmarkd.log.Errorf("Error: %v", err)
						return
					}
				}
			}()

			go func() {
				for {
					stdo, err := stdoReader.ReadString('\n')
					bitmarkd.log.Infof("bitmarkd stdout: %q", stdo)
					if nil != err {
						bitmarkd.log.Errorf("Error: %v", err)
						return
					}
				}
			}()

			if err := cmd.Wait(); nil != err {
				if bitmarkd.running {
					bitmarkd.log.Errorf("bitmarkd has terminated unexpectedly. failed: %v", err)
					bitmarkd.log.Errorf("bitmarkd will be restarted in 1 second...")
					time.Sleep(time.Second)
				}
				bitmarkd.process = nil
			}
		}
	}()

	// wait for 1 second if cmd has no error then return nil
	time.Sleep(time.Second * 1)
	return nil

}

func (bitmarkd *Bitmarkd) stopBitmarkd() error {
	if !bitmarkd.running {
		bitmarkd.log.Errorf("Stop bitmarkd failed: %v", fault.ErrBitmarkdIsNotRunning)
		return fault.ErrBitmarkdIsNotRunning
	}
	bitmarkd.running = false

	// if err := bitmarkd.process.Signal(os.Interrupt); nil != err {
	// bitmarkd.log.Errorf("Send interrupt to bitmarkd failed: %v", err)
	if bitmarkd.process == nil {
		return nil
	}
	if err := bitmarkd.process.Signal(os.Kill); nil != err {
		bitmarkd.log.Errorf("Send kill to bitmarkd failed: %v", err)
		return err
	}

	bitmarkd.log.Infof("Stop bitmarkd. PID: %d", bitmarkd.process.Pid)
	bitmarkd.process = nil
	return nil
}

func (bitmarkd *Bitmarkd) GetInfo(client *netrpc.Client) (*rpc.InfoReply, error) {

	var reply rpc.InfoReply
	if err := client.Call("Node.Info", rpc.InfoArguments{}, &reply); err != nil {
		bitmarkd.log.Errorf("Node.Info error: %v\n", err)
		return nil, fault.ErrNodeInfoRequestFail
	}

	return &reply, nil
}

// connect to bitmarkd RPC
func (bitmarkd *Bitmarkd) Connect(connect string) (net.Conn, error) {

	tlsConfig := &tls.Config{
		InsecureSkipVerify: true,
	}

	conn, err := tls.Dial("tcp", connect, tlsConfig)
	if nil != err {
		return nil, err
	}

	return conn, nil
}
<|endoftext|>


<commit_before>package services

import (
	"context"
	"io"
	"log"
	"os"

	"golang.org/x/text/encoding"

	"github.com/docker/docker/api/types"
)

type Instance struct {
	Session *Session                `json:"-"`
	Name    string                  `json:"name"`
	IP      string                  `json:"ip"`
	Conn    *types.HijackedResponse `json:"-"`
	ExecId  string                  `json:"-"`
	Ctx     context.Context         `json:"-"`
}

var dindImage string
var defaultDindImageName string

func init() {
	dindImage = getDindImageName()
}

func getDindImageName() string {
	dindImage := os.Getenv("DIND_IMAGE")
	defaultDindImageName = "docker:1.12.2-rc2-dind"
	if len(dindImage) == 0 {
		dindImage = defaultDindImageName
	}
	return dindImage
}

func NewInstance(session *Session) (*Instance, error) {
	log.Printf("NewInstance - using image: [%s]\n", dindImage)
	instance, err := CreateInstance(session.Id, dindImage)
	if err != nil {
		return nil, err
	}
	instance.Session = session

	if session.Instances == nil {
		session.Instances = make(map[string]*Instance)
	}
	session.Instances[instance.Name] = instance

	go instance.Exec()

	wsServer.BroadcastTo(session.Id, "new instance", instance.Name, instance.IP)

	return instance, nil
}

type sessionWriter struct {
	instance *Instance
}

func (s *sessionWriter) Write(p []byte) (n int, err error) {
	wsServer.BroadcastTo(s.instance.Session.Id, "terminal out", s.instance.Name, string(p))
	return len(p), nil
}

func (i *Instance) ResizeTerminal(cols, rows uint) error {
	return ResizeExecConnection(i.ExecId, i.Ctx, cols, rows)
}

func (i *Instance) Exec() {
	i.Ctx = context.Background()

	id, err := CreateExecConnection(i.Name, i.Ctx)
	if err != nil {
		return
	}
	i.ExecId = id
	conn, err := AttachExecConnection(id, i.Ctx)
	if err != nil {
		return
	}

	i.Conn = conn

	go func() {
		encoder := encoding.Replacement.NewEncoder()
		sw := &sessionWriter{instance: i}
		io.Copy(encoder.Writer(sw), conn.Reader)
	}()

	select {
	case <-i.Ctx.Done():
	}
}

func GetInstance(session *Session, name string) *Instance {
	//TODO: Use redis
	return session.Instances[name]
}
func DeleteInstance(session *Session, instance *Instance) error {
	//TODO: Use redis
	delete(session.Instances, instance.Name)
	err := DeleteContainer(instance.Name)

	wsServer.BroadcastTo(session.Id, "delete instance", instance.Name)

	return err
}
<commit_msg>Use 1.12.3 dind image<commit_after>package services

import (
	"context"
	"io"
	"log"
	"os"

	"golang.org/x/text/encoding"

	"github.com/docker/docker/api/types"
)

type Instance struct {
	Session *Session                `json:"-"`
	Name    string                  `json:"name"`
	IP      string                  `json:"ip"`
	Conn    *types.HijackedResponse `json:"-"`
	ExecId  string                  `json:"-"`
	Ctx     context.Context         `json:"-"`
}

var dindImage string
var defaultDindImageName string

func init() {
	dindImage = getDindImageName()
}

func getDindImageName() string {
	dindImage := os.Getenv("DIND_IMAGE")
	defaultDindImageName = "docker:1.12.3-dind"
	if len(dindImage) == 0 {
		dindImage = defaultDindImageName
	}
	return dindImage
}

func NewInstance(session *Session) (*Instance, error) {
	log.Printf("NewInstance - using image: [%s]\n", dindImage)
	instance, err := CreateInstance(session.Id, dindImage)
	if err != nil {
		return nil, err
	}
	instance.Session = session

	if session.Instances == nil {
		session.Instances = make(map[string]*Instance)
	}
	session.Instances[instance.Name] = instance

	go instance.Exec()

	wsServer.BroadcastTo(session.Id, "new instance", instance.Name, instance.IP)

	return instance, nil
}

type sessionWriter struct {
	instance *Instance
}

func (s *sessionWriter) Write(p []byte) (n int, err error) {
	wsServer.BroadcastTo(s.instance.Session.Id, "terminal out", s.instance.Name, string(p))
	return len(p), nil
}

func (i *Instance) ResizeTerminal(cols, rows uint) error {
	return ResizeExecConnection(i.ExecId, i.Ctx, cols, rows)
}

func (i *Instance) Exec() {
	i.Ctx = context.Background()

	id, err := CreateExecConnection(i.Name, i.Ctx)
	if err != nil {
		return
	}
	i.ExecId = id
	conn, err := AttachExecConnection(id, i.Ctx)
	if err != nil {
		return
	}

	i.Conn = conn

	go func() {
		encoder := encoding.Replacement.NewEncoder()
		sw := &sessionWriter{instance: i}
		io.Copy(encoder.Writer(sw), conn.Reader)
	}()

	select {
	case <-i.Ctx.Done():
	}
}

func GetInstance(session *Session, name string) *Instance {
	//TODO: Use redis
	return session.Instances[name]
}
func DeleteInstance(session *Session, instance *Instance) error {
	//TODO: Use redis
	delete(session.Instances, instance.Name)
	err := DeleteContainer(instance.Name)

	wsServer.BroadcastTo(session.Id, "delete instance", instance.Name)

	return err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"log"

	"github.com/hashicorp/memberlist"
	"github.com/newrelic/bosun/catalog"
	"github.com/newrelic/bosun/service"
)

type servicesDelegate struct {
	state             *catalog.ServicesState
	pendingBroadcasts [][]byte
	notifications     chan *service.Service
	inProcess         bool
	Metadata          NodeMetadata
}

type NodeMetadata struct {
	ClusterName string
	State       string
}

func NewServicesDelegate(state *catalog.ServicesState) *servicesDelegate {
	delegate := servicesDelegate{
		state:             state,
		pendingBroadcasts: make([][]byte, 0),
		notifications:     make(chan *service.Service, 25),
		inProcess:         false,
		Metadata:          NodeMetadata{ClusterName: "default"},
	}

	return &delegate
}

func (d *servicesDelegate) NodeMeta(limit int) []byte {
	log.Printf("NodeMeta(): %d\n", limit)
	data, err := json.Marshal(d.Metadata)
	if err != nil {
		log.Println("Error encoding Node metadata!")
		data = []byte("{}")
	}
	return data
}

func (d *servicesDelegate) NotifyMsg(message []byte) {
	if len(message) < 1 {
		log.Println("NotifyMsg(): empty")
		return
	}

	log.Printf("NotifyMsg(): %s\n", string(message))

	// TODO don't just send container structs, send message structs
	data := service.Decode(message)
	if data == nil {
		log.Printf("NotifyMsg(): error decoding!\n")
		return
	}

	// Lazily kick off goroutine
	if !d.inProcess {
		go func() {
			for entry := range d.notifications {
				d.state.AddServiceEntry(*entry)
			}
		}()
		d.inProcess = true
	}
	d.notifications <- data
}

func (d *servicesDelegate) GetBroadcasts(overhead, limit int) [][]byte {
	log.Printf("GetBroadcasts(): %d %d\n", overhead, limit)

	broadcast := make([][]byte, 0, 1)

	select {
	case broadcast = <-d.state.Broadcasts:
	default:
		if len(d.pendingBroadcasts) < 1 {
			return nil
		}
	}

	// Prefer newest messages (TODO what about tombstones?)
	broadcast = append(broadcast, d.pendingBroadcasts...)
	d.pendingBroadcasts = make([][]byte, 0, 1)

	broadcast, leftover := packPacket(broadcast, limit, overhead)
	if len(leftover) > 0 {
		d.pendingBroadcasts = leftover
	}

	if broadcast == nil || len(broadcast) < 1 {
		log.Println("Not enough space to fit any messages or message was nil")
		return nil
	}

	log.Printf("Sending broadcast %d msgs %d 1st length\n",
		len(broadcast), len(broadcast[0]),
	)
	if len(leftover) > 0 {
		log.Printf("Leaving %d messages unsent\n", len(leftover))
	}

	return broadcast
}

func (d *servicesDelegate) LocalState(join bool) []byte {
	log.Printf("LocalState(): %b\n", join)
	return d.state.Encode()
}

func (d *servicesDelegate) MergeRemoteState(buf []byte, join bool) {
	log.Printf("MergeRemoteState(): %s %b\n", string(buf), join)

	otherState, err := catalog.Decode(buf)
	if err != nil {
		log.Printf("Failed to MergeRemoteState(): %s", err.Error())
		return
	}

	log.Printf("Merging state: %s", otherState.Format(nil))

	d.state.Merge(otherState)
}

func (d *servicesDelegate) NotifyJoin(node *memberlist.Node) {
	log.Printf("NotifyJoin(): %s %s\n", node.Name, string(node.Meta))
}

func (d *servicesDelegate) NotifyLeave(node *memberlist.Node) {
	log.Printf("NotifyLeave(): %s\n", node.Name)
	go d.state.ExpireServer(node.Name)
}

func (d *servicesDelegate) NotifyUpdate(node *memberlist.Node) {
	log.Printf("NotifyUpdate(): %s\n", node.Name)
}

func packPacket(broadcasts [][]byte, limit int, overhead int) (packet [][]byte, leftover [][]byte) {
	total := 0
	leftover = make([][]byte, 0) // So we don't return unallocated buffer
	for _, message := range broadcasts {
		if total+len(message)+overhead < limit {
			packet = append(packet, message)
			total += len(message) + overhead
		} else {
			leftover = append(leftover, message)
		}
	}

	return packet, leftover
}
<commit_msg>Make it clear this is not an error.<commit_after>package main

import (
	"encoding/json"
	"log"

	"github.com/hashicorp/memberlist"
	"github.com/newrelic/bosun/catalog"
	"github.com/newrelic/bosun/service"
)

type servicesDelegate struct {
	state             *catalog.ServicesState
	pendingBroadcasts [][]byte
	notifications     chan *service.Service
	inProcess         bool
	Metadata          NodeMetadata
}

type NodeMetadata struct {
	ClusterName string
	State       string
}

func NewServicesDelegate(state *catalog.ServicesState) *servicesDelegate {
	delegate := servicesDelegate{
		state:             state,
		pendingBroadcasts: make([][]byte, 0),
		notifications:     make(chan *service.Service, 25),
		inProcess:         false,
		Metadata:          NodeMetadata{ClusterName: "default"},
	}

	return &delegate
}

func (d *servicesDelegate) NodeMeta(limit int) []byte {
	log.Printf("NodeMeta(): %d\n", limit)
	data, err := json.Marshal(d.Metadata)
	if err != nil {
		log.Println("Error encoding Node metadata!")
		data = []byte("{}")
	}
	return data
}

func (d *servicesDelegate) NotifyMsg(message []byte) {
	if len(message) < 1 {
		log.Println("NotifyMsg(): empty")
		return
	}

	log.Printf("NotifyMsg(): %s\n", string(message))

	// TODO don't just send container structs, send message structs
	data := service.Decode(message)
	if data == nil {
		log.Printf("NotifyMsg(): error decoding!\n")
		return
	}

	// Lazily kick off goroutine
	if !d.inProcess {
		go func() {
			for entry := range d.notifications {
				d.state.AddServiceEntry(*entry)
			}
		}()
		d.inProcess = true
	}
	d.notifications <- data
}

func (d *servicesDelegate) GetBroadcasts(overhead, limit int) [][]byte {
	log.Printf("GetBroadcasts(): %d %d\n", overhead, limit)

	broadcast := make([][]byte, 0, 1)

	select {
	case broadcast = <-d.state.Broadcasts:
	default:
		if len(d.pendingBroadcasts) < 1 {
			return nil
		}
	}

	// Prefer newest messages (TODO what about tombstones?)
	broadcast = append(broadcast, d.pendingBroadcasts...)
	d.pendingBroadcasts = make([][]byte, 0, 1)

	broadcast, leftover := packPacket(broadcast, limit, overhead)
	if len(leftover) > 0 {
		d.pendingBroadcasts = leftover
	}

	if broadcast == nil || len(broadcast) < 1 {
		log.Println("Note: Not enough space to fit any messages or message was nil")
		return nil
	}

	log.Printf("Sending broadcast %d msgs %d 1st length\n",
		len(broadcast), len(broadcast[0]),
	)
	if len(leftover) > 0 {
		log.Printf("Leaving %d messages unsent\n", len(leftover))
	}

	return broadcast
}

func (d *servicesDelegate) LocalState(join bool) []byte {
	log.Printf("LocalState(): %b\n", join)
	return d.state.Encode()
}

func (d *servicesDelegate) MergeRemoteState(buf []byte, join bool) {
	log.Printf("MergeRemoteState(): %s %b\n", string(buf), join)

	otherState, err := catalog.Decode(buf)
	if err != nil {
		log.Printf("Failed to MergeRemoteState(): %s", err.Error())
		return
	}

	log.Printf("Merging state: %s", otherState.Format(nil))

	d.state.Merge(otherState)
}

func (d *servicesDelegate) NotifyJoin(node *memberlist.Node) {
	log.Printf("NotifyJoin(): %s %s\n", node.Name, string(node.Meta))
}

func (d *servicesDelegate) NotifyLeave(node *memberlist.Node) {
	log.Printf("NotifyLeave(): %s\n", node.Name)
	go d.state.ExpireServer(node.Name)
}

func (d *servicesDelegate) NotifyUpdate(node *memberlist.Node) {
	log.Printf("NotifyUpdate(): %s\n", node.Name)
}

func packPacket(broadcasts [][]byte, limit int, overhead int) (packet [][]byte, leftover [][]byte) {
	total := 0
	leftover = make([][]byte, 0) // So we don't return unallocated buffer
	for _, message := range broadcasts {
		if total+len(message)+overhead < limit {
			packet = append(packet, message)
			total += len(message) + overhead
		} else {
			leftover = append(leftover, message)
		}
	}

	return packet, leftover
}
<|endoftext|>


<commit_before>package hoverfly

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"sync"

	log "github.com/Sirupsen/logrus"
	authBackend "github.com/SpectoLabs/hoverfly/core/authentication/backends"
	"github.com/SpectoLabs/hoverfly/core/cache"
	"github.com/SpectoLabs/hoverfly/core/matching"
	"github.com/SpectoLabs/hoverfly/core/metrics"
	"github.com/SpectoLabs/hoverfly/core/models"
	"github.com/SpectoLabs/hoverfly/core/modes"
	"github.com/rusenask/goproxy"
)

// SimulateMode - default mode when Hoverfly looks for captured requests to respond
const SimulateMode = "simulate"

// SynthesizeMode - all requests are sent to middleware to create response
const SynthesizeMode = "synthesize"

// ModifyMode - middleware is applied to outgoing and incoming traffic
const ModifyMode = "modify"

// CaptureMode - requests are captured and stored in cache
const CaptureMode = "capture"

// orPanic - wrapper for logging errors
func orPanic(err error) {
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Panic("Got error.")
	}
}

// Hoverfly provides access to hoverfly - updating/starting/stopping proxy, http client and configuration, cache access
type Hoverfly struct {
	RequestCache   cache.Cache
	RequestMatcher matching.RequestMatcher
	MetadataCache  cache.Cache
	Authentication authBackend.Authentication
	HTTP           *http.Client
	Cfg            *Configuration
	Counter        *metrics.CounterByMode

	ResponseDelays models.ResponseDelays

	Proxy   *goproxy.ProxyHttpServer
	SL      *StoppableListener
	mu      sync.Mutex
	version string

	modeMap map[string]modes.Mode
}

// GetNewHoverfly returns a configured ProxyHttpServer and DBClient
func GetNewHoverfly(cfg *Configuration, requestCache, metadataCache cache.Cache, authentication authBackend.Authentication) *Hoverfly {
	requestMatcher := matching.RequestMatcher{
		RequestCache:  requestCache,
		TemplateStore: matching.RequestTemplateStore{},
		Webserver:     &cfg.Webserver,
	}

	h := &Hoverfly{
		RequestCache:   requestCache,
		MetadataCache:  metadataCache,
		Authentication: authentication,
		HTTP:           GetDefaultHoverflyHTTPClient(cfg.TLSVerification),
		Cfg:            cfg,
		Counter:        metrics.NewModeCounter([]string{SimulateMode, SynthesizeMode, ModifyMode, CaptureMode}),
		ResponseDelays: &models.ResponseDelayList{},
		RequestMatcher: requestMatcher,
	}

	modeMap := make(map[string]modes.Mode)

	modeMap["capture"] = modes.CaptureMode{Hoverfly: h}
	modeMap["simulate"] = modes.SimulateMode{Hoverfly: h}
	modeMap["modify"] = modes.ModifyMode{Hoverfly: h}
	modeMap["synthesize"] = modes.SynthesizeMode{Hoverfly: h}

	h.modeMap = modeMap

	h.version = "v0.9.2"

	return h
}

func GetDefaultHoverflyHTTPClient(tlsVerification bool) *http.Client {
	return &http.Client{CheckRedirect: func(req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse
	}, Transport: &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: tlsVerification},
	}}
}

// StartProxy - starts proxy with current configuration, this method is non blocking.
func (hf *Hoverfly) StartProxy() error {

	rebuildHashes(hf.RequestCache, hf.Cfg.Webserver)

	if hf.Cfg.ProxyPort == "" {
		return fmt.Errorf("Proxy port is not set!")
	}

	if hf.Cfg.Webserver {
		hf.Proxy = NewWebserverProxy(hf)
	} else {
		hf.Proxy = NewProxy(hf)
	}

	log.WithFields(log.Fields{
		"destination": hf.Cfg.Destination,
		"port":        hf.Cfg.ProxyPort,
		"mode":        hf.Cfg.GetMode(),
	}).Info("current proxy configuration")

	// creating TCP listener
	listener, err := net.Listen("tcp", fmt.Sprintf(":%s", hf.Cfg.ProxyPort))
	if err != nil {
		return err
	}

	sl, err := NewStoppableListener(listener)
	if err != nil {
		return err
	}
	hf.SL = sl
	server := http.Server{}

	hf.Cfg.ProxyControlWG.Add(1)

	go func() {
		defer func() {
			log.Info("sending done signal")
			hf.Cfg.ProxyControlWG.Done()
		}()
		log.Info("serving proxy")
		server.Handler = hf.Proxy
		log.Warn(server.Serve(sl))
	}()

	return nil
}

// StopProxy - stops proxy
func (hf *Hoverfly) StopProxy() {
	hf.SL.Stop()
	hf.Cfg.ProxyControlWG.Wait()
}

// processRequest - processes incoming requests and based on proxy state (record/playback)
// returns HTTP response.
func (hf *Hoverfly) processRequest(req *http.Request) *http.Response {
	requestDetails, err := models.NewRequestDetailsFromHttpRequest(req)
	if err != nil {
		return modes.ErrorResponse(req, err, "Could not interpret HTTP request")
	}

	mode := hf.Cfg.GetMode()

	response, err := hf.modeMap[mode].Process(req, requestDetails)

	// Don't delete the error
	// and definitely don't delay people in capture mode
	if err != nil || mode == CaptureMode {
		return response
	}

	respDelay := hf.ResponseDelays.GetDelay(requestDetails)
	if respDelay != nil {
		respDelay.Execute()
	}

	return response
}

// DoRequest - performs request and returns response that should be returned to client and error
func (hf *Hoverfly) DoRequest(request *http.Request) (*http.Response, error) {

	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	requestBody, _ := ioutil.ReadAll(request.Body)

	request.Body = ioutil.NopCloser(bytes.NewReader(requestBody))

	resp, err := hf.HTTP.Do(request)

	request.Body = ioutil.NopCloser(bytes.NewReader(requestBody))
	if err != nil {
		return nil, err
	}

	resp.Header.Set("hoverfly", "Was-Here")

	return resp, nil

}

// GetResponse returns stored response from cache
func (hf *Hoverfly) GetResponse(requestDetails models.RequestDetails) (*models.ResponseDetails, *matching.MatchingError) {
	return hf.RequestMatcher.GetResponse(&requestDetails)
}

// save gets request fingerprint, extracts request body, status code and headers, then saves it to cache
func (hf *Hoverfly) Save(request *models.RequestDetails, response *models.ResponseDetails) error {

	pair := models.RequestResponsePair{
		Request:  *request,
		Response: *response,
	}

	err := hf.RequestMatcher.SaveRequestResponsePair(&pair)
	if err != nil {
		return err
	}

	return nil
}

func (this Hoverfly) ApplyMiddleware(pair models.RequestResponsePair) (models.RequestResponsePair, error) {
	if this.Cfg.Middleware.IsSet() {
		return this.Cfg.Middleware.Execute(pair)
	}

	return pair, nil
}

func (this Hoverfly) IsMiddlewareSet() bool {
	return this.Cfg.Middleware.IsSet()
}
<commit_msg>Updated hoverfly version to v0.10.0<commit_after>package hoverfly

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"sync"

	log "github.com/Sirupsen/logrus"
	authBackend "github.com/SpectoLabs/hoverfly/core/authentication/backends"
	"github.com/SpectoLabs/hoverfly/core/cache"
	"github.com/SpectoLabs/hoverfly/core/matching"
	"github.com/SpectoLabs/hoverfly/core/metrics"
	"github.com/SpectoLabs/hoverfly/core/models"
	"github.com/SpectoLabs/hoverfly/core/modes"
	"github.com/rusenask/goproxy"
)

// SimulateMode - default mode when Hoverfly looks for captured requests to respond
const SimulateMode = "simulate"

// SynthesizeMode - all requests are sent to middleware to create response
const SynthesizeMode = "synthesize"

// ModifyMode - middleware is applied to outgoing and incoming traffic
const ModifyMode = "modify"

// CaptureMode - requests are captured and stored in cache
const CaptureMode = "capture"

// orPanic - wrapper for logging errors
func orPanic(err error) {
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Panic("Got error.")
	}
}

// Hoverfly provides access to hoverfly - updating/starting/stopping proxy, http client and configuration, cache access
type Hoverfly struct {
	RequestCache   cache.Cache
	RequestMatcher matching.RequestMatcher
	MetadataCache  cache.Cache
	Authentication authBackend.Authentication
	HTTP           *http.Client
	Cfg            *Configuration
	Counter        *metrics.CounterByMode

	ResponseDelays models.ResponseDelays

	Proxy   *goproxy.ProxyHttpServer
	SL      *StoppableListener
	mu      sync.Mutex
	version string

	modeMap map[string]modes.Mode
}

// GetNewHoverfly returns a configured ProxyHttpServer and DBClient
func GetNewHoverfly(cfg *Configuration, requestCache, metadataCache cache.Cache, authentication authBackend.Authentication) *Hoverfly {
	requestMatcher := matching.RequestMatcher{
		RequestCache:  requestCache,
		TemplateStore: matching.RequestTemplateStore{},
		Webserver:     &cfg.Webserver,
	}

	h := &Hoverfly{
		RequestCache:   requestCache,
		MetadataCache:  metadataCache,
		Authentication: authentication,
		HTTP:           GetDefaultHoverflyHTTPClient(cfg.TLSVerification),
		Cfg:            cfg,
		Counter:        metrics.NewModeCounter([]string{SimulateMode, SynthesizeMode, ModifyMode, CaptureMode}),
		ResponseDelays: &models.ResponseDelayList{},
		RequestMatcher: requestMatcher,
	}

	modeMap := make(map[string]modes.Mode)

	modeMap["capture"] = modes.CaptureMode{Hoverfly: h}
	modeMap["simulate"] = modes.SimulateMode{Hoverfly: h}
	modeMap["modify"] = modes.ModifyMode{Hoverfly: h}
	modeMap["synthesize"] = modes.SynthesizeMode{Hoverfly: h}

	h.modeMap = modeMap

	h.version = "v0.10.0"

	return h
}

func GetDefaultHoverflyHTTPClient(tlsVerification bool) *http.Client {
	return &http.Client{CheckRedirect: func(req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse
	}, Transport: &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: tlsVerification},
	}}
}

// StartProxy - starts proxy with current configuration, this method is non blocking.
func (hf *Hoverfly) StartProxy() error {

	rebuildHashes(hf.RequestCache, hf.Cfg.Webserver)

	if hf.Cfg.ProxyPort == "" {
		return fmt.Errorf("Proxy port is not set!")
	}

	if hf.Cfg.Webserver {
		hf.Proxy = NewWebserverProxy(hf)
	} else {
		hf.Proxy = NewProxy(hf)
	}

	log.WithFields(log.Fields{
		"destination": hf.Cfg.Destination,
		"port":        hf.Cfg.ProxyPort,
		"mode":        hf.Cfg.GetMode(),
	}).Info("current proxy configuration")

	// creating TCP listener
	listener, err := net.Listen("tcp", fmt.Sprintf(":%s", hf.Cfg.ProxyPort))
	if err != nil {
		return err
	}

	sl, err := NewStoppableListener(listener)
	if err != nil {
		return err
	}
	hf.SL = sl
	server := http.Server{}

	hf.Cfg.ProxyControlWG.Add(1)

	go func() {
		defer func() {
			log.Info("sending done signal")
			hf.Cfg.ProxyControlWG.Done()
		}()
		log.Info("serving proxy")
		server.Handler = hf.Proxy
		log.Warn(server.Serve(sl))
	}()

	return nil
}

// StopProxy - stops proxy
func (hf *Hoverfly) StopProxy() {
	hf.SL.Stop()
	hf.Cfg.ProxyControlWG.Wait()
}

// processRequest - processes incoming requests and based on proxy state (record/playback)
// returns HTTP response.
func (hf *Hoverfly) processRequest(req *http.Request) *http.Response {
	requestDetails, err := models.NewRequestDetailsFromHttpRequest(req)
	if err != nil {
		return modes.ErrorResponse(req, err, "Could not interpret HTTP request")
	}

	mode := hf.Cfg.GetMode()

	response, err := hf.modeMap[mode].Process(req, requestDetails)

	// Don't delete the error
	// and definitely don't delay people in capture mode
	if err != nil || mode == CaptureMode {
		return response
	}

	respDelay := hf.ResponseDelays.GetDelay(requestDetails)
	if respDelay != nil {
		respDelay.Execute()
	}

	return response
}

// DoRequest - performs request and returns response that should be returned to client and error
func (hf *Hoverfly) DoRequest(request *http.Request) (*http.Response, error) {

	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	requestBody, _ := ioutil.ReadAll(request.Body)

	request.Body = ioutil.NopCloser(bytes.NewReader(requestBody))

	resp, err := hf.HTTP.Do(request)

	request.Body = ioutil.NopCloser(bytes.NewReader(requestBody))
	if err != nil {
		return nil, err
	}

	resp.Header.Set("hoverfly", "Was-Here")

	return resp, nil

}

// GetResponse returns stored response from cache
func (hf *Hoverfly) GetResponse(requestDetails models.RequestDetails) (*models.ResponseDetails, *matching.MatchingError) {
	return hf.RequestMatcher.GetResponse(&requestDetails)
}

// save gets request fingerprint, extracts request body, status code and headers, then saves it to cache
func (hf *Hoverfly) Save(request *models.RequestDetails, response *models.ResponseDetails) error {

	pair := models.RequestResponsePair{
		Request:  *request,
		Response: *response,
	}

	err := hf.RequestMatcher.SaveRequestResponsePair(&pair)
	if err != nil {
		return err
	}

	return nil
}

func (this Hoverfly) ApplyMiddleware(pair models.RequestResponsePair) (models.RequestResponsePair, error) {
	if this.Cfg.Middleware.IsSet() {
		return this.Cfg.Middleware.Execute(pair)
	}

	return pair, nil
}

func (this Hoverfly) IsMiddlewareSet() bool {
	return this.Cfg.Middleware.IsSet()
}
<|endoftext|>


<commit_before>package core

import (
	"fmt"

	pErr "github.com/tapglue/snaas/error"
	"github.com/tapglue/snaas/platform/pg"
	"github.com/tapglue/snaas/platform/sns"
	"github.com/tapglue/snaas/service/app"
	"github.com/tapglue/snaas/service/platform"
)

var (
	defaultActive = true
)

// PlatformCreateFunc stores the provided platform.
type PlatformCreateFunc func(
	currentApp *app.App,
	p *platform.Platform,
	cert, key string,
) (*platform.Platform, error)

// PlatformCreate stores the provided platform.
func PlatformCreate(
	platforms platform.Service,
	createAPNS sns.AppCreateAPNSFunc,
	createAPNSSandbox sns.AppCreateAPNSSandboxFunc,
	createAndroid sns.AppCreateGCMFunc,
) PlatformCreateFunc {
	return func(
		currentApp *app.App,
		p *platform.Platform,
		cert, key string,
	) (*platform.Platform, error) {
		arn := ""

		fmt.Printf("\n%s\n%s\n%#v\n\n", cert, key, p)

		switch p.Ecosystem {
		case platform.Android:
			var err error
			arn, err = createAndroid(p.Name, key)
			if err != nil {
				return nil, err
			}
		case platform.IOS:
			var err error
			arn, err = createAPNS(p.Name, cert, key)
			if err != nil {
				return nil, err
			}
		case platform.IOSSandbox:
			var err error
			arn, err = createAPNSSandbox(p.Name, cert, key)
			if err != nil {
				return nil, err
			}
		}

		p.AppID = currentApp.ID
		p.ARN = arn

		return platforms.Put(pg.MetaNamespace, p)
	}
}

// PlatformFetchActiveFunc returns the active platform for the current app and the
// given ecosystem.
type PlatformFetchActiveFunc func(*app.App, sns.Platform) (*platform.Platform, error)

// PlatformFetchActive returns the active platform for the current app and the
// given ecosystem.
func PlatformFetchActive(platforms platform.Service) PlatformFetchActiveFunc {
	return func(
		currentApp *app.App,
		ecosystem sns.Platform,
	) (*platform.Platform, error) {
		ps, err := platforms.Query(pg.MetaNamespace, platform.QueryOptions{
			Active: &defaultActive,
			AppIDs: []uint64{
				currentApp.ID,
			},
			Deleted: &defaultDeleted,
			Ecosystems: []sns.Platform{
				ecosystem,
			},
		})
		if err != nil {
			return nil, err
		}

		if len(ps) != 1 {
			return nil, pErr.Wrap(
				pErr.ErrNotFound,
				"no active platform found for %s",
				sns.PlatformIdentifiers[ecosystem],
			)
		}

		return ps[0], nil
	}
}

// PlatformFetchByARNFunc returns the Platform for the given ARN.
type PlatformFetchByARNFunc func(arn string) (*platform.Platform, error)

// PlatformFetchByARN returns the Platform for the given ARN.
func PlatformFetchByARN(platforms platform.Service) PlatformFetchByARNFunc {
	return func(arn string) (*platform.Platform, error) {
		ps, err := platforms.Query(pg.MetaNamespace, platform.QueryOptions{
			ARNs: []string{
				arn,
			},
			Deleted: &defaultDeleted,
		})
		if err != nil {
			return nil, err
		}

		if len(ps) != 1 {
			return nil, pErr.Wrap(
				pErr.ErrNotFound,
				"no platform found for '%s'",
				arn,
			)
		}

		return ps[0], nil
	}
}
<commit_msg>Remove log statement<commit_after>package core

import (
	pErr "github.com/tapglue/snaas/error"
	"github.com/tapglue/snaas/platform/pg"
	"github.com/tapglue/snaas/platform/sns"
	"github.com/tapglue/snaas/service/app"
	"github.com/tapglue/snaas/service/platform"
)

var (
	defaultActive = true
)

// PlatformCreateFunc stores the provided platform.
type PlatformCreateFunc func(
	currentApp *app.App,
	p *platform.Platform,
	cert, key string,
) (*platform.Platform, error)

// PlatformCreate stores the provided platform.
func PlatformCreate(
	platforms platform.Service,
	createAPNS sns.AppCreateAPNSFunc,
	createAPNSSandbox sns.AppCreateAPNSSandboxFunc,
	createAndroid sns.AppCreateGCMFunc,
) PlatformCreateFunc {
	return func(
		currentApp *app.App,
		p *platform.Platform,
		cert, key string,
	) (*platform.Platform, error) {
		arn := ""

		switch p.Ecosystem {
		case platform.Android:
			var err error
			arn, err = createAndroid(p.Name, key)
			if err != nil {
				return nil, err
			}
		case platform.IOS:
			var err error
			arn, err = createAPNS(p.Name, cert, key)
			if err != nil {
				return nil, err
			}
		case platform.IOSSandbox:
			var err error
			arn, err = createAPNSSandbox(p.Name, cert, key)
			if err != nil {
				return nil, err
			}
		}

		p.AppID = currentApp.ID
		p.ARN = arn

		return platforms.Put(pg.MetaNamespace, p)
	}
}

// PlatformFetchActiveFunc returns the active platform for the current app and the
// given ecosystem.
type PlatformFetchActiveFunc func(*app.App, sns.Platform) (*platform.Platform, error)

// PlatformFetchActive returns the active platform for the current app and the
// given ecosystem.
func PlatformFetchActive(platforms platform.Service) PlatformFetchActiveFunc {
	return func(
		currentApp *app.App,
		ecosystem sns.Platform,
	) (*platform.Platform, error) {
		ps, err := platforms.Query(pg.MetaNamespace, platform.QueryOptions{
			Active: &defaultActive,
			AppIDs: []uint64{
				currentApp.ID,
			},
			Deleted: &defaultDeleted,
			Ecosystems: []sns.Platform{
				ecosystem,
			},
		})
		if err != nil {
			return nil, err
		}

		if len(ps) != 1 {
			return nil, pErr.Wrap(
				pErr.ErrNotFound,
				"no active platform found for %s",
				sns.PlatformIdentifiers[ecosystem],
			)
		}

		return ps[0], nil
	}
}

// PlatformFetchByARNFunc returns the Platform for the given ARN.
type PlatformFetchByARNFunc func(arn string) (*platform.Platform, error)

// PlatformFetchByARN returns the Platform for the given ARN.
func PlatformFetchByARN(platforms platform.Service) PlatformFetchByARNFunc {
	return func(arn string) (*platform.Platform, error) {
		ps, err := platforms.Query(pg.MetaNamespace, platform.QueryOptions{
			ARNs: []string{
				arn,
			},
			Deleted: &defaultDeleted,
		})
		if err != nil {
			return nil, err
		}

		if len(ps) != 1 {
			return nil, pErr.Wrap(
				pErr.ErrNotFound,
				"no platform found for '%s'",
				arn,
			)
		}

		return ps[0], nil
	}
}
<|endoftext|>


<commit_before>// Radix sort for []float64.
package zfloat64

import (
	"math"
	"sort"
)

// Calling zfloat64.Sort() on slices smaller than this will result is sorting with sort.Sort() instead.
const MinSize = 128

const radix uint = 8
const radixShift uint = 3
const bitSize uint = 64

// Sorts x using a Radix sort (Small slices are sorted with sort.Sort() instead).
func Sort(x []float64) {
	if len(x) < MinSize {
		sort.Float64s(x)
	} else {
		SortBYOB(x, make([]float64, len(x)))
	}
}

// Similar to Sort(), but returns a sorted copy of x, leaving x unmodified.
func SortCopy(x []float64) []float64 {
	y := make([]float64, len(x))
	copy(y, x)
	Sort(y)
	return y
}

// Sorts x using a Radix sort, using supplied buffer space. Panics if
// len(x) is greater than len(buffer). Uses radix sort even on small slices.
func SortBYOB(x, buffer []float64) {
	if len(x) > len(buffer) {
		panic("Buffer too small")
	}
	if len(x) < 2 {
		return
	}

	nans := 0
	for idx, val := range x {
		// Don't sort NaNs, just put them up front and skip them
		if math.IsNaN(val) {
			x[idx] = x[nans]
			x[nans] = val
			nans++
		}
	}
	// Each pass processes a byte offset, copying back and forth between slices
	from := x[nans:]
	to := buffer[:len(from)]
	var key uint8
	var prev float64
	var uintVal uint64
	for keyOffset := uint(0); keyOffset < bitSize; keyOffset += radix {
		keyMask := uint64(0xFF << keyOffset) // Current 'digit' to look at
		var counts [256]int                  // Keep track of the number of elements for each kind of byte
		var offset [256]int                  // Keep track of where room is made for byte groups in the buffer
		sorted := true                       // Check for already sorted
		prev = 0                             // if elem is always >= prev it is already sorted
		for _, val := range from {
			uintVal = floatFlip(math.Float64bits(val))
			key = uint8((uintVal & keyMask) >> keyOffset) // fetch the byte at current 'digit'
			counts[key]++                                 // count of values to put in this digit's bucket
			if sorted {                                   // Detect sorted
				sorted = val >= prev
				prev = val
			}
		}
		if sorted {
			if (keyOffset>>radixShift)&uint(1) == 1 {
				copy(to, from)
			}
			return
		}
		// Find target bucket offsets
		for i := 1; i < len(offset); i++ {
			offset[i] = offset[i-1] + counts[i-1]
		}

		// Rebucket while copying to other buffer
		for _, val := range from {
			uintVal = floatFlip(math.Float64bits(val))
			key = uint8((uintVal & keyMask) >> keyOffset) // Get the digit
			to[offset[key]] = val                         // Copy the element to the digit's bucket
			offset[key]++                                 // One less space, move the offset
		}
		// On next pass copy data the other way
		to, from = from, to
	}
}

// Converts a uint64 that represents a true float to one sorts properly
func floatFlip(x uint64) uint64 {
	if (x & 0x8000000000000000) == 0x8000000000000000 {
		return x ^ 0xFFFFFFFFFFFFFFFF
	}
	return x ^ 0x8000000000000000
}
<commit_msg>Restored min length of []float64 to 256<commit_after>// Radix sort for []float64.
package zfloat64

import (
	"math"
	"sort"
)

// Calling zfloat64.Sort() on slices smaller than this will result is sorting with sort.Sort() instead.
const MinSize = 256

const radix uint = 8
const radixShift uint = 3
const bitSize uint = 64

// Sorts x using a Radix sort (Small slices are sorted with sort.Sort() instead).
func Sort(x []float64) {
	if len(x) < MinSize {
		sort.Float64s(x)
	} else {
		SortBYOB(x, make([]float64, len(x)))
	}
}

// Similar to Sort(), but returns a sorted copy of x, leaving x unmodified.
func SortCopy(x []float64) []float64 {
	y := make([]float64, len(x))
	copy(y, x)
	Sort(y)
	return y
}

// Sorts x using a Radix sort, using supplied buffer space. Panics if
// len(x) is greater than len(buffer). Uses radix sort even on small slices.
func SortBYOB(x, buffer []float64) {
	if len(x) > len(buffer) {
		panic("Buffer too small")
	}
	if len(x) < 2 {
		return
	}

	nans := 0
	for idx, val := range x {
		// Don't sort NaNs, just put them up front and skip them
		if math.IsNaN(val) {
			x[idx] = x[nans]
			x[nans] = val
			nans++
		}
	}
	// Each pass processes a byte offset, copying back and forth between slices
	from := x[nans:]
	to := buffer[:len(from)]
	var key uint8
	var prev float64
	var uintVal uint64
	for keyOffset := uint(0); keyOffset < bitSize; keyOffset += radix {
		keyMask := uint64(0xFF << keyOffset) // Current 'digit' to look at
		var counts [256]int                  // Keep track of the number of elements for each kind of byte
		var offset [256]int                  // Keep track of where room is made for byte groups in the buffer
		sorted := true                       // Check for already sorted
		prev = 0                             // if elem is always >= prev it is already sorted
		for _, val := range from {
			uintVal = floatFlip(math.Float64bits(val))
			key = uint8((uintVal & keyMask) >> keyOffset) // fetch the byte at current 'digit'
			counts[key]++                                 // count of values to put in this digit's bucket
			if sorted {                                   // Detect sorted
				sorted = val >= prev
				prev = val
			}
		}
		if sorted {
			if (keyOffset>>radixShift)&uint(1) == 1 {
				copy(to, from)
			}
			return
		}
		// Find target bucket offsets
		for i := 1; i < len(offset); i++ {
			offset[i] = offset[i-1] + counts[i-1]
		}

		// Rebucket while copying to other buffer
		for _, val := range from {
			uintVal = floatFlip(math.Float64bits(val))
			key = uint8((uintVal & keyMask) >> keyOffset) // Get the digit
			to[offset[key]] = val                         // Copy the element to the digit's bucket
			offset[key]++                                 // One less space, move the offset
		}
		// On next pass copy data the other way
		to, from = from, to
	}
}

// Converts a uint64 that represents a true float to one sorts properly
func floatFlip(x uint64) uint64 {
	if (x & 0x8000000000000000) == 0x8000000000000000 {
		return x ^ 0xFFFFFFFFFFFFFFFF
	}
	return x ^ 0x8000000000000000
}
<|endoftext|>