<commit_before>package gobject

/*
#ifndef uintptr
#define uintptr unsigned int*
#endif
#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <stdint.h>

static inline GObject* to_GObject(void* o) { return G_OBJECT(o); }
static inline void* new_GObject(GType typ) { return g_object_new(typ, NULL); }

static inline const gchar* getTypeName(void * o) { return G_OBJECT_TYPE_NAME(o); }

static inline GObjectClass* get_object_class(void* o) {
	return G_OBJECT_GET_CLASS(o);
}

static inline GType _get_type_from_instance(void* o) {
    return G_TYPE_FROM_INSTANCE(o);
}

extern void weak_ref_callback(gpointer data, GObject* object);

static void _g_object_weak_ref(GObject* object, gint64 data) {
	gint64* intdata = (gint64*)malloc(sizeof(gint64));
	*intdata = data;
	g_object_weak_ref(object, weak_ref_callback, (gpointer)intdata);
}

static void destroy_data(gpointer data) {
	free(data);
}

static void _g_clear_object(void* object) {
	GObject* o = G_OBJECT(object);
	g_clear_object(o);
}

*/
// #cgo pkg-config: gobject-2.0
import "C"
import "unsafe"
import "reflect"
import "time"

func GetTypeFromInstance(obj unsafe.Pointer) GType {
	return GType(C._get_type_from_instance(obj))
}

// Base interface which all gobject like structures must implement
// to be compatible with all gobject functions - public interfaces of gobject
type ObjectLike interface {
	ToNative() unsafe.Pointer
	Connect(s string, f interface{}, data ...interface{}) (*ClosureElement, *SignalError)
	Set(map[string]interface{})
	Get([]string) map[string]interface{}
}

//-----------------------------------------------------------------------
// GObject interfaces
//-----------------------------------------------------------------------
// Convenient struct - singleton
type gobject struct {
	object unsafe.Pointer
}

func (self gobject) ToNative() unsafe.Pointer {
	return self.object
}

func (self gobject) Connect(name string, f interface{}, data ...interface{}) (*ClosureElement, *SignalError) {
	return Connect(self, name, f, data...)
}

func (self gobject) Set(properties map[string]interface{}) {
	Set(self, properties)
}

func (self gobject) Get(properties []string) map[string]interface{} {
	return Get(self, properties)
}

func New(typ GType, properties map[string]interface{}) ObjectLike {
	obj := gobject{}
	obj.object = C.new_GObject(C.GType(typ))

	Set(obj, properties)

	return obj

}

func FindProperty(obj ObjectLike, propName string) *GParamSpec {
	cpn := GString(propName)
	defer cpn.Free()

	oc := C.get_object_class(obj.ToNative())
	pspec := C.g_object_class_find_property(oc, (*C.gchar)(cpn.GetPtr()))
	if pspec == nil {
		return nil
	}
	gpspec := GParamSpec{pspec}
	return &gpspec
}

func Set(obj ObjectLike, properties map[string]interface{}) {
	if len(properties) == 0 {
		return
	}

	for p, v := range properties {
		SetProperty(obj, p, v)
	}
}

func Get(obj ObjectLike, properties []string) map[string]interface{} {
	m := map[string]interface{}{}
	for _, p := range properties {
		gv := GetProperty(obj, p)
		if gv == nil {
			continue
		}
		defer gv.Free()
		val, err := ConvertToGo(gv.GetPtr(), gv.gtype)
		if err == nil {
			m[p] = val
		}
	}
	return m
}

func SetProperty(obj ObjectLike, propName string, value interface{}) {
	cpn := GString(propName)
	defer cpn.Free()
	v := ConvertToC(value)
	defer v.Free()

	C.g_object_set_property(C.to_GObject(obj.ToNative()), (*C.gchar)(cpn.GetPtr()),
		(*C.GValue)(v.ToCGValue()))

}

func GetProperty(obj ObjectLike, propName string) *GValue {
	pspec := FindProperty(obj, propName)
	if pspec == nil {
		return nil
	}
	gv := CreateCGValue(pspec.GetType())
	pn := GString(propName)
	defer pn.Free()
	C.g_object_get_property(C.to_GObject(obj.ToNative()),
		(*C.gchar)(pn.GetPtr()),
		(*C.GValue)(gv.ToCGValue()))
	return gv
}

func Ref(obj ObjectLike) {
	C.g_object_ref(C.gpointer(obj.ToNative()))
}

func Unref(obj ObjectLike) {
	C.g_object_unref(C.gpointer(obj.ToNative()))
}

func SignalLookup(name string, objectType GType) uint32 {
	n := GString(name)
	defer n.Free()
	s := C.g_signal_lookup((*C.gchar)(n.GetPtr()), C.GType(objectType))
	return uint32(s)
}

func getUniqueID() int64 {
	return time.Nanoseconds()
}

type SignalError struct {
	Err string
}

func (self SignalError) Error() string {
	return self.Err
}

func createClosure(f interface{}, data ...interface{}) ClosureFunc {
	cfunc := reflect.ValueOf(f)

	// cfunc is not function, then there is nothing to do
	if cfunc.Kind() != reflect.Func {
		return nil
	}

	// Test number and type of return arguments
	// If return value is bool and is the only one, then
	// return that value to handler.
	// For anything else automaticaly return true
	var isTrue bool = true
	if numReturn := cfunc.Type().NumOut(); numReturn == 1 {
		rt := cfunc.Type().Out(0)
		if rt.Kind() == reflect.Bool {
			isTrue = false
		}
	}

	// Do we have variadic function for additional arguments
	var argslice bool = false
	if cfunc.Type().IsVariadic() {
		argslice = true
	}

	return func(additionalArgs []interface{}) bool {
		// Additional data
		// Create slice of reflect.Value data
		var args = make([]reflect.Value, 0)
		if len(data) > 0 {
			for _, d := range data {
				args = append(args, reflect.ValueOf(d))
			}
		}
		if argslice == true {
			for _, i := range additionalArgs {
				args = append(args, reflect.ValueOf(i))
			}
		}
		res := cfunc.Call(args)
		if isTrue {
			return isTrue
		}
		return res[0].Bool()
	}
}

func CreateCustomClosure(f interface{}, data ...interface{}) (ClosureFunc, int64) {
	cFunc := createClosure(f, data...)

	return cFunc, getUniqueID()
}

func Connect(obj ObjectLike, name string, f interface{}, data ...interface{}) (*ClosureElement, *SignalError) {
	s_id := SignalLookup(name, GetTypeFromInstance(obj.ToNative()))

	if s_id == 0 {
		return nil, &SignalError{"Signal not found"}
	}
	uid := getUniqueID()
	c := createClosure(f, data...)
	cloEl := RegisterHandler(obj, name, uid, c)
	return cloEl, nil
}

func IsObjectFloating(obj ObjectLike) bool {
	b := C.g_object_is_floating(C.gpointer(obj.ToNative()))
	return GoBool(unsafe.Pointer(&b))
}

func RefSink(obj ObjectLike) {
	C.g_object_ref_sink(C.gpointer(obj.ToNative()))
}

func ClearObject(obj ObjectLike) {
	C._g_clear_object(obj.ToNative())
}

// WeakRef closure stack
type WeakClosureFunc func()

var _weakClosures map[int64]WeakClosureFunc

func WeakRef(obj ObjectLike, f WeakClosureFunc) int64 {
	uid := getUniqueID()
	_weakClosures[uid] = f
	o := C.to_GObject(obj.ToNative())
	C._g_object_weak_ref(o, C.gint64(uid))

	return uid
}

//export weak_ref_callback
func weak_ref_callback(data unsafe.Pointer, obj unsafe.Pointer) {
	cint := int64(*((*C.gint64)(data)))

	if f, ok := _weakClosures[cint]; ok {
		// Call WeakClosureFunc to clean up something
		f()

		// Remove this closure from _weakClosures
		delete(_weakClosures, cint)
	}

	// Free data
	C.destroy_data(C.gpointer(data))
}

func init() {
	_weakClosures = make(map[int64]WeakClosureFunc)
}
<commit_msg>To be compatible with latest go weekly.<commit_after>package gobject

/*
#ifndef uintptr
#define uintptr unsigned int*
#endif
#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <stdint.h>

static inline GObject* to_GObject(void* o) { return G_OBJECT(o); }
static inline void* new_GObject(GType typ) { return g_object_new(typ, NULL); }

static inline const gchar* getTypeName(void * o) { return G_OBJECT_TYPE_NAME(o); }

static inline GObjectClass* get_object_class(void* o) {
	return G_OBJECT_GET_CLASS(o);
}

static inline GType _get_type_from_instance(void* o) {
    return G_TYPE_FROM_INSTANCE(o);
}

extern void weak_ref_callback(gpointer data, GObject* object);

static void _g_object_weak_ref(GObject* object, gint64 data) {
	gint64* intdata = (gint64*)malloc(sizeof(gint64));
	*intdata = data;
	g_object_weak_ref(object, weak_ref_callback, (gpointer)intdata);
}

static void destroy_data(gpointer data) {
	free(data);
}

static void _g_clear_object(void* object) {
	GObject* o = G_OBJECT(object);
	g_clear_object(o);
}

*/
// #cgo pkg-config: gobject-2.0
import "C"
import "unsafe"
import "reflect"
import "time"

func GetTypeFromInstance(obj unsafe.Pointer) GType {
	return GType(C._get_type_from_instance(obj))
}

// Base interface which all gobject like structures must implement
// to be compatible with all gobject functions - public interfaces of gobject
type ObjectLike interface {
	ToNative() unsafe.Pointer
	Connect(s string, f interface{}, data ...interface{}) (*ClosureElement, *SignalError)
	Set(map[string]interface{})
	Get([]string) map[string]interface{}
}

//-----------------------------------------------------------------------
// GObject interfaces
//-----------------------------------------------------------------------
// Convenient struct - singleton
type gobject struct {
	object unsafe.Pointer
}

func (self gobject) ToNative() unsafe.Pointer {
	return self.object
}

func (self gobject) Connect(name string, f interface{}, data ...interface{}) (*ClosureElement, *SignalError) {
	return Connect(self, name, f, data...)
}

func (self gobject) Set(properties map[string]interface{}) {
	Set(self, properties)
}

func (self gobject) Get(properties []string) map[string]interface{} {
	return Get(self, properties)
}

func New(typ GType, properties map[string]interface{}) ObjectLike {
	obj := gobject{}
	obj.object = C.new_GObject(C.GType(typ))

	Set(obj, properties)

	return obj

}

func FindProperty(obj ObjectLike, propName string) *GParamSpec {
	cpn := GString(propName)
	defer cpn.Free()

	oc := C.get_object_class(obj.ToNative())
	pspec := C.g_object_class_find_property(oc, (*C.gchar)(cpn.GetPtr()))
	if pspec == nil {
		return nil
	}
	gpspec := GParamSpec{pspec}
	return &gpspec
}

func Set(obj ObjectLike, properties map[string]interface{}) {
	if len(properties) == 0 {
		return
	}

	for p, v := range properties {
		SetProperty(obj, p, v)
	}
}

func Get(obj ObjectLike, properties []string) map[string]interface{} {
	m := map[string]interface{}{}
	for _, p := range properties {
		gv := GetProperty(obj, p)
		if gv == nil {
			continue
		}
		defer gv.Free()
		val, err := ConvertToGo(gv.GetPtr(), gv.gtype)
		if err == nil {
			m[p] = val
		}
	}
	return m
}

func SetProperty(obj ObjectLike, propName string, value interface{}) {
	cpn := GString(propName)
	defer cpn.Free()
	v := ConvertToC(value)
	defer v.Free()

	C.g_object_set_property(C.to_GObject(obj.ToNative()), (*C.gchar)(cpn.GetPtr()),
		(*C.GValue)(v.ToCGValue()))

}

func GetProperty(obj ObjectLike, propName string) *GValue {
	pspec := FindProperty(obj, propName)
	if pspec == nil {
		return nil
	}
	gv := CreateCGValue(pspec.GetType())
	pn := GString(propName)
	defer pn.Free()
	C.g_object_get_property(C.to_GObject(obj.ToNative()),
		(*C.gchar)(pn.GetPtr()),
		(*C.GValue)(gv.ToCGValue()))
	return gv
}

func Ref(obj ObjectLike) {
	C.g_object_ref(C.gpointer(obj.ToNative()))
}

func Unref(obj ObjectLike) {
	C.g_object_unref(C.gpointer(obj.ToNative()))
}

func SignalLookup(name string, objectType GType) uint32 {
	n := GString(name)
	defer n.Free()
	s := C.g_signal_lookup((*C.gchar)(n.GetPtr()), C.GType(objectType))
	return uint32(s)
}

func getUniqueID() int64 {
	return time.Now().UnixNano()
}

type SignalError struct {
	Err string
}

func (self SignalError) Error() string {
	return self.Err
}

func createClosure(f interface{}, data ...interface{}) ClosureFunc {
	cfunc := reflect.ValueOf(f)

	// cfunc is not function, then there is nothing to do
	if cfunc.Kind() != reflect.Func {
		return nil
	}

	// Test number and type of return arguments
	// If return value is bool and is the only one, then
	// return that value to handler.
	// For anything else automaticaly return true
	var isTrue bool = true
	if numReturn := cfunc.Type().NumOut(); numReturn == 1 {
		rt := cfunc.Type().Out(0)
		if rt.Kind() == reflect.Bool {
			isTrue = false
		}
	}

	// Do we have variadic function for additional arguments
	var argslice bool = false
	if cfunc.Type().IsVariadic() {
		argslice = true
	}

	return func(additionalArgs []interface{}) bool {
		// Additional data
		// Create slice of reflect.Value data
		var args = make([]reflect.Value, 0)
		if len(data) > 0 {
			for _, d := range data {
				args = append(args, reflect.ValueOf(d))
			}
		}
		if argslice == true {
			for _, i := range additionalArgs {
				args = append(args, reflect.ValueOf(i))
			}
		}
		res := cfunc.Call(args)
		if isTrue {
			return isTrue
		}
		return res[0].Bool()
	}
}

func CreateCustomClosure(f interface{}, data ...interface{}) (ClosureFunc, int64) {
	cFunc := createClosure(f, data...)

	return cFunc, getUniqueID()
}

func Connect(obj ObjectLike, name string, f interface{}, data ...interface{}) (*ClosureElement, *SignalError) {
	s_id := SignalLookup(name, GetTypeFromInstance(obj.ToNative()))

	if s_id == 0 {
		return nil, &SignalError{"Signal not found"}
	}
	uid := getUniqueID()
	c := createClosure(f, data...)
	cloEl := RegisterHandler(obj, name, uid, c)
	return cloEl, nil
}

func IsObjectFloating(obj ObjectLike) bool {
	b := C.g_object_is_floating(C.gpointer(obj.ToNative()))
	return GoBool(unsafe.Pointer(&b))
}

func RefSink(obj ObjectLike) {
	C.g_object_ref_sink(C.gpointer(obj.ToNative()))
}

func ClearObject(obj ObjectLike) {
	C._g_clear_object(obj.ToNative())
}

// WeakRef closure stack
type WeakClosureFunc func()

var _weakClosures map[int64]WeakClosureFunc

func WeakRef(obj ObjectLike, f WeakClosureFunc) int64 {
	uid := getUniqueID()
	_weakClosures[uid] = f
	o := C.to_GObject(obj.ToNative())
	C._g_object_weak_ref(o, C.gint64(uid))

	return uid
}

//export weak_ref_callback
func weak_ref_callback(data unsafe.Pointer, obj unsafe.Pointer) {
	cint := int64(*((*C.gint64)(data)))

	if f, ok := _weakClosures[cint]; ok {
		// Call WeakClosureFunc to clean up something
		f()

		// Remove this closure from _weakClosures
		delete(_weakClosures, cint)
	}

	// Free data
	C.destroy_data(C.gpointer(data))
}

func init() {
	_weakClosures = make(map[int64]WeakClosureFunc)
}
<|endoftext|>


<commit_before>package turtle

// #cgo CFLAGS: -I ../raptor/src
// #cgo LDFLAGS: -lraptor2
// #include <stdio.h>
// #include <raptor2.h>
import "C"
import (
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"sync"
	"time"
)

var p *Parser

type Parser struct {
	dataset *DataSet
	sync.Mutex
}

type URI struct {
	Namespace string
	Value     string
}

func (u URI) String() string {
	if u.Namespace != "" {
		return u.Namespace + "#" + u.Value
	}
	return u.Value
}

func (u URI) Bytes() []byte {
	return []byte(u.Namespace + "#" + u.Value)
}

func (u URI) IsVariable() bool {
	return strings.HasPrefix(u.Value, "?")
}

func ParseURI(uri string) URI {
	uri = strings.TrimLeft(uri, "<")
	uri = strings.TrimRight(uri, ">")
	parts := strings.Split(uri, "#")
	parts[0] = strings.TrimRight(parts[0], "#")
	if len(parts) != 2 {
		return URI{Value: uri}
	}
	return URI{Namespace: parts[0], Value: parts[1]}
}

type Triple struct {
	Subject   URI
	Predicate URI
	Object    URI
}

func MakeTriple(sub, pred, obj string) Triple {
	s := ParseURI(sub)
	p := ParseURI(pred)
	o := ParseURI(obj)
	return Triple{
		Subject:   s,
		Predicate: p,
		Object:    o,
	}
}

func init() {
	p = &Parser{}
}

//export transform
func transform(_subject, _predicate, _object *C.char, sub_len, pred_len, obj_len C.int) {
	subject := C.GoStringN(_subject, sub_len)
	predicate := C.GoStringN(_predicate, pred_len)
	object := C.GoStringN(_object, obj_len)
	p.dataset.addTriple(subject, predicate, object)
}

//export registerNamespace
func registerNamespace(_namespace, _prefix *C.char, ns_len, pfx_len C.int) {
	namespace := C.GoStringN(_namespace, ns_len)
	prefix := C.GoStringN(_prefix, pfx_len)
	p.dataset.addNamespace(prefix, namespace)
}

// Return Parser instance
func GetParser() *Parser {
	return p
}

// Parses the given filename using the turtle format.
// Returns the dataset, and the time elapsed in parsing
func (p *Parser) Parse(filename string) (DataSet, time.Duration) {
	p.Lock()
	defer p.Unlock()
	start := time.Now()
	p.dataset = newDataSet()
	p.parseFile(filename)
	took := time.Since(start)
	return *p.dataset, took
}

// Writes the contents of the reader to a temporary file, and then reads in that file
func (p *Parser) ParseReader(r io.Reader) (DataSet, time.Duration, error) {
	p.Lock()
	defer p.Unlock()
	start := time.Now()
	p.dataset = newDataSet()
	f, err := ioutil.TempFile(".", "_raptor")
	if err != nil {
		return *p.dataset, time.Since(start), err
	}
	defer func() {
		os.Remove(f.Name())
	}()
	n, err := io.Copy(f, r)
	if err != nil {
		return *p.dataset, time.Since(start), err
	}
	log.Printf("Wrote %d bytes", n)
	p.parseFile(f.Name())
	took := time.Since(start)
	return *p.dataset, took, nil
}
<commit_msg>parse : URIs<commit_after>package turtle

// #cgo CFLAGS: -I ../raptor/src
// #cgo LDFLAGS: -lraptor2
// #include <stdio.h>
// #include <raptor2.h>
import "C"
import (
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"sync"
	"time"
)

var p *Parser

type Parser struct {
	dataset *DataSet
	sync.Mutex
}

type URI struct {
	Namespace string
	Value     string
}

func (u URI) String() string {
	if u.Namespace != "" {
		return u.Namespace + "#" + u.Value
	}
	return u.Value
}

func (u URI) Bytes() []byte {
	return []byte(u.Namespace + "#" + u.Value)
}

func (u URI) IsVariable() bool {
	return strings.HasPrefix(u.Value, "?")
}

func ParseURI(uri string) URI {
	uri = strings.TrimLeft(uri, "<")
	uri = strings.TrimRight(uri, ">")
	parts := strings.Split(uri, "#")
	parts[0] = strings.TrimRight(parts[0], "#")
	if len(parts) != 2 {
		// try to parse ":"
		parts = strings.SplitN(uri, ":", 2)
		if len(parts) > 1 {
			return URI{Namespace: parts[0], Value: parts[1]}
		}
		uri = strings.TrimPrefix(uri, "?") // parse variable
		return URI{Value: uri}
	}
	return URI{Namespace: parts[0], Value: parts[1]}
}

type Triple struct {
	Subject   URI
	Predicate URI
	Object    URI
}

func MakeTriple(sub, pred, obj string) Triple {
	s := ParseURI(sub)
	p := ParseURI(pred)
	o := ParseURI(obj)
	return Triple{
		Subject:   s,
		Predicate: p,
		Object:    o,
	}
}

func init() {
	p = &Parser{}
}

//export transform
func transform(_subject, _predicate, _object *C.char, sub_len, pred_len, obj_len C.int) {
	subject := C.GoStringN(_subject, sub_len)
	predicate := C.GoStringN(_predicate, pred_len)
	object := C.GoStringN(_object, obj_len)
	p.dataset.addTriple(subject, predicate, object)
}

//export registerNamespace
func registerNamespace(_namespace, _prefix *C.char, ns_len, pfx_len C.int) {
	namespace := C.GoStringN(_namespace, ns_len)
	prefix := C.GoStringN(_prefix, pfx_len)
	p.dataset.addNamespace(prefix, namespace)
}

// Return Parser instance
func GetParser() *Parser {
	return p
}

// Parses the given filename using the turtle format.
// Returns the dataset, and the time elapsed in parsing
func (p *Parser) Parse(filename string) (DataSet, time.Duration) {
	p.Lock()
	defer p.Unlock()
	start := time.Now()
	p.dataset = newDataSet()
	p.parseFile(filename)
	took := time.Since(start)
	return *p.dataset, took
}

// Writes the contents of the reader to a temporary file, and then reads in that file
func (p *Parser) ParseReader(r io.Reader) (DataSet, time.Duration, error) {
	p.Lock()
	defer p.Unlock()
	start := time.Now()
	p.dataset = newDataSet()
	f, err := ioutil.TempFile(".", "_raptor")
	if err != nil {
		return *p.dataset, time.Since(start), err
	}
	defer func() {
		os.Remove(f.Name())
	}()
	n, err := io.Copy(f, r)
	if err != nil {
		return *p.dataset, time.Since(start), err
	}
	log.Printf("Wrote %d bytes", n)
	p.parseFile(f.Name())
	took := time.Since(start)
	return *p.dataset, took, nil
}
<|endoftext|>


<commit_before>package mqtt

import (
	"bytes"
	"fmt"
	"strings"
	"sync"
	"text/template"
	"time"

	paho "github.com/eclipse/paho.mqtt.golang"
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"

	"github.com/brocaar/lora-gateway-bridge/internal/config"
	"github.com/brocaar/lora-gateway-bridge/internal/integration/mqtt/auth"
	"github.com/brocaar/loraserver/api/gw"
	"github.com/brocaar/lorawan"
)

// Backend implements a MQTT backend.
type Backend struct {
	sync.RWMutex

	auth                     auth.Authentication
	conn                     paho.Client
	closed                   bool
	clientOpts               *paho.ClientOptions
	downlinkFrameChan        chan gw.DownlinkFrame
	gatewayConfigurationChan chan gw.GatewayConfiguration
	gateways                 map[lorawan.EUI64]struct{}

	qos                  uint8
	eventTopicTemplate   *template.Template
	commandTopicTemplate *template.Template

	marshal   func(msg proto.Message) ([]byte, error)
	unmarshal func(b []byte, msg proto.Message) error
}

// NewBackend creates a new Backend.
func NewBackend(conf config.Config) (*Backend, error) {
	var err error

	b := Backend{
		qos:                      conf.Integration.MQTT.Auth.Generic.QOS,
		clientOpts:               paho.NewClientOptions(),
		downlinkFrameChan:        make(chan gw.DownlinkFrame),
		gatewayConfigurationChan: make(chan gw.GatewayConfiguration),
		gateways:                 make(map[lorawan.EUI64]struct{}),
	}

	switch conf.Integration.MQTT.Auth.Type {
	case "generic":
		b.auth, err = auth.NewGenericAuthentication(conf)
		if err != nil {
			return nil, errors.Wrap(err, "integation/mqtt: new generic authentication error")
		}
	case "gcp_cloud_iot_core":
		b.auth, err = auth.NewGCPCloudIoTCoreAuthentication(conf)
		if err != nil {
			return nil, errors.Wrap(err, "integration/mqtt: new GCP Cloud IoT Core authentication error")
		}

		conf.Integration.MQTT.EventTopicTemplate = "/devices/gw-{{ .GatewayID }}/events/{{ .EventType }}"
		conf.Integration.MQTT.CommandTopicTemplate = "/devices/gw-{{ .GatewayID }}/commands/#"
	case "azure_iot_hub":
		b.auth, err = auth.NewAzureIoTHubAuthentication(conf)
		if err != nil {
			return nil, errors.Wrap(err, "integration/mqtt: new azure iot hub authentication error")
		}

		conf.Integration.MQTT.EventTopicTemplate = "devices/{{ .GatewayID }}/messages/events/{{ .EventType }}"
		conf.Integration.MQTT.CommandTopicTemplate = "devices/{{ .GatewayID }}/messages/devicebound/#"
	default:
		return nil, fmt.Errorf("integration/mqtt: unknown auth type: %s", conf.Integration.MQTT.Auth.Type)
	}

	switch conf.Integration.Marshaler {
	case "json":
		b.marshal = func(msg proto.Message) ([]byte, error) {
			marshaler := &jsonpb.Marshaler{
				EnumsAsInts:  false,
				EmitDefaults: true,
			}
			str, err := marshaler.MarshalToString(msg)
			return []byte(str), err
		}

		b.unmarshal = func(b []byte, msg proto.Message) error {
			unmarshaler := &jsonpb.Unmarshaler{
				AllowUnknownFields: true, // we don't want to fail on unknown fields
			}
			return unmarshaler.Unmarshal(bytes.NewReader(b), msg)
		}
	case "protobuf":
		b.marshal = func(msg proto.Message) ([]byte, error) {
			return proto.Marshal(msg)
		}

		b.unmarshal = func(b []byte, msg proto.Message) error {
			return proto.Unmarshal(b, msg)
		}
	default:
		return nil, fmt.Errorf("integration/mqtt: unknown marshaler: %s", conf.Integration.Marshaler)
	}

	b.eventTopicTemplate, err = template.New("event").Parse(conf.Integration.MQTT.EventTopicTemplate)
	if err != nil {
		return nil, errors.Wrap(err, "integration/mqtt: parse event-topic template error")
	}

	b.commandTopicTemplate, err = template.New("event").Parse(conf.Integration.MQTT.CommandTopicTemplate)
	if err != nil {
		return nil, errors.Wrap(err, "integration/mqtt: parse event-topic template error")
	}

	b.clientOpts.SetProtocolVersion(4)
	b.clientOpts.SetAutoReconnect(false)
	b.clientOpts.SetOnConnectHandler(b.onConnected)
	b.clientOpts.SetConnectionLostHandler(b.onConnectionLost)

	if err = b.auth.Init(b.clientOpts); err != nil {
		return nil, errors.Wrap(err, "mqtt: init authentication error")
	}

	b.connectLoop()
	go b.reconnectLoop()

	return &b, nil
}

// Close closes the backend.
func (b *Backend) Close() error {
	b.Lock()
	b.closed = true
	b.Unlock()

	b.conn.Disconnect(250)
	return nil
}

// GetDownlinkFrameChan returns the downlink frame channel.
func (b *Backend) GetDownlinkFrameChan() chan gw.DownlinkFrame {
	return b.downlinkFrameChan
}

// GetGatewayConfigurationChan returns the gateway configuration channel.
func (b *Backend) GetGatewayConfigurationChan() chan gw.GatewayConfiguration {
	return b.gatewayConfigurationChan
}

// SubscribeGateway subscribes a gateway to its topics.
func (b *Backend) SubscribeGateway(gatewayID lorawan.EUI64) error {
	b.Lock()
	defer b.Unlock()

	if err := b.subscribeGateway(gatewayID); err != nil {
		return err
	}

	b.gateways[gatewayID] = struct{}{}
	return nil
}

func (b *Backend) subscribeGateway(gatewayID lorawan.EUI64) error {
	topic := bytes.NewBuffer(nil)
	if err := b.commandTopicTemplate.Execute(topic, struct{ GatewayID lorawan.EUI64 }{gatewayID}); err != nil {
		return errors.Wrap(err, "execute command topic template error")
	}
	log.WithFields(log.Fields{
		"topic": topic.String(),
		"qos":   b.qos,
	}).Info("integration/mqtt: subscribing to topic")

	if token := b.conn.Subscribe(topic.String(), b.qos, b.handleCommand); token.Wait() && token.Error() != nil {
		return errors.Wrap(token.Error(), "subscribe topic error")
	}
	return nil
}

// UnsubscribeGateway unsubscribes the gateway from its topics.
func (b *Backend) UnsubscribeGateway(gatewayID lorawan.EUI64) error {
	b.Lock()
	defer b.Unlock()

	topic := bytes.NewBuffer(nil)
	if err := b.commandTopicTemplate.Execute(topic, struct{ GatewayID lorawan.EUI64 }{gatewayID}); err != nil {
		return errors.Wrap(err, "execute command topic template error")
	}
	log.WithFields(log.Fields{
		"topic": topic.String(),
	}).Info("integration/mqtt: unsubscribe topic")

	if token := b.conn.Unsubscribe(topic.String()); token.Wait() && token.Error() != nil {
		return errors.Wrap(token.Error(), "unsubscribe topic error")
	}

	delete(b.gateways, gatewayID)
	return nil
}

// PublishEvent publishes the given event.
func (b *Backend) PublishEvent(gatewayID lorawan.EUI64, event string, v proto.Message) error {
	mqttEventCounter(event).Inc()
	return b.publish(gatewayID, event, v)
}

func (b *Backend) connect() error {
	b.Lock()
	defer b.Unlock()

	if err := b.auth.Update(b.clientOpts); err != nil {
		return errors.Wrap(err, "integration/mqtt: update authentication error")
	}

	b.conn = paho.NewClient(b.clientOpts)
	if token := b.conn.Connect(); token.Wait() && token.Error() != nil {
		return token.Error()
	}

	return nil
}

// connectLoop blocks until the client is connected
func (b *Backend) connectLoop() {
	for {
		if err := b.connect(); err != nil {
			log.WithError(err).Error("integration/mqtt: connection error")
			time.Sleep(time.Second * 2)

		} else {
			break
		}
	}
}

func (b *Backend) disconnect() error {
	mqttDisconnectCounter().Inc()

	b.Lock()
	defer b.Unlock()

	b.conn.Disconnect(250)
	return nil
}

func (b *Backend) reconnectLoop() {
	if b.auth.ReconnectAfter() > 0 {
		for {
			if b.closed {
				break
			}
			time.Sleep(b.auth.ReconnectAfter())
			log.Info("mqtt: re-connect triggered")

			mqttReconnectCounter().Inc()

			b.disconnect()
			b.connectLoop()
		}
	}
}

func (b *Backend) onConnected(c paho.Client) {
	mqttConnectCounter().Inc()

	b.RLock()
	defer b.RUnlock()

	log.Info("integration/mqtt: connected to mqtt broker")

	for gatewayID := range b.gateways {
		for {
			if err := b.subscribeGateway(gatewayID); err != nil {
				log.WithError(err).WithField("gateway_id", gatewayID).Error("integration/mqtt: subscribe gateway error")
				time.Sleep(time.Second)
				continue
			}

			break
		}
	}
}

func (b *Backend) onConnectionLost(c paho.Client, err error) {
	mqttDisconnectCounter().Inc()
	log.WithError(err).Error("mqtt: connection error")
	b.connectLoop()
}

func (b *Backend) handleDownlinkFrame(c paho.Client, msg paho.Message) {
	log.WithFields(log.Fields{
		"topic": msg.Topic(),
	}).Info("integration/mqtt: downlink frame received")

	var downlinkFrame gw.DownlinkFrame
	if err := b.unmarshal(msg.Payload(), &downlinkFrame); err != nil {
		log.WithError(err).Error("integration/mqtt: unmarshal downlink frame error")
		return
	}

	b.downlinkFrameChan <- downlinkFrame
}

func (b *Backend) handleGatewayConfiguration(c paho.Client, msg paho.Message) {
	log.WithFields(log.Fields{
		"topic": msg.Topic(),
	}).Info("integration/mqtt: gateway configuration received")

	var gatewayConfig gw.GatewayConfiguration
	if err := b.unmarshal(msg.Payload(), &gatewayConfig); err != nil {
		log.WithError(err).Error("integration/mqtt: unmarshal gateway configuration error")
		return
	}

	b.gatewayConfigurationChan <- gatewayConfig
}

func (b *Backend) handleCommand(c paho.Client, msg paho.Message) {
	if strings.HasSuffix(msg.Topic(), "down") || strings.Contains(msg.Topic(), "command=down") {
		mqttCommandCounter("down").Inc()
		b.handleDownlinkFrame(c, msg)
	} else if strings.HasSuffix(msg.Topic(), "config") || strings.Contains(msg.Topic(), "command=config") {
		mqttCommandCounter("config").Inc()
		b.handleGatewayConfiguration(c, msg)
	} else {
		log.WithFields(log.Fields{
			"topic": msg.Topic(),
		}).Warning("integration/mqtt: unexpected command received")
	}
}

func (b *Backend) publish(gatewayID lorawan.EUI64, event string, msg proto.Message) error {
	topic := bytes.NewBuffer(nil)
	if err := b.eventTopicTemplate.Execute(topic, struct {
		GatewayID lorawan.EUI64
		EventType string
	}{gatewayID, event}); err != nil {
		return errors.Wrap(err, "execute event template error")
	}

	bytes, err := b.marshal(msg)
	if err != nil {
		return errors.Wrap(err, "marshal message error")
	}

	log.WithFields(log.Fields{
		"topic": topic.String(),
		"qos":   b.qos,
		"event": event,
	}).Info("integration/mqtt: publishing event")
	if token := b.conn.Publish(topic.String(), b.qos, false, bytes); token.Wait() && token.Error() != nil {
		return token.Error()
	}
	return nil
}
<commit_msg>Set auto-reconnect to true in order to buffer messages.<commit_after>package mqtt

import (
	"bytes"
	"fmt"
	"strings"
	"sync"
	"text/template"
	"time"

	paho "github.com/eclipse/paho.mqtt.golang"
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"

	"github.com/brocaar/lora-gateway-bridge/internal/config"
	"github.com/brocaar/lora-gateway-bridge/internal/integration/mqtt/auth"
	"github.com/brocaar/loraserver/api/gw"
	"github.com/brocaar/lorawan"
)

// Backend implements a MQTT backend.
type Backend struct {
	sync.RWMutex

	auth                     auth.Authentication
	conn                     paho.Client
	closed                   bool
	clientOpts               *paho.ClientOptions
	downlinkFrameChan        chan gw.DownlinkFrame
	gatewayConfigurationChan chan gw.GatewayConfiguration
	gateways                 map[lorawan.EUI64]struct{}

	qos                  uint8
	eventTopicTemplate   *template.Template
	commandTopicTemplate *template.Template

	marshal   func(msg proto.Message) ([]byte, error)
	unmarshal func(b []byte, msg proto.Message) error
}

// NewBackend creates a new Backend.
func NewBackend(conf config.Config) (*Backend, error) {
	var err error

	b := Backend{
		qos:                      conf.Integration.MQTT.Auth.Generic.QOS,
		clientOpts:               paho.NewClientOptions(),
		downlinkFrameChan:        make(chan gw.DownlinkFrame),
		gatewayConfigurationChan: make(chan gw.GatewayConfiguration),
		gateways:                 make(map[lorawan.EUI64]struct{}),
	}

	switch conf.Integration.MQTT.Auth.Type {
	case "generic":
		b.auth, err = auth.NewGenericAuthentication(conf)
		if err != nil {
			return nil, errors.Wrap(err, "integation/mqtt: new generic authentication error")
		}
	case "gcp_cloud_iot_core":
		b.auth, err = auth.NewGCPCloudIoTCoreAuthentication(conf)
		if err != nil {
			return nil, errors.Wrap(err, "integration/mqtt: new GCP Cloud IoT Core authentication error")
		}

		conf.Integration.MQTT.EventTopicTemplate = "/devices/gw-{{ .GatewayID }}/events/{{ .EventType }}"
		conf.Integration.MQTT.CommandTopicTemplate = "/devices/gw-{{ .GatewayID }}/commands/#"
	case "azure_iot_hub":
		b.auth, err = auth.NewAzureIoTHubAuthentication(conf)
		if err != nil {
			return nil, errors.Wrap(err, "integration/mqtt: new azure iot hub authentication error")
		}

		conf.Integration.MQTT.EventTopicTemplate = "devices/{{ .GatewayID }}/messages/events/{{ .EventType }}"
		conf.Integration.MQTT.CommandTopicTemplate = "devices/{{ .GatewayID }}/messages/devicebound/#"
	default:
		return nil, fmt.Errorf("integration/mqtt: unknown auth type: %s", conf.Integration.MQTT.Auth.Type)
	}

	switch conf.Integration.Marshaler {
	case "json":
		b.marshal = func(msg proto.Message) ([]byte, error) {
			marshaler := &jsonpb.Marshaler{
				EnumsAsInts:  false,
				EmitDefaults: true,
			}
			str, err := marshaler.MarshalToString(msg)
			return []byte(str), err
		}

		b.unmarshal = func(b []byte, msg proto.Message) error {
			unmarshaler := &jsonpb.Unmarshaler{
				AllowUnknownFields: true, // we don't want to fail on unknown fields
			}
			return unmarshaler.Unmarshal(bytes.NewReader(b), msg)
		}
	case "protobuf":
		b.marshal = func(msg proto.Message) ([]byte, error) {
			return proto.Marshal(msg)
		}

		b.unmarshal = func(b []byte, msg proto.Message) error {
			return proto.Unmarshal(b, msg)
		}
	default:
		return nil, fmt.Errorf("integration/mqtt: unknown marshaler: %s", conf.Integration.Marshaler)
	}

	b.eventTopicTemplate, err = template.New("event").Parse(conf.Integration.MQTT.EventTopicTemplate)
	if err != nil {
		return nil, errors.Wrap(err, "integration/mqtt: parse event-topic template error")
	}

	b.commandTopicTemplate, err = template.New("event").Parse(conf.Integration.MQTT.CommandTopicTemplate)
	if err != nil {
		return nil, errors.Wrap(err, "integration/mqtt: parse event-topic template error")
	}

	b.clientOpts.SetProtocolVersion(4)
	b.clientOpts.SetAutoReconnect(true) // this is required for buffering messages in case offline!
	b.clientOpts.SetOnConnectHandler(b.onConnected)
	b.clientOpts.SetConnectionLostHandler(b.onConnectionLost)

	if err = b.auth.Init(b.clientOpts); err != nil {
		return nil, errors.Wrap(err, "mqtt: init authentication error")
	}

	b.connectLoop()
	go b.reconnectLoop()

	return &b, nil
}

// Close closes the backend.
func (b *Backend) Close() error {
	b.Lock()
	b.closed = true
	b.Unlock()

	b.conn.Disconnect(250)
	return nil
}

// GetDownlinkFrameChan returns the downlink frame channel.
func (b *Backend) GetDownlinkFrameChan() chan gw.DownlinkFrame {
	return b.downlinkFrameChan
}

// GetGatewayConfigurationChan returns the gateway configuration channel.
func (b *Backend) GetGatewayConfigurationChan() chan gw.GatewayConfiguration {
	return b.gatewayConfigurationChan
}

// SubscribeGateway subscribes a gateway to its topics.
func (b *Backend) SubscribeGateway(gatewayID lorawan.EUI64) error {
	b.Lock()
	defer b.Unlock()

	if err := b.subscribeGateway(gatewayID); err != nil {
		return err
	}

	b.gateways[gatewayID] = struct{}{}
	return nil
}

func (b *Backend) subscribeGateway(gatewayID lorawan.EUI64) error {
	topic := bytes.NewBuffer(nil)
	if err := b.commandTopicTemplate.Execute(topic, struct{ GatewayID lorawan.EUI64 }{gatewayID}); err != nil {
		return errors.Wrap(err, "execute command topic template error")
	}
	log.WithFields(log.Fields{
		"topic": topic.String(),
		"qos":   b.qos,
	}).Info("integration/mqtt: subscribing to topic")

	if token := b.conn.Subscribe(topic.String(), b.qos, b.handleCommand); token.Wait() && token.Error() != nil {
		return errors.Wrap(token.Error(), "subscribe topic error")
	}
	return nil
}

// UnsubscribeGateway unsubscribes the gateway from its topics.
func (b *Backend) UnsubscribeGateway(gatewayID lorawan.EUI64) error {
	b.Lock()
	defer b.Unlock()

	topic := bytes.NewBuffer(nil)
	if err := b.commandTopicTemplate.Execute(topic, struct{ GatewayID lorawan.EUI64 }{gatewayID}); err != nil {
		return errors.Wrap(err, "execute command topic template error")
	}
	log.WithFields(log.Fields{
		"topic": topic.String(),
	}).Info("integration/mqtt: unsubscribe topic")

	if token := b.conn.Unsubscribe(topic.String()); token.Wait() && token.Error() != nil {
		return errors.Wrap(token.Error(), "unsubscribe topic error")
	}

	delete(b.gateways, gatewayID)
	return nil
}

// PublishEvent publishes the given event.
func (b *Backend) PublishEvent(gatewayID lorawan.EUI64, event string, v proto.Message) error {
	mqttEventCounter(event).Inc()
	return b.publish(gatewayID, event, v)
}

func (b *Backend) connect() error {
	b.Lock()
	defer b.Unlock()

	if err := b.auth.Update(b.clientOpts); err != nil {
		return errors.Wrap(err, "integration/mqtt: update authentication error")
	}

	b.conn = paho.NewClient(b.clientOpts)
	if token := b.conn.Connect(); token.Wait() && token.Error() != nil {
		return token.Error()
	}

	return nil
}

// connectLoop blocks until the client is connected
func (b *Backend) connectLoop() {
	for {
		if err := b.connect(); err != nil {
			log.WithError(err).Error("integration/mqtt: connection error")
			time.Sleep(time.Second * 2)

		} else {
			break
		}
	}
}

func (b *Backend) disconnect() error {
	mqttDisconnectCounter().Inc()

	b.Lock()
	defer b.Unlock()

	b.conn.Disconnect(250)
	return nil
}

func (b *Backend) reconnectLoop() {
	if b.auth.ReconnectAfter() > 0 {
		for {
			if b.closed {
				break
			}
			time.Sleep(b.auth.ReconnectAfter())
			log.Info("mqtt: re-connect triggered")

			mqttReconnectCounter().Inc()

			b.disconnect()
			b.connectLoop()
		}
	}
}

func (b *Backend) onConnected(c paho.Client) {
	mqttConnectCounter().Inc()

	b.RLock()
	defer b.RUnlock()

	log.Info("integration/mqtt: connected to mqtt broker")

	for gatewayID := range b.gateways {
		for {
			if err := b.subscribeGateway(gatewayID); err != nil {
				log.WithError(err).WithField("gateway_id", gatewayID).Error("integration/mqtt: subscribe gateway error")
				time.Sleep(time.Second)
				continue
			}

			break
		}
	}
}

func (b *Backend) onConnectionLost(c paho.Client, err error) {
	mqttDisconnectCounter().Inc()
	log.WithError(err).Error("mqtt: connection error")
}

func (b *Backend) handleDownlinkFrame(c paho.Client, msg paho.Message) {
	log.WithFields(log.Fields{
		"topic": msg.Topic(),
	}).Info("integration/mqtt: downlink frame received")

	var downlinkFrame gw.DownlinkFrame
	if err := b.unmarshal(msg.Payload(), &downlinkFrame); err != nil {
		log.WithError(err).Error("integration/mqtt: unmarshal downlink frame error")
		return
	}

	b.downlinkFrameChan <- downlinkFrame
}

func (b *Backend) handleGatewayConfiguration(c paho.Client, msg paho.Message) {
	log.WithFields(log.Fields{
		"topic": msg.Topic(),
	}).Info("integration/mqtt: gateway configuration received")

	var gatewayConfig gw.GatewayConfiguration
	if err := b.unmarshal(msg.Payload(), &gatewayConfig); err != nil {
		log.WithError(err).Error("integration/mqtt: unmarshal gateway configuration error")
		return
	}

	b.gatewayConfigurationChan <- gatewayConfig
}

func (b *Backend) handleCommand(c paho.Client, msg paho.Message) {
	if strings.HasSuffix(msg.Topic(), "down") || strings.Contains(msg.Topic(), "command=down") {
		mqttCommandCounter("down").Inc()
		b.handleDownlinkFrame(c, msg)
	} else if strings.HasSuffix(msg.Topic(), "config") || strings.Contains(msg.Topic(), "command=config") {
		mqttCommandCounter("config").Inc()
		b.handleGatewayConfiguration(c, msg)
	} else {
		log.WithFields(log.Fields{
			"topic": msg.Topic(),
		}).Warning("integration/mqtt: unexpected command received")
	}
}

func (b *Backend) publish(gatewayID lorawan.EUI64, event string, msg proto.Message) error {
	topic := bytes.NewBuffer(nil)
	if err := b.eventTopicTemplate.Execute(topic, struct {
		GatewayID lorawan.EUI64
		EventType string
	}{gatewayID, event}); err != nil {
		return errors.Wrap(err, "execute event template error")
	}

	bytes, err := b.marshal(msg)
	if err != nil {
		return errors.Wrap(err, "marshal message error")
	}

	log.WithFields(log.Fields{
		"topic": topic.String(),
		"qos":   b.qos,
		"event": event,
	}).Info("integration/mqtt: publishing event")
	if token := b.conn.Publish(topic.String(), b.qos, false, bytes); token.Wait() && token.Error() != nil {
		return token.Error()
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/user"
	"runtime"
	"sort"
	"strings"
	"sync/atomic"
	"time"
)

const (
	helloVersion = "0.3"
)

var knownPaths []string
var boottime time.Time
var banner string
var requests int64
var usr *user.User

func inc() int64 {
	return atomic.AddInt64(&requests, 1)
}

func get() int64 {
	return atomic.LoadInt64(&requests)
}

func main() {

	boottime = time.Now()

	tls := true

	log.Printf("version=%s runtime=%s pid=%d GOMAXPROCS=%d", helloVersion, runtime.Version(), os.Getpid(), runtime.GOMAXPROCS(0))

	var errUser error
	usr, errUser = user.Current()
	if errUser != nil {
		log.Printf("current user error: %v", errUser)
	}
	if usr != nil {
		log.Printf("user: %s (uid: %s)", usr.Username, usr.Uid)
	}

	currDir, err := os.Getwd()
	if err != nil {
		log.Fatalf("Getwd: %s", err)
	}

	var addr, httpsAddr, key, cert string
	var disableKeepalive bool

	flag.StringVar(&key, "key", "key.pem", "TLS key file")
	flag.StringVar(&cert, "cert", "cert.pem", "TLS cert file")
	flag.StringVar(&addr, "addr", ":8080", "HTTP listen address")
	flag.StringVar(&httpsAddr, "httpsAddr", ":8443", "HTTPS listen address")
	flag.StringVar(&banner, "banner", "deploy #4", "banner will be displayed")
	flag.BoolVar(&disableKeepalive, "disableKeepalive", false, "disable keepalive")
	flag.Parse()

	keepalive := !disableKeepalive

	log.Print("banner: ", banner)
	log.Print("keepalive: ", keepalive)

	if !fileExists(key) {
		log.Printf("TLS key file not found: %s - disabling TLS", key)
		tls = false
	}

	if !fileExists(cert) {
		log.Printf("TLS cert file not found: %s - disabling TLS", cert)
		tls = false
	}

	// default handler
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { rootHandler(w, r, keepalive) })

	registerStatic("/www/", currDir)

	log.Printf("using TCP ports HTTP=%s HTTPS=%s TLS=%v", addr, httpsAddr, tls)

	if tls {
		serveHTTPS(addr, httpsAddr, cert, key, keepalive)
		return
	}

	log.Printf("serving HTTP on TCP %s", addr)
	if err := listenAndServe(addr, nil, keepalive); err != nil {
		log.Fatalf("listenAndServe: %s: %v", addr, err)
	}
}

func serveHTTPS(addr, httpsAddr, cert, key string, keepalive bool) {
	httpPort := "80"
	h := strings.Split(addr, ":")
	if len(h) > 1 {
		httpPort = h[1]
	}

	httpsPort := "443"
	hs := strings.Split(httpsAddr, ":")
	if len(hs) > 1 {
		httpsPort = hs[1]
	}

	if httpPort != httpsPort {
		log.Printf("installing redirect from HTTP=%s to HTTPS=%s", addr, httpsPort)

		redirectTLS := func(w http.ResponseWriter, r *http.Request) {
			host := strings.Split(r.Host, ":")[0]
			//code := http.StatusMovedPermanently // 301 permanent
			code := http.StatusFound // 302 temporary
			http.Redirect(w, r, "https://"+host+":"+httpsPort+r.RequestURI, code)
		}

		// http-to-https redirect server
		go func() {
			if err := listenAndServe(addr, http.HandlerFunc(redirectTLS), keepalive); err != nil {
				log.Fatalf("redirect: listenAndServe: %s: %v", addr, err)
			}
		}()
	}

	log.Printf("serving HTTPS on TCP %s", httpsAddr)
	if err := listenAndServeTLS(httpsAddr, cert, key, nil, keepalive); err != nil {
		log.Fatalf("listenAndServeTLS: %s: %v", httpsAddr, err)
	}
}

func listenAndServe(addr string, handler http.Handler, keepalive bool) error {
	server := &http.Server{Addr: addr, Handler: handler}
	server.SetKeepAlivesEnabled(keepalive)
	return server.ListenAndServe()
}

func listenAndServeTLS(addr, certFile, keyFile string, handler http.Handler, keepalive bool) error {
	server := &http.Server{Addr: addr, Handler: handler}
	server.SetKeepAlivesEnabled(keepalive)
	return server.ListenAndServeTLS(certFile, keyFile)
}

func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

type staticHandler struct {
	innerHandler http.Handler
}

func registerStatic(path, dir string) {
	http.Handle(path, staticHandler{http.StripPrefix(path, http.FileServer(http.Dir(dir)))})
	knownPaths = append(knownPaths, path)
	log.Printf("mapping www path %s to directory %s", path, dir)
}

func (handler staticHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	count := inc()
	log.Printf("staticHandler.ServeHTTP req=%d url=%s from=%s", count, r.URL.Path, r.RemoteAddr)
	handler.innerHandler.ServeHTTP(w, r)
}

func rootHandler(w http.ResponseWriter, r *http.Request, keepalive bool) {
	count := inc()
	log.Printf("rootHandler: req=%d from=%s", count, r.RemoteAddr)
	log.Printf("rootHandler: req=%d method=%s host=%s path=%s", count, r.Method, r.Host, r.URL.Path)
	log.Printf("rootHandler: req=%d query=%s", count, r.URL.RawQuery)

	var paths string
	for _, p := range knownPaths {
		paths += fmt.Sprintf("%s
", p, p)
	}

	var errMsg string
	if r.URL.Path != "/" {
		format := `

Path not found!

Method: %s

Host: %s

Path not found: [%s]

Query: [%s]

`
		errMsg = fmt.Sprintf(format, r.Method, r.Host, r.URL.Path, r.URL.RawQuery)
	}

	header :=
		`<!DOCTYPE html>

    <title>gowebhello root page</title>

gowebhello root page

    https://github.com/udhos/gowebhello is a simple golang replacement for 'python -m SimpleHTTPServer'.

`
	bodyTempl :=
		`
Welcome!

	gowebhello version %s runtime %s

        Keepalive: %v

	Application banner: %s

	Application arguments: %v

	Application dir: %s

	Process: %d

	User: %s (uid: %s)

	Server hostname: %s

	Your address: %s

	Request method=%s host=%s path=[%s] query=[%s]

	Current time: %s

	Uptime: %s

	Requests: %d

    %s

All known paths:

    %s
`

	footer :=
		`

`

	cwd, errCwd := os.Getwd()
	if errCwd != nil {
		cwd = cwd + " (error: " + errCwd.Error() + ")"
	}

	host, errHost := os.Hostname()
	if errHost != nil {
		host = host + " (error: " + errHost.Error() + ")"
	}

	now := time.Now()

	username := "?"
	uid := "?"

	if usr != nil {
		username = usr.Username
		uid = usr.Uid
	}

	body := fmt.Sprintf(bodyTempl, helloVersion, runtime.Version(), keepalive, banner, os.Args, cwd, os.Getpid(), username, uid, host, r.RemoteAddr, r.Method, r.Host, r.URL.Path, r.URL.RawQuery, now, time.Since(boottime), get(), errMsg, paths)

	if !keepalive {
		w.Header().Set("Connection", "close")
	}

	io.WriteString(w, header)
	io.WriteString(w, body)
	showHeaders(w, r)
	io.WriteString(w, footer)
}

func showHeaders(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "
Headers
\n")

	var headers []string
	for k, v := range r.Header {
		for _, vv := range v {
			headers = append(headers, k+": "+vv+"
\n")
		}
	}

	sort.Strings(headers)

	for _, h := range headers {
		io.WriteString(w, h)
	}
}
<commit_msg>get banner from environment<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/user"
	"runtime"
	"sort"
	"strings"
	"sync/atomic"
	"time"
)

const (
	helloVersion = "0.3"
)

var knownPaths []string
var boottime time.Time
var banner string
var requests int64
var usr *user.User
var env_banner string

func inc() int64 {
	return atomic.AddInt64(&requests, 1)
}

func get() int64 {
	return atomic.LoadInt64(&requests)
}

func main() {

	boottime = time.Now()

	tls := true

	log.Printf("version=%s runtime=%s pid=%d GOMAXPROCS=%d", helloVersion, runtime.Version(), os.Getpid(), runtime.GOMAXPROCS(0))

	var errUser error
	usr, errUser = user.Current()
	if errUser != nil {
		log.Printf("current user error: %v", errUser)
	}
	if usr != nil {
		log.Printf("user: %s (uid: %s)", usr.Username, usr.Uid)
	}

	currDir, err := os.Getwd()
	if err != nil {
		log.Fatalf("Getwd: %s", err)
	}

	var addr, httpsAddr, key, cert string
	var disableKeepalive bool

	flag.StringVar(&key, "key", "key.pem", "TLS key file")
	flag.StringVar(&cert, "cert", "cert.pem", "TLS cert file")
	flag.StringVar(&addr, "addr", ":8080", "HTTP listen address")
	flag.StringVar(&httpsAddr, "httpsAddr", ":8443", "HTTPS listen address")
	flag.StringVar(&banner, "banner", "deploy #4", "banner will be displayed")
	flag.BoolVar(&disableKeepalive, "disableKeepalive", false, "disable keepalive")
	flag.Parse()

	keepalive := !disableKeepalive

	env_banner = os.Getenv("GWH_BANNER")
        if env_banner != "" {
                banner = env_banner
        }

	log.Print("banner: ", banner)
	log.Print("keepalive: ", keepalive)

	if !fileExists(key) {
		log.Printf("TLS key file not found: %s - disabling TLS", key)
		tls = false
	}

	if !fileExists(cert) {
		log.Printf("TLS cert file not found: %s - disabling TLS", cert)
		tls = false
	}

	// default handler
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { rootHandler(w, r, keepalive) })

	registerStatic("/www/", currDir)

	log.Printf("using TCP ports HTTP=%s HTTPS=%s TLS=%v", addr, httpsAddr, tls)

	if tls {
		serveHTTPS(addr, httpsAddr, cert, key, keepalive)
		return
	}

	log.Printf("serving HTTP on TCP %s", addr)
	if err := listenAndServe(addr, nil, keepalive); err != nil {
		log.Fatalf("listenAndServe: %s: %v", addr, err)
	}
}

func serveHTTPS(addr, httpsAddr, cert, key string, keepalive bool) {
	httpPort := "80"
	h := strings.Split(addr, ":")
	if len(h) > 1 {
		httpPort = h[1]
	}

	httpsPort := "443"
	hs := strings.Split(httpsAddr, ":")
	if len(hs) > 1 {
		httpsPort = hs[1]
	}

	if httpPort != httpsPort {
		log.Printf("installing redirect from HTTP=%s to HTTPS=%s", addr, httpsPort)

		redirectTLS := func(w http.ResponseWriter, r *http.Request) {
			host := strings.Split(r.Host, ":")[0]
			//code := http.StatusMovedPermanently // 301 permanent
			code := http.StatusFound // 302 temporary
			http.Redirect(w, r, "https://"+host+":"+httpsPort+r.RequestURI, code)
		}

		// http-to-https redirect server
		go func() {
			if err := listenAndServe(addr, http.HandlerFunc(redirectTLS), keepalive); err != nil {
				log.Fatalf("redirect: listenAndServe: %s: %v", addr, err)
			}
		}()
	}

	log.Printf("serving HTTPS on TCP %s", httpsAddr)
	if err := listenAndServeTLS(httpsAddr, cert, key, nil, keepalive); err != nil {
		log.Fatalf("listenAndServeTLS: %s: %v", httpsAddr, err)
	}
}

func listenAndServe(addr string, handler http.Handler, keepalive bool) error {
	server := &http.Server{Addr: addr, Handler: handler}
	server.SetKeepAlivesEnabled(keepalive)
	return server.ListenAndServe()
}

func listenAndServeTLS(addr, certFile, keyFile string, handler http.Handler, keepalive bool) error {
	server := &http.Server{Addr: addr, Handler: handler}
	server.SetKeepAlivesEnabled(keepalive)
	return server.ListenAndServeTLS(certFile, keyFile)
}

func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

type staticHandler struct {
	innerHandler http.Handler
}

func registerStatic(path, dir string) {
	http.Handle(path, staticHandler{http.StripPrefix(path, http.FileServer(http.Dir(dir)))})
	knownPaths = append(knownPaths, path)
	log.Printf("mapping www path %s to directory %s", path, dir)
}

func (handler staticHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	count := inc()
	log.Printf("staticHandler.ServeHTTP req=%d url=%s from=%s", count, r.URL.Path, r.RemoteAddr)
	handler.innerHandler.ServeHTTP(w, r)
}

func rootHandler(w http.ResponseWriter, r *http.Request, keepalive bool) {
	count := inc()
	log.Printf("rootHandler: req=%d from=%s", count, r.RemoteAddr)
	log.Printf("rootHandler: req=%d method=%s host=%s path=%s", count, r.Method, r.Host, r.URL.Path)
	log.Printf("rootHandler: req=%d query=%s", count, r.URL.RawQuery)

	var paths string
	for _, p := range knownPaths {
		paths += fmt.Sprintf("%s
", p, p)
	}

	var errMsg string
	if r.URL.Path != "/" {
		format := `

Path not found!

Method: %s

Host: %s

Path not found: [%s]

Query: [%s]

`
		errMsg = fmt.Sprintf(format, r.Method, r.Host, r.URL.Path, r.URL.RawQuery)
	}

	header :=
		`<!DOCTYPE html>

    <title>gowebhello root page</title>

gowebhello root page

    https://github.com/udhos/gowebhello is a simple golang replacement for 'python -m SimpleHTTPServer'.

`
	bodyTempl :=
		`
Welcome!

	gowebhello version %s runtime %s

        Keepalive: %v

	Application banner: %s

	Application arguments: %v

	Application dir: %s

	Process: %d

	User: %s (uid: %s)

	Server hostname: %s

	Your address: %s

	Request method=%s host=%s path=[%s] query=[%s]

	Current time: %s

	Uptime: %s

	Requests: %d

    %s

All known paths:

    %s
`

	footer :=
		`

`

	cwd, errCwd := os.Getwd()
	if errCwd != nil {
		cwd = cwd + " (error: " + errCwd.Error() + ")"
	}

	host, errHost := os.Hostname()
	if errHost != nil {
		host = host + " (error: " + errHost.Error() + ")"
	}

	now := time.Now()

	username := "?"
	uid := "?"

	if usr != nil {
		username = usr.Username
		uid = usr.Uid
	}

	body := fmt.Sprintf(bodyTempl, helloVersion, runtime.Version(), keepalive, banner, os.Args, cwd, os.Getpid(), username, uid, host, r.RemoteAddr, r.Method, r.Host, r.URL.Path, r.URL.RawQuery, now, time.Since(boottime), get(), errMsg, paths)

	if !keepalive {
		w.Header().Set("Connection", "close")
	}

	io.WriteString(w, header)
	io.WriteString(w, body)
	showHeaders(w, r)
	io.WriteString(w, footer)
}

func showHeaders(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "
Headers
\n")

	var headers []string
	for k, v := range r.Header {
		for _, vv := range v {
			headers = append(headers, k+": "+vv+"
\n")
		}
	}

	sort.Strings(headers)

	for _, h := range headers {
		io.WriteString(w, h)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Hajime Hoshi
//
// 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 glfw

import (
	"fmt"
	"runtime"
	"unsafe"

	"golang.org/x/sys/windows"

	"github.com/hajimehoshi/ebiten/v2/internal/driver"
	"github.com/hajimehoshi/ebiten/v2/internal/glfw"
)

const (
	smCyCaption             = 4
	monitorDefaultToNearest = 2
)

type rect struct {
	left   int32
	top    int32
	right  int32
	bottom int32
}

type monitorInfo struct {
	cbSize    uint32
	rcMonitor rect
	rcWork    rect
	dwFlags   uint32
}

var (
	// user32 is defined at hideconsole_windows.go
	procGetSystemMetrics    = user32.NewProc("GetSystemMetrics")
	procGetForegroundWindow = user32.NewProc("GetForegroundWindow")
	procMonitorFromWindow   = user32.NewProc("MonitorFromWindow")
	procGetMonitorInfoW     = user32.NewProc("GetMonitorInfoW")
)

func getSystemMetrics(nIndex int) (int32, error) {
	r, _, e := procGetSystemMetrics.Call(uintptr(nIndex))
	if r == 0 {
		if e != nil && e != windows.ERROR_SUCCESS {
			return 0, fmt.Errorf("glfw: GetSystemMetrics failed: error code: %w", e)
		}
		return 0, fmt.Errorf("glfw: GetSystemMetrics returned 0")
	}
	return int32(r), nil
}

func getForegroundWindow() windows.HWND {
	r, _, _ := procGetForegroundWindow.Call()
	return windows.HWND(r)
}

func monitorFromWindow(hwnd windows.HWND, dwFlags uint32) uintptr {
	r, _, _ := procMonitorFromWindow.Call(uintptr(hwnd), uintptr(dwFlags))
	return r
}

func getMonitorInfoW(hMonitor uintptr, lpmi *monitorInfo) error {
	r, _, e := procGetMonitorInfoW.Call(hMonitor, uintptr(unsafe.Pointer(lpmi)))
	if r == 0 {
		if e != nil && e != windows.ERROR_SUCCESS {
			return fmt.Errorf("glfw: GetMonitorInfoW failed: error code: %w", e)
		}
		return fmt.Errorf("glfw: GetMonitorInfoW failed: returned 0")
	}
	return nil
}

// clearVideoModeScaleCache must be called from the main thread.
func clearVideoModeScaleCache() {}

// dipFromGLFWMonitorPixel must be called from the main thread.
func (u *UserInterface) dipFromGLFWMonitorPixel(x float64, monitor *glfw.Monitor) float64 {
	return x / u.deviceScaleFactor(monitor)
}

// dipFromGLFWPixel must be called from the main thread.
func (u *UserInterface) dipFromGLFWPixel(x float64, monitor *glfw.Monitor) float64 {
	return x / u.deviceScaleFactor(monitor)
}

// dipToGLFWPixel must be called from the main thread.
func (u *UserInterface) dipToGLFWPixel(x float64, monitor *glfw.Monitor) float64 {
	return x * u.deviceScaleFactor(monitor)
}

func (u *UserInterface) adjustWindowPosition(x, y int) (int, int) {
	mx, my := u.currentMonitor().GetPos()
	// As the video width/height might be wrong,
	// adjust x/y at least to enable to handle the window (#328)
	if x < mx {
		x = mx
	}
	t, err := getSystemMetrics(smCyCaption)
	if err != nil {
		panic(err)
	}
	if y < my+int(t) {
		y = my + int(t)
	}
	return x, y
}

func initialMonitorByOS() *glfw.Monitor {
	// Get the foreground window, that is common among multiple processes.
	w := getForegroundWindow()
	if w == 0 {
		// GetForegroundWindow can return null according to the document.
		return nil
	}
	return monitorFromWin32Window(w)
}

func currentMonitorByOS(w *glfw.Window) *glfw.Monitor {
	return monitorFromWin32Window(windows.HWND(w.GetWin32Window()))
}

func monitorFromWin32Window(w windows.HWND) *glfw.Monitor {
	// Get the current monitor by the window handle instead of the window position. It is because the window
	// position is not relaiable in some cases e.g. when the window is put across multiple monitors.

	m := monitorFromWindow(w, monitorDefaultToNearest)
	if m == 0 {
		// monitorFromWindow can return error on Wine. Ignore this.
		return nil
	}

	mi := monitorInfo{}
	mi.cbSize = uint32(unsafe.Sizeof(mi))
	if err := getMonitorInfoW(m, &mi); err != nil {
		panic(err)
	}

	x, y := int(mi.rcMonitor.left), int(mi.rcMonitor.top)
	for _, m := range ensureMonitors() {
		if m.x == x && m.y == y {
			return m.m
		}
	}
	return nil
}

func (u *UserInterface) nativeWindow() uintptr {
	return u.window.GetWin32Window()
}

func (u *UserInterface) isNativeFullscreen() bool {
	return false
}

func (u *UserInterface) setNativeCursor(shape driver.CursorShape) {
	// TODO: Use native API in the future (#1571)
	u.window.SetCursor(glfwSystemCursors[shape])
}

func (u *UserInterface) isNativeFullscreenAvailable() bool {
	return false
}

func (u *UserInterface) setNativeFullscreen(fullscreen bool) {
	panic(fmt.Sprintf("glfw: setNativeFullscreen is not implemented in this environment: %s", runtime.GOOS))
}

func (u *UserInterface) adjustViewSize() {
}

func initializeWindowAfterCreation(w *glfw.Window) {
}
<commit_msg>internal/uidriver/glfw: remove an unnecessary error handling<commit_after>// Copyright 2016 Hajime Hoshi
//
// 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 glfw

import (
	"fmt"
	"runtime"
	"unsafe"

	"golang.org/x/sys/windows"

	"github.com/hajimehoshi/ebiten/v2/internal/driver"
	"github.com/hajimehoshi/ebiten/v2/internal/glfw"
)

const (
	smCyCaption             = 4
	monitorDefaultToNearest = 2
)

type rect struct {
	left   int32
	top    int32
	right  int32
	bottom int32
}

type monitorInfo struct {
	cbSize    uint32
	rcMonitor rect
	rcWork    rect
	dwFlags   uint32
}

var (
	// user32 is defined at hideconsole_windows.go
	procGetSystemMetrics    = user32.NewProc("GetSystemMetrics")
	procGetForegroundWindow = user32.NewProc("GetForegroundWindow")
	procMonitorFromWindow   = user32.NewProc("MonitorFromWindow")
	procGetMonitorInfoW     = user32.NewProc("GetMonitorInfoW")
)

func getSystemMetrics(nIndex int) (int32, error) {
	r, _, _ := procGetSystemMetrics.Call(uintptr(nIndex))
	if r == 0 {
		// GetLastError doesn't provide an extended information.
		// See https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics
		return 0, fmt.Errorf("glfw: GetSystemMetrics returned 0")
	}
	return int32(r), nil
}

func getForegroundWindow() windows.HWND {
	r, _, _ := procGetForegroundWindow.Call()
	return windows.HWND(r)
}

func monitorFromWindow(hwnd windows.HWND, dwFlags uint32) uintptr {
	r, _, _ := procMonitorFromWindow.Call(uintptr(hwnd), uintptr(dwFlags))
	return r
}

func getMonitorInfoW(hMonitor uintptr, lpmi *monitorInfo) error {
	r, _, e := procGetMonitorInfoW.Call(hMonitor, uintptr(unsafe.Pointer(lpmi)))
	if r == 0 {
		if e != nil && e != windows.ERROR_SUCCESS {
			return fmt.Errorf("glfw: GetMonitorInfoW failed: error code: %w", e)
		}
		return fmt.Errorf("glfw: GetMonitorInfoW failed: returned 0")
	}
	return nil
}

// clearVideoModeScaleCache must be called from the main thread.
func clearVideoModeScaleCache() {}

// dipFromGLFWMonitorPixel must be called from the main thread.
func (u *UserInterface) dipFromGLFWMonitorPixel(x float64, monitor *glfw.Monitor) float64 {
	return x / u.deviceScaleFactor(monitor)
}

// dipFromGLFWPixel must be called from the main thread.
func (u *UserInterface) dipFromGLFWPixel(x float64, monitor *glfw.Monitor) float64 {
	return x / u.deviceScaleFactor(monitor)
}

// dipToGLFWPixel must be called from the main thread.
func (u *UserInterface) dipToGLFWPixel(x float64, monitor *glfw.Monitor) float64 {
	return x * u.deviceScaleFactor(monitor)
}

func (u *UserInterface) adjustWindowPosition(x, y int) (int, int) {
	mx, my := u.currentMonitor().GetPos()
	// As the video width/height might be wrong,
	// adjust x/y at least to enable to handle the window (#328)
	if x < mx {
		x = mx
	}
	t, err := getSystemMetrics(smCyCaption)
	if err != nil {
		panic(err)
	}
	if y < my+int(t) {
		y = my + int(t)
	}
	return x, y
}

func initialMonitorByOS() *glfw.Monitor {
	// Get the foreground window, that is common among multiple processes.
	w := getForegroundWindow()
	if w == 0 {
		// GetForegroundWindow can return null according to the document.
		return nil
	}
	return monitorFromWin32Window(w)
}

func currentMonitorByOS(w *glfw.Window) *glfw.Monitor {
	return monitorFromWin32Window(windows.HWND(w.GetWin32Window()))
}

func monitorFromWin32Window(w windows.HWND) *glfw.Monitor {
	// Get the current monitor by the window handle instead of the window position. It is because the window
	// position is not relaiable in some cases e.g. when the window is put across multiple monitors.

	m := monitorFromWindow(w, monitorDefaultToNearest)
	if m == 0 {
		// monitorFromWindow can return error on Wine. Ignore this.
		return nil
	}

	mi := monitorInfo{}
	mi.cbSize = uint32(unsafe.Sizeof(mi))
	if err := getMonitorInfoW(m, &mi); err != nil {
		panic(err)
	}

	x, y := int(mi.rcMonitor.left), int(mi.rcMonitor.top)
	for _, m := range ensureMonitors() {
		if m.x == x && m.y == y {
			return m.m
		}
	}
	return nil
}

func (u *UserInterface) nativeWindow() uintptr {
	return u.window.GetWin32Window()
}

func (u *UserInterface) isNativeFullscreen() bool {
	return false
}

func (u *UserInterface) setNativeCursor(shape driver.CursorShape) {
	// TODO: Use native API in the future (#1571)
	u.window.SetCursor(glfwSystemCursors[shape])
}

func (u *UserInterface) isNativeFullscreenAvailable() bool {
	return false
}

func (u *UserInterface) setNativeFullscreen(fullscreen bool) {
	panic(fmt.Sprintf("glfw: setNativeFullscreen is not implemented in this environment: %s", runtime.GOOS))
}

func (u *UserInterface) adjustViewSize() {
}

func initializeWindowAfterCreation(w *glfw.Window) {
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"sync"
	"sync/atomic"
	"time"
)

var ErrNoActiveInstances = errors.New("No active instances")

type App struct {
	config *AppConfig

	instances          []*Instance
	activeInstance     *Instance
	activeInstanceLock sync.Mutex

	rp       *httputil.ReverseProxy
	portPool *PortPool

	externalHostPort string

	instanceId uint32
}

func NewApp(config *AppConfig, portPool *PortPool) *App {
	app := &App{
		config:           config,
		instances:        make([]*Instance, 0, 3),
		portPool:         portPool,
		externalHostPort: fmt.Sprintf("%s:%d", config.ExternalHost, config.ExternalPort),
	}

	app.rp = &httputil.ReverseProxy{Director: func(req *http.Request) {}}

	app.startInstanceUpdater()

	return app
}

func (a *App) startInstanceUpdater() {
	ticker := time.NewTicker(time.Second)

	go func() {
		for {
			starting := false
			for _, instance := range a.instances {
				status := instance.UpdateStatus()
				if status == InstanceStatusServing && instance != a.activeInstance {
					a.activeInstanceLock.Lock()
					currentActive := a.activeInstance
					a.activeInstance = instance
					a.activeInstanceLock.Unlock()

					if currentActive != nil {
						currentActive.Stop()
					}
				} else if status == InstanceStatusExited && instance == a.activeInstance {
					a.activeInstance = nil
				} else if status == InstanceStatusStarting {
					starting = true
				}
			}

			if a.activeInstance == nil && !starting {
				// TODO retry count
				err := a.StartNewInstance()
				if err != nil {
					log.Print(err)
				}
			}

			a.Report()
			<-ticker.C
		}
	}()
}

func (a *App) reserveInstance() (*Instance, error) {
	a.activeInstanceLock.Lock()

	instance := a.activeInstance
	if instance == nil {
		return nil, ErrNoActiveInstances
	}
	instance.Serve()

	a.activeInstanceLock.Unlock()

	return instance, nil
}

func (a *App) StartNewInstance() error {
	newInstance, err := NewInstance(a, atomic.AddUint32(&a.instanceId, 1))
	if err != nil {
		return err
	}

	a.instances = append(a.instances, newInstance)
	return nil
}

func (a *App) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	instance, err := a.reserveInstance()

	defer func() {
		if err := recover(); err != nil {
			if err == ErrNoActiveInstances {
				log.Print(err)
				rw.WriteHeader(503)
				req.Body.Close()
			} else {
				log.Print(err)
			}
		}

		if instance != nil {
			instance.Done()
		}
	}()

	if err != nil {
		panic(err)
	}

	req.URL.Scheme = "http"
	req.URL.Host = instance.internalHostPort

	host, _, _ := net.SplitHostPort(req.RemoteAddr) //TODO parse real real ip, add fwd for
	req.Header.Add("X-Real-IP", host)

	a.rp.ServeHTTP(rw, req)
}

func (a *App) ListenAndServe() {
	http.ListenAndServe(a.externalHostPort, a)
}

func (a *App) Report() {
	displayN := 3

	l := len(a.instances)
	from := 0
	if l > displayN {
		from = l - displayN
	}

	fmt.Printf("[%s/%s]\n", a.config.Name, a.externalHostPort)
	for _, instance := range a.instances[from:l] {
		if instance == a.activeInstance {
			fmt.Print(" * ")
		} else {
			fmt.Print("   ")
		}
		fmt.Printf("%d/%s ", instance.id, instance.internalHostPort)
		switch instance.status {
		case InstanceStatusServing:
			fmt.Print("serving ")
		case InstanceStatusStarting:
			fmt.Print("starting")
		case InstanceStatusStopping:
			fmt.Print("stopping")
		case InstanceStatusStopped:
			fmt.Print("stopped ")
		case InstanceStatusFailed:
			fmt.Print("failed  ")
		case InstanceStatusExited:
			fmt.Print("exited  ")
		}
		fmt.Printf(" %s", time.Since(instance.lastChange)/time.Second*time.Second)
		fmt.Println()
	}
}
<commit_msg>Report instance process error<commit_after>package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"sync"
	"sync/atomic"
	"time"
)

var ErrNoActiveInstances = errors.New("No active instances")

type App struct {
	config *AppConfig

	instances          []*Instance
	activeInstance     *Instance
	activeInstanceLock sync.Mutex

	rp       *httputil.ReverseProxy
	portPool *PortPool

	externalHostPort string

	instanceId uint32
}

func NewApp(config *AppConfig, portPool *PortPool) *App {
	app := &App{
		config:           config,
		instances:        make([]*Instance, 0, 3),
		portPool:         portPool,
		externalHostPort: fmt.Sprintf("%s:%d", config.ExternalHost, config.ExternalPort),
	}

	app.rp = &httputil.ReverseProxy{Director: func(req *http.Request) {}}

	app.startInstanceUpdater()

	return app
}

func (a *App) startInstanceUpdater() {
	ticker := time.NewTicker(time.Second)

	go func() {
		for {
			starting := false
			for _, instance := range a.instances {
				status := instance.UpdateStatus()
				if status == InstanceStatusServing && instance != a.activeInstance {
					a.activeInstanceLock.Lock()
					currentActive := a.activeInstance
					a.activeInstance = instance
					a.activeInstanceLock.Unlock()

					if currentActive != nil {
						currentActive.Stop()
					}
				} else if status == InstanceStatusExited && instance == a.activeInstance {
					a.activeInstance = nil
				} else if status == InstanceStatusStarting {
					starting = true
				}
			}

			if a.activeInstance == nil && !starting {
				// TODO retry count
				err := a.StartNewInstance()
				if err != nil {
					log.Print(err)
				}
			}

			a.Report()
			<-ticker.C
		}
	}()
}

func (a *App) reserveInstance() (*Instance, error) {
	a.activeInstanceLock.Lock()

	instance := a.activeInstance
	if instance == nil {
		return nil, ErrNoActiveInstances
	}
	instance.Serve()

	a.activeInstanceLock.Unlock()

	return instance, nil
}

func (a *App) StartNewInstance() error {
	newInstance, err := NewInstance(a, atomic.AddUint32(&a.instanceId, 1))
	if err != nil {
		return err
	}

	a.instances = append(a.instances, newInstance)
	return nil
}

func (a *App) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	instance, err := a.reserveInstance()

	defer func() {
		if err := recover(); err != nil {
			if err == ErrNoActiveInstances {
				log.Print(err)
				rw.WriteHeader(503)
				req.Body.Close()
			} else {
				log.Print(err)
			}
		}

		if instance != nil {
			instance.Done()
		}
	}()

	if err != nil {
		panic(err)
	}

	req.URL.Scheme = "http"
	req.URL.Host = instance.internalHostPort

	host, _, _ := net.SplitHostPort(req.RemoteAddr) //TODO parse real real ip, add fwd for
	req.Header.Add("X-Real-IP", host)

	a.rp.ServeHTTP(rw, req)
}

func (a *App) ListenAndServe() {
	http.ListenAndServe(a.externalHostPort, a)
}

func (a *App) Report() {
	displayN := 3

	l := len(a.instances)
	from := 0
	if l > displayN {
		from = l - displayN
	}

	fmt.Printf("[%s/%s]\n", a.config.Name, a.externalHostPort)
	for _, instance := range a.instances[from:l] {
		if instance == a.activeInstance {
			fmt.Print(" * ")
		} else {
			fmt.Print("   ")
		}
		fmt.Printf("%d/%s ", instance.id, instance.internalHostPort)
		switch instance.status {
		case InstanceStatusServing:
			fmt.Print("serving ")
		case InstanceStatusStarting:
			fmt.Print("starting")
		case InstanceStatusStopping:
			fmt.Print("stopping")
		case InstanceStatusStopped:
			fmt.Print("stopped ")
		case InstanceStatusFailed:
			fmt.Print("failed  ")
		case InstanceStatusExited:
			fmt.Print("exited  ")
		}
		fmt.Printf(" %s", time.Since(instance.lastChange)/time.Second*time.Second)
		if instance.processErr != nil {
			fmt.Printf(" %q", instance.processErr)
		}
		fmt.Println()
	}
}
<|endoftext|>


<commit_before>package functional_test

import (
  "fmt"
  "github.com/keep94/gofunctional3/functional"
  "time"
)

// DateCount represents a count of some occurrence by date
type DateCount struct {
  Date time.Time
  Count int64
}

// YearCount represents a count of some occurrence by year
type YearCount struct {
  Year int
  Count int64
}

func emitByYear(s functional.Stream, e functional.Emitter) {
  var ptr interface{}
  var opened bool
  var incoming DateCount

  // As soon as caller calls Close() we quit without pulling unnecessary
  // values from underlying stream.
  if ptr, opened = e.EmitPtr(); !opened {
    return
  }
  var err error

  // We get the first date while propagating any errors to the caller.
  // Note that we stay in this loop until either we get a first date or
  // caller calls Close()
  for err = s.Next(&incoming); err != nil; err = s.Next(&incoming) {
    // Propagate error and yield execution to caller.
    e.Return(err)

    // After each call to Return, we must get the pointer caller supplied to
    // Next.
    if ptr, opened = e.EmitPtr(); !opened {
      return
    }
  }
  currentYear := incoming.Date.Year()

  // Running total for current year
  sum := incoming.Count

  // When Done marker is reached, we have to emit the count of the final year.
  for err = s.Next(&incoming); err != functional.Done; err = s.Next(&incoming) {

    // Propagate any errors to caller.
    if err != nil {
      e.Return(err)
      if ptr, opened = e.EmitPtr(); !opened {
        return
      }
      continue
    }
    year := incoming.Date.Year()

    // If year changed, emit the count for the current year.
    // Then change currentYear and and make sum be the running total for
    // that year.
    if year != currentYear {
      *ptr.(*YearCount) = YearCount{Year: currentYear, Count: sum}
      e.Return(nil)
      if ptr, opened = e.EmitPtr(); !opened {
        return
      }
      sum = incoming.Count
      currentYear = year
    } else {
      sum += incoming.Count
    }
  }
  // Emit the final year.
  *ptr.(*YearCount) = YearCount{Year: currentYear, Count: sum}

  // Note that we return nil, not functional.Done, since we are emitting the
  // count for the final year. The call to Finalize() in ByYear() takes care
  // of returning functional.Done to the caller.
  e.Return(nil)
}

// ByYear takes a Stream of DateCount instances and returns a Stream of
// YearCount instances by totaling the counts in the DateCount instances
// by year. The DateCount instances must be ordered by Date. Caller must Close
// the returned Stream.
func ByYear(s functional.Stream) functional.Stream {
  return functional.NewGenerator(func(e functional.Emitter) error {
    // Emit counts by year
    emitByYear(s, e)

    // Wait until caller calls Close() while returning functional.Done each time
    // caller calls Next().
    e.Finalize()

    // Do clean up that is visible to caller
    return s.Close()
  })
}

func YMD(year, month, day int) time.Time {
  return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
}

func ExampleNewGenerator() {
   s := functional.NewStreamFromPtrs(
      []*DateCount{
          {YMD(2013, 5, 24), 13},
          {YMD(2013, 4, 1), 5},
          {YMD(2013, 1, 1), 8},
          {YMD(2012, 12, 31), 24},
          {YMD(2012, 5, 26), 10}},
      nil)
  s = ByYear(s)
  defer s.Close()
  var yc YearCount
  for err := s.Next(&yc); err == nil; err = s.Next(&yc) {
    fmt.Printf("%d: %d\n", yc.Year, yc.Count)
  }
  // Output:
  // 2013: 26
  // 2012: 34
}
<commit_msg>Add License clause to example_newgenerator_test.go<commit_after>// Copyright 2013 Travis Keep. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or
// at http://opensource.org/licenses/BSD-3-Clause.

package functional_test

import (
  "fmt"
  "github.com/keep94/gofunctional3/functional"
  "time"
)

// DateCount represents a count of some occurrence by date
type DateCount struct {
  Date time.Time
  Count int64
}

// YearCount represents a count of some occurrence by year
type YearCount struct {
  Year int
  Count int64
}

func emitByYear(s functional.Stream, e functional.Emitter) {
  var ptr interface{}
  var opened bool
  var incoming DateCount

  // As soon as caller calls Close() we quit without pulling unnecessary
  // values from underlying stream.
  if ptr, opened = e.EmitPtr(); !opened {
    return
  }
  var err error

  // We get the first date while propagating any errors to the caller.
  // Note that we stay in this loop until either we get a first date or
  // caller calls Close()
  for err = s.Next(&incoming); err != nil; err = s.Next(&incoming) {
    // Propagate error and yield execution to caller.
    e.Return(err)

    // After each call to Return, we must get the pointer caller supplied to
    // Next.
    if ptr, opened = e.EmitPtr(); !opened {
      return
    }
  }
  currentYear := incoming.Date.Year()

  // Running total for current year
  sum := incoming.Count

  // When Done marker is reached, we have to emit the count of the final year.
  for err = s.Next(&incoming); err != functional.Done; err = s.Next(&incoming) {

    // Propagate any errors to caller.
    if err != nil {
      e.Return(err)
      if ptr, opened = e.EmitPtr(); !opened {
        return
      }
      continue
    }
    year := incoming.Date.Year()

    // If year changed, emit the count for the current year.
    // Then change currentYear and and make sum be the running total for
    // that year.
    if year != currentYear {
      *ptr.(*YearCount) = YearCount{Year: currentYear, Count: sum}
      e.Return(nil)
      if ptr, opened = e.EmitPtr(); !opened {
        return
      }
      sum = incoming.Count
      currentYear = year
    } else {
      sum += incoming.Count
    }
  }
  // Emit the final year.
  *ptr.(*YearCount) = YearCount{Year: currentYear, Count: sum}

  // Note that we return nil, not functional.Done, since we are emitting the
  // count for the final year. The call to Finalize() in ByYear() takes care
  // of returning functional.Done to the caller.
  e.Return(nil)
}

// ByYear takes a Stream of DateCount instances and returns a Stream of
// YearCount instances by totaling the counts in the DateCount instances
// by year. The DateCount instances must be ordered by Date. Caller must Close
// the returned Stream.
func ByYear(s functional.Stream) functional.Stream {
  return functional.NewGenerator(func(e functional.Emitter) error {
    // Emit counts by year
    emitByYear(s, e)

    // Wait until caller calls Close() while returning functional.Done each time
    // caller calls Next().
    e.Finalize()

    // Do clean up that is visible to caller
    return s.Close()
  })
}

func YMD(year, month, day int) time.Time {
  return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
}

func ExampleNewGenerator() {
   s := functional.NewStreamFromPtrs(
      []*DateCount{
          {YMD(2013, 5, 24), 13},
          {YMD(2013, 4, 1), 5},
          {YMD(2013, 1, 1), 8},
          {YMD(2012, 12, 31), 24},
          {YMD(2012, 5, 26), 10}},
      nil)
  s = ByYear(s)
  defer s.Close()
  var yc YearCount
  for err := s.Next(&yc); err == nil; err = s.Next(&yc) {
    fmt.Printf("%d: %d\n", yc.Year, yc.Count)
  }
  // Output:
  // 2013: 26
  // 2012: 34
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/exec"
	"bytes"
	"strings"
	"time"
	"io/ioutil"
	"regexp"
	"log"
	"sync"
)

var (
	photoRe = regexp.MustCompile(`(?i)^[^\.].*\.(dng|cr2|jpg|jpeg|arw|orf)$`)
	videoRe = regexp.MustCompile(`(?i)^[^\.].*\.(mov|mp4|wmv)$`)
)
func IsDirectory(name string) (isDir bool, err error) {
	info, err := os.Stat(name)
	if err != nil {
		return false, err
	}
	return info.IsDir(), nil
}

func GetExifData(file string) (map[string]string, error) {
	cmd := exec.Command("exiftool", file)

	var out bytes.Buffer
	cmd.Stdout = &out

	if err := cmd.Run(); err != nil {
		return nil, err
	}

	tags := make(map[string]string)

	data := strings.Trim(out.String(), " \r\n")
	lines := strings.Split(data, "\n")

	for _, line := range lines {
		k, v := strings.Replace(strings.TrimSpace(line[0:32]), " ", "", -1), strings.TrimSpace(line[33:])
		tags[k] = v
	}

	return tags, nil
}

func GetDateDirPath(exif map[string]string) (string, error) {
	t, err := time.Parse("2006:01:02 15:04:05", exif["Date/TimeOriginal"])
	if err == nil {
		return t.Format("2006/01/02"), nil
	}

	t, err = time.Parse("2006:01:02 15:04:05", exif["CreateDate"])
	if err == nil {
		return t.Format("2006/01/02"), nil
	}

	return "", err
}

func MoveFile(src, dst string) (error) {
	cmd := exec.Command("mv", src, dst)

	var out bytes.Buffer
	cmd.Stdout = &out

	if err := cmd.Run(); err != nil {
		return err
	}

	return nil
	//return os.Rename(src, dst)
}

func IsIgnoreFile(name string, option *Option) (bool) {
	return name == "." || name == ".." || name == "lightroom"
}

func GetFileNum(from string, option *Option) (int, error) {
	fileInfos, readErr := ioutil.ReadDir(from + "/")
	if readErr != nil {
		return 0, readErr
	}

	num := 0
	for _, fileInfo := range fileInfos {
		name := (fileInfo).Name()
		if IsIgnoreFile(name, option) {
			continue
		}

		filePath := from + "/" + name
		isDir, err := IsDirectory(filePath)
		if err != nil {
			return 0, err
		}

		if isDir {
			if option.Recursive {
				subNum, subErr := GetFileNum(from + "/" + name, option)
				if subErr != nil {
					return 0, subErr
				}
				num += subNum
			}
		} else {
			if photoRe.MatchString(name) || videoRe.MatchString(name) {
				num += 1
			}
		}
	}

	return num, nil
}

func TransferFile(name, filePath, dir string, option *Option) {
	exif, _ := GetExifData(filePath)
	if option.Verbose {
		log.Println(exif)
	}
	dateDirPath, dateDirPathErr := GetDateDirPath(exif)
	if dateDirPathErr != nil {
		log.Fatal(dateDirPathErr)
	}

	dstDir := option.To + "/" + dir + "/" + dateDirPath + "/"
	if option.DryRun == false {
		mkdirErr := os.MkdirAll(dstDir, 0755)
		if mkdirErr != nil {
			log.Fatal(mkdirErr)
		}
	}

	dstPath := dstDir + name
	log.Printf("%s -> %s", filePath, dstPath)

	if option.DryRun == false {
		moveErr := MoveFile(filePath, dstPath)
		if moveErr != nil {
			log.Fatal(moveErr)
		}
	}
}

func Transfer(wg *sync.WaitGroup, ch chan int, from string, option *Option) {
	fileInfos, readErr := ioutil.ReadDir(from + "/")
	if readErr != nil {
		log.Fatal(readErr)
	}

	for _, fileInfo := range fileInfos {
		wg.Add(1)
		go func(fileInfo os.FileInfo) {
			defer wg.Done()
			ch <- 1

			name := (fileInfo).Name()
			if IsIgnoreFile(name, option) {
				<-ch
				return
			}

			filePath := from + "/" + name
			isDir, err := IsDirectory(filePath)
			if err != nil {
				log.Fatal(err)
			}

			if isDir {
				if option.Recursive {
					Transfer(wg, ch, filePath, option)
				}
			} else {
				if photoRe.MatchString(name) {
					TransferFile(name, filePath, option.PhotoDir, option)
				} else if videoRe.MatchString(name) {
					TransferFile(name, filePath, option.VideoDir, option)
				}
			}

			<-ch
		}(fileInfo)
	}
}
<commit_msg>support exclude<commit_after>package main

import (
	"os"
	"os/exec"
	"bytes"
	"strings"
	"time"
	"io/ioutil"
	"regexp"
	"log"
	"sync"
)

var (
	photoRe = regexp.MustCompile(`(?i)^[^\.].*\.(dng|cr2|jpg|jpeg|arw|orf)$`)
	videoRe = regexp.MustCompile(`(?i)^[^\.].*\.(mov|mp4|wmv)$`)
)
func IsDirectory(name string) (isDir bool, err error) {
	info, err := os.Stat(name)
	if err != nil {
		return false, err
	}
	return info.IsDir(), nil
}

func GetExifData(file string) (map[string]string, error) {
	cmd := exec.Command("exiftool", file)

	var out bytes.Buffer
	cmd.Stdout = &out

	if err := cmd.Run(); err != nil {
		return nil, err
	}

	tags := make(map[string]string)

	data := strings.Trim(out.String(), " \r\n")
	lines := strings.Split(data, "\n")

	for _, line := range lines {
		k, v := strings.Replace(strings.TrimSpace(line[0:32]), " ", "", -1), strings.TrimSpace(line[33:])
		tags[k] = v
	}

	return tags, nil
}

func GetDateDirPath(exif map[string]string) (string, error) {
	t, err := time.Parse("2006:01:02 15:04:05", exif["Date/TimeOriginal"])
	if err == nil {
		return t.Format("2006/01/02"), nil
	}

	t, err = time.Parse("2006:01:02 15:04:05", exif["CreateDate"])
	if err == nil {
		return t.Format("2006/01/02"), nil
	}

	return "", err
}

func MoveFile(src, dst string) (error) {
	cmd := exec.Command("mv", src, dst)

	var out bytes.Buffer
	cmd.Stdout = &out

	if err := cmd.Run(); err != nil {
		return err
	}

	return nil
}

func IsIgnoreFile(name string, option *Option) (bool) {
	if name == "." || name == ".." {
		return true
	}

	for _, v := range option.Excludes {
		if name == v {
			return true
		}
	}

	return false
}

func GetFileNum(from string, option *Option) (int, error) {
	fileInfos, readErr := ioutil.ReadDir(from + "/")
	if readErr != nil {
		return 0, readErr
	}

	num := 0
	for _, fileInfo := range fileInfos {
		name := (fileInfo).Name()
		if IsIgnoreFile(name, option) {
			continue
		}

		filePath := from + "/" + name
		isDir, err := IsDirectory(filePath)
		if err != nil {
			return 0, err
		}

		if isDir {
			if option.Recursive {
				subNum, subErr := GetFileNum(from + "/" + name, option)
				if subErr != nil {
					return 0, subErr
				}
				num += subNum
			}
		} else {
			if photoRe.MatchString(name) || videoRe.MatchString(name) {
				num += 1
			}
		}
	}

	return num, nil
}

func TransferFile(name, filePath, dir string, option *Option) {
	exif, _ := GetExifData(filePath)
	if option.Verbose {
		log.Println(exif)
	}
	dateDirPath, dateDirPathErr := GetDateDirPath(exif)
	if dateDirPathErr != nil {
		log.Fatal(dateDirPathErr)
	}

	dstDir := option.To + "/" + dir + "/" + dateDirPath + "/"
	if option.DryRun == false {
		mkdirErr := os.MkdirAll(dstDir, 0755)
		if mkdirErr != nil {
			log.Fatal(mkdirErr)
		}
	}

	dstPath := dstDir + name
	log.Printf("%s -> %s", filePath, dstPath)

	if option.DryRun == false {
		moveErr := MoveFile(filePath, dstPath)
		if moveErr != nil {
			log.Fatal(moveErr)
		}
	}
}

func Transfer(wg *sync.WaitGroup, ch chan int, from string, option *Option) {
	fileInfos, readErr := ioutil.ReadDir(from + "/")
	if readErr != nil {
		log.Fatal(readErr)
	}

	for _, fileInfo := range fileInfos {
		wg.Add(1)
		go func(fileInfo os.FileInfo) {
			defer wg.Done()
			ch <- 1

			name := (fileInfo).Name()
			if IsIgnoreFile(name, option) {
				<-ch
				return
			}

			filePath := from + "/" + name
			isDir, err := IsDirectory(filePath)
			if err != nil {
				log.Fatal(err)
			}

			if isDir {
				if option.Recursive {
					Transfer(wg, ch, filePath, option)
				}
			} else {
				if photoRe.MatchString(name) {
					TransferFile(name, filePath, option.PhotoDir, option)
				} else if videoRe.MatchString(name) {
					TransferFile(name, filePath, option.VideoDir, option)
				}
			}

			<-ch
		}(fileInfo)
	}
}
<|endoftext|>


<commit_before>package web

import (
	"encoding/json"
	"errors"
	"io"
	"mime"
	"reflect"
	"strconv"
	"strings"
)

func contentType(val string) string {
	var ctype string

	if strings.ContainsRune(val, '/') {
		ctype = val
	} else {
		if !strings.HasPrefix(val, ".") {
			val = "." + val
		}
		ctype = mime.TypeByExtension(val)
	}

	return ctype
}

// TryParse try parse val to v
func TryParse(val string, v interface{}) error {
	if v == nil {
		return errors.New("TryParse(nil)")
	}

	rv := reflect.ValueOf(v)

	if rv.Kind() != reflect.Ptr {
		return errors.New("TryParse(non-pointer " + reflect.TypeOf(v).String() + ")")
	}

	if rv.IsNil() {
		return errors.New("TryParse(nil)")
	}

	for rv.Kind() == reflect.Ptr && !rv.IsNil() {
		rv = rv.Elem()
	}

	if !rv.CanSet() {
		return errors.New("TryParse(can not set value to v)")
	}

	switch rv.Interface().(type) {
	case string:
		rv.SetString(val)
		return nil
	case int, int8, int16, int32, int64:
		n, err := strconv.ParseInt(val, 10, 64)
		if err != nil {
			return err
		}
		if rv.OverflowInt(n) {
			return errors.New("TryParse(reflect.Value.OverflowInt)")
		}
		rv.SetInt(n)
		return nil
	case uint, uint8, uint16, uint32, uint64, uintptr:
		n, err := strconv.ParseUint(val, 10, 64)
		if err != nil {
			return err
		}
		if rv.OverflowUint(n) {
			return errors.New("TryParse(reflect.Value.OverflowUint)")
		}
		rv.SetUint(n)
		return nil
	case float32, float64:
		n, err := strconv.ParseFloat(val, rv.Type().Bits())
		if err != nil {
			return err
		}
		if rv.OverflowFloat(n) {
			return errors.New("TryParse(reflect.Value.OverflowFloat)")
		}
		rv.SetFloat(n)
		return nil
	case bool:
		n, err := strconv.ParseBool(val)
		if err != nil {
			return err
		}
		rv.SetBool(n)
		return nil
	default:
		return json.Unmarshal([]byte(val), v)
	}
}

// replace replace old to new and clean space ant \t
func replace(val string, old byte, new byte) string {
	l := len(val)

	prev := 0

	var str strings.Builder
	str.Grow(l)

	for pos := 0; pos < l; pos++ {
		r := val[pos]

		switch r {
		case '/':
			if pos > prev {
				str.WriteString(val[prev:pos])
			}
			prev = pos + 1
			str.WriteByte('_')
		case ' ', '\t':
			if pos > prev {
				str.WriteString(val[prev:pos])
			}
			prev = pos + 1
		}
	}

	if prev < l {
		str.WriteString(val[prev:])
	}

	return str.String()
}

// binaryRead decode data from binary
func binaryRead(r io.Reader, data interface{}) error {
	return errors.New("binaryRead not implemented")
}

// binaryWrite encode data to binary
func binaryWrite(w io.Writer, data interface{}) error {
	return errors.New("binaryWrite not implemented")
}
<commit_msg>clean<commit_after>package web

import (
	"encoding/json"
	"errors"
	"io"
	"mime"
	"reflect"
	"strconv"
	"strings"
)

func contentType(val string) string {
	var ctype string

	if strings.ContainsRune(val, '/') {
		ctype = val
	} else {
		if !strings.HasPrefix(val, ".") {
			val = "." + val
		}
		ctype = mime.TypeByExtension(val)
	}

	return ctype
}

// TryParse try parse val to v
func TryParse(val string, v interface{}) error {
	if v == nil {
		return errors.New("TryParse(nil)")
	}

	rv := reflect.ValueOf(v)

	if rv.Kind() != reflect.Ptr {
		return errors.New("TryParse(non-pointer " + reflect.TypeOf(v).String() + ")")
	}

	if rv.IsNil() {
		return errors.New("TryParse(nil)")
	}

	for rv.Kind() == reflect.Ptr && !rv.IsNil() {
		rv = rv.Elem()
	}

	if !rv.CanSet() {
		return errors.New("TryParse(can not set value to v)")
	}

	switch rv.Interface().(type) {
	case string:
		rv.SetString(val)
		return nil
	case int, int8, int16, int32, int64:
		n, err := strconv.ParseInt(val, 10, 64)
		if err != nil {
			return err
		}
		if rv.OverflowInt(n) {
			return errors.New("TryParse(reflect.Value.OverflowInt)")
		}
		rv.SetInt(n)
		return nil
	case uint, uint8, uint16, uint32, uint64, uintptr:
		n, err := strconv.ParseUint(val, 10, 64)
		if err != nil {
			return err
		}
		if rv.OverflowUint(n) {
			return errors.New("TryParse(reflect.Value.OverflowUint)")
		}
		rv.SetUint(n)
		return nil
	case float32, float64:
		n, err := strconv.ParseFloat(val, rv.Type().Bits())
		if err != nil {
			return err
		}
		if rv.OverflowFloat(n) {
			return errors.New("TryParse(reflect.Value.OverflowFloat)")
		}
		rv.SetFloat(n)
		return nil
	case bool:
		n, err := strconv.ParseBool(val)
		if err != nil {
			return err
		}
		rv.SetBool(n)
		return nil
	default:
		return json.Unmarshal([]byte(val), v)
	}
}

// replace replace old to new and clean space ant \t
func replace(val string, old byte, new byte) string {
	l := len(val)

	prev := 0

	var str strings.Builder
	str.Grow(l)

	for pos := 0; pos < l; pos++ {
		r := val[pos]

		switch r {
		case '/':
			if pos > prev {
				str.WriteString(val[prev:pos])
			}
			prev = pos + 1

			if pos > 0 && prev < l {
				str.WriteByte('_')
			}
		case ' ', '\t':
			if pos > prev {
				str.WriteString(val[prev:pos])
			}
			prev = pos + 1
		}
	}

	if prev < l {
		str.WriteString(val[prev:])
	}

	return str.String()
}

// binaryRead decode data from binary
func binaryRead(r io.Reader, data interface{}) error {
	return errors.New("binaryRead not implemented")
}

// binaryWrite encode data to binary
func binaryWrite(w io.Writer, data interface{}) error {
	return errors.New("binaryWrite not implemented")
}
<|endoftext|>


<commit_before>package chi

import (
	"fmt"
	"net/http"

	"golang.org/x/net/context"
)

// Build a chained chi.Handler from a list of middlewares
func chain(middlewares []interface{}, handlers ...interface{}) Handler {
	// join a middleware stack with inline middlewares
	mws := append(middlewares, handlers[:len(handlers)-1]...)

	// request handler
	handler := handlers[len(handlers)-1]

	// Assert the types in the middleware chain
	for _, mw := range mws {
		assertMiddleware(mw)
	}

	// Set the request handler to a context handler type
	var cxh Handler
	switch t := handler.(type) {
	default:
		panic(fmt.Sprintf("chi: unsupported handler signature: %T", t))
	case Handler:
		cxh = t
	case func(context.Context, http.ResponseWriter, *http.Request):
		cxh = HandlerFunc(t)
	case http.Handler:
		cxh = HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			t.ServeHTTP(w, r)
		})
	case func(http.ResponseWriter, *http.Request):
		cxh = HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			t(w, r)
		})
	}

	// Return ahead of time if there aren't any middlewares for the chain
	if len(mws) == 0 {
		return cxh
	}

	// Wrap the end handler with the middleware chain
	h := mwrap(mws[len(mws)-1])(cxh)
	for i := len(mws) - 2; i >= 0; i-- {
		f := mwrap(mws[i])
		h = f(h)
	}

	return h
}

// Wrap http.Handler middleware to chi.Handler middlewares
func mwrap(middleware interface{}) func(Handler) Handler {
	switch mw := middleware.(type) {
	default:
		panic(fmt.Sprintf("chi: unsupported handler signature: %T", mw))

	case func(Handler) Handler:
		return mw

	case func(http.Handler) http.Handler:
		return func(next Handler) Handler {
			var ww http.ResponseWriter
			var rr *http.Request

			hfn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				ww, rr = w, r
			})
			wfn := mw(hfn).ServeHTTP

			return HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
				wfn(w, r)
				next.ServeHTTPC(ctx, ww, rr)
			})
		}
	}
}

// Runtime type checking of the middleware signature
func assertMiddleware(middleware interface{}) interface{} {
	switch t := middleware.(type) {
	default:
		panic(fmt.Sprintf("chi: unsupported middleware signature: %T", t))
	case func(http.Handler) http.Handler:
	case func(Handler) Handler:
	}
	return middleware
}
<commit_msg>Fix for standard middleware chaining<commit_after>package chi

import (
	"fmt"
	"net/http"

	"golang.org/x/net/context"
)

// Build a chained chi.Handler from a list of middlewares
func chain(middlewares []interface{}, handlers ...interface{}) Handler {
	// join a middleware stack with inline middlewares
	mws := append(middlewares, handlers[:len(handlers)-1]...)

	// request handler
	handler := handlers[len(handlers)-1]

	// Assert the types in the middleware chain
	for _, mw := range mws {
		assertMiddleware(mw)
	}

	// Set the request handler to a context handler type
	var cxh Handler
	switch t := handler.(type) {
	default:
		panic(fmt.Sprintf("chi: unsupported handler signature: %T", t))
	case Handler:
		cxh = t
	case func(context.Context, http.ResponseWriter, *http.Request):
		cxh = HandlerFunc(t)
	case http.Handler:
		cxh = HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			t.ServeHTTP(w, r)
		})
	case func(http.ResponseWriter, *http.Request):
		cxh = HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			t(w, r)
		})
	}

	// Return ahead of time if there aren't any middlewares for the chain
	if len(mws) == 0 {
		return cxh
	}

	// Wrap the end handler with the middleware chain
	h := mwrap(mws[len(mws)-1])(cxh)
	for i := len(mws) - 2; i >= 0; i-- {
		f := mwrap(mws[i])
		h = f(h)
	}

	return h
}

// Wrap http.Handler middleware to chi.Handler middlewares
func mwrap(middleware interface{}) func(Handler) Handler {
	switch mw := middleware.(type) {
	default:
		panic(fmt.Sprintf("chi: unsupported handler signature: %T", mw))

	case func(Handler) Handler:
		return mw

	case func(http.Handler) http.Handler:
		return func(next Handler) Handler {
			return HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
				wfn := func(w http.ResponseWriter, r *http.Request) {
					next.ServeHTTPC(ctx, w, r)
				}
				mw(http.HandlerFunc(wfn)).ServeHTTP(w, r)
			})
		}
	}
}

// Runtime type checking of the middleware signature
func assertMiddleware(middleware interface{}) interface{} {
	switch t := middleware.(type) {
	default:
		panic(fmt.Sprintf("chi: unsupported middleware signature: %T", t))
	case func(http.Handler) http.Handler:
	case func(Handler) Handler:
	}
	return middleware
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io"
	"strings"
	"unicode"
)

// TrimAPIPrefix removes the API-specific prefix from a spec name.
// e.g., glTest becomes Test; GLX_TEST becomes TEST; egl0Test stays egl0Test
func TrimAPIPrefix(name string) string {
	prefixes := []string{"glX", "wgl", "egl", "gl", "GLX_", "WGL_", "EGL_", "GL_"}

	trimmed := name
	prefix := ""
	for _, p := range prefixes {
		if strings.HasPrefix(name, p) {
			trimmed = strings.TrimPrefix(name, p)
			prefix = p
			break
		}
	}

	if strings.IndexAny(trimmed, "0123456789") == 0 {
		return prefix + trimmed
	}
	return trimmed
}

// BlankLineStrippingWriter removes whitespace- or comment-only lines delimited
// by \n. A necessary evil to work around how text/template handles whitespace.
type BlankLineStrippingWriter struct {
	output io.Writer
	buf    *bytes.Buffer
}

// NewBlankLineStrippingWriter creates a new BlankLineStrippingWriter.
func NewBlankLineStrippingWriter(wrapped io.Writer) *BlankLineStrippingWriter {
	return &BlankLineStrippingWriter{wrapped, new(bytes.Buffer)}
}

func isBlank(line string) bool {
	blank := true
	for _, ch := range line {
		if !unicode.IsSpace(ch) && ch != '/' {
			blank = false
			break
		}
	}
	return blank
}

func (w BlankLineStrippingWriter) Write(p []byte) (int, error) {
	// Buffer the current write
	// Error is always nil.
	w.buf.Write(p)
	n := 0

	// Write non-empty lines from the buffer
	for {
		line, err := w.buf.ReadString('\n')
		if err != nil {
			// Did not have a whole line to read, rebuffer the unconsumed data
			// Error is always nil.
			w.buf.Write([]byte(line))
			return 0, nil
		}
		if !isBlank(line) {
			// Error is always nil.
			w.output.Write([]byte(line))
		}
		n += len(line)
	}
}
<commit_msg>BlankLineStrippingWriter: remove unused variable<commit_after>package main

import (
	"bytes"
	"io"
	"strings"
	"unicode"
)

// TrimAPIPrefix removes the API-specific prefix from a spec name.
// e.g., glTest becomes Test; GLX_TEST becomes TEST; egl0Test stays egl0Test
func TrimAPIPrefix(name string) string {
	prefixes := []string{"glX", "wgl", "egl", "gl", "GLX_", "WGL_", "EGL_", "GL_"}

	trimmed := name
	prefix := ""
	for _, p := range prefixes {
		if strings.HasPrefix(name, p) {
			trimmed = strings.TrimPrefix(name, p)
			prefix = p
			break
		}
	}

	if strings.IndexAny(trimmed, "0123456789") == 0 {
		return prefix + trimmed
	}
	return trimmed
}

// BlankLineStrippingWriter removes whitespace- or comment-only lines delimited
// by \n. A necessary evil to work around how text/template handles whitespace.
type BlankLineStrippingWriter struct {
	output io.Writer
	buf    *bytes.Buffer
}

// NewBlankLineStrippingWriter creates a new BlankLineStrippingWriter.
func NewBlankLineStrippingWriter(wrapped io.Writer) *BlankLineStrippingWriter {
	return &BlankLineStrippingWriter{wrapped, new(bytes.Buffer)}
}

func isBlank(line string) bool {
	blank := true
	for _, ch := range line {
		if !unicode.IsSpace(ch) && ch != '/' {
			blank = false
			break
		}
	}
	return blank
}

func (w BlankLineStrippingWriter) Write(p []byte) (int, error) {
	// Buffer the current write
	// Error is always nil.
	w.buf.Write(p)

	// Write non-empty lines from the buffer
	for {
		line, err := w.buf.ReadString('\n')
		if err != nil {
			// Did not have a whole line to read, rebuffer the unconsumed data
			// Error is always nil.
			w.buf.Write([]byte(line))
			return 0, nil
		}
		if !isBlank(line) {
			// Error is always nil.
			w.output.Write([]byte(line))
		}
	}
}
<|endoftext|>