<commit_before>package rest

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

// Resource represents a domain model.
type Resource interface{}

// ResourceHandler specifies the endpoint handlers for working with a resource. This
// consists of the business logic for performing CRUD operations.
type ResourceHandler interface {
	// ResourceName is used to identify what resource a handler corresponds to and is
	// used in the endpoint URLs, i.e. /api/:version/resourceName. This should be
	// unique across all ResourceHandlers.
	ResourceName() string

	// CreateURI returns the URI for creating a resource.
	CreateURI() string

	CreateDocumentation() string

	// ReadURI returns the URI for reading a specific resource.
	ReadURI() string

	ReadDocumentation() string

	// ReadListURI returns the URI for reading a list of resources.
	ReadListURI() string

	ReadListDocumentation() string

	// UpdateURI returns the URI for updating a specific resource.
	UpdateURI() string

	UpdateDocumentation() string

	// UpdateListURI returns the URI for updating a list of resources.
	UpdateListURI() string

	UpdateListDocumentation() string

	// DeleteURI returns the URI for deleting a specific resource.
	DeleteURI() string

	DeleteDocumentation() string

	// CreateResource is the logic that corresponds to creating a new resource at
	// POST /api/:version/resourceName. Typically, this would insert a record into a
	// database. It returns the newly created resource or an error if the create failed.
	CreateResource(RequestContext, Payload, string) (Resource, error)

	// ReadResourceList is the logic that corresponds to reading multiple resources,
	// perhaps with specified query parameters accessed through the RequestContext. This
	// is mapped to GET /api/:version/resourceName. Typically, this would make some sort
	// of database query to fetch the resources. It returns the slice of results, a
	// cursor (or empty) string, and error (or nil).
	ReadResourceList(RequestContext, int, string, string) ([]Resource, string, error)

	// ReadResource is the logic that corresponds to reading a single resource by its ID
	// at GET /api/:version/resourceName/{id}. Typically, this would make some sort of
	// database query to load the resource. If the resource doesn't exist, nil should be
	// returned along with an appropriate error.
	ReadResource(RequestContext, string, string) (Resource, error)

	// UpdateResourceList is the logic that corresponds to updating a collection of
	// resources at PUT /api/:version/resourceName. Typically, this would make some
	// sort of database update call. It returns the updated resources or an error if
	// the update failed.
	UpdateResourceList(RequestContext, []Payload, string) ([]Resource, error)

	// UpdateResource is the logic that corresponds to updating an existing resource at
	// PUT /api/:version/resourceName/{id}. Typically, this would make some sort of
	// database update call. It returns the updated resource or an error if the update
	// failed.
	UpdateResource(RequestContext, string, Payload, string) (Resource, error)

	// DeleteResource is the logic that corresponds to deleting an existing resource at
	// DELETE /api/:version/resourceName/{id}. Typically, this would make some sort of
	// database delete call. It returns the deleted resource or an error if the delete
	// failed.
	DeleteResource(RequestContext, string, string) (Resource, error)

	// Authenticate is logic that is used to authenticate requests. The default behavior
	// of Authenticate, seen in BaseResourceHandler, always returns nil, meaning all
	// requests are authenticated. Returning an error means that the request is
	// unauthorized and any error message will be sent back with the response.
	Authenticate(*http.Request) error

	// Rules returns the resource rules to apply to incoming requests and outgoing
	// responses. The default behavior, seen in BaseResourceHandler, is to apply no
	// rules.
	Rules() Rules
}

// requestHandler constructs http.HandlerFuncs responsible for handling HTTP requests.
type requestHandler struct {
	API
}

// handleCreate returns a HandlerFunc which will deserialize the request payload, pass
// it to the provided create function, and then serialize and dispatch the response.
// The serialization mechanism used is specified by the "format" query parameter.
func (h requestHandler) handleCreate(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		data, err := decodePayload(payloadString(r.Body))
		if err != nil {
			// Payload decoding failed.
			ctx = ctx.setError(err)
			ctx = ctx.setStatus(http.StatusInternalServerError)
		} else {
			data, err := applyInboundRules(data, rules, version)
			if err != nil {
				// Type coercion failed.
				ctx = ctx.setError(UnprocessableRequest(err.Error()))
			} else {
				resource, err := handler.CreateResource(ctx, data, ctx.Version())
				if err == nil {
					resource = applyOutboundRules(resource, rules, version)
				}
				ctx = ctx.setResult(resource)
				ctx = ctx.setStatus(http.StatusCreated)
				if err != nil {
					ctx = ctx.setError(err)
				}
			}
		}

		h.sendResponse(w, ctx)
	}
}

// handleReadList returns a HandlerFunc which will pass the request context to the
// provided read function and then serialize and dispatch the response. The
// serialization mechanism used is specified by the "format" query parameter.
func (h requestHandler) handleReadList(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		resources, cursor, err := handler.ReadResourceList(
			ctx, ctx.Limit(), ctx.Cursor(), version)

		if err == nil {
			// Apply rules to results.
			for idx, resource := range resources {
				resources[idx] = applyOutboundRules(resource, rules, version)
			}
		}

		ctx = ctx.setResult(resources)
		ctx = ctx.setCursor(cursor)
		ctx = ctx.setError(err)
		ctx = ctx.setStatus(http.StatusOK)

		h.sendResponse(w, ctx)
	}
}

// handleRead returns a HandlerFunc which will pass the resource id to the provided
// read function and then serialize and dispatch the response. The serialization
// mechanism used is specified by the "format" query parameter.
func (h requestHandler) handleRead(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		resource, err := handler.ReadResource(ctx, ctx.ResourceID(), version)
		if err == nil {
			resource = applyOutboundRules(resource, rules, version)
		}

		ctx = ctx.setResult(resource)
		ctx = ctx.setError(err)
		ctx = ctx.setStatus(http.StatusOK)

		h.sendResponse(w, ctx)
	}
}

// handleUpdateList returns a HandlerFunc which will deserialize the request payload,
// pass it to the provided update function, and then serialize and dispatch the
// response. The serialization mechanism used is specified by the "format" query
// parameter.
func (h requestHandler) handleUpdateList(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		payloadStr := payloadString(r.Body)
		var data []Payload
		var err error
		data, err = decodePayloadSlice(payloadStr)
		if err != nil {
			var p Payload
			p, err = decodePayload(payloadStr)
			data = []Payload{p}
		}

		if err != nil {
			// Payload decoding failed.
			ctx = ctx.setError(BadRequest(err.Error()))
		} else {
			for i := range data {
				data[i], err = applyInboundRules(data[i], rules, version)
			}
			if err != nil {
				// Type coercion failed.
				ctx = ctx.setError(UnprocessableRequest(err.Error()))
			} else {
				resources, err := handler.UpdateResourceList(ctx, data, version)
				if err == nil {
					// Apply rules to results.
					for idx, resource := range resources {
						resources[idx] = applyOutboundRules(resource, rules, version)
					}
				}

				ctx = ctx.setResult(resources)
				ctx = ctx.setError(err)
				ctx = ctx.setStatus(http.StatusOK)
			}
		}

		h.sendResponse(w, ctx)
	}
}

// handleUpdate returns a HandlerFunc which will deserialize the request payload,
// pass it to the provided update function, and then serialize and dispatch the
// response. The serialization mechanism used is specified by the "format" query
// parameter.
func (h requestHandler) handleUpdate(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		data, err := decodePayload(payloadString(r.Body))
		if err != nil {
			// Payload decoding failed.
			ctx = ctx.setError(err)
			ctx = ctx.setStatus(http.StatusInternalServerError)
		} else {
			data, err := applyInboundRules(data, rules, version)
			if err != nil {
				// Type coercion failed.
				ctx = ctx.setError(UnprocessableRequest(err.Error()))
			} else {
				resource, err := handler.UpdateResource(
					ctx, ctx.ResourceID(), data, version)
				if err == nil {
					resource = applyOutboundRules(resource, rules, version)
				}

				ctx = ctx.setResult(resource)
				ctx = ctx.setError(err)
				ctx = ctx.setStatus(http.StatusOK)
			}
		}

		h.sendResponse(w, ctx)
	}
}

// handleDelete returns a HandlerFunc which will pass the resource id to the provided
// delete function and then serialize and dispatch the response. The serialization
// mechanism used is specified by the "format" query parameter.
func (h requestHandler) handleDelete(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		resource, err := handler.DeleteResource(ctx, ctx.ResourceID(), version)
		if err == nil {
			resource = applyOutboundRules(resource, rules, version)
		}

		ctx = ctx.setResult(resource)
		ctx = ctx.setError(err)
		ctx = ctx.setStatus(http.StatusOK)

		h.sendResponse(w, ctx)
	}
}

// sendResponse writes a success or error response to the provided http.ResponseWriter
// based on the contents of the RequestContext.
func (h requestHandler) sendResponse(w http.ResponseWriter, ctx RequestContext) {
	format := ctx.ResponseFormat()
	serializer, err := h.responseSerializer(format)
	if err != nil {
		// Fall back to json serialization.
		serializer = jsonSerializer{}
		ctx = ctx.setError(NotImplemented(fmt.Sprintf("Format not implemented: %s", format)))
	}

	sendResponse(w, NewResponse(ctx), serializer)
}

// sendResponse writes a response to the http.ResponseWriter.
func sendResponse(w http.ResponseWriter, r response, serializer ResponseSerializer) {
	status := r.Status
	contentType := serializer.ContentType()
	response, err := serializer.Serialize(r.Payload)
	if err != nil {
		log.Printf("Response serialization failed: %s", err)
		status = http.StatusInternalServerError
		contentType = "text/plain"
		response = []byte(err.Error())
	}

	w.Header().Set("Content-Type", contentType)
	w.WriteHeader(status)
	w.Write(response)
}

// decodePayload unmarshals the JSON payload and returns the resulting map. If the
// content is empty, an empty map is returned. If decoding fails, nil is returned
// with an error.
func decodePayload(payload []byte) (Payload, error) {
	if len(payload) == 0 {
		return map[string]interface{}{}, nil
	}

	var data Payload
	if err := json.Unmarshal(payload, &data); err != nil {
		return nil, err
	}

	return data, nil
}

// decodePayloadSlice unmarshals the JSON payload and returns the resulting slice.
// If the content is empty, an empty list is returned. If decoding fails, nil is
// returned with an error.
func decodePayloadSlice(payload []byte) ([]Payload, error) {
	if len(payload) == 0 {
		return []Payload{}, nil
	}

	var data []Payload
	if err := json.Unmarshal(payload, &data); err != nil {
		return nil, err
	}

	return data, nil
}

// payloadString returns the given io.Reader as a string. The reader must be rewound
// after calling this in order to be read again.
func payloadString(payload io.Reader) []byte {
	payloadStr, err := ioutil.ReadAll(payload)
	if err != nil {
		return nil
	}
	return payloadStr
}
<commit_msg>Add docstrings<commit_after>package rest

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

// Resource represents a domain model.
type Resource interface{}

// ResourceHandler specifies the endpoint handlers for working with a resource. This
// consists of the business logic for performing CRUD operations.
type ResourceHandler interface {
	// ResourceName is used to identify what resource a handler corresponds to and is
	// used in the endpoint URLs, i.e. /api/:version/resourceName. This should be
	// unique across all ResourceHandlers.
	ResourceName() string

	// CreateURI returns the URI for creating a resource.
	CreateURI() string

	// CreateDocumentation returns a string describing the handler's create endpoint.
	CreateDocumentation() string

	// ReadURI returns the URI for reading a specific resource.
	ReadURI() string

	// ReadDocumentation returns a string describing the handler's read endpoint.
	ReadDocumentation() string

	// ReadListURI returns the URI for reading a list of resources.
	ReadListURI() string

	// ReadListDocumentation returns a string describing the handler's read list endpoint.
	ReadListDocumentation() string

	// UpdateURI returns the URI for updating a specific resource.
	UpdateURI() string

	// UpdateDocumentation returns a string describing the handler's update endpoint.
	UpdateDocumentation() string

	// UpdateListURI returns the URI for updating a list of resources.
	UpdateListURI() string

	// UpdateListDocumentation returns a string describing the handler's update list
	// endpoint.
	UpdateListDocumentation() string

	// DeleteURI returns the URI for deleting a specific resource.
	DeleteURI() string

	// DeleteDocumentation returns a string describing the handler's delete endpoint.
	DeleteDocumentation() string

	// CreateResource is the logic that corresponds to creating a new resource at
	// POST /api/:version/resourceName. Typically, this would insert a record into a
	// database. It returns the newly created resource or an error if the create failed.
	CreateResource(RequestContext, Payload, string) (Resource, error)

	// ReadResourceList is the logic that corresponds to reading multiple resources,
	// perhaps with specified query parameters accessed through the RequestContext. This
	// is mapped to GET /api/:version/resourceName. Typically, this would make some sort
	// of database query to fetch the resources. It returns the slice of results, a
	// cursor (or empty) string, and error (or nil).
	ReadResourceList(RequestContext, int, string, string) ([]Resource, string, error)

	// ReadResource is the logic that corresponds to reading a single resource by its ID
	// at GET /api/:version/resourceName/{id}. Typically, this would make some sort of
	// database query to load the resource. If the resource doesn't exist, nil should be
	// returned along with an appropriate error.
	ReadResource(RequestContext, string, string) (Resource, error)

	// UpdateResourceList is the logic that corresponds to updating a collection of
	// resources at PUT /api/:version/resourceName. Typically, this would make some
	// sort of database update call. It returns the updated resources or an error if
	// the update failed.
	UpdateResourceList(RequestContext, []Payload, string) ([]Resource, error)

	// UpdateResource is the logic that corresponds to updating an existing resource at
	// PUT /api/:version/resourceName/{id}. Typically, this would make some sort of
	// database update call. It returns the updated resource or an error if the update
	// failed.
	UpdateResource(RequestContext, string, Payload, string) (Resource, error)

	// DeleteResource is the logic that corresponds to deleting an existing resource at
	// DELETE /api/:version/resourceName/{id}. Typically, this would make some sort of
	// database delete call. It returns the deleted resource or an error if the delete
	// failed.
	DeleteResource(RequestContext, string, string) (Resource, error)

	// Authenticate is logic that is used to authenticate requests. The default behavior
	// of Authenticate, seen in BaseResourceHandler, always returns nil, meaning all
	// requests are authenticated. Returning an error means that the request is
	// unauthorized and any error message will be sent back with the response.
	Authenticate(*http.Request) error

	// Rules returns the resource rules to apply to incoming requests and outgoing
	// responses. The default behavior, seen in BaseResourceHandler, is to apply no
	// rules.
	Rules() Rules
}

// requestHandler constructs http.HandlerFuncs responsible for handling HTTP requests.
type requestHandler struct {
	API
}

// handleCreate returns a HandlerFunc which will deserialize the request payload, pass
// it to the provided create function, and then serialize and dispatch the response.
// The serialization mechanism used is specified by the "format" query parameter.
func (h requestHandler) handleCreate(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		data, err := decodePayload(payloadString(r.Body))
		if err != nil {
			// Payload decoding failed.
			ctx = ctx.setError(err)
			ctx = ctx.setStatus(http.StatusInternalServerError)
		} else {
			data, err := applyInboundRules(data, rules, version)
			if err != nil {
				// Type coercion failed.
				ctx = ctx.setError(UnprocessableRequest(err.Error()))
			} else {
				resource, err := handler.CreateResource(ctx, data, ctx.Version())
				if err == nil {
					resource = applyOutboundRules(resource, rules, version)
				}
				ctx = ctx.setResult(resource)
				ctx = ctx.setStatus(http.StatusCreated)
				if err != nil {
					ctx = ctx.setError(err)
				}
			}
		}

		h.sendResponse(w, ctx)
	}
}

// handleReadList returns a HandlerFunc which will pass the request context to the
// provided read function and then serialize and dispatch the response. The
// serialization mechanism used is specified by the "format" query parameter.
func (h requestHandler) handleReadList(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		resources, cursor, err := handler.ReadResourceList(
			ctx, ctx.Limit(), ctx.Cursor(), version)

		if err == nil {
			// Apply rules to results.
			for idx, resource := range resources {
				resources[idx] = applyOutboundRules(resource, rules, version)
			}
		}

		ctx = ctx.setResult(resources)
		ctx = ctx.setCursor(cursor)
		ctx = ctx.setError(err)
		ctx = ctx.setStatus(http.StatusOK)

		h.sendResponse(w, ctx)
	}
}

// handleRead returns a HandlerFunc which will pass the resource id to the provided
// read function and then serialize and dispatch the response. The serialization
// mechanism used is specified by the "format" query parameter.
func (h requestHandler) handleRead(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		resource, err := handler.ReadResource(ctx, ctx.ResourceID(), version)
		if err == nil {
			resource = applyOutboundRules(resource, rules, version)
		}

		ctx = ctx.setResult(resource)
		ctx = ctx.setError(err)
		ctx = ctx.setStatus(http.StatusOK)

		h.sendResponse(w, ctx)
	}
}

// handleUpdateList returns a HandlerFunc which will deserialize the request payload,
// pass it to the provided update function, and then serialize and dispatch the
// response. The serialization mechanism used is specified by the "format" query
// parameter.
func (h requestHandler) handleUpdateList(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		payloadStr := payloadString(r.Body)
		var data []Payload
		var err error
		data, err = decodePayloadSlice(payloadStr)
		if err != nil {
			var p Payload
			p, err = decodePayload(payloadStr)
			data = []Payload{p}
		}

		if err != nil {
			// Payload decoding failed.
			ctx = ctx.setError(BadRequest(err.Error()))
		} else {
			for i := range data {
				data[i], err = applyInboundRules(data[i], rules, version)
			}
			if err != nil {
				// Type coercion failed.
				ctx = ctx.setError(UnprocessableRequest(err.Error()))
			} else {
				resources, err := handler.UpdateResourceList(ctx, data, version)
				if err == nil {
					// Apply rules to results.
					for idx, resource := range resources {
						resources[idx] = applyOutboundRules(resource, rules, version)
					}
				}

				ctx = ctx.setResult(resources)
				ctx = ctx.setError(err)
				ctx = ctx.setStatus(http.StatusOK)
			}
		}

		h.sendResponse(w, ctx)
	}
}

// handleUpdate returns a HandlerFunc which will deserialize the request payload,
// pass it to the provided update function, and then serialize and dispatch the
// response. The serialization mechanism used is specified by the "format" query
// parameter.
func (h requestHandler) handleUpdate(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		data, err := decodePayload(payloadString(r.Body))
		if err != nil {
			// Payload decoding failed.
			ctx = ctx.setError(err)
			ctx = ctx.setStatus(http.StatusInternalServerError)
		} else {
			data, err := applyInboundRules(data, rules, version)
			if err != nil {
				// Type coercion failed.
				ctx = ctx.setError(UnprocessableRequest(err.Error()))
			} else {
				resource, err := handler.UpdateResource(
					ctx, ctx.ResourceID(), data, version)
				if err == nil {
					resource = applyOutboundRules(resource, rules, version)
				}

				ctx = ctx.setResult(resource)
				ctx = ctx.setError(err)
				ctx = ctx.setStatus(http.StatusOK)
			}
		}

		h.sendResponse(w, ctx)
	}
}

// handleDelete returns a HandlerFunc which will pass the resource id to the provided
// delete function and then serialize and dispatch the response. The serialization
// mechanism used is specified by the "format" query parameter.
func (h requestHandler) handleDelete(handler ResourceHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := NewContext(nil, r)
		version := ctx.Version()
		rules := handler.Rules()

		resource, err := handler.DeleteResource(ctx, ctx.ResourceID(), version)
		if err == nil {
			resource = applyOutboundRules(resource, rules, version)
		}

		ctx = ctx.setResult(resource)
		ctx = ctx.setError(err)
		ctx = ctx.setStatus(http.StatusOK)

		h.sendResponse(w, ctx)
	}
}

// sendResponse writes a success or error response to the provided http.ResponseWriter
// based on the contents of the RequestContext.
func (h requestHandler) sendResponse(w http.ResponseWriter, ctx RequestContext) {
	format := ctx.ResponseFormat()
	serializer, err := h.responseSerializer(format)
	if err != nil {
		// Fall back to json serialization.
		serializer = jsonSerializer{}
		ctx = ctx.setError(NotImplemented(fmt.Sprintf("Format not implemented: %s", format)))
	}

	sendResponse(w, NewResponse(ctx), serializer)
}

// sendResponse writes a response to the http.ResponseWriter.
func sendResponse(w http.ResponseWriter, r response, serializer ResponseSerializer) {
	status := r.Status
	contentType := serializer.ContentType()
	response, err := serializer.Serialize(r.Payload)
	if err != nil {
		log.Printf("Response serialization failed: %s", err)
		status = http.StatusInternalServerError
		contentType = "text/plain"
		response = []byte(err.Error())
	}

	w.Header().Set("Content-Type", contentType)
	w.WriteHeader(status)
	w.Write(response)
}

// decodePayload unmarshals the JSON payload and returns the resulting map. If the
// content is empty, an empty map is returned. If decoding fails, nil is returned
// with an error.
func decodePayload(payload []byte) (Payload, error) {
	if len(payload) == 0 {
		return map[string]interface{}{}, nil
	}

	var data Payload
	if err := json.Unmarshal(payload, &data); err != nil {
		return nil, err
	}

	return data, nil
}

// decodePayloadSlice unmarshals the JSON payload and returns the resulting slice.
// If the content is empty, an empty list is returned. If decoding fails, nil is
// returned with an error.
func decodePayloadSlice(payload []byte) ([]Payload, error) {
	if len(payload) == 0 {
		return []Payload{}, nil
	}

	var data []Payload
	if err := json.Unmarshal(payload, &data); err != nil {
		return nil, err
	}

	return data, nil
}

// payloadString returns the given io.Reader as a string. The reader must be rewound
// after calling this in order to be read again.
func payloadString(payload io.Reader) []byte {
	payloadStr, err := ioutil.ReadAll(payload)
	if err != nil {
		return nil
	}
	return payloadStr
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"flag"
	"fmt"
	"github.com/dchest/uniuri"
	"github.com/mssola/user_agent"
	"github.com/op/go-logging"
	"net/http"
	"strconv"
	"strings"
)

var Size int

func prefix(r *http.Request) string {
	ua := new(user_agent.UserAgent)
	ua.Parse(r.UserAgent())

	os := ua.OS()
	var ret string
	if strings.Contains(os, "Linux") {
		ret = "lin"
	} else if strings.Contains(os, "Windows") {
		ret = "win"
	} else {
		ret = "srv"
	}

	return ret
}

func randomName(length int) string {
	return uniuri.NewLen(length)
}

func hashName(id string) string {
	//    h := md5.New()
	//    h.Write([]byte(id))
	//    return base64.URLEncoding.EncodeToString(h.Sum(nil))
	return base64.URLEncoding.EncodeToString([]byte(id))
}

func handler(w http.ResponseWriter, r *http.Request) {
	id := r.FormValue("id")

	tmpsize := r.FormValue("size")

	if len(tmpsize) != 0 {
		s, err := strconv.Atoi(tmpsize)
		*size = s
		if err != nil {
			fmt.Println(err)
			return
		}
	}

	var name string

	pre := r.FormValue("prefix")
	if len(pre) != 0 {
		name = pre
	} else {
		name = prefix(r)
	}
	log.Debug("Prefix = %s", name)

	instance := r.FormValue("instance")

	name = strings.Join([]string{name, instance}, "")
	if len(name) >= *size {
		http.Error(w, "instance too long", 500)
		return
	}

	var suffix string
	if len(id) != 0 {
		ts := hashName(id)
		if len(ts) >= *size-len(name) {
			suffix = ts[0 : *size-len(name)]
		} else {
			suffix = ts
		}
	} else {
		suffix = randomName(*size - len(name))
	}
	log.Debug("Suffix = %s", suffix)
	name = strings.Join([]string{name, suffix}, "")

	fmt.Fprintf(w, "%s", name)
}

var bind = flag.String("bind", "", "Address to bind. Format IP:PORT")
var size = flag.Int("size", 10, "Default final hostname size")
var debug = flag.Bool("d", false, "turn on debug info")

var log = logging.MustGetLogger("bapteme")

func main() {
	flag.Parse()
	var format = logging.MustStringFormatter("%{level} %{message}")
	logging.SetFormatter(format)
	if *debug {
		logging.SetLevel(logging.DEBUG, "bapteme")
	} else {
		logging.SetLevel(logging.INFO, "bapteme")
	}

	log.Info("Bind to %s", *bind)

	http.HandleFunc("/", handler)
	//    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	//              handler(w, r, *size)
	//       })
	http.ListenAndServe(*bind, nil)
}
<commit_msg>Fix variable manipulation Rename flag variables<commit_after>package main

import (
	"encoding/base64"
	"flag"
	"fmt"
	"github.com/dchest/uniuri"
	"github.com/mssola/user_agent"
	"github.com/op/go-logging"
	"net/http"
	"strconv"
	"strings"
)

func prefix(r *http.Request) string {
	ua := new(user_agent.UserAgent)
	ua.Parse(r.UserAgent())

	os := ua.OS()
	var ret string
	if strings.Contains(os, "Linux") {
		ret = "lin"
	} else if strings.Contains(os, "Windows") {
		ret = "win"
	} else {
		ret = "srv"
	}

	return ret
}

func randomName(length int) string {
	return uniuri.NewLen(length)
}

func hashName(id string) string {
	//    h := md5.New()
	//    h.Write([]byte(id))
	//    return base64.URLEncoding.EncodeToString(h.Sum(nil))
	return base64.URLEncoding.EncodeToString([]byte(id))
}

func handler(w http.ResponseWriter, r *http.Request) {
	id := r.FormValue("id")

  var err error
  var size int
	formSize := r.FormValue("size")

	if formSize != "" {
		size , err = strconv.Atoi(formSize)
		if err != nil {
			fmt.Println(err)
			return
		}
	} else {
    size = *flagSize
  }

	var name string

	pre := r.FormValue("prefix")
	if len(pre) != 0 {
		name = pre
	} else {
		name = prefix(r)
	}
	log.Debug("Prefix = %s", name)

	instance := r.FormValue("instance")

	name = strings.Join([]string{name, instance}, "")
	if len(name) >= size {
		http.Error(w, "instance too long", 500)
		return
	}

	var suffix string
	if len(id) != 0 {
		ts := hashName(id)
		if len(ts) >= size-len(name) {
			suffix = ts[0 : size-len(name)]
		} else {
			suffix = ts
		}
	} else {
		suffix = randomName(size - len(name))
	}
	log.Debug("Suffix = %s", suffix)
	name = strings.Join([]string{name, suffix}, "")

	fmt.Fprintf(w, "%s", name)
}

var (
  flagBind = flag.String("bind", "", "Address to bind. Format IP:PORT")
  flagSize = flag.Int("size", 10, "Default final hostname size")
  flagDebug = flag.Bool("d", false, "turn on debug info")
)

var log = logging.MustGetLogger("bapteme")

func main() {
	flag.Parse()
	var format = logging.MustStringFormatter("%{level} %{message}")
	logging.SetFormatter(format)
	if *flagDebug {
		logging.SetLevel(logging.DEBUG, "bapteme")
	} else {
		logging.SetLevel(logging.INFO, "bapteme")
	}

	log.Info("Bind to %s", *flagBind)

	http.HandleFunc("/", handler)
	//    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	//              handler(w, r, *size)
	//       })
	http.ListenAndServe(*flagBind, nil)
}
<|endoftext|>


<commit_before>// Copyright 2013-2015 go-diameter 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 sm

import (
	"errors"
	"math/rand"
	"net"
	"time"

	"github.com/fiorix/go-diameter/diam"
	"github.com/fiorix/go-diameter/diam/avp"
	"github.com/fiorix/go-diameter/diam/datatype"
	"github.com/fiorix/go-diameter/diam/dict"
	"github.com/fiorix/go-diameter/diam/sm/parser"
)

var (
	// ErrMissingStateMachine is returned by Dial or DialTLS when
	// the Client does not have a valid StateMachine set.
	ErrMissingStateMachine = errors.New("client state machine is nil")

	// ErrHandshakeTimeout is returned by Dial or DialTLS when the
	// client does not receive a handshake answer from the server.
	//
	// If the client is configured to retransmit messages, the
	// handshake timeout only occurs after all retransmits are
	// attempted and none has an aswer.
	ErrHandshakeTimeout = errors.New("handshake timeout (no response)")
)

// A Client is a diameter client that automatically performs a handshake
// with the server after the connection is established.
//
// It sends a Capabilities-Exchange-Request with the AVPs defined in it,
// and expects a Capabilities-Exchange-Answer with a success (2001) result
// code. If enabled, the client will send Device-Watchdog-Request messages
// in background until the connection is terminated.
type Client struct {
	Dict                        *dict.Parser  // Dictionary parser
	Handler                     *StateMachine // Message handler
	MaxRetransmits              int           // Max number of retransmissions before aborting
	RetransmitInterval          time.Duration // Interval between retransmissions
	EnableWatchdog              bool          // Enable automatic DWR
	WatchdogInterval            time.Duration // Interval between DWRs
	SupportedVendorID           []*diam.AVP   // Supported vendor ID
	AcctApplicationID           []*diam.AVP   // Acct applications
	AuthApplicationID           []*diam.AVP   // Auth applications
	VendorSpecificApplicationID []*diam.AVP   // Vendor specific applications
}

// Dial calls the address set as ip:port, performs a handshake and optionally
// start a watchdog goroutine in background.
func (cli *Client) Dial(addr string) (diam.Conn, error) {
	return cli.dial(func() (diam.Conn, error) {
		return diam.Dial(addr, cli.Handler, cli.Dict)
	})
}

// DialTLS is like Dial, but using TLS.
func (cli *Client) DialTLS(addr, certFile, keyFile string) (diam.Conn, error) {
	return cli.dial(func() (diam.Conn, error) {
		return diam.DialTLS(addr, certFile, keyFile, cli.Handler, cli.Dict)
	})
}

type dialFunc func() (diam.Conn, error)

func (cli *Client) dial(f dialFunc) (diam.Conn, error) {
	if err := cli.validate(); err != nil {
		return nil, err
	}
	c, err := f()
	if err != nil {
		return nil, err
	}
	return cli.handshake(c)
}

func (cli *Client) validate() error {
	if cli.Handler == nil {
		return ErrMissingStateMachine
	}
	if cli.Dict == nil {
		cli.Dict = dict.Default
	}
	if cli.RetransmitInterval == 0 {
		// Set default RetransmitInterval.
		cli.RetransmitInterval = time.Second
	}
	if cli.WatchdogInterval == 0 {
		// Set default WatchdogInterval
		cli.WatchdogInterval = time.Second
	}
	app := &parser.Application{
		AcctApplicationID:           cli.AcctApplicationID,
		AuthApplicationID:           cli.AuthApplicationID,
		VendorSpecificApplicationID: cli.VendorSpecificApplicationID,
	}
	// Make sure the given applications exist in the dictionary
	// before sending a CER.
	_, err := app.Parse(cli.Dict)
	if err != nil {
		return err
	}
	return nil
}

func (cli *Client) handshake(c diam.Conn) (diam.Conn, error) {
	ip, _, err := net.SplitHostPort(c.LocalAddr().String())
	if err != nil {
		return nil, err
	}
	osid, m := cli.makeCER(net.ParseIP(ip))
	// Ignore CER, but not DWR.
	cli.Handler.mux.HandleFunc("CER", func(c diam.Conn, m *diam.Message) {})
	// Handle CEA and DWA.
	errc := make(chan error)
	osidc := make(chan uint32)
	cli.Handler.mux.Handle("CEA", handleCEA(cli.Handler, osid, errc))
	cli.Handler.mux.Handle("DWA", handshakeOK(handleDWA(cli.Handler, osidc)))
	for i := 0; i < (cli.MaxRetransmits + 1); i++ {
		_, err := m.WriteTo(c)
		if err != nil {
			return nil, err
		}
		select {
		case err := <-errc: // Wait for CEA.
			if err != nil {
				close(errc)
				return nil, err
			}
			if cli.EnableWatchdog {
				go cli.watchdog(c, osidc)
			}
			return c, nil
		case <-time.After(cli.RetransmitInterval):
		}
	}
	return nil, ErrHandshakeTimeout
}

func (cli *Client) makeCER(ip net.IP) (osid uint32, m *diam.Message) {
	osid = rand.Uint32()
	m = diam.NewRequest(diam.CapabilitiesExchange, 0, cli.Dict)
	m.NewAVP(avp.OriginHost, avp.Mbit, 0, cli.Handler.cfg.OriginHost)
	m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cli.Handler.cfg.OriginRealm)
	m.NewAVP(avp.HostIPAddress, avp.Mbit, 0, datatype.Address(ip))
	m.NewAVP(avp.VendorID, avp.Mbit, 0, cli.Handler.cfg.VendorID)
	m.NewAVP(avp.ProductName, 0, 0, cli.Handler.cfg.ProductName)
	m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(osid))
	if cli.SupportedVendorID != nil {
		for _, a := range cli.SupportedVendorID {
			m.AddAVP(a)
		}
	}
	if cli.AuthApplicationID != nil {
		for _, a := range cli.AuthApplicationID {
			m.AddAVP(a)
		}
	}
	m.NewAVP(avp.InbandSecurityID, avp.Mbit, 0, datatype.Unsigned32(0))
	if cli.AcctApplicationID != nil {
		for _, a := range cli.AcctApplicationID {
			m.AddAVP(a)
		}
	}
	if cli.VendorSpecificApplicationID != nil {
		for _, a := range cli.VendorSpecificApplicationID {
			m.AddAVP(a)
		}
	}
	m.NewAVP(avp.FirmwareRevision, avp.Mbit, 0, cli.Handler.cfg.FirmwareRevision)
	return osid, m
}

func (cli *Client) watchdog(c diam.Conn, osidc chan uint32) {
	disconnect := c.(diam.CloseNotifier).CloseNotify()
	var osid uint32
	for {
		select {
		case <-disconnect:
			return
		case <-time.After(cli.WatchdogInterval):
			osid++
			cli.dwr(c, osid, osidc)
		}
	}
}

func (cli *Client) dwr(c diam.Conn, osid uint32, osidc chan uint32) {
	m := cli.makeDWR(osid)
	for i := 0; i < (cli.MaxRetransmits + 1); i++ {
		_, err := m.WriteTo(c)
		if err != nil {
			return
		}
		select {
		case resp := <-osidc:
			if resp == osid {
				return
			}
		case <-time.After(cli.RetransmitInterval):
		}
	}
	// Watchdog failed, disconnect.
	c.Close()
}

func (cli *Client) makeDWR(osid uint32) *diam.Message {
	m := diam.NewRequest(diam.DeviceWatchdog, 0, cli.Dict)
	m.NewAVP(avp.OriginHost, avp.Mbit, 0, cli.Handler.cfg.OriginHost)
	m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cli.Handler.cfg.OriginRealm)
	m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(osid))
	return m
}
<commit_msg>Close client connection when handshake fails<commit_after>// Copyright 2013-2015 go-diameter 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 sm

import (
	"errors"
	"math/rand"
	"net"
	"time"

	"github.com/fiorix/go-diameter/diam"
	"github.com/fiorix/go-diameter/diam/avp"
	"github.com/fiorix/go-diameter/diam/datatype"
	"github.com/fiorix/go-diameter/diam/dict"
	"github.com/fiorix/go-diameter/diam/sm/parser"
)

var (
	// ErrMissingStateMachine is returned by Dial or DialTLS when
	// the Client does not have a valid StateMachine set.
	ErrMissingStateMachine = errors.New("client state machine is nil")

	// ErrHandshakeTimeout is returned by Dial or DialTLS when the
	// client does not receive a handshake answer from the server.
	//
	// If the client is configured to retransmit messages, the
	// handshake timeout only occurs after all retransmits are
	// attempted and none has an aswer.
	ErrHandshakeTimeout = errors.New("handshake timeout (no response)")
)

// A Client is a diameter client that automatically performs a handshake
// with the server after the connection is established.
//
// It sends a Capabilities-Exchange-Request with the AVPs defined in it,
// and expects a Capabilities-Exchange-Answer with a success (2001) result
// code. If enabled, the client will send Device-Watchdog-Request messages
// in background until the connection is terminated.
type Client struct {
	Dict                        *dict.Parser  // Dictionary parser
	Handler                     *StateMachine // Message handler
	MaxRetransmits              int           // Max number of retransmissions before aborting
	RetransmitInterval          time.Duration // Interval between retransmissions
	EnableWatchdog              bool          // Enable automatic DWR
	WatchdogInterval            time.Duration // Interval between DWRs
	SupportedVendorID           []*diam.AVP   // Supported vendor ID
	AcctApplicationID           []*diam.AVP   // Acct applications
	AuthApplicationID           []*diam.AVP   // Auth applications
	VendorSpecificApplicationID []*diam.AVP   // Vendor specific applications
}

// Dial calls the address set as ip:port, performs a handshake and optionally
// start a watchdog goroutine in background.
func (cli *Client) Dial(addr string) (diam.Conn, error) {
	return cli.dial(func() (diam.Conn, error) {
		return diam.Dial(addr, cli.Handler, cli.Dict)
	})
}

// DialTLS is like Dial, but using TLS.
func (cli *Client) DialTLS(addr, certFile, keyFile string) (diam.Conn, error) {
	return cli.dial(func() (diam.Conn, error) {
		return diam.DialTLS(addr, certFile, keyFile, cli.Handler, cli.Dict)
	})
}

type dialFunc func() (diam.Conn, error)

func (cli *Client) dial(f dialFunc) (diam.Conn, error) {
	if err := cli.validate(); err != nil {
		return nil, err
	}
	c, err := f()
	if err != nil {
		return nil, err
	}
	return cli.handshake(c)
}

func (cli *Client) validate() error {
	if cli.Handler == nil {
		return ErrMissingStateMachine
	}
	if cli.Dict == nil {
		cli.Dict = dict.Default
	}
	if cli.RetransmitInterval == 0 {
		// Set default RetransmitInterval.
		cli.RetransmitInterval = time.Second
	}
	if cli.WatchdogInterval == 0 {
		// Set default WatchdogInterval
		cli.WatchdogInterval = time.Second
	}
	app := &parser.Application{
		AcctApplicationID:           cli.AcctApplicationID,
		AuthApplicationID:           cli.AuthApplicationID,
		VendorSpecificApplicationID: cli.VendorSpecificApplicationID,
	}
	// Make sure the given applications exist in the dictionary
	// before sending a CER.
	_, err := app.Parse(cli.Dict)
	if err != nil {
		return err
	}
	return nil
}

func (cli *Client) handshake(c diam.Conn) (diam.Conn, error) {
	ip, _, err := net.SplitHostPort(c.LocalAddr().String())
	if err != nil {
		return nil, err
	}
	osid, m := cli.makeCER(net.ParseIP(ip))
	// Ignore CER, but not DWR.
	cli.Handler.mux.HandleFunc("CER", func(c diam.Conn, m *diam.Message) {})
	// Handle CEA and DWA.
	errc := make(chan error)
	osidc := make(chan uint32)
	cli.Handler.mux.Handle("CEA", handleCEA(cli.Handler, osid, errc))
	cli.Handler.mux.Handle("DWA", handshakeOK(handleDWA(cli.Handler, osidc)))
	for i := 0; i < (cli.MaxRetransmits + 1); i++ {
		_, err := m.WriteTo(c)
		if err != nil {
			return nil, err
		}
		select {
		case err := <-errc: // Wait for CEA.
			if err != nil {
				close(errc)
				return nil, err
			}
			if cli.EnableWatchdog {
				go cli.watchdog(c, osidc)
			}
			return c, nil
		case <-time.After(cli.RetransmitInterval):
		}
	}
	c.Close()
	return nil, ErrHandshakeTimeout
}

func (cli *Client) makeCER(ip net.IP) (osid uint32, m *diam.Message) {
	osid = rand.Uint32()
	m = diam.NewRequest(diam.CapabilitiesExchange, 0, cli.Dict)
	m.NewAVP(avp.OriginHost, avp.Mbit, 0, cli.Handler.cfg.OriginHost)
	m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cli.Handler.cfg.OriginRealm)
	m.NewAVP(avp.HostIPAddress, avp.Mbit, 0, datatype.Address(ip))
	m.NewAVP(avp.VendorID, avp.Mbit, 0, cli.Handler.cfg.VendorID)
	m.NewAVP(avp.ProductName, 0, 0, cli.Handler.cfg.ProductName)
	m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(osid))
	if cli.SupportedVendorID != nil {
		for _, a := range cli.SupportedVendorID {
			m.AddAVP(a)
		}
	}
	if cli.AuthApplicationID != nil {
		for _, a := range cli.AuthApplicationID {
			m.AddAVP(a)
		}
	}
	m.NewAVP(avp.InbandSecurityID, avp.Mbit, 0, datatype.Unsigned32(0))
	if cli.AcctApplicationID != nil {
		for _, a := range cli.AcctApplicationID {
			m.AddAVP(a)
		}
	}
	if cli.VendorSpecificApplicationID != nil {
		for _, a := range cli.VendorSpecificApplicationID {
			m.AddAVP(a)
		}
	}
	m.NewAVP(avp.FirmwareRevision, avp.Mbit, 0, cli.Handler.cfg.FirmwareRevision)
	return osid, m
}

func (cli *Client) watchdog(c diam.Conn, osidc chan uint32) {
	disconnect := c.(diam.CloseNotifier).CloseNotify()
	var osid uint32
	for {
		select {
		case <-disconnect:
			return
		case <-time.After(cli.WatchdogInterval):
			osid++
			cli.dwr(c, osid, osidc)
		}
	}
}

func (cli *Client) dwr(c diam.Conn, osid uint32, osidc chan uint32) {
	m := cli.makeDWR(osid)
	for i := 0; i < (cli.MaxRetransmits + 1); i++ {
		_, err := m.WriteTo(c)
		if err != nil {
			return
		}
		select {
		case resp := <-osidc:
			if resp == osid {
				return
			}
		case <-time.After(cli.RetransmitInterval):
		}
	}
	// Watchdog failed, disconnect.
	c.Close()
}

func (cli *Client) makeDWR(osid uint32) *diam.Message {
	m := diam.NewRequest(diam.DeviceWatchdog, 0, cli.Dict)
	m.NewAVP(avp.OriginHost, avp.Mbit, 0, cli.Handler.cfg.OriginHost)
	m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cli.Handler.cfg.OriginRealm)
	m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(osid))
	return m
}
<|endoftext|>


<commit_before>/*
 Copyright 2016 Padduck, LLC

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 	http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

package templates

const Bungeecord = `{
  "pufferd": {
    "type": "java",
    "display": "Bungeecord - Minecraft",
    "install": {
      "commands": [
        {
          "files": "http://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/BungeeCord.jar",
          "type": "download"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"BungeeCord.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      }
    }
  }
}`

const Spigot = `{
  "pufferd": {
    "type": "java",
    "display": "Spigot - Minecraft",
    "install": {
      "commands": [
        {
          "files": "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar",
          "type": "download"
        },
        {
          "commands": [
            "java -jar BuildTools.jar --rev ${version}",
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        },
        {
          "source": "spigot-*.jar",
          "target": "server.jar",
          "type": "move"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "version": {
      	"value": "1.10",
      	"required": true,
      	"desc": "Version of Minecraft to install",
      	"display": "Version",
      	"internal": false
      },
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      }
    }
  }
}`

const CraftbukkitBySpigot = `{
  "pufferd": {
    "type": "java",
    "display": "CraftBukkit by Spigot - Minecraft",
    "install": {
      "commands": [
        {
          "files": "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar",
          "type": "download"
        },
        {
          "commands": [
            "java -jar BuildTools.jar --rev ${version}",
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        },
        {
          "source": "craftbukkit-*.jar",
          "target": "server.jar",
          "type": "move"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "version": {
      	"value": "1.10",
      	"required": true,
      	"desc": "Version of Minecraft to install",
      	"display": "Version",
      	"internal": false
      },
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      }
    }
  }
}`

const Vanilla = `{
  "pufferd": {
    "type": "java",
    "display": "Vanilla - Minecraft",
    "install": {
      "commands": [
        {
          "type": "download",
          "files": "https://s3.amazonaws.com/Minecraft.Download/versions/${version}/minecraft_server.${version}.jar"
        },
        {
          "source": "minecraft_server.*.jar",
          "target": "server.jar",
          "type": "move"
        },
        {
          "commands": [
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "version": {
      	"value": "1.10",
      	"required": true,
      	"desc": "Version of Minecraft to install",
      	"display": "Version",
      	"internal": false
      },
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      }
    }
  }
}`

const Forge = `{
  "pufferd": {
    "type": "java",
    "display": "MinecraftForge - Minecraft",
    "install": {
      "commands": [
        {
          "type": "download",
          "files": "http://files.minecraftforge.net/maven/net/minecraftforge/forge/1.10.2-12.18.1.2011/forge-1.10.2-12.18.1.2011-installer.jar"
        },
        {
          "source": "forge-*.jar",
          "target": "installer.jar",
          "type": "move"
        },
        {
          "commands": [
            "java -jar installer.jar --installServer",
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        },
        {
          "source": "forge-*-universal.jar",
          "target": "server.jar",
          "type": "move"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      }
    }
  }
}`

const Sponge = `{
  "pufferd": {
    "type": "java",
    "display": "SpongeForge - Minecraft",
    "install": {
      "commands": [
        {
          "type": "download",
          "files": [
          	"http://files.minecraftforge.net/maven/net/minecraftforge/forge/1.10.2-12.18.1.2011/forge-1.10.2-12.18.1.2011-installer.jar",
          	"http://files.minecraftforge.net/maven/org/spongepowered/spongeforge/1.8.9-1890-4.2.0-BETA-1653/spongeforge-1.8.9-1890-4.2.0-BETA-1653.jar"
          ]
        },
        {
          "source": "forge-*.jar",
          "target": "installer.jar",
          "type": "move"
        },
        {
          "target": "mods",
          "type": "mkdir"
        },
        {
          "source": "spongeforge-*.jar",
          "target": "mods",
          "type": "move"
        },
        {
          "commands": [
            "java -jar installer.jar --installServer",
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        },
        {
          "source": "forge-*-universal.jar",
          "target": "server.jar",
          "type": "move"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      }
    }
  }
}`
<commit_msg>Update versions to 1.11.2<commit_after>/*
 Copyright 2016 Padduck, LLC

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 	http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

package templates

const Bungeecord = `{
  "pufferd": {
    "type": "java",
    "display": "Bungeecord - Minecraft",
    "install": {
      "commands": [
        {
          "files": "http://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/BungeeCord.jar",
          "type": "download"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"BungeeCord.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      }
    }
  }
}`

const Spigot = `{
  "pufferd": {
    "type": "java",
    "display": "Spigot - Minecraft",
    "install": {
      "commands": [
        {
          "files": "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar",
          "type": "download"
        },
        {
          "commands": [
            "java -jar BuildTools.jar --rev ${version}",
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        },
        {
          "source": "spigot-*.jar",
          "target": "server.jar",
          "type": "move"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "version": {
      	"value": "1.11.2",
      	"required": true,
      	"desc": "Version of Minecraft to install",
      	"display": "Version",
      	"internal": false
      },
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      }
    }
  }
}`

const CraftbukkitBySpigot = `{
  "pufferd": {
    "type": "java",
    "display": "CraftBukkit by Spigot - Minecraft",
    "install": {
      "commands": [
        {
          "files": "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar",
          "type": "download"
        },
        {
          "commands": [
            "java -jar BuildTools.jar --rev ${version}",
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        },
        {
          "source": "craftbukkit-*.jar",
          "target": "server.jar",
          "type": "move"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "version": {
      	"value": "1.11.2",
      	"required": true,
      	"desc": "Version of Minecraft to install",
      	"display": "Version",
      	"internal": false
      },
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      }
    }
  }
}`

const Vanilla = `{
  "pufferd": {
    "type": "java",
    "display": "Vanilla - Minecraft",
    "install": {
      "commands": [
        {
          "type": "download",
          "files": "https://s3.amazonaws.com/Minecraft.Download/versions/${version}/minecraft_server.${version}.jar"
        },
        {
          "source": "minecraft_server.*.jar",
          "target": "server.jar",
          "type": "move"
        },
        {
          "commands": [
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "version": {
      	"value": "1.11.2",
      	"required": true,
      	"desc": "Version of Minecraft to install",
      	"display": "Version",
      	"internal": false
      },
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      }
    }
  }
}`

const Forge = `{
  "pufferd": {
    "type": "java",
    "display": "MinecraftForge - Minecraft",
    "install": {
      "commands": [
        {
          "type": "download",
          "files": "http://files.minecraftforge.net/maven/net/minecraftforge/forge/${version}/forge-${version}-installer.jar"
        },
        {
          "source": "forge-*.jar",
          "target": "installer.jar",
          "type": "move"
        },
        {
          "commands": [
            "java -jar installer.jar --installServer",
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        },
        {
          "source": "forge-*-universal.jar",
          "target": "server.jar",
          "type": "move"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      },
      "version": {
      	"value": "1.10.2-12.18.1.2011",
      	"required": true,
      	"desc": "Version of Forge to install",
      	"display": "Version",
      	"internal": false
      }
    }
  }
}`

const Sponge = `{
  "pufferd": {
    "type": "java",
    "display": "SpongeForge - Minecraft",
    "install": {
      "commands": [
        {
          "type": "download",
          "files": [
          	"http://files.minecraftforge.net/maven/net/minecraftforge/forge/${forgeversion}/forge-${forgeversion}-installer.jar",
          	"http://files.minecraftforge.net/maven/org/spongepowered/spongeforge/${spongeversion}/spongeforge-${spongeversion}.jar"
          ]
        },
        {
          "source": "forge-*.jar",
          "target": "installer.jar",
          "type": "move"
        },
        {
          "target": "mods",
          "type": "mkdir"
        },
        {
          "source": "spongeforge-*.jar",
          "target": "mods",
          "type": "move"
        },
        {
          "commands": [
            "java -jar installer.jar --installServer",
            "echo eula=${eula} > eula.txt"
          ],
          "type": "command"
        },
        {
          "source": "forge-*-universal.jar",
          "target": "server.jar",
          "type": "move"
        }
      ]
    },
    "run": {
      "stop": "stop",
      "pre": [],
      "post": [],
      "arguments": [
      	"-Xmx${memory}M",
      	"-jar",
      	"server.jar"
      ],
      "program": "java"
    },
    "environment": {
      "type": "standard"
    },
    "data": {
      "memory": {
      	"value": "1024",
      	"required": true,
      	"desc": "How much memory in MB to allocate to the Java Heap",
      	"display": "Memory (MB)",
      	"internal": false
      },
      "ip": {
        "value": "0.0.0.0",
        "required": true,
        "desc": "What IP to bind the server to",
        "display": "IP",
        "internal": false
      },
      "port": {
        "value": "25565",
        "required": true,
        "desc": "What port to bind the server to",
        "display": "Port",
        "internal": false
      },
      "eula": {
        "value": "false",
        "required": true,
        "desc": "Do you agree to the Minecraft EULA?",
        "display": "EULA Agreement (true/false)",
        "internal": false
      },
      "forgeversion": {
      	"value": "1.10.2-12.18.1.2011",
      	"required": true,
      	"desc": "Version of Forge to install",
      	"display": "Forge Version",
      	"internal": false
      },
      "spongeversion": {
      	"value": "1.8.9-1890-4.2.0-BETA-1653",
      	"required": true,
      	"desc": "Version of Sponge to install",
      	"display": "Sponge Version",
      	"internal": false
      }
    }
  }
}`
<|endoftext|>


<commit_before>package main

import (
	"bitbucket.org/gdamore/mangos"
	"bitbucket.org/gdamore/mangos/protocol/rep"
	"bitbucket.org/gdamore/mangos/transport/all"
	"fmt"
	"github.com/ugorji/go/codec"
	"reflect"
	"strconv"
	"time"
)

var (
	mh codec.MsgpackHandle
	b  []byte
)

func boomerangMetrics(map[string][]string) {}

func jsMetrics(map[string]string) {}

// Calculate delta between start and end
func delta(start string, end string) (int, error) {
	s, err := strconv.Atoi(start)
	if err != nil {
		return -1, err
	}
	e, err := strconv.Atoi(end)
	if err != nil {
		return -1, err
	}
	return e - s, nil
}

func decode(buf []byte) (error, map[string][]string) {

	doc := map[string][]string(nil)
	dec := codec.NewDecoderBytes(buf, &mh)
	err := dec.Decode(&doc)

	if err != nil {
		return err, nil
	}
	return nil, doc
}

func main() {
	// consumer --type boomerang --remote tcp://127.0.0.1:8000 --statsd 192.168.33.20:8125

	url := "tcp://127.0.0.1:8000"

	responseServerReady := make(chan struct{})
	responseServer, err := rep.NewSocket()
	defer responseServer.Close()

	all.AddTransports(responseServer)
	if err != nil {
		fmt.Println("Error connecting: ", err)
		return
	}

	fmt.Println("Consumer ready")

	go func() {
		var err error
		var serverMsg *mangos.Message

		if err = responseServer.Listen(url); err != nil {
			fmt.Printf("\nServer listen failed: %v", err)
			return
		}

		close(responseServerReady)
		mh.MapType = reflect.TypeOf(map[string][]string(nil))

		for {
			if serverMsg, err = responseServer.RecvMsg(); err != nil {
				fmt.Printf("\nServer receive failed: %v", err)
			}

			err, d := decode(serverMsg.Body)

			fmt.Println("------ server msg ------ ")
			nt_dns, _ := delta(d["nt_dns_st"][0], d["nt_dns_end"][0])                               // domainLookupEnd - domainLookupStart
			nt_con, _ := delta(d["nt_con_st"][0], d["nt_con_end"][0])                               // connectEnd - connectStart
			nt_domcontloaded, _ := delta(d["nt_domcontloaded_st"][0], d["nt_domcontloaded_end"][0]) // domContentLoadedEnd - domContentLoadedStart
			nt_processed, _ := delta(d["nt_domcontloaded_st"][0], d["nt_domcomp"][0])               // domComplete - domContentLoadedStart
			nt_request, _ := delta(d["nt_req_st"][0], d["nt_res_st"][0])                            // ResponseStart - RequestStart
			nt_response, _ := delta(d["nt_res_st"][0], d["nt_res_end"][0])                          // ResponseEnd - ResponseStart
			nt_navtype := d["nt_nav_type"][0]
			roundtrip, _ := delta(d["rt.bstart"][0], d["rt.end"][0])
			page := d["r"][0]
			url := d["u"][0]
			//referer := d["r2"][0]

			fmt.Println("Navigation type: ", nt_navtype)
			fmt.Println("Navigation timing DNS: ", nt_dns)
			fmt.Println("Navigation timing Connection: ", nt_con)
			fmt.Println("Navigation timing DOM content loaded: ", nt_domcontloaded)
			fmt.Println("Navigation timing DOM processing: ", nt_processed)
			fmt.Println("Navigation timing Request: ", nt_request)
			fmt.Println("Navigation timing Response: ", nt_response)
			fmt.Println("Roundtrip: ", roundtrip)
			fmt.Println("Page: ", page)
			fmt.Println("URL: ", url)
			//fmt.Println("Referer: ", referer)
			//			for k, v := range d {
			//				fmt.Println(k, v)
			//			}
			fmt.Println("------ server msg ------ ")

			serverMsg.Body = []byte("OK")

			if err = responseServer.SendMsg(serverMsg); err != nil {
				fmt.Printf("\nServer send failed: %v", err)
				return
			}
		}
		fmt.Println("Listening")
	}()

	for {
		time.Sleep(10 * time.Second)
	}
}
<commit_msg>consumer cli flags<commit_after>package main

import (
	"bitbucket.org/gdamore/mangos"
	"bitbucket.org/gdamore/mangos/protocol/rep"
	"bitbucket.org/gdamore/mangos/transport/all"
	"flag"
	"fmt"
	"github.com/ugorji/go/codec"
	"reflect"
	"strconv"
	"time"
)

var (
	mh codec.MsgpackHandle
	b  []byte
)

func boomerangMetrics(map[string][]string) {}

func jsMetrics(map[string]string) {}

// Calculate delta between start and end
func delta(start string, end string) (int, error) {
	s, err := strconv.Atoi(start)
	if err != nil {
		return -1, err
	}
	e, err := strconv.Atoi(end)
	if err != nil {
		return -1, err
	}
	return e - s, nil
}

func decode(buf []byte) (error, map[string][]string) {

	doc := map[string][]string(nil)
	dec := codec.NewDecoderBytes(buf, &mh)
	err := dec.Decode(&doc)

	if err != nil {
		return err, nil
	}
	return nil, doc
}

func main() {
	// consumer --type boomerang --remote tcp://127.0.0.1:8000 --statsd 192.168.33.20:8125
	var (
		listenAddr   string
		statsdServer string
		trackerType  string
	)

	flag.StringVar(&listenAddr, "listen", "tcp://127.0.0.1:8000", "Listening string - default: tcp://127.0.0.1:8000")
	flag.StringVar(&statsdServer, "statsd", "127.0.0.1:8125", "statsd endpoint - default: 127.0.0.1:8125")
	flag.StringVar(&trackerType, "tracker", "boomerang", "tracker type - default: boomerang [boomerang, js]")

	responseServerReady := make(chan struct{})
	responseServer, err := rep.NewSocket()
	defer responseServer.Close()

	all.AddTransports(responseServer)
	if err != nil {
		fmt.Println("Error connecting: ", err)
		return
	}
	fmt.Println("Listening:", listenAddr)
	fmt.Println("Statsd endpoint:", statsdServer)
	fmt.Println("Tracker type: ", trackerType)
	fmt.Println("Consumer ready")

	go func() {
		var err error
		var serverMsg *mangos.Message

		if err = responseServer.Listen(listenAddr); err != nil {
			fmt.Printf("\nServer listen failed: %v", err)
			return
		}

		close(responseServerReady)
		mh.MapType = reflect.TypeOf(map[string][]string(nil))

		for {
			if serverMsg, err = responseServer.RecvMsg(); err != nil {
				fmt.Printf("\nServer receive failed: %v", err)
			}

			err, d := decode(serverMsg.Body)

			fmt.Println("------ server msg ------ ")
			nt_dns, _ := delta(d["nt_dns_st"][0], d["nt_dns_end"][0])                               // domainLookupEnd - domainLookupStart
			nt_con, _ := delta(d["nt_con_st"][0], d["nt_con_end"][0])                               // connectEnd - connectStart
			nt_domcontloaded, _ := delta(d["nt_domcontloaded_st"][0], d["nt_domcontloaded_end"][0]) // domContentLoadedEnd - domContentLoadedStart
			nt_processed, _ := delta(d["nt_domcontloaded_st"][0], d["nt_domcomp"][0])               // domComplete - domContentLoadedStart
			nt_request, _ := delta(d["nt_req_st"][0], d["nt_res_st"][0])                            // ResponseStart - RequestStart
			nt_response, _ := delta(d["nt_res_st"][0], d["nt_res_end"][0])                          // ResponseEnd - ResponseStart
			nt_navtype := d["nt_nav_type"][0]
			roundtrip, _ := delta(d["rt.bstart"][0], d["rt.end"][0])
			page := d["r"][0]
			url := d["u"][0]
			//referer := d["r2"][0]

			fmt.Println("Navigation type: ", nt_navtype)
			fmt.Println("Navigation timing DNS: ", nt_dns)
			fmt.Println("Navigation timing Connection: ", nt_con)
			fmt.Println("Navigation timing DOM content loaded: ", nt_domcontloaded)
			fmt.Println("Navigation timing DOM processing: ", nt_processed)
			fmt.Println("Navigation timing Request: ", nt_request)
			fmt.Println("Navigation timing Response: ", nt_response)
			fmt.Println("Roundtrip: ", roundtrip)
			fmt.Println("Page: ", page)
			fmt.Println("URL: ", url)
			//fmt.Println("Referer: ", referer)
			//			for k, v := range d {
			//				fmt.Println(k, v)
			//			}
			fmt.Println("------ server msg ------ ")

			serverMsg.Body = []byte("OK")

			if err = responseServer.SendMsg(serverMsg); err != nil {
				fmt.Printf("\nServer send failed: %v", err)
				return
			}
		}
		fmt.Println("Listening")
	}()

	for {
		time.Sleep(10 * time.Second)
	}
}
<|endoftext|>


<commit_before>package service

import (
    "fmt"
    "time"

    "golang.org/x/net/context"

    "github.com/servicekit/servicekit-go/coordinator"
    "github.com/servicekit/servicekit-go/logger"
    "github.com/servicekit/servicekit-go/spec"
)

type GRPCServer interface {
    Serve(ctx context.Context, network, addr, pem, key string) error
}

type GRPCService struct {
    ID      string
    Service string
    Tags    []string
    Address string
    Port    int

    server GRPCServer
    pem    string
    key    string

    TTL time.Duration

    c coordinator.Coordinator

    log *logger.Logger

    errorChan chan error
}

func NewGRPCService(id string, service string, tags []string, address string, port int, server GRPCServer, pem, key string, ttl time.Duration, c coordinator.Coordinator, log *logger.Logger) *GRPCService {
    return &GRPCService{
        ID:      id,
        Service: service,
        Tags:    tags,
        Address: address,
        Port:    port,

        server: server,
        pem:    pem,
        key:    key,

        TTL: ttl,
        c:   c,
        log: log,

        errorChan: make(chan error),
    }
}

func (g *GRPCService) getService() spec.Service {
    return spec.Service{
        ID:      g.ID,
        Service: g.Service,
        Tags:    g.Tags,
        Address: g.Address,
        Port:    g.Port,
    }
}

func (g *GRPCService) Start(ctx context.Context, delayRegisterTime time.Duration) error {
    go func() {
        err := g.server.Serve(
            ctx,
            "tcp",
            fmt.Sprintf("%s:%d", g.Address, g.Port),
            g.pem,
            g.key,
        )
        g.errorChan <- err
    }()

    time.Sleep(delayRegisterTime)

    var err error

    select {
    case err = <-g.errorChan:
    default:
        err = g.c.Register(ctx, g.getService())
    }

    return err
}
<commit_msg>update grpc<commit_after>package service

import (
    "fmt"
    "time"

    "golang.org/x/net/context"

    "github.com/servicekit/servicekit-go/coordinator"
    "github.com/servicekit/servicekit-go/logger"
    "github.com/servicekit/servicekit-go/spec"
)

type GRPCServer interface {
    Serve(ctx context.Context, network, addr, pem, key string) error
}

type GRPCService struct {
    ID      string
    Service string
    Tags    []string
    Address string
    Port    int

    server GRPCServer
    pem    string
    key    string

    TTL time.Duration

    c coordinator.Coordinator

    log *logger.Logger

    errorChan chan error
}

func NewGRPCService(id string, service string, tags []string, address string, port int, server GRPCServer, pem, key string, ttl time.Duration, c coordinator.Coordinator, log *logger.Logger) *GRPCService {
    return &GRPCService{
        ID:      id,
        Service: service,
        Tags:    tags,
        Address: address,
        Port:    port,

        server: server,
        pem:    pem,
        key:    key,

        TTL: ttl,
        c:   c,
        log: log,

        errorChan: make(chan error),
    }
}

func (g *GRPCService) getService() *spec.Service {
    return &spec.Service{
        ID:      g.ID,
        Service: g.Service,
        Tags:    g.Tags,
        Address: g.Address,
        Port:    g.Port,
    }
}

func (g *GRPCService) Start(ctx context.Context, delayRegisterTime time.Duration) error {
    go func() {
        err := g.server.Serve(
            ctx,
            "tcp",
            fmt.Sprintf("%s:%d", g.Address, g.Port),
            g.pem,
            g.key,
        )
        g.errorChan <- err
    }()

    time.Sleep(delayRegisterTime)

    var err error

    select {
    case err = <-g.errorChan:
    default:
        err = g.c.Register(ctx, g.getService())
    }

    return err
}
<|endoftext|>


<commit_before>/*
 * This file is part of the CDI project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright 2019 Red Hat, Inc.
 *
 */

package webhooks

import (
	admissionv1beta1 "k8s.io/api/admission/v1beta1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	k8sfield "k8s.io/apimachinery/pkg/util/validation/field"
	"k8s.io/client-go/kubernetes"
	"k8s.io/klog"

	cdiv1alpha1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1alpha1"
	"kubevirt.io/containerized-data-importer/pkg/apiserver/webhooks/api"
	"kubevirt.io/containerized-data-importer/pkg/controller"
	"kubevirt.io/containerized-data-importer/pkg/token"
)

type dataVolumeMutatingWebhook struct {
	client         kubernetes.Interface
	tokenGenerator token.Generator
}

var (
	tokenResource = metav1.GroupVersionResource{
		Group:    "",
		Version:  "v1",
		Resource: "persistentvolumeclaims",
	}
)

func (wh *dataVolumeMutatingWebhook) Admit(ar admissionv1beta1.AdmissionReview) *admissionv1beta1.AdmissionResponse {
	var dataVolume, oldDataVolume cdiv1alpha1.DataVolume
	deserializer := codecs.UniversalDeserializer()

	klog.V(3).Infof("Got AdmissionReview %+v", ar)

	if err := validateDataVolumeResource(ar); err != nil {
		return toAdmissionResponseError(err)
	}

	if _, _, err := deserializer.Decode(ar.Request.Object.Raw, nil, &dataVolume); err != nil {
		return toAdmissionResponseError(err)
	}

	pvcSource := dataVolume.Spec.Source.PVC

	if pvcSource == nil {
		klog.V(3).Infof("DataVolume %s/%s not cloning", dataVolume.Namespace, dataVolume.Name)
		return allowedAdmissionResponse()
	}

	sourceNamespace := pvcSource.Namespace
	if sourceNamespace == "" {
		sourceNamespace = dataVolume.Namespace
	}

	if ar.Request.Operation == admissionv1beta1.Update {
		if _, _, err := deserializer.Decode(ar.Request.OldObject.Raw, nil, &oldDataVolume); err != nil {
			return toAdmissionResponseError(err)
		}

		_, ok := oldDataVolume.Annotations[controller.AnnCloneToken]
		if ok {
			klog.V(3).Infof("DataVolume %s/%s already has clone token", dataVolume.Namespace, dataVolume.Name)
			return allowedAdmissionResponse()
		}
	}

	ok, reason, err := api.CanClonePVC(wh.client, pvcSource.Namespace, pvcSource.Name, ar.Request.UserInfo)
	if err != nil {
		return toAdmissionResponseError(err)
	}

	if !ok {
		causes := []metav1.StatusCause{
			{
				Type:    metav1.CauseTypeFieldValueInvalid,
				Message: reason,
				Field:   k8sfield.NewPath("spec", "source", "PVC", "namespace").String(),
			},
		}
		return toRejectedAdmissionResponse(causes)
	}

	tokenData := &token.Payload{
		Operation: token.OperationClone,
		Name:      pvcSource.Name,
		Namespace: pvcSource.Namespace,
		Resource:  tokenResource,
		Params: map[string]string{
			"targetNamespace": dataVolume.Namespace,
			"targetName":      dataVolume.Name,
		},
	}

	token, err := wh.tokenGenerator.Generate(tokenData)
	if err != nil {
		return toAdmissionResponseError(err)
	}

	modifiedDataVolume := dataVolume.DeepCopy()
	if modifiedDataVolume.Annotations == nil {
		modifiedDataVolume.Annotations = make(map[string]string)
	}

	modifiedDataVolume.Annotations[controller.AnnCloneToken] = token

	klog.V(3).Infof("Sending patch response...")

	return toPatchResponse(dataVolume, modifiedDataVolume)
}
<commit_msg>fix token creation, some params may be empty<commit_after>/*
 * This file is part of the CDI project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright 2019 Red Hat, Inc.
 *
 */

package webhooks

import (
	admissionv1beta1 "k8s.io/api/admission/v1beta1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	k8sfield "k8s.io/apimachinery/pkg/util/validation/field"
	"k8s.io/client-go/kubernetes"
	"k8s.io/klog"

	cdiv1alpha1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1alpha1"
	"kubevirt.io/containerized-data-importer/pkg/apiserver/webhooks/api"
	"kubevirt.io/containerized-data-importer/pkg/controller"
	"kubevirt.io/containerized-data-importer/pkg/token"
)

type dataVolumeMutatingWebhook struct {
	client         kubernetes.Interface
	tokenGenerator token.Generator
}

var (
	tokenResource = metav1.GroupVersionResource{
		Group:    "",
		Version:  "v1",
		Resource: "persistentvolumeclaims",
	}
)

func (wh *dataVolumeMutatingWebhook) Admit(ar admissionv1beta1.AdmissionReview) *admissionv1beta1.AdmissionResponse {
	var dataVolume, oldDataVolume cdiv1alpha1.DataVolume
	deserializer := codecs.UniversalDeserializer()

	klog.V(3).Infof("Got AdmissionReview %+v", ar)

	if err := validateDataVolumeResource(ar); err != nil {
		return toAdmissionResponseError(err)
	}

	if _, _, err := deserializer.Decode(ar.Request.Object.Raw, nil, &dataVolume); err != nil {
		return toAdmissionResponseError(err)
	}

	pvcSource := dataVolume.Spec.Source.PVC
	targetNamespace, targetName := dataVolume.Namespace, dataVolume.Name
	if targetNamespace == "" {
		targetNamespace = ar.Request.Namespace
	}

	if targetName == "" {
		targetName = ar.Request.Name
	}

	if pvcSource == nil {
		klog.V(3).Infof("DataVolume %s/%s not cloning", targetNamespace, targetName)
		return allowedAdmissionResponse()
	}

	sourceNamespace, sourceName := pvcSource.Namespace, pvcSource.Name
	if sourceNamespace == "" {
		sourceNamespace = ar.Request.Namespace
	}

	if ar.Request.Operation == admissionv1beta1.Update {
		if _, _, err := deserializer.Decode(ar.Request.OldObject.Raw, nil, &oldDataVolume); err != nil {
			return toAdmissionResponseError(err)
		}

		_, ok := oldDataVolume.Annotations[controller.AnnCloneToken]
		if ok {
			klog.V(3).Infof("DataVolume %s/%s already has clone token", targetNamespace, targetName)
			return allowedAdmissionResponse()
		}
	}

	ok, reason, err := api.CanClonePVC(wh.client, sourceNamespace, sourceName, ar.Request.UserInfo)
	if err != nil {
		return toAdmissionResponseError(err)
	}

	if !ok {
		causes := []metav1.StatusCause{
			{
				Type:    metav1.CauseTypeFieldValueInvalid,
				Message: reason,
				Field:   k8sfield.NewPath("spec", "source", "PVC", "namespace").String(),
			},
		}
		return toRejectedAdmissionResponse(causes)
	}

	tokenData := &token.Payload{
		Operation: token.OperationClone,
		Name:      sourceName,
		Namespace: sourceNamespace,
		Resource:  tokenResource,
		Params: map[string]string{
			"targetNamespace": targetNamespace,
			"targetName":      targetName,
		},
	}

	token, err := wh.tokenGenerator.Generate(tokenData)
	if err != nil {
		return toAdmissionResponseError(err)
	}

	modifiedDataVolume := dataVolume.DeepCopy()
	if modifiedDataVolume.Annotations == nil {
		modifiedDataVolume.Annotations = make(map[string]string)
	}

	modifiedDataVolume.Annotations[controller.AnnCloneToken] = token

	klog.V(3).Infof("Sending patch response...")

	return toPatchResponse(dataVolume, modifiedDataVolume)
}
<|endoftext|>


<commit_before>package mem

import (
	"fmt"
	"io/ioutil"

	"github.com/scottyw/tetromino/options"
)

type mbc interface {
	read(uint16) uint8
	write(uint16, uint8)
}

type mbc1 struct {
	rom        []byte
	bank       uint16
	romBank    uint8
	ramBank    uint8
	romMode    bool
	ramEnabled bool
}

func (m *mbc1) accessRom(addr uint16) uint8 {
	if int(addr) > len(m.rom) {
		panic(fmt.Sprintf("Attempt to access address 0x%04x but MBC1 ROM only has length 0x%04x", addr, len(m.rom)))
	}
	return m.rom[addr]
}

func (m *mbc1) read(addr uint16) uint8 {
	switch {
	case addr < 0x4000:
		return m.accessRom(addr)
	case addr < 0x8000:
		return m.accessRom((m.bank-1)*0x4000 + addr)
	case addr < 0xa000:
		panic(fmt.Sprintf("MBC1 has no mapping for address 0x%04x", addr))
	case addr < 0xc000:
		panic(fmt.Sprintf("MBC1 RAM Bank not implemented! Address: 0x%04x", addr))
	default:
		panic(fmt.Sprintf("MBC1 has no mapping for address 0x%04x", addr))
	}
}

func (m *mbc1) updateBank() {
	if m.romMode {
		m.bank = uint16(m.ramBank<<5 | m.romBank)
	} else {
		m.bank = uint16(m.romBank)
	}
}

func (m *mbc1) write(addr uint16, value uint8) {
	switch {
	case addr < 0x2000:
		//		m.ramEnabled = value&0x0a > 0
	case addr < 0x4000:
		m.romBank = value & 0x1f
		if m.romBank == 0 {
			m.romBank++
		}
	case addr < 0x6000:
		m.ramBank = value & 0x03
	case addr < 0x8000:
		m.romMode = value&0x01 == 0
	default:
		panic(fmt.Sprintf("MBC1 has no mapping for address 0x%04x", addr))
	}
	m.updateBank()
}

func newMBC() mbc {
	var rom []byte
	if *options.RomFilename != "" {
		var err error
		rom, err = ioutil.ReadFile(*options.RomFilename)
		if err != nil {
			panic(fmt.Sprintf("Failed to read the ROM file at \"%s\" (%v)", *options.RomFilename, err))
		}
	} else {
		fmt.Println("No ROM filename specified. Continuing ...")
	}
	return &mbc1{
		rom:  rom,
		bank: 1,
	}
}
<commit_msg>Handle unspecified rom file more gracefully<commit_after>package mem

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/scottyw/tetromino/options"
)

type mbc interface {
	read(uint16) uint8
	write(uint16, uint8)
}

type mbc1 struct {
	rom        []byte
	bank       uint16
	romBank    uint8
	ramBank    uint8
	romMode    bool
	ramEnabled bool
}

func (m *mbc1) accessRom(addr uint16) uint8 {
	if int(addr) > len(m.rom) {
		if len(m.rom) == 0 {
			fmt.Println("No ROM filename specified ...")
			os.Exit(1)
		}
		panic(fmt.Sprintf("Attempt to access address 0x%04x but MBC1 ROM only has length 0x%04x", addr, len(m.rom)))
	}
	return m.rom[addr]
}

func (m *mbc1) read(addr uint16) uint8 {
	switch {
	case addr < 0x4000:
		return m.accessRom(addr)
	case addr < 0x8000:
		return m.accessRom((m.bank-1)*0x4000 + addr)
	case addr < 0xa000:
		panic(fmt.Sprintf("MBC1 has no mapping for address 0x%04x", addr))
	case addr < 0xc000:
		panic(fmt.Sprintf("MBC1 RAM Bank not implemented! Address: 0x%04x", addr))
	default:
		panic(fmt.Sprintf("MBC1 has no mapping for address 0x%04x", addr))
	}
}

func (m *mbc1) updateBank() {
	if m.romMode {
		m.bank = uint16(m.ramBank<<5 | m.romBank)
	} else {
		m.bank = uint16(m.romBank)
	}
}

func (m *mbc1) write(addr uint16, value uint8) {
	switch {
	case addr < 0x2000:
		//		m.ramEnabled = value&0x0a > 0
	case addr < 0x4000:
		m.romBank = value & 0x1f
		if m.romBank == 0 {
			m.romBank++
		}
	case addr < 0x6000:
		m.ramBank = value & 0x03
	case addr < 0x8000:
		m.romMode = value&0x01 == 0
	default:
		panic(fmt.Sprintf("MBC1 has no mapping for address 0x%04x", addr))
	}
	m.updateBank()
}

func newMBC() mbc {
	var rom []byte
	if *options.RomFilename != "" {
		var err error
		rom, err = ioutil.ReadFile(*options.RomFilename)
		if err != nil {
			panic(fmt.Sprintf("Failed to read the ROM file at \"%s\" (%v)", *options.RomFilename, err))
		}
	}
	return &mbc1{
		rom:  rom,
		bank: 1,
	}
}
<|endoftext|>