<commit_before>package service

import (
	"bytes"
	"context"
	"database/sql"
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// KeyAuthUserID to use in context.
const KeyAuthUserID key = "auth_user_id"

const (
	verificationCodeLifespan = time.Minute * 15
	tokenLifespan            = time.Hour * 24 * 14
)

var (
	// ErrUnimplemented denotes that the method is not implemented.
	ErrUnimplemented = errors.New("unimplemented")
	// ErrUnauthenticated denotes no authenticated user in context.
	ErrUnauthenticated = errors.New("unauthenticated")
	// ErrInvalidRedirectURI denotes that the given redirect uri was not valid.
	ErrInvalidRedirectURI = errors.New("invalid redirect uri")
	// ErrInvalidVerificationCode denotes that the given verification code is not valid.
	ErrInvalidVerificationCode = errors.New("invalid verification code")
	// ErrVerificationCodeNotFound denotes that the verification code was not found.
	ErrVerificationCodeNotFound = errors.New("verification code not found")
	// ErrVerificationCodeExpired denotes that the verification code is already expired.
	ErrVerificationCodeExpired = errors.New("verification code expired")
)

var rxUUID = regexp.MustCompile("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")

var magicLinkMailTmpl *template.Template

type key string

// LoginOutput response.
type LoginOutput struct {
	Token     string    `json:"token"`
	ExpiresAt time.Time `json:"expiresAt"`
	AuthUser  User      `json:"authUser"`
}

// SendMagicLink to login without passwords.
func (s *Service) SendMagicLink(ctx context.Context, email, redirectURI string) error {
	email = strings.TrimSpace(email)
	if !rxEmail.MatchString(email) {
		return ErrInvalidEmail
	}

	uri, err := url.ParseRequestURI(redirectURI)
	if err != nil {
		return ErrInvalidRedirectURI
	}

	var verificationCode string
	err = s.db.QueryRowContext(ctx, `
		INSERT INTO verification_codes (user_id) VALUES (
			(SELECT id FROM users WHERE email = $1)
		) RETURNING id`, email).Scan(&verificationCode)
	if isForeignKeyViolation(err) {
		return ErrUserNotFound
	}

	if err != nil {
		return fmt.Errorf("could not insert verification code: %v", err)
	}

	magicLink := s.origin
	magicLink.Path = "/api/auth_redirect"
	q := magicLink.Query()
	q.Set("verification_code", verificationCode)
	q.Set("redirect_uri", uri.String())
	magicLink.RawQuery = q.Encode()

	if magicLinkMailTmpl == nil {
		magicLinkMailTmpl, err = template.ParseFiles("web/template/mail/magic-link.html")
		if err != nil {
			return fmt.Errorf("could not parse magic link mail template: %v", err)
		}
	}

	var mail bytes.Buffer
	if err = magicLinkMailTmpl.Execute(&mail, map[string]interface{}{
		"MagicLink": magicLink.String(),
		"Minutes":   int(verificationCodeLifespan.Minutes()),
	}); err != nil {
		return fmt.Errorf("could not execute magic link mail template: %v", err)
	}

	if err = s.sendMail(email, "Magic Link", mail.String()); err != nil {
		return fmt.Errorf("could not send magic link: %v", err)
	}

	return nil
}

// AuthURI to be redirected to and complete the login flow.
// It contains the token in the hash fragment.
func (s *Service) AuthURI(ctx context.Context, verificationCode, redirectURI string) (string, error) {
	verificationCode = strings.TrimSpace(verificationCode)
	if !rxUUID.MatchString(verificationCode) {
		return "", ErrInvalidVerificationCode
	}

	uri, err := url.ParseRequestURI(redirectURI)
	if err != nil {
		return "", ErrInvalidRedirectURI
	}

	var uid int64
	var ts time.Time
	err = s.db.QueryRowContext(ctx, `
		DELETE FROM verification_codes WHERE id = $1
		RETURNING user_id, created_at`, verificationCode).Scan(&uid, &ts)
	if err == sql.ErrNoRows {
		return "", ErrVerificationCodeNotFound
	}

	if err != nil {
		return "", fmt.Errorf("could not delete verification code: %v", err)
	}

	if ts.Add(verificationCodeLifespan).Before(time.Now()) {
		return "", ErrVerificationCodeExpired
	}

	token, err := s.codec.EncodeToString(strconv.FormatInt(uid, 10))
	if err != nil {
		return "", fmt.Errorf("could not create token: %v", err)
	}

	exp, err := time.Now().Add(tokenLifespan).MarshalText()
	if err != nil {
		return "", fmt.Errorf("could not marshall token expiration timestamp: %v", err)
	}

	f := url.Values{}
	f.Set("token", token)
	f.Set("expires_at", string(exp))
	uri.Fragment = f.Encode()

	return uri.String(), nil
}

// Login insecurely. For development purposes only.
func (s *Service) Login(ctx context.Context, email string) (LoginOutput, error) {
	var out LoginOutput

	if s.origin.Hostname() == "localhost" {
		return out, ErrUnimplemented
	}

	email = strings.TrimSpace(email)
	if !rxEmail.MatchString(email) {
		return out, ErrInvalidEmail
	}

	var avatar sql.NullString
	query := "SELECT id, username, avatar FROM users WHERE email = $1"
	err := s.db.QueryRowContext(ctx, query, email).Scan(&out.AuthUser.ID, &out.AuthUser.Username, &avatar)

	if err == sql.ErrNoRows {
		return out, ErrUserNotFound
	}

	if err != nil {
		return out, fmt.Errorf("could not query select user: %v", err)
	}

	out.AuthUser.AvatarURL = s.avatarURL(avatar)

	out.Token, err = s.codec.EncodeToString(strconv.FormatInt(out.AuthUser.ID, 10))
	if err != nil {
		return out, fmt.Errorf("could not create token: %v", err)
	}

	out.ExpiresAt = time.Now().Add(tokenLifespan)

	return out, nil
}

// AuthUserID from token.
func (s *Service) AuthUserID(token string) (int64, error) {
	str, err := s.codec.DecodeToString(token)
	if err != nil {
		return 0, fmt.Errorf("could not decode token: %v", err)
	}

	i, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return 0, fmt.Errorf("could not parse auth user id from token: %v", err)
	}

	return i, nil
}

// AuthUser from context.
// It requires the user ID in the context, so add it with a middleware or something.
func (s *Service) AuthUser(ctx context.Context) (User, error) {
	var u User
	uid, ok := ctx.Value(KeyAuthUserID).(int64)
	if !ok {
		return u, ErrUnauthenticated
	}

	return s.userByID(ctx, uid)
}

func (s *Service) deleteExpiredVerificationCodesCronJob(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			return
		case <-time.After(time.Hour * 24):
			if _, err := s.db.ExecContext(ctx,
				fmt.Sprintf(`DELETE FROM verification_codes WHERE created_at < now() - INTERVAL '%dm'`,
					int(verificationCodeLifespan.Minutes()))); err != nil {
				log.Printf("could not delete expired verification codes: %v\n", err)
			}
		}
	}
}
<commit_msg>fix: expose login on localhost<commit_after>package service

import (
	"bytes"
	"context"
	"database/sql"
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// KeyAuthUserID to use in context.
const KeyAuthUserID key = "auth_user_id"

const (
	verificationCodeLifespan = time.Minute * 15
	tokenLifespan            = time.Hour * 24 * 14
)

var (
	// ErrUnimplemented denotes that the method is not implemented.
	ErrUnimplemented = errors.New("unimplemented")
	// ErrUnauthenticated denotes no authenticated user in context.
	ErrUnauthenticated = errors.New("unauthenticated")
	// ErrInvalidRedirectURI denotes that the given redirect uri was not valid.
	ErrInvalidRedirectURI = errors.New("invalid redirect uri")
	// ErrInvalidVerificationCode denotes that the given verification code is not valid.
	ErrInvalidVerificationCode = errors.New("invalid verification code")
	// ErrVerificationCodeNotFound denotes that the verification code was not found.
	ErrVerificationCodeNotFound = errors.New("verification code not found")
	// ErrVerificationCodeExpired denotes that the verification code is already expired.
	ErrVerificationCodeExpired = errors.New("verification code expired")
)

var rxUUID = regexp.MustCompile("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")

var magicLinkMailTmpl *template.Template

type key string

// LoginOutput response.
type LoginOutput struct {
	Token     string    `json:"token"`
	ExpiresAt time.Time `json:"expiresAt"`
	AuthUser  User      `json:"authUser"`
}

// SendMagicLink to login without passwords.
func (s *Service) SendMagicLink(ctx context.Context, email, redirectURI string) error {
	email = strings.TrimSpace(email)
	if !rxEmail.MatchString(email) {
		return ErrInvalidEmail
	}

	uri, err := url.ParseRequestURI(redirectURI)
	if err != nil {
		return ErrInvalidRedirectURI
	}

	var verificationCode string
	err = s.db.QueryRowContext(ctx, `
		INSERT INTO verification_codes (user_id) VALUES (
			(SELECT id FROM users WHERE email = $1)
		) RETURNING id`, email).Scan(&verificationCode)
	if isForeignKeyViolation(err) {
		return ErrUserNotFound
	}

	if err != nil {
		return fmt.Errorf("could not insert verification code: %v", err)
	}

	magicLink := s.origin
	magicLink.Path = "/api/auth_redirect"
	q := magicLink.Query()
	q.Set("verification_code", verificationCode)
	q.Set("redirect_uri", uri.String())
	magicLink.RawQuery = q.Encode()

	if magicLinkMailTmpl == nil {
		magicLinkMailTmpl, err = template.ParseFiles("web/template/mail/magic-link.html")
		if err != nil {
			return fmt.Errorf("could not parse magic link mail template: %v", err)
		}
	}

	var mail bytes.Buffer
	if err = magicLinkMailTmpl.Execute(&mail, map[string]interface{}{
		"MagicLink": magicLink.String(),
		"Minutes":   int(verificationCodeLifespan.Minutes()),
	}); err != nil {
		return fmt.Errorf("could not execute magic link mail template: %v", err)
	}

	if err = s.sendMail(email, "Magic Link", mail.String()); err != nil {
		return fmt.Errorf("could not send magic link: %v", err)
	}

	return nil
}

// AuthURI to be redirected to and complete the login flow.
// It contains the token in the hash fragment.
func (s *Service) AuthURI(ctx context.Context, verificationCode, redirectURI string) (string, error) {
	verificationCode = strings.TrimSpace(verificationCode)
	if !rxUUID.MatchString(verificationCode) {
		return "", ErrInvalidVerificationCode
	}

	uri, err := url.ParseRequestURI(redirectURI)
	if err != nil {
		return "", ErrInvalidRedirectURI
	}

	var uid int64
	var ts time.Time
	err = s.db.QueryRowContext(ctx, `
		DELETE FROM verification_codes WHERE id = $1
		RETURNING user_id, created_at`, verificationCode).Scan(&uid, &ts)
	if err == sql.ErrNoRows {
		return "", ErrVerificationCodeNotFound
	}

	if err != nil {
		return "", fmt.Errorf("could not delete verification code: %v", err)
	}

	if ts.Add(verificationCodeLifespan).Before(time.Now()) {
		return "", ErrVerificationCodeExpired
	}

	token, err := s.codec.EncodeToString(strconv.FormatInt(uid, 10))
	if err != nil {
		return "", fmt.Errorf("could not create token: %v", err)
	}

	exp, err := time.Now().Add(tokenLifespan).MarshalText()
	if err != nil {
		return "", fmt.Errorf("could not marshall token expiration timestamp: %v", err)
	}

	f := url.Values{}
	f.Set("token", token)
	f.Set("expires_at", string(exp))
	uri.Fragment = f.Encode()

	return uri.String(), nil
}

// Login insecurely. For development purposes only.
func (s *Service) Login(ctx context.Context, email string) (LoginOutput, error) {
	var out LoginOutput

	if s.origin.Hostname() != "localhost" {
		return out, ErrUnimplemented
	}

	email = strings.TrimSpace(email)
	if !rxEmail.MatchString(email) {
		return out, ErrInvalidEmail
	}

	var avatar sql.NullString
	query := "SELECT id, username, avatar FROM users WHERE email = $1"
	err := s.db.QueryRowContext(ctx, query, email).Scan(&out.AuthUser.ID, &out.AuthUser.Username, &avatar)

	if err == sql.ErrNoRows {
		return out, ErrUserNotFound
	}

	if err != nil {
		return out, fmt.Errorf("could not query select user: %v", err)
	}

	out.AuthUser.AvatarURL = s.avatarURL(avatar)

	out.Token, err = s.codec.EncodeToString(strconv.FormatInt(out.AuthUser.ID, 10))
	if err != nil {
		return out, fmt.Errorf("could not create token: %v", err)
	}

	out.ExpiresAt = time.Now().Add(tokenLifespan)

	return out, nil
}

// AuthUserID from token.
func (s *Service) AuthUserID(token string) (int64, error) {
	str, err := s.codec.DecodeToString(token)
	if err != nil {
		return 0, fmt.Errorf("could not decode token: %v", err)
	}

	i, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return 0, fmt.Errorf("could not parse auth user id from token: %v", err)
	}

	return i, nil
}

// AuthUser from context.
// It requires the user ID in the context, so add it with a middleware or something.
func (s *Service) AuthUser(ctx context.Context) (User, error) {
	var u User
	uid, ok := ctx.Value(KeyAuthUserID).(int64)
	if !ok {
		return u, ErrUnauthenticated
	}

	return s.userByID(ctx, uid)
}

func (s *Service) deleteExpiredVerificationCodesCronJob(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			return
		case <-time.After(time.Hour * 24):
			if _, err := s.db.ExecContext(ctx,
				fmt.Sprintf(`DELETE FROM verification_codes WHERE created_at < now() - INTERVAL '%dm'`,
					int(verificationCodeLifespan.Minutes()))); err != nil {
				log.Printf("could not delete expired verification codes: %v\n", err)
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
 * A Go package to copy a Dataset
 *
 * Copyright (C) 2017 Lawrence Woodman <lwoodman@vlifesystems.com>
 *
 * Licensed under an MIT licence.  Please see LICENCE.md for details.
 */

// Package dcopy copies a Dataset so that you can work consistently on
// the same Dataset.  This is important where a database is likely to be
// updated while you are working on it.  The copy of the database is stored
// in an sqlite3 database located in a temporary directory.
package dcopy

import (
	"encoding/csv"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/lawrencewoodman/ddataset"
	"github.com/lawrencewoodman/ddataset/dcsv"
	"github.com/lawrencewoodman/ddataset/internal"
)

// DCopy represents a copy of a Dataset
type DCopy struct {
	dataset    ddataset.Dataset
	tmpDir     string
	isReleased bool
	numRecords int64
}

// DCopyConn represents a connection to a DCopy Dataset
type DCopyConn struct {
	conn ddataset.Conn
	err  error
}

// New creates a new DCopy Dataset which will be a copy of the Dataset
// supplied at the time it is run. Please note that this creates a file
// on the disk containing a copy of the supplied Dataset.  The copy is
// created in a sub-directory of tmpDir.  If tmpDir is the empty string,
// then it uses the default system temporary directory.
func New(dataset ddataset.Dataset, tmpDir string) (ddataset.Dataset, error) {
	tmpDir, err := ioutil.TempDir(tmpDir, "dcopy")
	if err != nil {
		return nil, err
	}
	copyFilename := filepath.Join(tmpDir, "copy.csv")
	f, err := os.Create(copyFilename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	w := csv.NewWriter(f)

	conn, err := dataset.Open()
	if err != nil {
		os.RemoveAll(tmpDir)
		return nil, err
	}
	defer conn.Close()

	strRecord := make([]string, len(dataset.Fields()))
	for conn.Next() {
		record := conn.Read()
		for i, f := range dataset.Fields() {
			strRecord[i] = record[f].String()
		}
		if err := w.Write(strRecord); err != nil {
			os.RemoveAll(tmpDir)
			return nil, fmt.Errorf("error writing record to csv copy: %s", err)
		}
	}

	if err := conn.Err(); err != nil {
		os.RemoveAll(tmpDir)
		return nil, err
	}

	w.Flush()
	if err := w.Error(); err != nil {
		os.RemoveAll(tmpDir)
		return nil, err
	}

	return &DCopy{
		dataset:    dcsv.New(copyFilename, false, ',', dataset.Fields()),
		tmpDir:     tmpDir,
		isReleased: false,
		numRecords: -1,
	}, nil
}

// Open creates a connection to the Dataset
func (d *DCopy) Open() (ddataset.Conn, error) {
	if d.isReleased {
		return nil, ddataset.ErrReleased
	}
	conn, err := d.dataset.Open()
	if err != nil {
		return nil, err
	}
	return &DCopyConn{
		conn: conn,
		err:  nil,
	}, nil
}

// Fields returns the field names used by the Dataset
func (d *DCopy) Fields() []string {
	if d.isReleased {
		return []string{}
	}
	return d.dataset.Fields()
}

// NumRecords returns the number of records in the Dataset.  If there is
// a problem getting the number of records it returns -1.
func (d *DCopy) NumRecords() int64 {
	if d.numRecords != -1 {
		return d.numRecords
	}
	d.numRecords = internal.CountNumRecords(d)
	return d.numRecords
}

// Release releases any resources associated with the Dataset d,
// rendering it unusable in the future.  In this case it deletes
// the temporary copy of the Dataset.
func (d *DCopy) Release() error {
	if !d.isReleased {
		err := os.RemoveAll(d.tmpDir)
		if err == nil {
			d.isReleased = true
		}
		return err
	}
	return ddataset.ErrReleased
}

// Next returns whether there is a Record to be Read
func (c *DCopyConn) Next() bool {
	return c.conn.Next()
}

// Err returns any errors from the connection
func (c *DCopyConn) Err() error {
	return c.conn.Err()
}

// Read returns the current Record
func (c *DCopyConn) Read() ddataset.Record {
	return c.conn.Read()
}

// Close closes the connection and deletes the copy
func (c *DCopyConn) Close() error {
	return c.conn.Close()
}

func getRecords(conn ddataset.Conn, num int) ([]ddataset.Record, error) {
	n := 0
	records := []ddataset.Record{}
	for n < num && conn.Next() {
		record := conn.Read().Clone()
		n++
		records = append(records, record)
	}
	return records, conn.Err()
}
<commit_msg>Remove redundant getRecords function<commit_after>/*
 * A Go package to copy a Dataset
 *
 * Copyright (C) 2017 Lawrence Woodman <lwoodman@vlifesystems.com>
 *
 * Licensed under an MIT licence.  Please see LICENCE.md for details.
 */

// Package dcopy copies a Dataset so that you can work consistently on
// the same Dataset.  This is important where a database is likely to be
// updated while you are working on it.  The copy of the database is stored
// in an sqlite3 database located in a temporary directory.
package dcopy

import (
	"encoding/csv"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/lawrencewoodman/ddataset"
	"github.com/lawrencewoodman/ddataset/dcsv"
	"github.com/lawrencewoodman/ddataset/internal"
)

// DCopy represents a copy of a Dataset
type DCopy struct {
	dataset    ddataset.Dataset
	tmpDir     string
	isReleased bool
	numRecords int64
}

// DCopyConn represents a connection to a DCopy Dataset
type DCopyConn struct {
	conn ddataset.Conn
	err  error
}

// New creates a new DCopy Dataset which will be a copy of the Dataset
// supplied at the time it is run. Please note that this creates a file
// on the disk containing a copy of the supplied Dataset.  The copy is
// created in a sub-directory of tmpDir.  If tmpDir is the empty string,
// then it uses the default system temporary directory.
func New(dataset ddataset.Dataset, tmpDir string) (ddataset.Dataset, error) {
	tmpDir, err := ioutil.TempDir(tmpDir, "dcopy")
	if err != nil {
		return nil, err
	}
	copyFilename := filepath.Join(tmpDir, "copy.csv")
	f, err := os.Create(copyFilename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	w := csv.NewWriter(f)

	conn, err := dataset.Open()
	if err != nil {
		os.RemoveAll(tmpDir)
		return nil, err
	}
	defer conn.Close()

	strRecord := make([]string, len(dataset.Fields()))
	for conn.Next() {
		record := conn.Read()
		for i, f := range dataset.Fields() {
			strRecord[i] = record[f].String()
		}
		if err := w.Write(strRecord); err != nil {
			os.RemoveAll(tmpDir)
			return nil, fmt.Errorf("error writing record to csv copy: %s", err)
		}
	}

	if err := conn.Err(); err != nil {
		os.RemoveAll(tmpDir)
		return nil, err
	}

	w.Flush()
	if err := w.Error(); err != nil {
		os.RemoveAll(tmpDir)
		return nil, err
	}

	return &DCopy{
		dataset:    dcsv.New(copyFilename, false, ',', dataset.Fields()),
		tmpDir:     tmpDir,
		isReleased: false,
		numRecords: -1,
	}, nil
}

// Open creates a connection to the Dataset
func (d *DCopy) Open() (ddataset.Conn, error) {
	if d.isReleased {
		return nil, ddataset.ErrReleased
	}
	conn, err := d.dataset.Open()
	if err != nil {
		return nil, err
	}
	return &DCopyConn{
		conn: conn,
		err:  nil,
	}, nil
}

// Fields returns the field names used by the Dataset
func (d *DCopy) Fields() []string {
	if d.isReleased {
		return []string{}
	}
	return d.dataset.Fields()
}

// NumRecords returns the number of records in the Dataset.  If there is
// a problem getting the number of records it returns -1.
func (d *DCopy) NumRecords() int64 {
	if d.numRecords != -1 {
		return d.numRecords
	}
	d.numRecords = internal.CountNumRecords(d)
	return d.numRecords
}

// Release releases any resources associated with the Dataset d,
// rendering it unusable in the future.  In this case it deletes
// the temporary copy of the Dataset.
func (d *DCopy) Release() error {
	if !d.isReleased {
		err := os.RemoveAll(d.tmpDir)
		if err == nil {
			d.isReleased = true
		}
		return err
	}
	return ddataset.ErrReleased
}

// Next returns whether there is a Record to be Read
func (c *DCopyConn) Next() bool {
	return c.conn.Next()
}

// Err returns any errors from the connection
func (c *DCopyConn) Err() error {
	return c.conn.Err()
}

// Read returns the current Record
func (c *DCopyConn) Read() ddataset.Record {
	return c.conn.Read()
}

// Close closes the connection and deletes the copy
func (c *DCopyConn) Close() error {
	return c.conn.Close()
}
<|endoftext|>


<commit_before>// Package debug provides micro debug packages
package debug

var (
	// DefaultName is the name of debug service
	DefaultName = "go.micro.debug"
)
<commit_msg>Delete debug.go<commit_after><|endoftext|>


<commit_before>package db

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/leptonyu/goeast/wechat"
	"io/ioutil"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
	"net/http"
	"time"
)

const (
	//Base URL
	Url = `http://www.goeastmandarin.com`
	//Home
	Home = `/`
	//Contact
	Contact = `/contact-us`
	//AboutUs
	Campus       = "/campus"
	Teachers     = "/our-teachers"
	Galleries    = "/galleries"
	Testimonials = "/testimonials"
	//Courses
	One2one = "/1-on-1-tutoring"
	Online  = "/online-courses"
	Onsite  = "/on-site-courses"
	//Blog
	Blog = "/blog"
	//Events
	Events = "/events"
	//url
	url = "http://www.goeastmandarin.com"
	//
	MaxArticles = 3
)

// this struct is used for caching the GoEast site.
// Then we can speed up the responds of WeChat requests.
// There will be some goroutines used for update the cache in period time.
type Msg struct {
	Name       string    // Key of msg, list at the const in this package.
	Content    string    // Content of msg, this content is formated as json.
	CreateTime time.Time // create time of the content.
}

// Query the specific Msg by key, such as
/*
	r := c.QueryMsg(db.Events)
*/
func (c *DBConfig) QueryMsg(key string) (r *Msg, err error) {
	r = &Msg{}
	_, err = c.Query(func(database *mgo.Database) (interface{}, error) {
		err := database.C("web").Find(bson.M{"name": key}).One(&r)
		return r, err
	})
	if err != nil {
		return c.UpdateMsg(key)
	}
	return r, nil
}

// Update Msg into database.
// If the Msg with key Msg.Name does not exist, then it will create a new one.
func (c *DBConfig) UpdateMsg(key string) (r *Msg, err error) {
	res, err := http.Get(url + key + "?format=json-pretty")
	if err != nil {
		return
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return
	}
	r = &Msg{
		Name:       key,
		Content:    string(body),
		CreateTime: time.Now(),
	}
	_, err = c.Query(func(database *mgo.Database) (interface{}, error) {
		return database.C("web").Upsert(bson.M{"name": key}, r)
	})
	if err != nil {
		return nil, err
	}
	return r, nil
}

type requestLog struct {
	From   string
	To     string
	Create int
	Id     int64
	Type   string
	Value  string
}

func (c *DBConfig) Log(r *wechat.Request) {
	bs, err := json.Marshal(r)
	if err != nil {
		log.Fatal(err)
		return
	}
	rl := &requestLog{
		From:   r.FromUserName,
		To:     r.ToUserName,
		Create: r.CreateTime,
		Id:     r.MsgId,
		Type:   r.MsgType,
		Value:  string(bs),
	}
	c.Query(func(d *mgo.Database) (interface{}, error) {
		d.C("userinfo").Upsert(bson.M{
			"from": rl.From,
			"to":   rl.To,
			"type": rl.Type,
			"id":   rl.Id,
		}, rl)
		return nil, nil
	})
}

func (c *DBConfig) QueryLog(username, typename string) ([]*wechat.Request, error) {
	if username == "" && typename == "" {
		return nil, errors.New("Pamater invalid")
	} else if username == "" {
		rs := []*wechat.Request{}
		_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
			return nil,
				d.C("userinfo").Find(bson.M{"type": typename}).All(&rs)
		})
		return rs, err
	} else if typename == "" {
		rs := []*wechat.Request{}
		_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
			return nil, d.C("userinfo").Find(bson.M{"from": username}).All(&rs)
		})
		return rs, err
	} else {
		rs := []*wechat.Request{}
		_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
			return nil, d.C("userinfo").Find(bson.M{"from": username, "type": typename}).All(&rs)
		})
		return rs, err
	}
}

type User struct {
	Id       string
	Username string
	Admin    bool
}

func (c *DBConfig) IsAdmin(id string) bool {
	if id == "" {
		return false
	}
	for _, user := range c.admins {
		if user.Id == id {
			return true
		}
	}
	return false
}

func (c *DBConfig) GetAdmin(id string) (*User, error) {
	if id == "" {
		return nil, errors.New("Speficy the admin id")
	}
	for _, user := range c.admins {
		if user.Id == id {
			return user, nil
		}
	}
	return nil, errors.New("User with id " + id + " is not admin!")
}
func (c *DBConfig) FindAdmins() []*User {
	user := []*User{}
	_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
		return nil, d.C("user").Find(bson.M{"admin": true}).All(&user)
	})
	if err != nil {
		return []*User{}
	}
	return user
}

func (c *DBConfig) Upsert(user *User) error {
	_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
		return d.C("user").Upsert(bson.M{"id": user.Id}, user)
	})
	if err == nil {
		c.admins = c.FindAdmins()
	}
	return err
}

func (c *DBConfig) UpsertWithUser(id, username string, isAdmin bool) error {
	return c.Upsert(&User{
		Id:       id,
		Username: username,
		Admin:    isAdmin,
	})
}

func Admin() func(*DBConfig, wechat.ResponseWriter, *wechat.Request) error {
	return func(c *DBConfig, w wechat.ResponseWriter, r *wechat.Request) error {
		for _, v := range c.admins {
			if r.FromUserName == v.Id {
				w.ReplyText(fmt.Sprintf(`Hello %v, you are the admin.
adm:help
	Get Admin Help
adm:status
	Get Admin Status
`, v.Username))
				return nil
			}
		}
		return errors.New("You are not administrator!")
		return nil
	}
}
<commit_msg>update<commit_after>package db

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/leptonyu/goeast/wechat"
	"io/ioutil"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
	"net/http"
	"time"
)

const (
	//Base URL
	Url = `http://www.goeastmandarin.com`
	//Home
	Home = `/`
	//Contact
	Contact = `/contact-us`
	//AboutUs
	Campus       = "/campus"
	Teachers     = "/our-teachers"
	Galleries    = "/galleries"
	Testimonials = "/testimonials"
	//Courses
	One2one = "/1-on-1-tutoring"
	Online  = "/online-courses"
	Onsite  = "/on-site-courses"
	//Blog
	Blog = "/blog"
	//Events
	Events = "/events"
	//url
	url = "http://www.goeastmandarin.com"
	//
	MaxArticles = 3
)

// this struct is used for caching the GoEast site.
// Then we can speed up the responds of WeChat requests.
// There will be some goroutines used for update the cache in period time.
type Msg struct {
	Name       string    // Key of msg, list at the const in this package.
	Content    string    // Content of msg, this content is formated as json.
	CreateTime time.Time // create time of the content.
}

// Query the specific Msg by key, such as
/*
	r := c.QueryMsg(db.Events)
*/
func (c *DBConfig) QueryMsg(key string) (r *Msg, err error) {
	r = &Msg{}
	_, err = c.Query(func(database *mgo.Database) (interface{}, error) {
		err := database.C("web").Find(bson.M{"name": key}).One(&r)
		return r, err
	})
	if err != nil {
		return c.UpdateMsg(key)
	}
	return r, nil
}

// Update Msg into database.
// If the Msg with key Msg.Name does not exist, then it will create a new one.
func (c *DBConfig) UpdateMsg(key string) (r *Msg, err error) {
	res, err := http.Get(url + key + "?format=json-pretty")
	if err != nil {
		return
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return
	}
	r = &Msg{
		Name:       key,
		Content:    string(body),
		CreateTime: time.Now(),
	}
	_, err = c.Query(func(database *mgo.Database) (interface{}, error) {
		return database.C("web").Upsert(bson.M{"name": key}, r)
	})
	if err != nil {
		return nil, err
	}
	return r, nil
}

type requestLog struct {
	From   string
	To     string
	Create int
	Id     int64
	Type   string
	Value  string
}

func (c *DBConfig) Log(r *wechat.Request) {
	bs, err := json.Marshal(r)
	if err != nil {
		log.Fatal(err)
		return
	}
	rl := &requestLog{
		From:   r.FromUserName,
		To:     r.ToUserName,
		Create: r.CreateTime,
		Id:     r.MsgId,
		Type:   r.MsgType,
		Value:  string(bs),
	}
	c.Query(func(d *mgo.Database) (interface{}, error) {
		d.C("userinfo").Upsert(bson.M{
			"from": rl.From,
			"to":   rl.To,
			"type": rl.Type,
			"id":   rl.Id,
		}, rl)
		return nil, nil
	})
}

func (c *DBConfig) QueryLog(username, typename string) ([]*wechat.Request, error) {
	if username == "" && typename == "" {
		return nil, errors.New("Pamater invalid")
	} else if username == "" {
		rs := []*wechat.Request{}
		_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
			return nil,
				d.C("userinfo").Find(bson.M{"type": typename}).All(&rs)
		})
		return rs, err
	} else if typename == "" {
		rs := []*wechat.Request{}
		_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
			return nil, d.C("userinfo").Find(bson.M{"from": username}).All(&rs)
		})
		return rs, err
	} else {
		rs := []*wechat.Request{}
		_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
			return nil, d.C("userinfo").Find(bson.M{"from": username, "type": typename}).All(&rs)
		})
		return rs, err
	}
}

type User struct {
	Id       string
	Username string
	Admin    bool
}

func (c *DBConfig) IsAdmin(id string) bool {
	if id == "" {
		return false
	}
	for _, user := range c.admins {
		if user.Id == id {
			return true
		}
	}
	return false
}

func (c *DBConfig) GetAdmin(id string) (*User, error) {
	if id == "" {
		return nil, errors.New("Speficy the admin id")
	}
	for _, user := range c.admins {
		if user.Id == id {
			return user, nil
		}
	}
	return nil, errors.New("User with id " + id + " is not admin!")
}
func (c *DBConfig) FindAdmins() []*User {
	user := []*User{}
	_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
		return nil, d.C("user").Find(bson.M{"admin": true}).All(&user)
	})
	if err != nil {
		return []*User{}
	}
	return user
}

func (c *DBConfig) Upsert(user *User) error {
	_, err := c.Query(func(d *mgo.Database) (interface{}, error) {
		return d.C("user").Upsert(bson.M{"id": user.Id}, user)
	})
	if err == nil {
		c.admins = c.FindAdmins()
	}
	return err
}

func (c *DBConfig) UpsertWithUser(id, username string, isAdmin bool) error {
	return c.Upsert(&User{
		Id:       id,
		Username: username,
		Admin:    isAdmin,
	})
}

func Admin() func(*DBConfig, wechat.ResponseWriter, *wechat.Request) error {
	return func(c *DBConfig, w wechat.ResponseWriter, r *wechat.Request) error {
		for _, v := range c.admins {
			if r.FromUserName == v.Id {
				w.ReplyText(fmt.Sprintf(`Hello %v, you are the admin.
adm:help
	Get Admin Help
adm:status
	Get Admin Status
`, v.Username))
				return nil
			}
		}
		return errors.New("You are not administrator!")
	}
}
<|endoftext|>


<commit_before>package decimal

import (
	"encoding/json"
	"math"
	"strconv"
	"strings"
)

// Decimal64p2 is a decimal number implementation based on int64 with 2 digits after point fixed precision
type Decimal64p2 int64

// PRECISION_2 defines fixed precision with 2 digits after point
const PRECISION_2 = 2

// NewDecimal64p2() creates Decimal64p2 from integer and decimal parts
func NewDecimal64p2(intPart int64, decimalPart int8) Decimal64p2 {
	switch {
	case decimalPart > 0:
		if decimalPart > 99 {
			panic("decimalPart > 99")
		}
		if intPart < 0 {
			panic("decimalPart > 0 && intPart < 0")
		}
	case decimalPart < 0:
		if decimalPart < -99 {
			panic("decimalPart < -99")
		}
		if intPart > 0 {
			panic("decimalPart < 0 && intPart > 0")
		}
	}

	return Decimal64p2(intPart*100 + int64(decimalPart))
}

// NewDecimal64p2FromFloat64() creates Decimal64p2 from float64
func NewDecimal64p2FromFloat64(f float64) Decimal64p2 {
	return Decimal64p2(round(f * 100))
}

// AsFloat64() converts decimal to float64
func (d Decimal64p2) AsFloat64() float64 {
	return float64(d) / 100
}

// IntPart() returns integer part of the decimal
func (d Decimal64p2) IntPart() int64 {
	return int64(d / 100)
}

// DecimalPart() returns part after point
func (d Decimal64p2) DecimalPart() int64 {
	result := int64(d - d/100*100)
	if result < 0 {
		result *= -1
	}
	return result
}

// String() renders decimal to string. If integer the .00 is NOT rendered.
func (d Decimal64p2) String() string {
	if d == 0 {
		return "0"
	}
	var sign string
	i := int64(d)
	if i < 0 {
		sign = "-"
		i *= -1
	}
	s := strconv.FormatInt(i, 10)
	if i <= 9 {
		return sign + "0.0" + s
	} else if i <= 99 {
		return sign + "0." + s
	}

	var left, right string
	left = s[:len(s)-PRECISION_2]
	right = s[len(s)-PRECISION_2:]
	if right == "00" {
		return sign + left
	}
	return sign + strings.Join([]string{left, right}, ".")
}

// ParseDecimal64p2() creates Decimal64p2 from a string
func ParseDecimal64p2(s string) (d Decimal64p2, err error) {
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return d, err
	}
	return NewDecimal64p2FromFloat64(f), nil
}

func round(num float64) int {
	return int(num + math.Copysign(0.5, num))
}

func toFixed(num float64, precision int) float64 {
	output := math.Pow(10, float64(precision))
	return float64(round(num*output)) / output
}

// MarshalJSON() marshals decimal to JSON
func (d Decimal64p2) MarshalJSON() ([]byte, error) {
	return []byte(d.String()), nil
}

// UnmarshalJSON() unmarshals JSON to decimal
func (d *Decimal64p2) UnmarshalJSON(data []byte) error {
	var f float64
	if err := json.Unmarshal(data, &f); err != nil {
		return err
	}
	*d = NewDecimal64p2FromFloat64(f)
	return nil
}

// Abs() returns absolute value for the decimal
func (d Decimal64p2) Abs() Decimal64p2 {
	if d < 0 {
		return d * -1
	}
	return d
}
<commit_msg>Eliminating golint warnings - correct formatting (2)<commit_after>package decimal

import (
	"encoding/json"
	"math"
	"strconv"
	"strings"
)

// Decimal64p2 is a decimal number implementation based on int64 with 2 digits after point fixed precision
type Decimal64p2 int64

// PRECISION_2 defines fixed precision with 2 digits after point
const PRECISION_2 = 2

// NewDecimal64p2 creates Decimal64p2 from integer and decimal parts
func NewDecimal64p2(intPart int64, decimalPart int8) Decimal64p2 {
	switch {
	case decimalPart > 0:
		if decimalPart > 99 {
			panic("decimalPart > 99")
		}
		if intPart < 0 {
			panic("decimalPart > 0 && intPart < 0")
		}
	case decimalPart < 0:
		if decimalPart < -99 {
			panic("decimalPart < -99")
		}
		if intPart > 0 {
			panic("decimalPart < 0 && intPart > 0")
		}
	}

	return Decimal64p2(intPart*100 + int64(decimalPart))
}

// NewDecimal64p2FromFloat64 creates Decimal64p2 from float64
func NewDecimal64p2FromFloat64(f float64) Decimal64p2 {
	return Decimal64p2(round(f * 100))
}

// AsFloat64 converts decimal to float64
func (d Decimal64p2) AsFloat64() float64 {
	return float64(d) / 100
}

// IntPart returns integer part of the decimal
func (d Decimal64p2) IntPart() int64 {
	return int64(d / 100)
}

// DecimalPart returns part after point
func (d Decimal64p2) DecimalPart() int64 {
	result := int64(d - d/100*100)
	if result < 0 {
		result *= -1
	}
	return result
}

// String renders decimal to string. If integer the .00 is NOT rendered.
func (d Decimal64p2) String() string {
	if d == 0 {
		return "0"
	}
	var sign string
	i := int64(d)
	if i < 0 {
		sign = "-"
		i *= -1
	}
	s := strconv.FormatInt(i, 10)
	if i <= 9 {
		return sign + "0.0" + s
	} else if i <= 99 {
		return sign + "0." + s
	}

	var left, right string
	left = s[:len(s)-PRECISION_2]
	right = s[len(s)-PRECISION_2:]
	if right == "00" {
		return sign + left
	}
	return sign + strings.Join([]string{left, right}, ".")
}

// ParseDecimal64p2 creates Decimal64p2 from a string
func ParseDecimal64p2(s string) (d Decimal64p2, err error) {
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return d, err
	}
	return NewDecimal64p2FromFloat64(f), nil
}

func round(num float64) int {
	return int(num + math.Copysign(0.5, num))
}

func toFixed(num float64, precision int) float64 {
	output := math.Pow(10, float64(precision))
	return float64(round(num*output)) / output
}

// MarshalJSON marshals decimal to JSON
func (d Decimal64p2) MarshalJSON() ([]byte, error) {
	return []byte(d.String()), nil
}

// UnmarshalJSON unmarshals JSON to decimal
func (d *Decimal64p2) UnmarshalJSON(data []byte) error {
	var f float64
	if err := json.Unmarshal(data, &f); err != nil {
		return err
	}
	*d = NewDecimal64p2FromFloat64(f)
	return nil
}

// Abs returns absolute value for the decimal
func (d Decimal64p2) Abs() Decimal64p2 {
	if d < 0 {
		return d * -1
	}
	return d
}
<|endoftext|>


<commit_before>package controllers

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
)

func APIEndpoints(c *gin.Context) {
	var reqScheme string

	if c.Request.TLS != nil {
		reqScheme = "https"
	} else {
		reqScheme = "http"
	}

	reqHost := c.Request.Host
	baseURL := fmt.Sprintf("%s://%s", reqScheme, reqHost)

	resources := map[string]string{
		"companies_url": baseURL + "/companies",
		"company_url":   baseURL + "/companies/{id}",
		"emails_url":    baseURL + "/emails",
		"email_url":     baseURL + "/emails/{id}",
		"jobs_url":      baseURL + "/jobs",
		"job_url":       baseURL + "/jobs/{id}",
		"profiles_url":  baseURL + "/profiles",
		"profile_url":   baseURL + "/profiles/{id}",
		"users_url":     baseURL + "/users",
		"user_url":      baseURL + "/users/{id}",
	}

	c.IndentedJSON(http.StatusOK, resources)
}
<commit_msg>Fit to master example<commit_after>package controllers

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
)

func APIEndpoints(c *gin.Context) {
	var reqScheme string

	if c.Request.TLS != nil {
		reqScheme = "https"
	} else {
		reqScheme = "http"
	}

	reqHost := c.Request.Host
	baseURL := fmt.Sprintf("%s://%s", reqScheme, reqHost)

	resources := map[string]string{
		"companies_url": baseURL + "/api/companies",
		"company_url":   baseURL + "/api/companies/{id}",
		"emails_url":    baseURL + "/api/emails",
		"email_url":     baseURL + "/api/emails/{id}",
		"jobs_url":      baseURL + "/api/jobs",
		"job_url":       baseURL + "/api/jobs/{id}",
		"profiles_url":  baseURL + "/api/profiles",
		"profile_url":   baseURL + "/api/profiles/{id}",
		"users_url":     baseURL + "/api/users",
		"user_url":      baseURL + "/api/users/{id}",
	}

	c.IndentedJSON(http.StatusOK, resources)
}
<|endoftext|>


<commit_before>package main

import (
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

func main() {
	a := app.New()
	w := a.NewWindow("fyne")

	// w.Resize(fyne.NewSize(300, 300))
	// w.SetFixedSize(true)
	w.SetFullScreen(true)

	hello := widget.NewLabel("Hello Fyne!")

	img := canvas.NewImageFromFile("logo.png")
	img.FillMode = canvas.ImageFillOriginal

	w.SetContent(container.NewVBox(
		img,
		hello,
		widget.NewButton("Hi!", func() {
			hello.SetText("Welcome :)")
			w.CenterOnScreen()
		}),
		widget.NewButton("Quit", func() {
			a.Quit()
		}),
	))

	// w.RequestFocus() // TODO(dvrkps): panic on macos.

	w.ShowAndRun()
}
<commit_msg>fyne: add ctrl tab shorcut<commit_after>package main

import (
	"log"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/driver/desktop"
	"fyne.io/fyne/v2/widget"
)

func main() {
	a := app.New()
	w := a.NewWindow("fyne")

	// w.Resize(fyne.NewSize(300, 300))
	// w.SetFixedSize(true)
	w.SetFullScreen(true)

	ctrlTab := desktop.CustomShortcut{KeyName: fyne.KeyTab, Modifier: desktop.ControlModifier}
	w.Canvas().AddShortcut(&ctrlTab, func(s fyne.Shortcut) {
		log.Println("ups")
		w.Hide()
	})

	hello := widget.NewLabel("Hello Fyne!")

	img := canvas.NewImageFromFile("logo.png")
	img.FillMode = canvas.ImageFillOriginal

	w.SetContent(container.NewVBox(
		img,
		hello,
		widget.NewButton("Hi!", func() {
			hello.SetText("Welcome :)")
			w.CenterOnScreen()
		}),
		widget.NewButton("Quit", func() {
			a.Quit()
		}),
	))

	// w.RequestFocus() // TODO(dvrkps): panic on macos.

	w.ShowAndRun()
}
<|endoftext|>


<commit_before>package game

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"strings"

	"golang.org/x/net/websocket"

	"github.com/ghthor/aodd/game/datastore"
	"github.com/ghthor/engine/net/encoding"
	"github.com/ghthor/engine/net/protocol"
	"github.com/ghthor/engine/rpg2d"
)

type LoginReq struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type packetHandler func(actorHandler) (actorHandler, error)

type actorHandler struct {
	protocol.Conn
	handlePacket packetHandler

	sim       rpg2d.RunningSimulation
	datastore datastore.Datastore

	actor *actor
}

// Starts the packet handler loop.
// This function is blocking.
func (c actorHandler) run() (err error) {
	for {
		c, err = c.handlePacket(c)
		if err != nil {
			break
		}
	}
	return
}

var ErrWebsocketClientDisconnected = errors.New("websocket client disconnected")

type ErrUnexpectedPacket struct {
	Handler packetHandler
	Packet  encoding.Packet
}

func (e ErrUnexpectedPacket) String() string {
	return fmt.Sprint("unexpected packet {%v} in %v", e.Packet, e.Handler)
}

func (e ErrUnexpectedPacket) Error() string {
	return e.String()
}

// An implementation of packetHandler which
// will handle an actor logging in.
func (c actorHandler) loginHandler() (actorHandler, error) {
	packet, err := c.Read()
	if err != nil {
		return c, err
	}

	if packet.Type == encoding.PT_DISCONNECT {
		return c, ErrWebsocketClientDisconnected
	}

	switch packet.Type {
	case encoding.PT_JSON:
		switch packet.Msg {
		case "login":
			return c.respondToLoginReq(packet)
		case "create":
			return c.respondToCreateReq(packet)
		default:
		}
	default:
	}

	// TODO Improve this message with how to login
	c.SendMessage("notLoggedIn", "")
	return c, nil
}

// A login request is a event that can modify the
// state of the packet handler. If the login is
// successful the packet handler will transition
// to the input handler..
func (c actorHandler) respondToLoginReq(p encoding.Packet) (actorHandler, error) {
	r := LoginReq{}

	err := json.Unmarshal([]byte(p.Payload), &r)
	if err != nil {
		return c, errors.New(fmt.Sprint("error parsing login request:", err))
	}

	actor, exists := c.datastore.ActorExists(r.Name)
	if !exists {
		log.Printf("login failed: actor %s doesn't exist", r.Name)
		c.SendJson("actorDoesntExist", r)
		return c, nil
	}

	if !actor.Authenticate(r.Name, r.Password) {
		log.Printf("login failed: password for %s was incorrect", r.Name)
		c.SendMessage("authFailed", r.Name)
		return c, nil
	}

	c = c.loginActor(actor)

	log.Print("login success: ", r.Name)
	c.SendJson("loginSuccess", c.actor.ToState())
	return c, nil
}

// A create request is an event that can modify th
// state of the packet handler. If the create is
// successful the packet handler will transition
// in the input handler.
func (c actorHandler) respondToCreateReq(p encoding.Packet) (actorHandler, error) {
	r := LoginReq{}

	err := json.Unmarshal([]byte(p.Payload), &r)
	if err != nil {
		// TODO determine if this an error that should terminate the connection
		return c, errors.New(fmt.Sprint("error parsing login request:", err))
	}

	_, exists := c.datastore.ActorExists(r.Name)
	if exists {
		log.Printf("create failed: actor %s already exists", r.Name)
		c.SendMessage("actorAlreadyExists", "actor already exists")
		return c, nil
	}

	actor, err := c.datastore.AddActor(r.Name, r.Password)
	if err != nil {
		// TODO Instead of terminating the connection here
		// we should retry contacting the database or something
		return c, err
	}

	c = c.loginActor(actor)

	log.Print("created actor: ", actor.Name)

	c.SendJson("createSuccess", c.actor.ToState())
	return c, nil
}

// Creates a new actor struct using a datastore.Actor struct.
// Adds this new actor into the simulation.
func (c actorHandler) loginActor(dsactor datastore.Actor) actorHandler {
	// Set the actor this connection is now associated with
	// Mutate the packet handler into the next state
	c.handlePacket = (actorHandler).inputHandler

	// Create an actorEntity for this object
	c.actor = &actor{
		actorEntity{
			id: dsactor.Id,

			name: dsactor.Name,

			cell:   dsactor.Loc,
			facing: dsactor.Facing,
		},

		newActorConn(c),

		actorCmdRequest{},
	}

	c.sim.ConnectActor(c.actor)
	return c
}

// An implementation of packetHandler which will
// process input requests and prepare them
// for consumption by the input phase.
func (c actorHandler) inputHandler() (actorHandler, error) {
	packet, err := c.Read()
	if err != nil {
		return c, err
	}

	if packet.Type == encoding.PT_DISCONNECT {
		return c, ErrWebsocketClientDisconnected
	}

	switch packet.Type {
	case encoding.PT_MESSAGE:
		if strings.Contains(packet.Msg, "move") {
			err := c.actor.SubmitCmd(packet.Msg, packet.Payload)
			if err != nil {
				c.SendError("invalidActorCommand", err.Error())
			}
			return c, nil
		}
	default:
	}

	c.SendMessage("alreadyLoggedIn", "an actor has already been logged into this connection")
	return c, nil
}

// Return the actor bound to the connection.
func (c actorHandler) Actor() datastore.Actor {
	if c.actor == nil {
		return datastore.Actor{}
	}

	return datastore.Actor{
		Id: c.actor.id,

		Name: c.actor.name,

		Loc:    c.actor.cell,
		Facing: c.actor.facing,
	}
}

func newWebsocketActorHandler(sim rpg2d.RunningSimulation, datastore datastore.Datastore) websocket.Handler {
	return func(ws *websocket.Conn) {
		err := actorHandler{
			Conn:         protocol.NewWebsocketConn(ws),
			handlePacket: (actorHandler).loginHandler,

			sim:       sim,
			datastore: datastore,
		}.run()

		// TODO Maybe send a http response if there is an error
		if err != nil {
			log.Printf("disconnected: %v", err)
		}
	}
}
<commit_msg>Disconnect an actor if the websocket is disconnected<commit_after>package game

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"strings"

	"golang.org/x/net/websocket"

	"github.com/ghthor/aodd/game/datastore"
	"github.com/ghthor/engine/net/encoding"
	"github.com/ghthor/engine/net/protocol"
	"github.com/ghthor/engine/rpg2d"
)

type LoginReq struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type packetHandler func(actorHandler) (actorHandler, error)

type actorHandler struct {
	protocol.Conn
	handlePacket packetHandler

	sim       rpg2d.RunningSimulation
	datastore datastore.Datastore

	actor *actor
}

// Starts the packet handler loop.
// This function is blocking.
func (c actorHandler) run() (err error) {
	for {
		c, err = c.handlePacket(c)
		if err != nil {
			if c.actor != nil {
				c.sim.RemoveActor(c.actor)
			}
			break
		}
	}
	return
}

var ErrWebsocketClientDisconnected = errors.New("websocket client disconnected")

type ErrUnexpectedPacket struct {
	Handler packetHandler
	Packet  encoding.Packet
}

func (e ErrUnexpectedPacket) String() string {
	return fmt.Sprint("unexpected packet {%v} in %v", e.Packet, e.Handler)
}

func (e ErrUnexpectedPacket) Error() string {
	return e.String()
}

// An implementation of packetHandler which
// will handle an actor logging in.
func (c actorHandler) loginHandler() (actorHandler, error) {
	packet, err := c.Read()
	if err != nil {
		return c, err
	}

	if packet.Type == encoding.PT_DISCONNECT {
		return c, ErrWebsocketClientDisconnected
	}

	switch packet.Type {
	case encoding.PT_JSON:
		switch packet.Msg {
		case "login":
			return c.respondToLoginReq(packet)
		case "create":
			return c.respondToCreateReq(packet)
		default:
		}
	default:
	}

	// TODO Improve this message with how to login
	c.SendMessage("notLoggedIn", "")
	return c, nil
}

// A login request is a event that can modify the
// state of the packet handler. If the login is
// successful the packet handler will transition
// to the input handler..
func (c actorHandler) respondToLoginReq(p encoding.Packet) (actorHandler, error) {
	r := LoginReq{}

	err := json.Unmarshal([]byte(p.Payload), &r)
	if err != nil {
		return c, errors.New(fmt.Sprint("error parsing login request:", err))
	}

	actor, exists := c.datastore.ActorExists(r.Name)
	if !exists {
		log.Printf("login failed: actor %s doesn't exist", r.Name)
		c.SendJson("actorDoesntExist", r)
		return c, nil
	}

	if !actor.Authenticate(r.Name, r.Password) {
		log.Printf("login failed: password for %s was incorrect", r.Name)
		c.SendMessage("authFailed", r.Name)
		return c, nil
	}

	c = c.loginActor(actor)

	log.Print("login success: ", r.Name)
	c.SendJson("loginSuccess", c.actor.ToState())
	return c, nil
}

// A create request is an event that can modify th
// state of the packet handler. If the create is
// successful the packet handler will transition
// in the input handler.
func (c actorHandler) respondToCreateReq(p encoding.Packet) (actorHandler, error) {
	r := LoginReq{}

	err := json.Unmarshal([]byte(p.Payload), &r)
	if err != nil {
		// TODO determine if this an error that should terminate the connection
		return c, errors.New(fmt.Sprint("error parsing login request:", err))
	}

	_, exists := c.datastore.ActorExists(r.Name)
	if exists {
		log.Printf("create failed: actor %s already exists", r.Name)
		c.SendMessage("actorAlreadyExists", "actor already exists")
		return c, nil
	}

	actor, err := c.datastore.AddActor(r.Name, r.Password)
	if err != nil {
		// TODO Instead of terminating the connection here
		// we should retry contacting the database or something
		return c, err
	}

	c = c.loginActor(actor)

	log.Print("created actor: ", actor.Name)

	c.SendJson("createSuccess", c.actor.ToState())
	return c, nil
}

// Creates a new actor struct using a datastore.Actor struct.
// Adds this new actor into the simulation.
func (c actorHandler) loginActor(dsactor datastore.Actor) actorHandler {
	// Set the actor this connection is now associated with
	// Mutate the packet handler into the next state
	c.handlePacket = (actorHandler).inputHandler

	// Create an actorEntity for this object
	c.actor = &actor{
		actorEntity{
			id: dsactor.Id,

			name: dsactor.Name,

			cell:   dsactor.Loc,
			facing: dsactor.Facing,
		},

		newActorConn(c),

		actorCmdRequest{},
	}

	c.sim.ConnectActor(c.actor)
	return c
}

// An implementation of packetHandler which will
// process input requests and prepare them
// for consumption by the input phase.
func (c actorHandler) inputHandler() (actorHandler, error) {
	packet, err := c.Read()
	if err != nil {
		return c, err
	}

	if packet.Type == encoding.PT_DISCONNECT {
		return c, ErrWebsocketClientDisconnected
	}

	switch packet.Type {
	case encoding.PT_MESSAGE:
		if strings.Contains(packet.Msg, "move") {
			err := c.actor.SubmitCmd(packet.Msg, packet.Payload)
			if err != nil {
				c.SendError("invalidActorCommand", err.Error())
			}
			return c, nil
		}
	default:
	}

	c.SendMessage("alreadyLoggedIn", "an actor has already been logged into this connection")
	return c, nil
}

// Return the actor bound to the connection.
func (c actorHandler) Actor() datastore.Actor {
	if c.actor == nil {
		return datastore.Actor{}
	}

	return datastore.Actor{
		Id: c.actor.id,

		Name: c.actor.name,

		Loc:    c.actor.cell,
		Facing: c.actor.facing,
	}
}

func newWebsocketActorHandler(sim rpg2d.RunningSimulation, datastore datastore.Datastore) websocket.Handler {
	return func(ws *websocket.Conn) {
		err := actorHandler{
			Conn:         protocol.NewWebsocketConn(ws),
			handlePacket: (actorHandler).loginHandler,

			sim:       sim,
			datastore: datastore,
		}.run()

		// TODO Maybe send a http response if there is an error
		if err != nil {
			log.Printf("disconnected: %v", err)
		}
	}
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"monkey/ast"
	"monkey/lexer"
	"monkey/token"
)

type Parser struct {
	l      *lexer.Lexer
	errors [] string

	curToken  token.Token
	peekToken token.Token
}

func New(l *lexer.Lexer) *Parser {
	p := &Parser{
		l:      l,
		errors: []string{},
	}

	p.nextToken()
	p.nextToken()

	return p
}

func (p *Parser) Errors() []string {
	return p.errors
}

func (p *Parser) peekError(t token.TokenType) {
	msg := fmt.Sprintf("expected next token to be %s, got %s instead", t, p.peekToken.Type)
	p.errors = append(p.errors, msg)
}

func (p *Parser) nextToken() {
	p.curToken = p.peekToken
	p.peekToken = p.l.NextToken()
}

func (p *Parser) curTokenIs(t token.TokenType) bool {
	return p.curToken.Type == t
}

func (p *Parser) peekTokenIs(t token.TokenType) bool {
	return p.peekToken.Type == t
}

func (p *Parser) expectPeek(t token.TokenType) bool {
	if p.peekTokenIs(t) {
		p.nextToken()
		return true
	} else {
		p.peekError(t)
		return false
	}
}

func (p *Parser) ParseProgram() *ast.Program {
	program := &ast.Program{}
	program.Statements = []ast.Statement{}

	for p.curToken.Type != token.EOF {
		stmt := p.parseStatement()
		if stmt != nil {
			program.Statements = append(program.Statements, stmt)
		}
		p.nextToken()
	}

	return program
}

func (p *Parser) parseStatement() ast.Statement {
	switch p.curToken.Type {
		case token.LET:
			return p.parseLetStatement()
		case token.RETURN:
			return p.parseReturnStatement()
		default:
			return nil
	}
}

func (p *Parser) parseLetStatement() *ast.LetStatement {
	stmt := &ast.LetStatement{Token: p.curToken}

	if !p.expectPeek(token.IDENT) {
		return nil
	}

	stmt.Name = &ast.Identifier{Token: p.curToken, Value: p.curToken.Literal}

	if !p.expectPeek(token.ASSIGN) {
		return nil
	}

	for !p.curTokenIs(token.SEMICOLON) {
		p.nextToken()
	}

	return stmt
}

func (p *Parser) parseReturnStatement() *ast.ReturnStatement {
	stmt := &ast.ReturnStatement{Token: p.curToken}

	p.nextToken()

	for !p.curTokenIs(token.SEMICOLON) {
		p.nextToken()
	}

	return stmt
}<commit_msg>set up pratt parser<commit_after>package parser

import (
	"fmt"
	"monkey/ast"
	"monkey/lexer"
	"monkey/token"
)

type (
	prefixParseFn func() ast.Expression
	infixParseFn func(ast.Expression) ast.Expression
)

type Parser struct {
	l      *lexer.Lexer
	errors [] string

	curToken  token.Token
	peekToken token.Token

	prefixParseFns map[token.TokenType]prefixParseFn
	infixParseFns  map[token.TokenType]infixParseFn
}

func New(l *lexer.Lexer) *Parser {
	p := &Parser{
		l:      l,
		errors: []string{},
	}

	p.nextToken()
	p.nextToken()

	return p
}

func (p *Parser) Errors() []string {
	return p.errors
}

func (p *Parser) peekError(t token.TokenType) {
	msg := fmt.Sprintf("expected next token to be %s, got %s instead", t, p.peekToken.Type)
	p.errors = append(p.errors, msg)
}

func (p *Parser) nextToken() {
	p.curToken = p.peekToken
	p.peekToken = p.l.NextToken()
}

func (p *Parser) curTokenIs(t token.TokenType) bool {
	return p.curToken.Type == t
}

func (p *Parser) peekTokenIs(t token.TokenType) bool {
	return p.peekToken.Type == t
}

func (p *Parser) expectPeek(t token.TokenType) bool {
	if p.peekTokenIs(t) {
		p.nextToken()
		return true
	} else {
		p.peekError(t)
		return false
	}
}

func (p *Parser) registerPrefix(tokenType token.TokenType, fn prefixParseFn) {
	p.prefixParseFns[tokenType] = fn
}

func (p *Parser) registerInfix(tokenType token.TokenType, fn infixParseFn) {
	p.infixParseFns[tokenType] = fn
}

func (p *Parser) ParseProgram() *ast.Program {
	program := &ast.Program{}
	program.Statements = []ast.Statement{}

	for p.curToken.Type != token.EOF {
		stmt := p.parseStatement()
		if stmt != nil {
			program.Statements = append(program.Statements, stmt)
		}
		p.nextToken()
	}

	return program
}

func (p *Parser) parseStatement() ast.Statement {
	switch p.curToken.Type {
		case token.LET:
			return p.parseLetStatement()
		case token.RETURN:
			return p.parseReturnStatement()
		default:
			return nil
	}
}

func (p *Parser) parseLetStatement() *ast.LetStatement {
	stmt := &ast.LetStatement{Token: p.curToken}

	if !p.expectPeek(token.IDENT) {
		return nil
	}

	stmt.Name = &ast.Identifier{Token: p.curToken, Value: p.curToken.Literal}

	if !p.expectPeek(token.ASSIGN) {
		return nil
	}

	for !p.curTokenIs(token.SEMICOLON) {
		p.nextToken()
	}

	return stmt
}

func (p *Parser) parseReturnStatement() *ast.ReturnStatement {
	stmt := &ast.ReturnStatement{Token: p.curToken}

	p.nextToken()

	for !p.curTokenIs(token.SEMICOLON) {
		p.nextToken()
	}

	return stmt
}<|endoftext|>


<commit_before>// EVH is designed to be a single-use file transfer system.  Its purpose is to replace
// aging methods of sharing files such as FTP.  With the advent of services like
// DropBox, Box, Google Drive and the like, this type of service is becoming more
// commonplace EVH has some differentiating features that make it an especially
// good tool for corporations and/or home use.
//
// EVH runs in two modes: server and client.  Server hosts a web server interface for
// uploading and downloading files.  The Client is for uploading only and runs
// in a terminal.  This app is designed to run on all platforms that Go supports.
package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"
	"os"
)

// Flags
var ConfigFileFlag string
var DstEmailFlag string
var ExpirationFlag string
var FileDescrFlag string
var FilesFieldFlag string
var ProgressFlag bool
var ServerFlag bool
var SrcEmailFlag string
var UrlFlag string
var Evh1ImportFlag bool
var ProxyUrlFlag string

// Global Variables
var UploadUrlPath = "/upload/"
var DownloadUrlPath = "/download/"
var AdminUrlPath = "/admin/"
var Files []string
var HttpProto = "http"
var SiteDown bool
var Templates *template.Template

// Constants
const VERSION = "2.5.11"

func init() {
	flag.StringVar(&ConfigFileFlag, "c", "", "Location of the Configuration file")
	flag.BoolVar(&ServerFlag, "server", false, "Listen for incoming file uploads")

	// Client flags
	flag.StringVar(&UrlFlag, "url", "", "Remote server URL to send files to (client only)")
	flag.StringVar(&FilesFieldFlag, "field", "", "Field name of the form (client only)")
	flag.StringVar(&SrcEmailFlag, "from", "", "Email address of uploader (client only)")
	flag.StringVar(&DstEmailFlag, "to", "", "Comma separated set of email address(es) of file recipient(s) (client only)")
	flag.StringVar(&FileDescrFlag, "description", "", "File desription (use quotes) (client only)")
	flag.BoolVar(&ProgressFlag, "progress", true, "Show progress bar during upload (client only)")
	flag.StringVar(&ExpirationFlag, "expires", "", "Example 1:d for 1 day (client only)")
	flag.BoolVar(&Evh1ImportFlag, "import", false, "Import data from EVH1 instance (client only)")
	flag.StringVar(&ProxyUrlFlag, "proxy", "", "URL/Address for proxy (env=use environment proxy, other=use as defined")
}

func main() {
	flag.Parse()

	// Load in our Config
	Config = NewConfig(ConfigFileFlag)
	Config.ImportFlags()

	if ServerFlag {
		// Final sanity check
		if Config.Server.Assets == "" {
			log.Fatal("ERROR: Cannot continue without specifying assets path")
		}
		if Config.Server.Templates == "" {
			log.Fatal("ERROR: Cannot continue without specifying templates path")
		}
		if Config.Server.ListenAddr == "" {
			log.Fatal("ERROR: Cannot continue without specifying listenaddr value")
		}
		if Config.Server.Mailserver == "" {
			log.Println("WARNING: cannot send emails, mailserver not set")
		}

		// Set so all generated URLs use https if enabled
		if Config.Server.Ssl {
			HttpProto = "https"
		}

		// Setup our assets dir (if it don't already exist)
		err := os.MkdirAll(Config.Server.Assets, 0700)
		if err != nil {
			log.Fatal("Cannot setup assetdir as needed: " + err.Error())
		}

		// Parse our html templates
		go RefreshTemplates()
		go ScrubDownloads()

		// Register our handler functions
		http.HandleFunc(UploadUrlPath, SSLCheck(UploadHandler))
		http.HandleFunc(DownloadUrlPath, SSLCheck(AssetHandler))
		http.HandleFunc(AdminUrlPath, BasicAuth(SSLCheck(AdminHandler)))
		http.HandleFunc("/", Evh1Intercept(SSLCheck(HomeHandler)))

		// Listen
		log.Println("Listening...")

		// Spawn HTTPS listener in another thread
		go func() {
			if Config.Server.Ssl == false || Config.Server.SslPort == "" {
				return
			}
			var addrSsl = Config.Server.ListenAddr + ":" + Config.Server.SslPort
			listenErrSsl := http.ListenAndServeTLS(addrSsl, Config.Server.CertFile, Config.Server.KeyFile, nil)
			if listenErrSsl != nil {
				log.Fatal("ERROR: ssl listen problem: " + listenErrSsl.Error())
			}
		}()

		// Start non-SSL listener
		var addrNonSsl = Config.Server.ListenAddr + ":" + Config.Server.NonSslPort
		listenErr := http.ListenAndServe(addrNonSsl, nil)
		if listenErr != nil {
			log.Fatal("ERROR: non-ssl listen problem: " + listenErr.Error())
		}
	} else {
		// Run import if requested
		if Evh1ImportFlag {
			SpitSlurp()
			return
		}

		// Final sanity check
		if Config.Client.DestEmail == "" {
			log.Println("WARNING: no -destemail value set, cannot send reciever an email")
		}
		if Config.Client.Email == "" {
			log.Println("WARNING: no -email value set, cannot send email to uploader")
		}
		if Config.Client.Field == "" {
			log.Println("WARNING: no -field value set, using \"file\" instead")
			Config.Client.Field = "file"
		}
		if Config.Client.Url == "" {
			log.Fatal("ERROR: Cannot continue without specifying -url value")
		}

		// All filenames are unflagged arguments, loop through them and uplod the file(s)
		for _, fname := range flag.Args() {
			fi, err := os.Stat(fname)
			if err != nil {
				log.Println("WARNING: Cannot read file, skipping ", fname, ": ", err.Error())
			} else {
				if fi.Mode().IsRegular() {
					Files = append(Files, fname)
				}
			}
		}

		Upload(Files)
	}
}
<commit_msg>Removed SSLv3 support<commit_after>// EVH is designed to be a single-use file transfer system.  Its purpose is to replace
// aging methods of sharing files such as FTP.  With the advent of services like
// DropBox, Box, Google Drive and the like, this type of service is becoming more
// commonplace EVH has some differentiating features that make it an especially
// good tool for corporations and/or home use.
//
// EVH runs in two modes: server and client.  Server hosts a web server interface for
// uploading and downloading files.  The Client is for uploading only and runs
// in a terminal.  This app is designed to run on all platforms that Go supports.
package main

import (
	"crypto/tls"
	"flag"
	"html/template"
	"log"
	"net/http"
	"os"
)

// Flags
var ConfigFileFlag string
var DstEmailFlag string
var ExpirationFlag string
var FileDescrFlag string
var FilesFieldFlag string
var ProgressFlag bool
var ServerFlag bool
var SrcEmailFlag string
var UrlFlag string
var Evh1ImportFlag bool
var ProxyUrlFlag string

// Global Variables
var UploadUrlPath = "/upload/"
var DownloadUrlPath = "/download/"
var AdminUrlPath = "/admin/"
var Files []string
var HttpProto = "http"
var SiteDown bool
var Templates *template.Template

// Constants
const VERSION = "2.5.11"

func init() {
	flag.StringVar(&ConfigFileFlag, "c", "", "Location of the Configuration file")
	flag.BoolVar(&ServerFlag, "server", false, "Listen for incoming file uploads")

	// Client flags
	flag.StringVar(&UrlFlag, "url", "", "Remote server URL to send files to (client only)")
	flag.StringVar(&FilesFieldFlag, "field", "", "Field name of the form (client only)")
	flag.StringVar(&SrcEmailFlag, "from", "", "Email address of uploader (client only)")
	flag.StringVar(&DstEmailFlag, "to", "", "Comma separated set of email address(es) of file recipient(s) (client only)")
	flag.StringVar(&FileDescrFlag, "description", "", "File desription (use quotes) (client only)")
	flag.BoolVar(&ProgressFlag, "progress", true, "Show progress bar during upload (client only)")
	flag.StringVar(&ExpirationFlag, "expires", "", "Example 1:d for 1 day (client only)")
	flag.BoolVar(&Evh1ImportFlag, "import", false, "Import data from EVH1 instance (client only)")
	flag.StringVar(&ProxyUrlFlag, "proxy", "", "URL/Address for proxy (env=use environment proxy, other=use as defined")
}

func main() {
	flag.Parse()

	// Load in our Config
	Config = NewConfig(ConfigFileFlag)
	Config.ImportFlags()

	if ServerFlag {
		// Final sanity check
		if Config.Server.Assets == "" {
			log.Fatal("ERROR: Cannot continue without specifying assets path")
		}
		if Config.Server.Templates == "" {
			log.Fatal("ERROR: Cannot continue without specifying templates path")
		}
		if Config.Server.ListenAddr == "" {
			log.Fatal("ERROR: Cannot continue without specifying listenaddr value")
		}
		if Config.Server.Mailserver == "" {
			log.Println("WARNING: cannot send emails, mailserver not set")
		}

		// Set so all generated URLs use https if enabled
		if Config.Server.Ssl {
			HttpProto = "https"
		}

		// Setup our assets dir (if it don't already exist)
		err := os.MkdirAll(Config.Server.Assets, 0700)
		if err != nil {
			log.Fatal("Cannot setup assetdir as needed: " + err.Error())
		}

		// Parse our html templates
		go RefreshTemplates()
		go ScrubDownloads()

		// Register our handler functions
		http.HandleFunc(UploadUrlPath, SSLCheck(UploadHandler))
		http.HandleFunc(DownloadUrlPath, SSLCheck(AssetHandler))
		http.HandleFunc(AdminUrlPath, BasicAuth(SSLCheck(AdminHandler)))
		http.HandleFunc("/", Evh1Intercept(SSLCheck(HomeHandler)))

		// Listen
		log.Println("Listening...")

		// Spawn HTTPS listener in another thread
		go func() {
			if Config.Server.Ssl == false || Config.Server.SslPort == "" {
				return
			}
			var addrSsl = Config.Server.ListenAddr + ":" + Config.Server.SslPort
			//listenErrSsl := http.ListenAndServeTLS(addrSsl, Config.Server.CertFile, Config.Server.KeyFile, nil)

			var config = &tls.Config{MinVersion: tls.VersionTLS10}
			var server = &http.Server{Addr: addrSsl, TLSConfig: config}
			listenErrSsl := server.ListenAndServeTLS(Config.Server.CertFile, Config.Server.KeyFile)

			if listenErrSsl != nil {
				log.Fatal("ERROR: ssl listen problem: " + listenErrSsl.Error())
			}
		}()

		// Start non-SSL listener
		var addrNonSsl = Config.Server.ListenAddr + ":" + Config.Server.NonSslPort
		listenErr := http.ListenAndServe(addrNonSsl, nil)
		if listenErr != nil {
			log.Fatal("ERROR: non-ssl listen problem: " + listenErr.Error())
		}
	} else {
		// Run import if requested
		if Evh1ImportFlag {
			SpitSlurp()
			return
		}

		// Final sanity check
		if Config.Client.DestEmail == "" {
			log.Println("WARNING: no -destemail value set, cannot send reciever an email")
		}
		if Config.Client.Email == "" {
			log.Println("WARNING: no -email value set, cannot send email to uploader")
		}
		if Config.Client.Field == "" {
			log.Println("WARNING: no -field value set, using \"file\" instead")
			Config.Client.Field = "file"
		}
		if Config.Client.Url == "" {
			log.Fatal("ERROR: Cannot continue without specifying -url value")
		}

		// All filenames are unflagged arguments, loop through them and uplod the file(s)
		for _, fname := range flag.Args() {
			fi, err := os.Stat(fname)
			if err != nil {
				log.Println("WARNING: Cannot read file, skipping ", fname, ": ", err.Error())
			} else {
				if fi.Mode().IsRegular() {
					Files = append(Files, fname)
				}
			}
		}

		Upload(Files)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode basic struct
type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("failed in function main(), error is %v", err)
	}
}

//Init function
//Step1: 获得调用init()的caller, 并且保存在"admin"中
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	fmt.Println("started get caller's metatdat")
	adminCert, err := stub.GetCallerMetadata()

	if err != nil {
		return nil, errors.New("failed getting metadata")
	}

	if len(adminCert) == 0 {
		return nil, errors.New("Invalid admin certificate. Empty.")
	}

	fmt.Printf("the administrator is [%v]", adminCert)

	// stub.PutState("admin", adminCert)
	return nil, nil
}

// Invoke function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")

	return nil, nil
}

//Query funciton
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")

	switch function {
	case "getState":
		fmt.Println("started in function getState()")
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}

		key := args[0]
		result, err := stub.GetState(key)

		if err != nil {
			return nil, errors.New("Failed in function getState")
		}
		return result, err
	}
	return nil, nil
}
<commit_msg>demo6.go<commit_after>package main

import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode basic struct
type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("failed in function main(), error is %v", err)
	}
}

//Init function
//Step1: 获得调用init()的caller, 并且保存在"admin"中
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	fmt.Println("started get caller's metatdat")
	// adminCert, _ := stub.GetCallerMetadata()
	// fmt.Printf("the administrator is [%v]", adminCert)

	// if err != nil {
	// 	return nil, errors.New("failed getting metadata")
	// }
	//
	// if len(adminCert) == 0 {
	// 	return nil, errors.New("Invalid admin certificate. Empty.")
	// }

	// stub.PutState("admin", adminCert)
	return nil, nil
}

// Invoke function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")

	return nil, nil
}

//Query funciton
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")

	switch function {
	case "getState":
		fmt.Println("started in function getState()")
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}

		key := args[0]
		result, err := stub.GetState(key)

		if err != nil {
			return nil, errors.New("Failed in function getState")
		}
		return result, err
	}
	return nil, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// 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.

// Integration with the systemd D-Bus API.  See http://www.freedesktop.org/wiki/Software/systemd/dbus/
package dbus

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"sync"

	"github.com/godbus/dbus"
)

const (
	alpha        = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`
	num          = `0123456789`
	alphanum     = alpha + num
	signalBuffer = 100
)

// needsEscape checks whether a byte in a potential dbus ObjectPath needs to be escaped
func needsEscape(i int, b byte) bool {
	// Escape everything that is not a-z-A-Z-0-9
	// Also escape 0-9 if it's the first character
	return strings.IndexByte(alphanum, b) == -1 ||
		(i == 0 && strings.IndexByte(num, b) != -1)
}

// PathBusEscape sanitizes a constituent string of a dbus ObjectPath using the
// rules that systemd uses for serializing special characters.
func PathBusEscape(path string) string {
	// Special case the empty string
	if len(path) == 0 {
		return "_"
	}
	n := []byte{}
	for i := 0; i < len(path); i++ {
		c := path[i]
		if needsEscape(i, c) {
			e := fmt.Sprintf("_%x", c)
			n = append(n, []byte(e)...)
		} else {
			n = append(n, c)
		}
	}
	return string(n)
}

// Conn is a connection to systemd's dbus endpoint.
type Conn struct {
	// sysconn/sysobj are only used to call dbus methods
	sysconn *dbus.Conn
	sysobj  *dbus.Object

	// sigconn/sigobj are only used to receive dbus signals
	sigconn *dbus.Conn
	sigobj  *dbus.Object

	jobListener struct {
		jobs map[dbus.ObjectPath]chan<- string
		sync.Mutex
	}
	subscriber struct {
		updateCh chan<- *SubStateUpdate
		errCh    chan<- error
		sync.Mutex
		ignore      map[dbus.ObjectPath]int64
		cleanIgnore int64
	}
}

// New establishes a connection to the system bus and authenticates.
// Callers should call Close() when done with the connection.
func New() (*Conn, error) {
	return newConnection(func() (*dbus.Conn, error) {
		return dbusAuthHelloConnection(dbus.SystemBusPrivate)
	})
}

// NewUserConnection establishes a connection to the session bus and
// authenticates. This can be used to connect to systemd user instances.
// Callers should call Close() when done with the connection.
func NewUserConnection() (*Conn, error) {
	return newConnection(func() (*dbus.Conn, error) {
		return dbusAuthHelloConnection(dbus.SessionBusPrivate)
	})
}

// NewSystemdConnection establishes a private, direct connection to systemd.
// This can be used for communicating with systemd without a dbus daemon.
// Callers should call Close() when done with the connection.
func NewSystemdConnection() (*Conn, error) {
	return newConnection(func() (*dbus.Conn, error) {
		// We skip Hello when talking directly to systemd.
		return dbusAuthConnection(func() (*dbus.Conn, error) {
			return dbus.Dial("unix:path=/run/systemd/private")
		})
	})
}

// Close closes an established connection
func (c *Conn) Close() {
	c.sysconn.Close()
	c.sigconn.Close()
}

func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
	sysconn, err := createBus()
	if err != nil {
		return nil, err
	}

	sigconn, err := createBus()
	if err != nil {
		sysconn.Close()
		return nil, err
	}

	c := &Conn{
		sysconn: sysconn,
		sysobj:  systemdObject(sysconn),
		sigconn: sigconn,
		sigobj:  systemdObject(sigconn),
	}

	c.subscriber.ignore = make(map[dbus.ObjectPath]int64)
	c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string)

	// Setup the listeners on jobs so that we can get completions
	c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
		"type='signal', interface='org.freedesktop.systemd1.Manager', member='JobRemoved'")

	c.dispatch()
	return c, nil
}

func dbusAuthConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
	conn, err := createBus()
	if err != nil {
		return nil, err
	}

	// Only use EXTERNAL method, and hardcode the uid (not username)
	// to avoid a username lookup (which requires a dynamically linked
	// libc)
	methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))}

	err = conn.Auth(methods)
	if err != nil {
		conn.Close()
		return nil, err
	}

	return conn, nil
}

func dbusAuthHelloConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
	conn, err := dbusAuthConnection(createBus)
	if err != nil {
		return nil, err
	}

	if err = conn.Hello(); err != nil {
		conn.Close()
		return nil, err
	}

	return conn, nil
}

func systemdObject(conn *dbus.Conn) *dbus.Object {
	return conn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1"))
}
<commit_msg>dbus: Fix breakage from godbus changing *dbus.Object to dbus.BusObject interface.<commit_after>// Copyright 2015 CoreOS, Inc.
//
// 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.

// Integration with the systemd D-Bus API.  See http://www.freedesktop.org/wiki/Software/systemd/dbus/
package dbus

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"sync"

	"github.com/godbus/dbus"
)

const (
	alpha        = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`
	num          = `0123456789`
	alphanum     = alpha + num
	signalBuffer = 100
)

// needsEscape checks whether a byte in a potential dbus ObjectPath needs to be escaped
func needsEscape(i int, b byte) bool {
	// Escape everything that is not a-z-A-Z-0-9
	// Also escape 0-9 if it's the first character
	return strings.IndexByte(alphanum, b) == -1 ||
		(i == 0 && strings.IndexByte(num, b) != -1)
}

// PathBusEscape sanitizes a constituent string of a dbus ObjectPath using the
// rules that systemd uses for serializing special characters.
func PathBusEscape(path string) string {
	// Special case the empty string
	if len(path) == 0 {
		return "_"
	}
	n := []byte{}
	for i := 0; i < len(path); i++ {
		c := path[i]
		if needsEscape(i, c) {
			e := fmt.Sprintf("_%x", c)
			n = append(n, []byte(e)...)
		} else {
			n = append(n, c)
		}
	}
	return string(n)
}

// Conn is a connection to systemd's dbus endpoint.
type Conn struct {
	// sysconn/sysobj are only used to call dbus methods
	sysconn *dbus.Conn
	sysobj  dbus.BusObject

	// sigconn/sigobj are only used to receive dbus signals
	sigconn *dbus.Conn
	sigobj  dbus.BusObject

	jobListener struct {
		jobs map[dbus.ObjectPath]chan<- string
		sync.Mutex
	}
	subscriber struct {
		updateCh chan<- *SubStateUpdate
		errCh    chan<- error
		sync.Mutex
		ignore      map[dbus.ObjectPath]int64
		cleanIgnore int64
	}
}

// New establishes a connection to the system bus and authenticates.
// Callers should call Close() when done with the connection.
func New() (*Conn, error) {
	return newConnection(func() (*dbus.Conn, error) {
		return dbusAuthHelloConnection(dbus.SystemBusPrivate)
	})
}

// NewUserConnection establishes a connection to the session bus and
// authenticates. This can be used to connect to systemd user instances.
// Callers should call Close() when done with the connection.
func NewUserConnection() (*Conn, error) {
	return newConnection(func() (*dbus.Conn, error) {
		return dbusAuthHelloConnection(dbus.SessionBusPrivate)
	})
}

// NewSystemdConnection establishes a private, direct connection to systemd.
// This can be used for communicating with systemd without a dbus daemon.
// Callers should call Close() when done with the connection.
func NewSystemdConnection() (*Conn, error) {
	return newConnection(func() (*dbus.Conn, error) {
		// We skip Hello when talking directly to systemd.
		return dbusAuthConnection(func() (*dbus.Conn, error) {
			return dbus.Dial("unix:path=/run/systemd/private")
		})
	})
}

// Close closes an established connection
func (c *Conn) Close() {
	c.sysconn.Close()
	c.sigconn.Close()
}

func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
	sysconn, err := createBus()
	if err != nil {
		return nil, err
	}

	sigconn, err := createBus()
	if err != nil {
		sysconn.Close()
		return nil, err
	}

	c := &Conn{
		sysconn: sysconn,
		sysobj:  systemdObject(sysconn),
		sigconn: sigconn,
		sigobj:  systemdObject(sigconn),
	}

	c.subscriber.ignore = make(map[dbus.ObjectPath]int64)
	c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string)

	// Setup the listeners on jobs so that we can get completions
	c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
		"type='signal', interface='org.freedesktop.systemd1.Manager', member='JobRemoved'")

	c.dispatch()
	return c, nil
}

func dbusAuthConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
	conn, err := createBus()
	if err != nil {
		return nil, err
	}

	// Only use EXTERNAL method, and hardcode the uid (not username)
	// to avoid a username lookup (which requires a dynamically linked
	// libc)
	methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))}

	err = conn.Auth(methods)
	if err != nil {
		conn.Close()
		return nil, err
	}

	return conn, nil
}

func dbusAuthHelloConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
	conn, err := dbusAuthConnection(createBus)
	if err != nil {
		return nil, err
	}

	if err = conn.Hello(); err != nil {
		conn.Close()
		return nil, err
	}

	return conn, nil
}

func systemdObject(conn *dbus.Conn) dbus.BusObject {
	return conn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1"))
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Datacratic. All rights reserved.

package control

import (
	"math"
	"sync"
	"time"
)

// Task defines an interface for executing tasks.
type Task interface {
	Do()
}

// TaskFunc defines an helper type for using function literals as a Task.
type TaskFunc func()

// Do executes the function literal as a Task.
func (f TaskFunc) Do() {
	f()
}

// DefaultGeneratorSmoothingFactor contains the default weight of the exponential moving average that estimates the time taken by the handler.
var DefaultGeneratorSmoothingFactor = 0.80

// DefaultGeneratorSleepPrecision defines the default duration that will trigger a wait after each request.
var DefaultGeneratorSleepPrecision = 50 * time.Millisecond

// DefaultGeneratorSamplingPeriod defines the default approximate duration over which the QPS is sampled.
var DefaultGeneratorSamplingPeriod = time.Second

// Generator adapts itself to call an handler a fixed number of times per second.
// It operates by creating B concurrent batches that will call the handler N times repeatedly.
// After each call to the handler, it waits W seconds to space requests evently over time.
// To avoid sleeping for very small amount of time, those waits are grouped based on the supplied precision.
// Note that the system adjusts B and W based on its estimation of the time R taken by the handler.
// Therefore, if the variability of R is high, it may make it harder for the system to stabilize to a steady state.
type Generator struct {
	// Handler contains what gets executed periodically.
	Handler Task
	// QPS contains the number of calls that will be done per second.
	QPS float64
	// SmoothingFactor contains the weight of the exponential moving average that estimates the time taken by the handler.
	// Will use DefaultGeneratorSmoothingFactor if 0.
	SmoothingFactor float64
	// SleepPrecision contains the minimal duration that will trigger a wait after each request.
	// Will use DefaultGeneratorSleepPrecision if 0.
	SleepPrecision time.Duration
	// SamplingPeriod contains the approximate duration over which the QPS is sampled.
	// Will use DefaultGeneratorSamplingPeriod if 0.
	SamplingPeriod time.Duration
}

// Start begins calling the handler at the requested frequency.
func (generator *Generator) Start() {
	if generator.Handler == nil {
		panic("generator requires an handler")
	}

	go generator.run()
}

func (generator *Generator) evaluate(r float64) (b int, n int, w float64) {
	sampling := generator.SamplingPeriod
	if sampling == 0 {
		sampling = DefaultGeneratorSamplingPeriod
	}

	s := sampling.Seconds()

	// sampling period S=(R+W)*N
	// with maximum QPS per B is Q=1/R and B = QPS/Q
	// thus, because QPS=B/(R+W)
	// we end up with both W=B/QPS-R and N=S/(R+W)

	qps := generator.QPS
	if r > 0 {
		b = int(math.Ceil(qps * r))
	} else {
		b = 1
	}

	w = float64(b)/qps - r
	n = int(math.Ceil(s / (r + w)))
	return
}

func (generator *Generator) run() {
	precision := generator.SleepPrecision
	if precision == 0 {
		precision = DefaultGeneratorSleepPrecision
	}

	type batch struct {
		requests int
		duration time.Duration
		passback interface{}
	}

	results := make(chan batch)

	pool := sync.Pool{
		New: func() interface{} {
			batches := make(chan batch)

			// starts a batch that executes tasks and waits N times
			go func() {
				for item := range batches {
					t0 := time.Now()
					dt := time.Duration(0)

					for i := 0; i != item.requests; i++ {
						generator.Handler.Do()
						if dt += item.duration; dt >= precision {
							time.Sleep(dt)
							dt = 0
						}
					}

					time.Sleep(dt)
					item.duration = time.Since(t0)
					results <- item
				}
			}()

			return batches
		},
	}

	// perform a quick approximation with a first batch of 1 request
	queue := pool.Get().(chan batch)
	queue <- batch{
		requests: 1,
		duration: 0,
		passback: queue,
	}

	first := <-results
	pool.Put(first.passback)

	// set initial values
	r := first.duration.Seconds()
	batches, n, w := generator.evaluate(r)
	working := 0

	ticks := time.NewTicker(time.Second)
	count := 0
	total := batch{}

	smoothing := generator.SmoothingFactor
	if smoothing == 0 {
		smoothing = DefaultGeneratorSmoothingFactor
	}

	for {
		// start as many concurrent batches as it is required
		for working < batches {
			working++
			queue := pool.Get().(chan batch)
			queue <- batch{
				requests: n,
				duration: time.Duration(1e9*w) * time.Nanosecond,
				passback: queue,
			}
		}

		select {
		case item := <-results:
			count++
			total.requests += item.requests
			total.duration += item.duration

			working--
			pool.Put(item.passback)

		case <-ticks.C:
			if count == 0 {
				break
			}

			m := smoothing
			r = m*r + (1.0-m)*(total.duration.Seconds()/float64(total.requests)-w)
			batches, n, w = generator.evaluate(r)

			count = 0
			total.requests = 0
			total.duration = 0
		}
	}
}
<commit_msg>Re-architecture of rtbkit and re-organization of various dependencies.<commit_after>// Copyright (c) 2014 Datacratic. All rights reserved.

package control

import (
	"log"
	"math"
	"sync"
	"time"
)

// Task defines an interface for executing tasks.
type Task interface {
	Do()
}

// TaskFunc defines an helper type for using function literals as a Task.
type TaskFunc func()

// Do executes the function literal as a Task.
func (f TaskFunc) Do() {
	f()
}

// DefaultGeneratorSmoothingFactor contains the default weight of the exponential moving average that estimates the time taken by the handler.
var DefaultGeneratorSmoothingFactor = 0.80

// DefaultGeneratorSleepPrecision defines the default duration that will trigger a wait after each request.
var DefaultGeneratorSleepPrecision = 50 * time.Millisecond

// DefaultGeneratorSamplingPeriod defines the default approximate duration over which the QPS is sampled.
var DefaultGeneratorSamplingPeriod = time.Second

// Generator adapts itself to call an handler a fixed number of times per second.
// It operates by creating B concurrent batches that will call the handler N times repeatedly.
// After each call to the handler, it waits W seconds to space requests evently over time.
// To avoid sleeping for very small amount of time, those waits are grouped based on the supplied precision.
// Note that the system adjusts B and W based on its estimation of the time R taken by the handler.
// Therefore, if the variability of R is high, it may make it harder for the system to stabilize to a steady state.
type Generator struct {
	// Handler contains what gets executed periodically.
	Handler Task
	// QPS contains the number of calls that will be done per second.
	QPS float64
	// SmoothingFactor contains the weight of the exponential moving average that estimates the time taken by the handler.
	// Will use DefaultGeneratorSmoothingFactor if 0.
	SmoothingFactor float64
	// SleepPrecision contains the minimal duration that will trigger a wait after each request.
	// Will use DefaultGeneratorSleepPrecision if 0.
	SleepPrecision time.Duration
	// SamplingPeriod contains the approximate duration over which the QPS is sampled.
	// Will use DefaultGeneratorSamplingPeriod if 0.
	SamplingPeriod time.Duration
}

// Start begins calling the handler at the requested frequency.
func (generator *Generator) Start() {
	if generator.Handler == nil {
		log.Panic("generator requires an handler")
	}

	go generator.run()
}

func (generator *Generator) evaluate(r float64) (b int, n int, w float64) {
	sampling := generator.SamplingPeriod
	if sampling == 0 {
		sampling = DefaultGeneratorSamplingPeriod
	}

	s := sampling.Seconds()

	// sampling period S=(R+W)*N
	// with maximum QPS per B is Q=1/R and B = QPS/Q
	// thus, because QPS=B/(R+W)
	// we end up with both W=B/QPS-R and N=S/(R+W)

	qps := generator.QPS
	if r > 0 {
		b = int(math.Ceil(qps * r))
	} else {
		b = 1
	}

	w = float64(b)/qps - r
	n = int(math.Ceil(s / (r + w)))
	return
}

func (generator *Generator) run() {
	precision := generator.SleepPrecision
	if precision == 0 {
		precision = DefaultGeneratorSleepPrecision
	}

	type batch struct {
		requests int
		duration time.Duration
		passback interface{}
	}

	results := make(chan batch)

	pool := sync.Pool{
		New: func() interface{} {
			batches := make(chan batch)

			// starts a batch that executes tasks and waits N times
			go func() {
				for item := range batches {
					t0 := time.Now()
					dt := time.Duration(0)

					for i := 0; i != item.requests; i++ {
						generator.Handler.Do()
						if dt += item.duration; dt >= precision {
							time.Sleep(dt)
							dt = 0
						}
					}

					time.Sleep(dt)
					item.duration = time.Since(t0)
					results <- item
				}
			}()

			return batches
		},
	}

	// perform a quick approximation with a first batch of 1 request
	queue := pool.Get().(chan batch)
	queue <- batch{
		requests: 1,
		duration: 0,
		passback: queue,
	}

	first := <-results
	pool.Put(first.passback)

	// set initial values
	r := first.duration.Seconds()
	batches, n, w := generator.evaluate(r)
	working := 0

	ticks := time.NewTicker(time.Second)
	count := 0
	total := batch{}

	smoothing := generator.SmoothingFactor
	if smoothing == 0 {
		smoothing = DefaultGeneratorSmoothingFactor
	}

	for {
		// start as many concurrent batches as it is required
		for working < batches {
			working++
			queue := pool.Get().(chan batch)
			queue <- batch{
				requests: n,
				duration: time.Duration(1e9*w) * time.Nanosecond,
				passback: queue,
			}
		}

		select {
		case item := <-results:
			count++
			total.requests += item.requests
			total.duration += item.duration

			working--
			pool.Put(item.passback)

		case <-ticks.C:
			if count == 0 {
				break
			}

			m := smoothing
			r = m*r + (1.0-m)*(total.duration.Seconds()/float64(total.requests)-w)
			batches, n, w = generator.evaluate(r)

			count = 0
			total.requests = 0
			total.duration = 0
		}
	}
}
<|endoftext|>


<commit_before>package goinsta

import (
	"crypto/hmac"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"net/url"
	"strings"
)

const (
	volatileSeed = "12345"
)

func generateMD5Hash(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

func generateHMAC(text []byte, key string) string {
	hasher := hmac.New(sha256.New, []byte(key))
	hasher.Write(text)
	return hex.EncodeToString(hasher.Sum(nil))
}

func generateDeviceID(seed string) string {
	hash := generateMD5Hash(seed + volatileSeed)
	return "android-" + hash[:16]
}

func generateUUID(replace bool) string {
	uuid := make([]byte, 16)
	io.ReadFull(rand.Reader, uuid)
	uuid[8] = uuid[8]&^0xc0 | 0x80
	uuid[6] = uuid[6]&^0xf0 | 0x40

	tUUID := fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])

	if replace {
		return strings.Replace(tUUID, "-", "", -1)
	}
	return tUUID
}

func generateSignature(data []byte) map[string]string {
	data := make(map[string]string)
	data["ig_sig_key_version"] = goInstaSigKeyVersion
	data["signed_body"] = fmt.Sprintf(
		"%s.%s", generateHMAC(data, goInstaIGSigKey), url.QueryEscape(b2s(data)),
	)
}
<commit_msg>fixed errors<commit_after>package goinsta

import (
	"crypto/hmac"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"net/url"
	"strings"
)

const (
	volatileSeed = "12345"
)

func generateMD5Hash(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

func generateHMAC(text []byte, key string) string {
	hasher := hmac.New(sha256.New, []byte(key))
	hasher.Write(text)
	return hex.EncodeToString(hasher.Sum(nil))
}

func generateDeviceID(seed string) string {
	hash := generateMD5Hash(seed + volatileSeed)
	return "android-" + hash[:16]
}

func generateUUID(replace bool) string {
	uuid := make([]byte, 16)
	io.ReadFull(rand.Reader, uuid)
	uuid[8] = uuid[8]&^0xc0 | 0x80
	uuid[6] = uuid[6]&^0xf0 | 0x40

	tUUID := fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])

	if replace {
		return strings.Replace(tUUID, "-", "", -1)
	}
	return tUUID
}

func generateSignature(data []byte) map[string]string {
	m := make(map[string]string)
	m["ig_sig_key_version"] = goInstaSigKeyVersion
	m["signed_body"] = fmt.Sprintf(
		"%s.%s", generateHMAC(data, goInstaIGSigKey), url.QueryEscape(b2s(data)),
	)
	return m
}
<|endoftext|>


<commit_before><commit_msg>Cleanup s390x exclude test list with build-gcs tests<commit_after><|endoftext|>


<commit_before><commit_msg>add package in helper<commit_after>package main<|endoftext|>