<commit_before>package air

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

// Response represents the current HTTP response.
//
// It's embedded with the `http.ResponseWriter`, the `http.Hijacker`, the `http.CloseNotifier`,
// the `http.Flusher` and the `http.Pusher`.
type Response struct {
	http.ResponseWriter
	http.Hijacker
	http.CloseNotifier
	http.Flusher
	http.Pusher

	context *Context

	StatusCode int
	Size       int
	Written    bool
	Data       Map
}

// NewResponse returns a pointer of a new instance of the `Response`.
func NewResponse(c *Context) *Response {
	return &Response{
		context:    c,
		StatusCode: http.StatusOK,
		Data:       make(Map),
	}
}

// Write implements the `http.ResponseWriter#Write()`.
func (r *Response) Write(b []byte) (int, error) {
	if !r.Written {
		r.WriteHeader(r.StatusCode)
	}
	n, err := r.ResponseWriter.Write(b)
	r.Size += n
	return n, err
}

// WriteHeader implements the `http.ResponseWriter#WriteHeader()`.
func (r *Response) WriteHeader(statusCode int) {
	if r.Written {
		r.context.Air.Logger.Warn("response already written")
		return
	}
	r.ResponseWriter.WriteHeader(statusCode)
	r.StatusCode = statusCode
	r.Written = true
}

// SetCookie adds a "Set-Cookie" header in the r. The provided cookie must have a valid `Name`.
// Invalid cookies may be silently dropped.
func (r *Response) SetCookie(cookie *http.Cookie) {
	http.SetCookie(r, cookie)
}

// Render renders one or more HTML templates with the `Data` of the r and sends a "text/html" HTTP
// response. The default `Renderer` does it by using the `template.Template`. the rults rendered by
// the former can be inherited by accessing the `Data["InheritedHTML"]` of the r.
func (r *Response) Render(templates ...string) error {
	buf := &bytes.Buffer{}
	for _, t := range templates {
		r.Data["InheritedHTML"] = template.HTML(buf.Bytes())
		buf.Reset()
		if err := r.context.Air.Renderer.Render(buf, t, r.Data); err != nil {
			return err
		}
	}
	return r.Blob(MIMETextHTML+CharsetUTF8, buf.Bytes())
}

// HTML sends a "text/html" HTTP response with the html.
func (r *Response) HTML(html string) error {
	return r.Blob(MIMETextHTML+CharsetUTF8, []byte(html))
}

// String sends a "text/plain" HTTP response with the s.
func (r *Response) String(s string) error {
	return r.Blob(MIMETextPlain+CharsetUTF8, []byte(s))
}

// JSON sends an "application/json" HTTP response with the type i.
func (r *Response) JSON(i interface{}) error {
	b, err := json.Marshal(i)
	if r.context.Air.Config.DebugMode {
		b, err = json.MarshalIndent(i, "", "\t")
	}
	if err != nil {
		return err
	}
	return r.Blob(MIMEApplicationJSON+CharsetUTF8, b)
}

// JSONP sends an "application/javascript" HTTP response with the type i. It uses the callback to
// construct the JSONP payload.
func (r *Response) JSONP(i interface{}, callback string) error {
	b, err := json.Marshal(i)
	if err != nil {
		return err
	}
	b = append([]byte(callback+"("), b...)
	b = append(b, []byte(");")...)
	return r.Blob(MIMEApplicationJavaScript+CharsetUTF8, b)
}

// XML sends an "application/xml" HTTP response with the type i.
func (r *Response) XML(i interface{}) error {
	b, err := xml.Marshal(i)
	if r.context.Air.Config.DebugMode {
		b, err = xml.MarshalIndent(i, "", "\t")
	}
	if err != nil {
		return err
	}
	return r.Blob(MIMEApplicationXML+CharsetUTF8, append([]byte(xml.Header), b...))
}

// Blob sends a blob HTTP response with the contentType and the b.
func (r *Response) Blob(contentType string, b []byte) error {
	r.Header().Set(HeaderContentType, contentType)
	_, err := r.Write(b)
	return err
}

// Stream sends a streaming HTTP response with the contentType and the reader.
func (r *Response) Stream(contentType string, reader io.Reader) error {
	r.Header().Set(HeaderContentType, contentType)
	_, err := io.Copy(r, reader)
	return err
}

// File sends a file HTTP response with the file.
func (r *Response) File(file string) error {
	if fi, err := os.Stat(file); os.IsNotExist(err) {
		return ErrNotFound
	} else if fi.IsDir() {
		file = filepath.Join("index.html")
		if _, err := os.Stat(file); os.IsNotExist(err) {
			return ErrNotFound
		}
	}

	abs, err := filepath.Abs(file)
	if err != nil {
		return err
	}

	if a := r.context.Air.Coffer.Asset(abs); a != nil {
		http.ServeContent(r, r.context.Request.Request, a.Name(), a.ModTime(), a)
	} else {
		f, err := os.Open(abs)
		if err != nil {
			return err
		}
		defer f.Close()

		fi, err := f.Stat()
		if err != nil {
			return err
		}

		http.ServeContent(r, r.context.Request.Request, fi.Name(), fi.ModTime(), f)
	}

	return nil
}

// Attachment sends an HTTP response with the file and the filename as attachment, prompting client
// to save the file.
func (r *Response) Attachment(file, filename string) error {
	return r.contentDisposition("attachment", file, filename)
}

// Inline sends an HTTP response with the file and the filename as inline, opening the file in the
// browser.
func (r *Response) Inline(file, filename string) error {
	return r.contentDisposition("inline", file, filename)
}

// contentDisposition sends an HTTP response with the file and the filename as the dispositionType.
func (r *Response) contentDisposition(dispositionType, file, filename string) error {
	r.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%s",
		dispositionType, filename))
	return r.File(file)
}

// NoContent sends an HTTP response with no body.
func (r *Response) NoContent() error { return nil }

// Redirect redirects the current HTTP request to the url with the statusCode.
func (r *Response) Redirect(statusCode int, url string) error {
	if statusCode < http.StatusMultipleChoices || statusCode > http.StatusTemporaryRedirect {
		return ErrInvalidRedirectCode
	}
	r.Header().Set(HeaderLocation, url)
	r.WriteHeader(statusCode)
	return nil
}

// feed feeds the rw into where it should be.
func (r *Response) feed(rw http.ResponseWriter) {
	r.ResponseWriter = rw
	r.Hijacker, _ = rw.(http.Hijacker)
	r.CloseNotifier, _ = rw.(http.CloseNotifier)
	r.Flusher, _ = rw.(http.Flusher)
	r.Pusher, _ = rw.(http.Pusher)
}

// reset resets all fields in the r.
func (r *Response) reset() {
	r.ResponseWriter = nil
	r.StatusCode = http.StatusOK
	r.Size = 0
	r.Written = false
	for k := range r.Data {
		delete(r.Data, k)
	}
}
<commit_msg>fix: `Response#File()` cannot handle directory properly<commit_after>package air

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

// Response represents the current HTTP response.
//
// It's embedded with the `http.ResponseWriter`, the `http.Hijacker`, the `http.CloseNotifier`,
// the `http.Flusher` and the `http.Pusher`.
type Response struct {
	http.ResponseWriter
	http.Hijacker
	http.CloseNotifier
	http.Flusher
	http.Pusher

	context *Context

	StatusCode int
	Size       int
	Written    bool
	Data       Map
}

// NewResponse returns a pointer of a new instance of the `Response`.
func NewResponse(c *Context) *Response {
	return &Response{
		context:    c,
		StatusCode: http.StatusOK,
		Data:       make(Map),
	}
}

// Write implements the `http.ResponseWriter#Write()`.
func (r *Response) Write(b []byte) (int, error) {
	if !r.Written {
		r.WriteHeader(r.StatusCode)
	}
	n, err := r.ResponseWriter.Write(b)
	r.Size += n
	return n, err
}

// WriteHeader implements the `http.ResponseWriter#WriteHeader()`.
func (r *Response) WriteHeader(statusCode int) {
	if r.Written {
		r.context.Air.Logger.Warn("response already written")
		return
	}
	r.ResponseWriter.WriteHeader(statusCode)
	r.StatusCode = statusCode
	r.Written = true
}

// SetCookie adds a "Set-Cookie" header in the r. The provided cookie must have a valid `Name`.
// Invalid cookies may be silently dropped.
func (r *Response) SetCookie(cookie *http.Cookie) {
	http.SetCookie(r, cookie)
}

// Render renders one or more HTML templates with the `Data` of the r and sends a "text/html" HTTP
// response. The default `Renderer` does it by using the `template.Template`. the rults rendered by
// the former can be inherited by accessing the `Data["InheritedHTML"]` of the r.
func (r *Response) Render(templates ...string) error {
	buf := &bytes.Buffer{}
	for _, t := range templates {
		r.Data["InheritedHTML"] = template.HTML(buf.Bytes())
		buf.Reset()
		if err := r.context.Air.Renderer.Render(buf, t, r.Data); err != nil {
			return err
		}
	}
	return r.Blob(MIMETextHTML+CharsetUTF8, buf.Bytes())
}

// HTML sends a "text/html" HTTP response with the html.
func (r *Response) HTML(html string) error {
	return r.Blob(MIMETextHTML+CharsetUTF8, []byte(html))
}

// String sends a "text/plain" HTTP response with the s.
func (r *Response) String(s string) error {
	return r.Blob(MIMETextPlain+CharsetUTF8, []byte(s))
}

// JSON sends an "application/json" HTTP response with the type i.
func (r *Response) JSON(i interface{}) error {
	b, err := json.Marshal(i)
	if r.context.Air.Config.DebugMode {
		b, err = json.MarshalIndent(i, "", "\t")
	}
	if err != nil {
		return err
	}
	return r.Blob(MIMEApplicationJSON+CharsetUTF8, b)
}

// JSONP sends an "application/javascript" HTTP response with the type i. It uses the callback to
// construct the JSONP payload.
func (r *Response) JSONP(i interface{}, callback string) error {
	b, err := json.Marshal(i)
	if err != nil {
		return err
	}
	b = append([]byte(callback+"("), b...)
	b = append(b, []byte(");")...)
	return r.Blob(MIMEApplicationJavaScript+CharsetUTF8, b)
}

// XML sends an "application/xml" HTTP response with the type i.
func (r *Response) XML(i interface{}) error {
	b, err := xml.Marshal(i)
	if r.context.Air.Config.DebugMode {
		b, err = xml.MarshalIndent(i, "", "\t")
	}
	if err != nil {
		return err
	}
	return r.Blob(MIMEApplicationXML+CharsetUTF8, append([]byte(xml.Header), b...))
}

// Blob sends a blob HTTP response with the contentType and the b.
func (r *Response) Blob(contentType string, b []byte) error {
	r.Header().Set(HeaderContentType, contentType)
	_, err := r.Write(b)
	return err
}

// Stream sends a streaming HTTP response with the contentType and the reader.
func (r *Response) Stream(contentType string, reader io.Reader) error {
	r.Header().Set(HeaderContentType, contentType)
	_, err := io.Copy(r, reader)
	return err
}

// File sends a file HTTP response with the file.
func (r *Response) File(file string) error {
	if fi, err := os.Stat(file); os.IsNotExist(err) {
		return ErrNotFound
	} else if fi.IsDir() {
		file = filepath.Join(file, "index.html")
		if _, err := os.Stat(file); os.IsNotExist(err) {
			return ErrNotFound
		}
	}

	abs, err := filepath.Abs(file)
	if err != nil {
		return err
	}

	if a := r.context.Air.Coffer.Asset(abs); a != nil {
		http.ServeContent(r, r.context.Request.Request, a.Name(), a.ModTime(), a)
	} else {
		f, err := os.Open(abs)
		if err != nil {
			return err
		}
		defer f.Close()

		fi, err := f.Stat()
		if err != nil {
			return err
		}

		http.ServeContent(r, r.context.Request.Request, fi.Name(), fi.ModTime(), f)
	}

	return nil
}

// Attachment sends an HTTP response with the file and the filename as attachment, prompting client
// to save the file.
func (r *Response) Attachment(file, filename string) error {
	return r.contentDisposition("attachment", file, filename)
}

// Inline sends an HTTP response with the file and the filename as inline, opening the file in the
// browser.
func (r *Response) Inline(file, filename string) error {
	return r.contentDisposition("inline", file, filename)
}

// contentDisposition sends an HTTP response with the file and the filename as the dispositionType.
func (r *Response) contentDisposition(dispositionType, file, filename string) error {
	r.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%s",
		dispositionType, filename))
	return r.File(file)
}

// NoContent sends an HTTP response with no body.
func (r *Response) NoContent() error { return nil }

// Redirect redirects the current HTTP request to the url with the statusCode.
func (r *Response) Redirect(statusCode int, url string) error {
	if statusCode < http.StatusMultipleChoices || statusCode > http.StatusTemporaryRedirect {
		return ErrInvalidRedirectCode
	}
	r.Header().Set(HeaderLocation, url)
	r.WriteHeader(statusCode)
	return nil
}

// feed feeds the rw into where it should be.
func (r *Response) feed(rw http.ResponseWriter) {
	r.ResponseWriter = rw
	r.Hijacker, _ = rw.(http.Hijacker)
	r.CloseNotifier, _ = rw.(http.CloseNotifier)
	r.Flusher, _ = rw.(http.Flusher)
	r.Pusher, _ = rw.(http.Pusher)
}

// reset resets all fields in the r.
func (r *Response) reset() {
	r.ResponseWriter = nil
	r.StatusCode = http.StatusOK
	r.Size = 0
	r.Written = false
	for k := range r.Data {
		delete(r.Data, k)
	}
}
<|endoftext|>


<commit_before>/* Copyright (c) 2017 Jason Ish
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package useragent

import (
	"github.com/jasonish/evebox/eve"
	"github.com/ua-parser/uap-go/uaparser"
)

var parser *uaparser.Parser

func init() {
	parser = uaparser.NewFromSaved()
}

type EveUserAgentFilter struct{}

func (f *EveUserAgentFilter) setValue(ua map[string]string, name string, value string) {
	switch value {
	case "":
		return
	case "Other":
		return
	default:
		ua[name] = value
	}
}

func (f *EveUserAgentFilter) Filter(event eve.RawEveEvent) {
	if event.EventType() != "http" {
		return
	}

	httpUserAgent := event.GetMap("http").GetString("http_user_agent")
	if httpUserAgent == "" {
		return
	}

	parsed := parser.Parse(event.GetMap("http").GetString("http_user_agent"))

	ua := map[string]string{}

	f.setValue(ua, "name", parsed.UserAgent.Family)
	f.setValue(ua, "major", parsed.UserAgent.Major)
	f.setValue(ua, "minor", parsed.UserAgent.Minor)
	f.setValue(ua, "patch", parsed.UserAgent.Patch)

	f.setValue(ua, "os", parsed.Os.ToString())
	f.setValue(ua, "os_name", parsed.Os.Family)
	f.setValue(ua, "os_major", parsed.Os.Major)
	f.setValue(ua, "os_minor", parsed.Os.Minor)

	f.setValue(ua, "device", parsed.Device.ToString())

	if len(ua) > 0 {
		event.GetMap("http")["user_agent"] = ua
	}
}
<commit_msg>useragent filter: cache lookups<commit_after>/* Copyright (c) 2017 Jason Ish
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package useragent

import (
	"github.com/jasonish/evebox/eve"
	"github.com/jasonish/evebox/log"
	"github.com/ua-parser/uap-go/uaparser"
)

var parser *uaparser.Parser

func init() {
	parser = uaparser.NewFromSaved()
}

type EveUserAgentFilter struct {
	cache map[string]map[string]string
}

func (f *EveUserAgentFilter) setValue(ua map[string]string, name string, value string) {
	switch value {
	case "":
		return
	case "Other":
		return
	default:
		ua[name] = value
	}
}

func (f *EveUserAgentFilter) Filter(event eve.RawEveEvent) {
	if event.EventType() != "http" {
		return
	}

	httpUserAgent := event.GetMap("http").GetString("http_user_agent")
	if httpUserAgent == "" {
		return
	}

	var ua map[string]string

	ua = f.cache[httpUserAgent]
	if ua != nil {
		log.Println("using cached user agent")
		if len(ua) > 0 {
			event.GetMap("http")["user_agent"] = ua
		}
	}

	parsed := parser.Parse(event.GetMap("http").GetString("http_user_agent"))

	ua = map[string]string{}

	f.setValue(ua, "name", parsed.UserAgent.Family)
	f.setValue(ua, "major", parsed.UserAgent.Major)
	f.setValue(ua, "minor", parsed.UserAgent.Minor)
	f.setValue(ua, "patch", parsed.UserAgent.Patch)

	f.setValue(ua, "os", parsed.Os.ToString())
	f.setValue(ua, "os_name", parsed.Os.Family)
	f.setValue(ua, "os_major", parsed.Os.Major)
	f.setValue(ua, "os_minor", parsed.Os.Minor)

	f.setValue(ua, "device", parsed.Device.ToString())

	if len(ua) > 0 {
		event.GetMap("http")["user_agent"] = ua
	}
	if f.cache == nil {
		f.cache = map[string]map[string]string{}
	}
	f.cache[httpUserAgent] = ua
}
<|endoftext|>


<commit_before>package weather

import (
	"fmt"
	"github.com/0x263b/Porygon2"
	"github.com/0x263b/Porygon2/web"
	"time"
)

func forecast(command *bot.Cmd, matches []string) (msg string, err error) {

	var location string = matches[1]
	var coords string

	if location == "" {
		location, coords = checkLocation(command.Nick)
		if coords == "" {
			return "Location not provided, nor on file. Use `-set location <location>` to save", nil
		}
	} else {
		coords = getCoords(location)
		if coords == "" {
			return fmt.Sprintf("Could not find %s", location), nil
		}
	}

	data := &Forecast{}
	err = web.GetJSON(fmt.Sprintf(DarkSkyURL, bot.Config.API.Weather, coords), data)
	if err != nil {
		return fmt.Sprintf("Could not get weather for: %s", location), nil
	}

	units := "°C"
	if data.Flags.Units == "us" {
		units = "°F"
	}

	output := fmt.Sprintf("Forecast | %s ", location)

	for i := range data.Daily.Data[0:4] {
		tm := time.Unix(data.Daily.Data[i].Time, 0)
		day := tm.Weekday()
		output += fmt.Sprintf("| %s: %s %v%s/%v%s ",
			day,
			Emoji(data.Daily.Data[i].Icon),
			Round(data.Daily.Data[i].TemperatureMax),
			units,
			Round(data.Daily.Data[i].TemperatureMin),
			units,
		)
	}

	return output, nil
}

func init() {
	bot.RegisterCommand(
		"^f(?:o(?:recast)?)?(?: (.+))?$",
		forecast)
}
<commit_msg>Local time<commit_after>package weather

import (
	"fmt"
	"github.com/0x263b/Porygon2"
	"github.com/0x263b/Porygon2/web"
	"time"
)

func forecast(command *bot.Cmd, matches []string) (msg string, err error) {

	var location string = matches[1]
	var coords string

	if location == "" {
		location, coords = checkLocation(command.Nick)
		if coords == "" {
			return "Location not provided, nor on file. Use `-set location <location>` to save", nil
		}
	} else {
		coords = getCoords(location)
		if coords == "" {
			return fmt.Sprintf("Could not find %s", location), nil
		}
	}

	data := &Forecast{}
	err = web.GetJSON(fmt.Sprintf(DarkSkyURL, bot.Config.API.Weather, coords), data)
	if err != nil {
		return fmt.Sprintf("Could not get weather for: %s", location), nil
	}

	units := "°C"
	if data.Flags.Units == "us" {
		units = "°F"
	}

	output := fmt.Sprintf("Forecast | %s ", location)

	for i := range data.Daily.Data[0:4] {
		tm := time.Unix(data.Daily.Data[i].Time, 0)
		loc, _ := time.LoadLocation(data.Timezone)
		day := tm.In(loc).Weekday()
		output += fmt.Sprintf("| %s: %s %v%s/%v%s ",
			day,
			Emoji(data.Daily.Data[i].Icon),
			Round(data.Daily.Data[i].TemperatureMax),
			units,
			Round(data.Daily.Data[i].TemperatureMin),
			units,
		)
	}

	return output, nil
}

func init() {
	bot.RegisterCommand(
		"^f(?:o(?:recast)?)?(?: (.+))?$",
		forecast)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"math"
	"math/rand"
	"reflect"
	"strconv"
	"testing/quick"
)

type Block struct {
	Miner      *Device
	Votes      *Votes
	Counter    int32
	Nonce      int64
	Difficulty int32
	Previous   *Block
	hash       []byte
}

func (b *Block) Generate(r *rand.Rand, size int) reflect.Value {
	miner, _ := quick.Value(reflect.TypeOf(&Device{}), r)
	votes, _ := quick.Value(reflect.TypeOf(&Votes{}), r)
	counter, _ := quick.Value(reflect.TypeOf(int32(0)), r)
	nonce, _ := quick.Value(reflect.TypeOf(int64(0)), r)
	difficulty, _ := quick.Value(reflect.TypeOf(int32(0)), r)

	b = &Block{}
	reflect.ValueOf(&b.Miner).Elem().Set(miner)
	reflect.ValueOf(&b.Votes).Elem().Set(votes)
	reflect.ValueOf(&b.Counter).Elem().Set(counter)
	reflect.ValueOf(&b.Nonce).Elem().Set(nonce)
	reflect.ValueOf(&b.Difficulty).Elem().Set(difficulty)

	// we leave the Previous block as nil, so tests will run
	// faster

	return reflect.ValueOf(b)

}

func (b *Block) ComputeHash() []byte {
	if b == nil {
		return nil
	}

	if b.hash != nil {
		return b.hash
	}

	var totalshasum bytes.Buffer
	totalshasum.Write(b.Miner.ComputeHash())
	totalshasum.Write(b.Votes.ComputeHash())
	totalshasum.Write([]byte(strconv.Itoa(int(b.Nonce))))
	totalshasum.Write([]byte(strconv.Itoa(int(b.Counter))))
	totalshasum.Write(b.Previous.ComputeHash())

	return DoubleSha256(totalshasum.Bytes())
}

func (b *Block) Mine() error {
	var i int64
	for ; i <= math.MaxInt32; i++ {
		b.hash = nil
		b.Nonce = i
		if b.Valid() {
			return nil
		}
	}

	return errors.New("Couldn't find valid block")
}

func (b *Block) Valid() bool {
	for i, byte := range b.ComputeHash() {
		if int32(i) > b.Difficulty {
			return true
		} else if byte != 0 {
			return false
		}
	}
	return false
}
<commit_msg>cache the hash to Block.Hash attr<commit_after>package main

import (
	"bytes"
	"errors"
	"math"
	"math/rand"
	"reflect"
	"strconv"
	"testing/quick"
)

type Block struct {
	Miner      *Device
	Votes      *Votes
	Counter    int32
	Nonce      int64
	Difficulty int32
	Previous   *Block
	Hash       []byte
}

func (b *Block) Generate(r *rand.Rand, size int) reflect.Value {
	miner, _ := quick.Value(reflect.TypeOf(&Device{}), r)
	votes, _ := quick.Value(reflect.TypeOf(&Votes{}), r)
	counter, _ := quick.Value(reflect.TypeOf(int32(0)), r)
	nonce, _ := quick.Value(reflect.TypeOf(int64(0)), r)
	difficulty, _ := quick.Value(reflect.TypeOf(int32(0)), r)

	b = &Block{}
	reflect.ValueOf(&b.Miner).Elem().Set(miner)
	reflect.ValueOf(&b.Votes).Elem().Set(votes)
	reflect.ValueOf(&b.Counter).Elem().Set(counter)
	reflect.ValueOf(&b.Nonce).Elem().Set(nonce)
	reflect.ValueOf(&b.Difficulty).Elem().Set(difficulty)

	// we leave the Previous block as nil, so tests will run
	// faster

	return reflect.ValueOf(b)

}

func (b *Block) ComputeHash() []byte {
	if b == nil {
		return nil
	}

	var totalshasum bytes.Buffer
	totalshasum.Write(b.Miner.ComputeHash())
	totalshasum.Write(b.Votes.ComputeHash())
	totalshasum.Write([]byte(strconv.Itoa(int(b.Nonce))))
	totalshasum.Write([]byte(strconv.Itoa(int(b.Counter))))
	totalshasum.Write(b.Previous.ComputeHash())

	b.Hash = DoubleSha256(totalshasum.Bytes())
	return b.Hash
}

func (b *Block) Mine() error {
	var i int64
	for ; i <= math.MaxInt32; i++ {
		b.Hash = nil
		b.Nonce = i
		if b.Valid() {
			return nil
		}
	}

	return errors.New("Couldn't find valid block")
}

func (b *Block) Valid() bool {
	for i, byte := range b.ComputeHash() {
		if int32(i) > b.Difficulty {
			return true
		} else if byte != 0 {
			return false
		}
	}
	return false
}
<|endoftext|>


<commit_before>package sdk

/*
   Copyright 2016 Alexander I.Grafov <grafov@gmail.com>

   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.

   ॐ तारे तुत्तारे तुरे स्व
*/

import (
	"bytes"
	"encoding/json"
	"strings"

	"github.com/gosimple/slug"
)

var (
	boardID uint
)

// Constants for templating
const (
	TemplatingHideNone = iota
	TemplatingHideLabel
	TemplatingHideVariable
)

type (
	// Board represents Grafana dashboard.
	Board struct {
		ID              uint       `json:"id,omitempty"`
		Slug            string     `json:"slug"`
		Title           string     `json:"title"`
		OriginalTitle   string     `json:"originalTitle"`
		Tags            []string   `json:"tags"`
		Style           string     `json:"style"`
		Timezone        string     `json:"timezone"`
		Editable        bool       `json:"editable"`
		HideControls    bool       `json:"hideControls" graf:"hide-controls"`
		SharedCrosshair bool       `json:"sharedCrosshair" graf:"shared-crosshair"`
		Rows            []*Row     `json:"rows"`
		Templating      Templating `json:"templating"`
		Annotations     struct {
			List []Annotation `json:"list"`
		} `json:"annotations"`
		Refresh       *BoolString `json:"refresh,omitempty"`
		SchemaVersion uint        `json:"schemaVersion"`
		Version       uint        `json:"version"`
		Links         []link      `json:"links"`
		Time          Time        `json:"time"`
		Timepicker    Timepicker  `json:"timepicker"`
		lastPanelID   uint
		GraphTooltip  int `json:"graphTooltip,omitempty"`
	}
	Time struct {
		From string `json:"from"`
		To   string `json:"to"`
	}
	Timepicker struct {
		Now              *bool    `json:"now,omitempty"`
		RefreshIntervals []string `json:"refresh_intervals"`
		TimeOptions      []string `json:"time_options"`
	}
	Templating struct {
		List []TemplateVar `json:"list"`
	}
	TemplateVar struct {
		Name        string   `json:"name"`
		Type        string   `json:"type"`
		Auto        bool     `json:"auto,omitempty"`
		AutoCount   *int     `json:"auto_count,omitempty"`
		Datasource  *string  `json:"datasource"`
		Refresh     BoolInt  `json:"refresh"`
		Options     []Option `json:"options"`
		IncludeAll  bool     `json:"includeAll"`
		AllFormat   string   `json:"allFormat"`
		Multi       bool     `json:"multi"`
		MultiFormat string   `json:"multiFormat"`
		Query       string   `json:"query"`
		Regex       string   `json:"regex"`
		Current     Current  `json:"current"`
		Label       string   `json:"label"`
		Hide        uint8    `json:"hide"`
		Sort        int      `json:"sort"`
	}
	// for templateVar
	Option struct {
		Text     string `json:"text"`
		Value    string `json:"value"`
		Selected bool   `json:"selected"`
	}
	// for templateVar
	Current struct {
		Tags  []*string   `json:"tags,omitempty"`
		Text  string      `json:"text"`
		Value interface{} `json:"value"` // TODO select more precise type
	}
	Annotation struct {
		Name       string  `json:"name"`
		Datasource *string `json:"datasource"`
		ShowLine   bool    `json:"showLine"`
		IconColor  string  `json:"iconColor"`
		LineColor  string  `json:"lineColor"`
		IconSize   uint    `json:"iconSize"`
		Enable     bool    `json:"enable"`
		Query      string  `json:"query"`
		TextField  string  `json:"textField"`
	}
)

// link represents link to another dashboard or external weblink
type link struct {
	Title       string   `json:"title"`
	Type        string   `json:"type"`
	AsDropdown  *bool    `json:"asDropdown,omitempty"`
	DashURI     *string  `json:"dashUri,omitempty"`
	Dashboard   *string  `json:"dashboard,omitempty"`
	Icon        *string  `json:"icon,omitempty"`
	IncludeVars bool     `json:"includeVars"`
	KeepTime    *bool    `json:"keepTime,omitempty"`
	Params      *string  `json:"params,omitempty"`
	Tags        []string `json:"tags,omitempty"`
	TargetBlank *bool    `json:"targetBlank,omitempty"`
	Tooltip     *string  `json:"tooltip,omitempty"`
	URL         *string  `json:"url,omitempty"`
}

// Height of rows maybe passed as number (ex 200) or
// as string (ex "200px") or empty string
type Height string

func (h *Height) UnmarshalJSON(raw []byte) error {
	if raw == nil || bytes.Compare(raw, []byte(`"null"`)) == 0 {
		return nil
	}
	if raw[0] != '"' {
		tmp := []byte{'"'}
		raw = append(tmp, raw...)
		raw = append(raw, byte('"'))
	}
	var tmp string
	err := json.Unmarshal(raw, &tmp)
	*h = Height(tmp)
	return err
}

func NewBoard(title string) *Board {
	boardID++
	return &Board{
		ID:           boardID,
		Title:        title,
		Style:        "dark",
		Timezone:     "browser",
		Editable:     true,
		HideControls: false,
		Rows:         []*Row{}}
}

func (b *Board) RemoveTags(tags ...string) {
	tagFound := make(map[string]int, len(b.Tags))
	for i, tag := range b.Tags {
		tagFound[tag] = i
	}
	for _, removeTag := range tags {
		if i, ok := tagFound[removeTag]; ok {
			b.Tags = append(b.Tags[:i], b.Tags[i+1:]...)
		}
	}
}

func (b *Board) AddTags(tags ...string) {
	tagFound := make(map[string]bool, len(b.Tags))
	for _, tag := range b.Tags {
		tagFound[tag] = true
	}
	for _, tag := range tags {
		if tagFound[tag] {
			continue
		}
		b.Tags = append(b.Tags, tag)
	}
}

func (b *Board) HasTag(tag string) bool {
	for _, t := range b.Tags {
		if t == tag {
			return true
		}
	}
	return false
}

func (b *Board) AddRow(title string) *Row {
	if title == "" {
		title = "New row"
	}
	row := &Row{
		Title:    title,
		Collapse: false,
		Editable: true,
		Height:   "250px",
	}
	b.Rows = append(b.Rows, row)
	return row
}

func (b *Board) UpdateSlug() string {
	b.Slug = strings.ToLower(slug.Make(b.Title))
	return b.Slug
}
<commit_msg>UID and AllValue fields for generated JSON (#16)<commit_after>package sdk

/*
   Copyright 2016 Alexander I.Grafov <grafov@gmail.com>

   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.

   ॐ तारे तुत्तारे तुरे स्व
*/

import (
	"bytes"
	"encoding/json"
	"strings"

	"github.com/gosimple/slug"
)

var (
	boardID uint
)

// Constants for templating
const (
	TemplatingHideNone = iota
	TemplatingHideLabel
	TemplatingHideVariable
)

type (
	// Board represents Grafana dashboard.
	Board struct {
		ID              uint       `json:"id,omitempty"`
		UID             string     `json:"uid,omitempty"`
		Slug            string     `json:"slug"`
		Title           string     `json:"title"`
		OriginalTitle   string     `json:"originalTitle"`
		Tags            []string   `json:"tags"`
		Style           string     `json:"style"`
		Timezone        string     `json:"timezone"`
		Editable        bool       `json:"editable"`
		HideControls    bool       `json:"hideControls" graf:"hide-controls"`
		SharedCrosshair bool       `json:"sharedCrosshair" graf:"shared-crosshair"`
		Rows            []*Row     `json:"rows"`
		Templating      Templating `json:"templating"`
		Annotations     struct {
			List []Annotation `json:"list"`
		} `json:"annotations"`
		Refresh       *BoolString `json:"refresh,omitempty"`
		SchemaVersion uint        `json:"schemaVersion"`
		Version       uint        `json:"version"`
		Links         []link      `json:"links"`
		Time          Time        `json:"time"`
		Timepicker    Timepicker  `json:"timepicker"`
		lastPanelID   uint
		GraphTooltip  int `json:"graphTooltip,omitempty"`
	}
	Time struct {
		From string `json:"from"`
		To   string `json:"to"`
	}
	Timepicker struct {
		Now              *bool    `json:"now,omitempty"`
		RefreshIntervals []string `json:"refresh_intervals"`
		TimeOptions      []string `json:"time_options"`
	}
	Templating struct {
		List []TemplateVar `json:"list"`
	}
	TemplateVar struct {
		Name        string   `json:"name"`
		Type        string   `json:"type"`
		Auto        bool     `json:"auto,omitempty"`
		AutoCount   *int     `json:"auto_count,omitempty"`
		Datasource  *string  `json:"datasource"`
		Refresh     BoolInt  `json:"refresh"`
		Options     []Option `json:"options"`
		IncludeAll  bool     `json:"includeAll"`
		AllFormat   string   `json:"allFormat"`
		AllValue    string   `json:"allValue"`
		Multi       bool     `json:"multi"`
		MultiFormat string   `json:"multiFormat"`
		Query       string   `json:"query"`
		Regex       string   `json:"regex"`
		Current     Current  `json:"current"`
		Label       string   `json:"label"`
		Hide        uint8    `json:"hide"`
		Sort        int      `json:"sort"`
	}
	// for templateVar
	Option struct {
		Text     string `json:"text"`
		Value    string `json:"value"`
		Selected bool   `json:"selected"`
	}
	// for templateVar
	Current struct {
		Tags  []*string   `json:"tags,omitempty"`
		Text  string      `json:"text"`
		Value interface{} `json:"value"` // TODO select more precise type
	}
	Annotation struct {
		Name       string  `json:"name"`
		Datasource *string `json:"datasource"`
		ShowLine   bool    `json:"showLine"`
		IconColor  string  `json:"iconColor"`
		LineColor  string  `json:"lineColor"`
		IconSize   uint    `json:"iconSize"`
		Enable     bool    `json:"enable"`
		Query      string  `json:"query"`
		TextField  string  `json:"textField"`
	}
)

// link represents link to another dashboard or external weblink
type link struct {
	Title       string   `json:"title"`
	Type        string   `json:"type"`
	AsDropdown  *bool    `json:"asDropdown,omitempty"`
	DashURI     *string  `json:"dashUri,omitempty"`
	Dashboard   *string  `json:"dashboard,omitempty"`
	Icon        *string  `json:"icon,omitempty"`
	IncludeVars bool     `json:"includeVars"`
	KeepTime    *bool    `json:"keepTime,omitempty"`
	Params      *string  `json:"params,omitempty"`
	Tags        []string `json:"tags,omitempty"`
	TargetBlank *bool    `json:"targetBlank,omitempty"`
	Tooltip     *string  `json:"tooltip,omitempty"`
	URL         *string  `json:"url,omitempty"`
}

// Height of rows maybe passed as number (ex 200) or
// as string (ex "200px") or empty string
type Height string

func (h *Height) UnmarshalJSON(raw []byte) error {
	if raw == nil || bytes.Compare(raw, []byte(`"null"`)) == 0 {
		return nil
	}
	if raw[0] != '"' {
		tmp := []byte{'"'}
		raw = append(tmp, raw...)
		raw = append(raw, byte('"'))
	}
	var tmp string
	err := json.Unmarshal(raw, &tmp)
	*h = Height(tmp)
	return err
}

func NewBoard(title string) *Board {
	boardID++
	return &Board{
		ID:           boardID,
		Title:        title,
		Style:        "dark",
		Timezone:     "browser",
		Editable:     true,
		HideControls: false,
		Rows:         []*Row{}}
}

func (b *Board) RemoveTags(tags ...string) {
	tagFound := make(map[string]int, len(b.Tags))
	for i, tag := range b.Tags {
		tagFound[tag] = i
	}
	for _, removeTag := range tags {
		if i, ok := tagFound[removeTag]; ok {
			b.Tags = append(b.Tags[:i], b.Tags[i+1:]...)
		}
	}
}

func (b *Board) AddTags(tags ...string) {
	tagFound := make(map[string]bool, len(b.Tags))
	for _, tag := range b.Tags {
		tagFound[tag] = true
	}
	for _, tag := range tags {
		if tagFound[tag] {
			continue
		}
		b.Tags = append(b.Tags, tag)
	}
}

func (b *Board) HasTag(tag string) bool {
	for _, t := range b.Tags {
		if t == tag {
			return true
		}
	}
	return false
}

func (b *Board) AddRow(title string) *Row {
	if title == "" {
		title = "New row"
	}
	row := &Row{
		Title:    title,
		Collapse: false,
		Editable: true,
		Height:   "250px",
	}
	b.Rows = append(b.Rows, row)
	return row
}

func (b *Board) UpdateSlug() string {
	b.Slug = strings.ToLower(slug.Make(b.Title))
	return b.Slug
}
<|endoftext|>


<commit_before>package modelview

import (
	"errors"
	"github.com/gopns/gopns/model"
	"regexp"
)

type RegisterDeviceView struct {
	userAlias  string
	deviceType model.DeviceType
	token      string
	locale     string
	timezone   string
}

func NewRegisterDeviceView(userAlias string, dt model.DeviceType, token string, locale string, timezone string) *NewRegisterDeviceView {
	return &NewRegisterDeviceView{userAlias: userAlias, token: token, locale: locale, timezone: timezone}
}

func (dv RegisterDeviceView) UserAlias() string {
	return dv.userAlias
}

func (dv RegisterDeviceView) Locale() string {
	return dv.locale
}

func (dv RegisterDeviceView) DeviceType() model.DeviceType {
	return dv.deviceType
}

func (dv RegisterDeviceView) Token() string {
	return dv.token
}

func (dv RegisterDeviceView) Timezone() string {
	return dv.timezone
}

func (dv *RegisterDeviceView) SetUserAlias(id string) {
	dv.userAlias = id
}

func (dv *RegisterDeviceView) SetLocale(locale string) {
	dv.locale = locale
}

func (dv *RegisterDeviceView) SetTimezone(timezone string) {
	dv.timezone = timezone
}

func (dv *RegisterDeviceView) SetDeviceType(dt model.DeviceType) {
	dv.deviceType = dt
}

func (dv *RegisterDeviceView) SetToken(token string) {
	dv.token = token
}

func (dv *RegisterDeviceView) ToDevice() (*model.Device, error) {
	device := new(model.Device)
	device.SetUserAlias(dv.userAlias)
	device.setToken(dv.token)
	device.setTimezone(dv.timezone)
	if err := device.SetDeviceType(dv.deviceType); err != nil {
		return nil, err
	}
	if err := device.SetLocale(dv.locale); err != nil {
		return nil, err
	}

	return device, nil
}

type DeviceList struct {
	Devices []model.Device
	Cursor  string `json:",omitempty"`
}
<commit_msg>update device view models<commit_after>package modelview

import (
	"errors"
	"github.com/gopns/gopns/model"
	"regexp"
)

//Eventually they will diverge
type DeviceView model.Device

func ConvertToDeviceView(d model.Device) *DeviceView {
	return &DeviceView(d)
}

type DeviceRegisterView struct {
	userAlias  string
	deviceType model.DeviceType
	token      string
	locale     string
	timezone   string
}

func NewDeviceRegisterView(userAlias string, dt model.DeviceType, token string, locale string, timezone string) *NewRegisterDeviceView {
	return &NewDeviceRegisterView{userAlias: userAlias, token: token, locale: locale, timezone: timezone}
}

func (dv DeviceRegisterView) UserAlias() string {
	return dv.userAlias
}

func (dv DeviceRegisterView) Locale() string {
	return dv.locale
}

func (dv DeviceRegisterView) DeviceType() model.DeviceType {
	return dv.deviceType
}

func (dv DeviceRegisterView) Token() string {
	return dv.token
}

func (dv DeviceRegisterView) Timezone() string {
	return dv.timezone
}

func (dv *DeviceRegisterView) SetUserAlias(id string) {
	dv.userAlias = id
}

func (dv *DeviceRegisterView) SetLocale(locale string) {
	dv.locale = locale
}

func (dv *DeviceRegisterView) SetTimezone(timezone string) {
	dv.timezone = timezone
}

func (dv *DeviceRegisterView) SetDeviceType(dt model.DeviceType) {
	dv.deviceType = dt
}

func (dv *DeviceRegisterView) SetToken(token string) {
	dv.token = token
}

func (dv *DeviceRegisterView) ToDevice() (*model.Device, error) {
	device := new(model.Device)
	device.SetUserAlias(dv.userAlias)
	device.setToken(dv.token)
	device.setTimezone(dv.timezone)
	if err := device.SetDeviceType(dv.deviceType); err != nil {
		return nil, err
	}
	if err := device.SetLocale(dv.locale); err != nil {
		return nil, err
	}

	return device, nil
}

type DeviceList struct {
	Devices []model.Device
	Cursor  string `json:",omitempty"`
}
<|endoftext|>


<commit_before>// +build unit

// Copyright 2017 Google, 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.

package util

import (
	"testing"

	"github.com/GoogleCloudPlatform/docker-credential-gcr/mock/mock_cmd" // mocks must be generated before test execution
	"github.com/GoogleCloudPlatform/docker-credential-gcr/util/cmd"
	"github.com/golang/mock/gomock"
)

func mockGetVersionCmd(ctrl *gomock.Controller, returnVals ...interface{}) cmd.Command {
	mockCmd := mock_cmd.NewMockCommand(ctrl)
	mockCmd.EXPECT().Exec("version", "--format", "'{{.Client.Version}}'").Return(returnVals...)
	return mockCmd
}

func TestDockerClientVersion_Basic(t *testing.T) {
	t.Parallel()
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("1.2.3"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "" {
		t.Errorf("Expected patchSuffix to be blank, got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_WithSuffix(t *testing.T) {
	t.Parallel()
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("1.2.3-dev"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "dev" {
		t.Errorf("Expected patchSuffix to be \"dev\", got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_SingleQuotedWithSuffix(t *testing.T) {
	t.Parallel()
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("'1.2.3-dev'"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "dev" {
		t.Errorf("Expected patchSuffix to be \"dev\", got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_SingleQuotes(t *testing.T) {
	t.Parallel()
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("'1.2.3'"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "" {
		t.Errorf("Expected patchSuffix to be blank, got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_Whitespace(t *testing.T) {
	t.Parallel()
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("1.2.3\n"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "" {
		t.Errorf("Expected patchSuffix to be blank, got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_WhitespaceQuoted(t *testing.T) {
	t.Parallel()
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("'1.2.3'\n"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "" {
		t.Errorf("Expected patchSuffix to be blank, got \"%s\"", patchSuffix)
	}
}
<commit_msg>de-parallelize docker client version tests to avoid test failures<commit_after>// +build unit

// Copyright 2017 Google, 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.

package util

import (
	"testing"

	"github.com/GoogleCloudPlatform/docker-credential-gcr/mock/mock_cmd" // mocks must be generated before test execution
	"github.com/GoogleCloudPlatform/docker-credential-gcr/util/cmd"
	"github.com/golang/mock/gomock"
)

func mockGetVersionCmd(ctrl *gomock.Controller, returnVals ...interface{}) cmd.Command {
	mockCmd := mock_cmd.NewMockCommand(ctrl)
	mockCmd.EXPECT().Exec("version", "--format", "'{{.Client.Version}}'").Return(returnVals...)
	return mockCmd
}

func TestDockerClientVersion_Basic(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("1.2.3"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "" {
		t.Errorf("Expected patchSuffix to be blank, got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_WithSuffix(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("1.2.3-dev"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "dev" {
		t.Errorf("Expected patchSuffix to be \"dev\", got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_SingleQuotedWithSuffix(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("'1.2.3-dev'"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "dev" {
		t.Errorf("Expected patchSuffix to be \"dev\", got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_SingleQuotes(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("'1.2.3'"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "" {
		t.Errorf("Expected patchSuffix to be blank, got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_Whitespace(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("1.2.3\n"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "" {
		t.Errorf("Expected patchSuffix to be blank, got \"%s\"", patchSuffix)
	}
}

func TestDockerClientVersion_WhitespaceQuoted(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	// Mock out the executor.
	docker = mockGetVersionCmd(mockCtrl, []byte("'1.2.3'\n"), nil)

	major, minor, patch, patchSuffix, err := DockerClientVersion()

	if err != nil {
		t.Fatalf("DockerClientVersion returned an err: %v", err)
	}

	if major != 1 {
		t.Errorf("Expected major version number to be 1, got %d", major)
	}
	if minor != 2 {
		t.Errorf("Expected minor version number to be 2, got %d", minor)
	}
	if patch != 3 {
		t.Errorf("Expected patch version number to be 3, got %d", patch)
	}
	if patchSuffix != "" {
		t.Errorf("Expected patchSuffix to be blank, got \"%s\"", patchSuffix)
	}
}
<|endoftext|>


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

package runtime

import "unsafe"

// This file handles some syscalls from the syscall package
// Especially, syscalls use during forkAndExecInChild which must not split the stack

//go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_dup2 dup2 "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_execve execve "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fork fork "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setgid setgid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setgroups setgroups "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setsid setsid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setuid setuid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setpgid setpgid "libc.a/shr_64.o"

//go:linkname libc_chdir libc_chdir
//go:linkname libc_chroot libc_chroot
//go:linkname libc_dup2 libc_dup2
//go:linkname libc_execve libc_execve
//go:linkname libc_fcntl libc_fcntl
//go:linkname libc_fork libc_fork
//go:linkname libc_ioctl libc_ioctl
//go:linkname libc_setgid libc_setgid
//go:linkname libc_setgroups libc_setgroups
//go:linkname libc_setsid libc_setsid
//go:linkname libc_setuid libc_setuid
//go:linkname libc_setpgid libc_setpgid

var (
	libc_chdir,
	libc_chroot,
	libc_dup2,
	libc_execve,
	libc_fcntl,
	libc_fork,
	libc_ioctl,
	libc_setgid,
	libc_setgroups,
	libc_setsid,
	libc_setuid,
	libc_setpgid libFunc
)

// In syscall_syscall6 and syscall_rawsyscall6, r2 is always 0
// as it's never used on AIX
// TODO: remove r2 from zsyscall_aix_$GOARCH.go

// Syscall is needed because some packages (like net) need it too.
// The best way is to return EINVAL and let Golang handles its failure
// If the syscall can't fail, this function can redirect it to a real syscall.
//go:nosplit
func syscall_Syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
	return 0, 0, _EINVAL
}

// This is syscall.RawSyscall, it exists to satisfy some build dependency,
// but it doesn't work.
func syscall_RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
	panic("RawSyscall not available on AIX")
}

//go:nosplit
func syscall_syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
	c := getg().m.libcall
	c.fn = uintptr(unsafe.Pointer(fn))
	c.n = nargs
	c.args = uintptr(noescape(unsafe.Pointer(&a1)))

	entersyscallblock()
	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
	exitsyscall()
	return c.r1, 0, c.err
}

//go:nosplit
func syscall_rawSyscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
	c := getg().m.libcall
	c.fn = uintptr(unsafe.Pointer(fn))
	c.n = nargs
	c.args = uintptr(noescape(unsafe.Pointer(&a1)))

	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))

	return c.r1, 0, c.err
}

//go:linkname syscall_chdir syscall.chdir
//go:nosplit
func syscall_chdir(path uintptr) (err uintptr) {
	_, err = syscall1(&libc_chdir, path)
	return
}

//go:linkname syscall_chroot1 syscall.chroot1
//go:nosplit
func syscall_chroot1(path uintptr) (err uintptr) {
	_, err = syscall1(&libc_chroot, path)
	return
}

// like close, but must not split stack, for fork.
//go:linkname syscall_close syscall.close
//go:nosplit
func syscall_close(fd int32) int32 {
	_, err := syscall1(&libc_close, uintptr(fd))
	return int32(err)
}

//go:linkname syscall_dup2child syscall.dup2child
//go:nosplit
func syscall_dup2child(old, new uintptr) (val, err uintptr) {
	val, err = syscall2(&libc_dup2, old, new)
	return
}

//go:linkname syscall_execve syscall.execve
//go:nosplit
func syscall_execve(path, argv, envp uintptr) (err uintptr) {
	_, err = syscall3(&libc_execve, path, argv, envp)
	return
}

// like exit, but must not split stack, for fork.
//go:linkname syscall_exit syscall.exit
//go:nosplit
func syscall_exit(code uintptr) {
	syscall1(&libc_exit, code)
}

//go:linkname syscall_fcntl1 syscall.fcntl1
//go:nosplit
func syscall_fcntl1(fd, cmd, arg uintptr) (val, err uintptr) {
	val, err = syscall3(&libc_fcntl, fd, cmd, arg)
	return

}

//go:linkname syscall_forkx syscall.forkx
//go:nosplit
func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
	pid, err = syscall1(&libc_fork, flags)
	return
}

//go:linkname syscall_getpid syscall.getpid
//go:nosplit
func syscall_getpid() (pid, err uintptr) {
	pid, err = syscall0(&libc_getpid)
	return
}

//go:linkname syscall_ioctl syscall.ioctl
//go:nosplit
func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
	_, err = syscall3(&libc_ioctl, fd, req, arg)
	return
}

//go:linkname syscall_setgid syscall.setgid
//go:nosplit
func syscall_setgid(gid uintptr) (err uintptr) {
	_, err = syscall1(&libc_setgid, gid)
	return
}

//go:linkname syscall_setgroups1 syscall.setgroups1
//go:nosplit
func syscall_setgroups1(ngid, gid uintptr) (err uintptr) {
	_, err = syscall2(&libc_setgroups, ngid, gid)
	return
}

//go:linkname syscall_setsid syscall.setsid
//go:nosplit
func syscall_setsid() (pid, err uintptr) {
	pid, err = syscall0(&libc_setsid)
	return
}

//go:linkname syscall_setuid syscall.setuid
//go:nosplit
func syscall_setuid(uid uintptr) (err uintptr) {
	_, err = syscall1(&libc_setuid, uid)
	return
}

//go:linkname syscall_setpgid syscall.setpgid
//go:nosplit
func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
	_, err = syscall2(&libc_setpgid, pid, pgid)
	return
}

//go:linkname syscall_write1 syscall.write1
//go:nosplit
func syscall_write1(fd, buf, nbyte uintptr) (n, err uintptr) {
	n, err = syscall3(&libc_write, fd, buf, nbyte)
	return
}
<commit_msg>runtime: move libcall to stack for syscall package on aix/ppc64<commit_after>// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import "unsafe"

// This file handles some syscalls from the syscall package
// Especially, syscalls use during forkAndExecInChild which must not split the stack

//go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_dup2 dup2 "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_execve execve "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fork fork "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setgid setgid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setgroups setgroups "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setsid setsid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setuid setuid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setpgid setpgid "libc.a/shr_64.o"

//go:linkname libc_chdir libc_chdir
//go:linkname libc_chroot libc_chroot
//go:linkname libc_dup2 libc_dup2
//go:linkname libc_execve libc_execve
//go:linkname libc_fcntl libc_fcntl
//go:linkname libc_fork libc_fork
//go:linkname libc_ioctl libc_ioctl
//go:linkname libc_setgid libc_setgid
//go:linkname libc_setgroups libc_setgroups
//go:linkname libc_setsid libc_setsid
//go:linkname libc_setuid libc_setuid
//go:linkname libc_setpgid libc_setpgid

var (
	libc_chdir,
	libc_chroot,
	libc_dup2,
	libc_execve,
	libc_fcntl,
	libc_fork,
	libc_ioctl,
	libc_setgid,
	libc_setgroups,
	libc_setsid,
	libc_setuid,
	libc_setpgid libFunc
)

// In syscall_syscall6 and syscall_rawsyscall6, r2 is always 0
// as it's never used on AIX
// TODO: remove r2 from zsyscall_aix_$GOARCH.go

// Syscall is needed because some packages (like net) need it too.
// The best way is to return EINVAL and let Golang handles its failure
// If the syscall can't fail, this function can redirect it to a real syscall.
//go:nosplit
func syscall_Syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
	return 0, 0, _EINVAL
}

// This is syscall.RawSyscall, it exists to satisfy some build dependency,
// but it doesn't work.
func syscall_RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
	panic("RawSyscall not available on AIX")
}

//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
	c := libcall{
		fn:   fn,
		n:    nargs,
		args: uintptr(unsafe.Pointer(&a1)),
	}

	entersyscallblock()
	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
	exitsyscall()
	return c.r1, 0, c.err
}

//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
	c := libcall{
		fn:   fn,
		n:    nargs,
		args: uintptr(unsafe.Pointer(&a1)),
	}

	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))

	return c.r1, 0, c.err
}

//go:linkname syscall_chdir syscall.chdir
//go:nosplit
func syscall_chdir(path uintptr) (err uintptr) {
	_, err = syscall1(&libc_chdir, path)
	return
}

//go:linkname syscall_chroot1 syscall.chroot1
//go:nosplit
func syscall_chroot1(path uintptr) (err uintptr) {
	_, err = syscall1(&libc_chroot, path)
	return
}

// like close, but must not split stack, for fork.
//go:linkname syscall_close syscall.close
//go:nosplit
func syscall_close(fd int32) int32 {
	_, err := syscall1(&libc_close, uintptr(fd))
	return int32(err)
}

//go:linkname syscall_dup2child syscall.dup2child
//go:nosplit
func syscall_dup2child(old, new uintptr) (val, err uintptr) {
	val, err = syscall2(&libc_dup2, old, new)
	return
}

//go:linkname syscall_execve syscall.execve
//go:nosplit
func syscall_execve(path, argv, envp uintptr) (err uintptr) {
	_, err = syscall3(&libc_execve, path, argv, envp)
	return
}

// like exit, but must not split stack, for fork.
//go:linkname syscall_exit syscall.exit
//go:nosplit
func syscall_exit(code uintptr) {
	syscall1(&libc_exit, code)
}

//go:linkname syscall_fcntl1 syscall.fcntl1
//go:nosplit
func syscall_fcntl1(fd, cmd, arg uintptr) (val, err uintptr) {
	val, err = syscall3(&libc_fcntl, fd, cmd, arg)
	return

}

//go:linkname syscall_forkx syscall.forkx
//go:nosplit
func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
	pid, err = syscall1(&libc_fork, flags)
	return
}

//go:linkname syscall_getpid syscall.getpid
//go:nosplit
func syscall_getpid() (pid, err uintptr) {
	pid, err = syscall0(&libc_getpid)
	return
}

//go:linkname syscall_ioctl syscall.ioctl
//go:nosplit
func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
	_, err = syscall3(&libc_ioctl, fd, req, arg)
	return
}

//go:linkname syscall_setgid syscall.setgid
//go:nosplit
func syscall_setgid(gid uintptr) (err uintptr) {
	_, err = syscall1(&libc_setgid, gid)
	return
}

//go:linkname syscall_setgroups1 syscall.setgroups1
//go:nosplit
func syscall_setgroups1(ngid, gid uintptr) (err uintptr) {
	_, err = syscall2(&libc_setgroups, ngid, gid)
	return
}

//go:linkname syscall_setsid syscall.setsid
//go:nosplit
func syscall_setsid() (pid, err uintptr) {
	pid, err = syscall0(&libc_setsid)
	return
}

//go:linkname syscall_setuid syscall.setuid
//go:nosplit
func syscall_setuid(uid uintptr) (err uintptr) {
	_, err = syscall1(&libc_setuid, uid)
	return
}

//go:linkname syscall_setpgid syscall.setpgid
//go:nosplit
func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
	_, err = syscall2(&libc_setpgid, pid, pgid)
	return
}

//go:linkname syscall_write1 syscall.write1
//go:nosplit
func syscall_write1(fd, buf, nbyte uintptr) (n, err uintptr) {
	n, err = syscall3(&libc_write, fd, buf, nbyte)
	return
}
<|endoftext|>


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

package net

import (
	"os"
	"syscall"
	"time"
)

func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
	if err := fd.incref(); err != nil {
		return err
	}
	defer fd.decref()
	// The kernel expects milliseconds so round to next highest
	// millisecond.
	d += (time.Millisecond - time.Nanosecond)
	msecs := int(d / time.Millisecond)
	if err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, msecs); err != nil {
		return os.NewSyscallError("setsockopt", err)
	}
	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, msecs))
}
<commit_msg>net: use internal/poll for DragonFly setKeepAlivePeriod<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"runtime"
	"syscall"
	"time"
)

func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
	// The kernel expects milliseconds so round to next highest
	// millisecond.
	d += (time.Millisecond - time.Nanosecond)
	msecs := int(d / time.Millisecond)
	if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, msecs); err != nil {
		return wrapSyscallError("setsockopt", err)
	}
	err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, msecs)
	runtime.KeepAlive(fd)
	return wrapSyscallError("setsockopt", err)
}
<|endoftext|>


<commit_before>package job

import (
	"context"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"errors"
	"fmt"
	"net"
	"sync/atomic"
	"testing"
	"time"

	"golang.org/x/crypto/ssh"
)

func expect(t *testing.T, want, got interface{}) {
	if want != got {
		t.Errorf("want <%T>%+v, got: <%T>%+v", want, want, got, got)
	}
}

func TestCreateClient(t *testing.T) {
	const (
		user     = "testUser"
		question = "Password: "
		answer   = "rootroot"
	)

	config := &ssh.ServerConfig{
		KeyboardInteractiveCallback: func(c ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
			a, err := client(user, "", []string{question}, []bool{false})
			expect(t, 1, len(a))
			expect(t, answer, a[0])
			expect(t, nil, err)

			if a[0] != answer {
				return nil, errors.New("invalid answer")
			}

			return nil, nil
		},
	}

	key, err := generateSSHKey()
	if err != nil {
		t.Fatal(err)
	}

	config.AddHostKey(key)

	s, err := newSSHTestServer(config)
	if err != nil {
		t.Fatal("expected nil, got", err)
	}
	defer s.Close()

	client, err := createClient(s.listener.Addr().String(), user, "", "", map[string]string{
		question: answer,
	})
	if client == nil {
		t.Error("expected a client, got nil")
	}
	expect(t, nil, err)
}

func TestKIHappyPath(t *testing.T) {
	const (
		user     = "user"
		question = "Password: "
		pw       = "123"
	)
	c := keyboardInteractiveChallenge(user, map[string]string{
		question: pw,
	})
	answers, _ := c(user, "", []string{question}, nil)
	expect(t, 1, len(answers))
	expect(t, pw, answers[0])
}

func TestKINoQuestions(t *testing.T) {
	const (
		user     = "user"
		question = "Password: "
		pw       = "123"
	)
	c := keyboardInteractiveChallenge(user, map[string]string{
		question: pw,
	})
	answers, _ := c(user, "", []string{}, nil)
	expect(t, 0, len(answers))
}

func TestConnectionTimeout(t *testing.T) {
	conn := &errorConn{
		c:   make(chan struct{}),
		err: errors.New("errorConn closed"),
	}

	createClient = func(addr, user, keyFile, password string, keyboardInteractive map[string]string) (*sshClient, error) {
		return &sshClient{
			c:       &ssh.Client{Conn: conn},
			trashed: make(chan struct{}),
		}, nil
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	InitializeSSHClientStore(time.Hour * 24 * 365)

	client1, err := newSSHClient(ctx, "", "", "", "", nil)
	expect(t, nil, err)

	if client1 == nil {
		t.Fatalf("Expected client1 to be non-nil")
	}

	close(conn.c)
	<-client1.trashed

	client2, err := newSSHClient(ctx, "", "", "", "", nil)
	expect(t, nil, err)

	if client2 == nil {
		t.Fatalf("Expected client2 to be non-nil")
	}

	if client1 == client2 {
		t.Fatalf("Expected to get a new client, got the old one")
	}
}

type errorConn struct {
	c   chan struct{}
	err error
}

func (e *errorConn) User() string { return "no user" }

func (e *errorConn) SessionID() []byte { return []byte{} }

func (e *errorConn) ClientVersion() []byte { return []byte{} }

func (e *errorConn) ServerVersion() []byte { return []byte{} }

func (e *errorConn) RemoteAddr() net.Addr { panic("") }

func (e *errorConn) LocalAddr() net.Addr { panic("") }

func (e *errorConn) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) {
	return false, []byte{}, nil
}

func (e *errorConn) OpenChannel(name string, data []byte) (ssh.Channel, <-chan *ssh.Request, error) {
	return nil, nil, errors.New("error")
}

func (e *errorConn) Close() error { return nil }

func (e *errorConn) Wait() error {
	<-e.c
	return e.err
}

type testServer struct {
	successfulConnections int32
	listener              net.Listener
	cancel                context.CancelFunc
}

func (s *testServer) Close() {
	s.cancel()
	s.listener.Close()
}

func newSSHTestServer(config *ssh.ServerConfig) (*testServer, error) {
	s := &testServer{}
	var ctx context.Context
	ctx, s.cancel = context.WithCancel(context.Background())

	s.listener = newLocalListener()

	go func() {
		conn, err := s.listener.Accept()
		if err != nil {
			// log.Println("sshtest: error accepting connection", err)
			return
		}

		_, chans, reqs, err := ssh.NewServerConn(conn, config)
		if err != nil {
			fmt.Println("error opening server conn", err)
			return
		}

		go ssh.DiscardRequests(reqs)

		go func() {
			for {
				select {
				case newChannel, ok := <-chans:
					if !ok {
						fmt.Println("new connection channel close")
						return
					}
					channel, _, err := newChannel.Accept()
					if err != nil {
						fmt.Println("error accepting new channel", err)
					}

					atomic.AddInt32(&s.successfulConnections, 1)
					channel.Close()
				case <-ctx.Done():
					return
				}
			}
		}()
	}()

	return s, nil
}

func generateSSHKey() (ssh.Signer, error) {
	pk, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
	if err != nil {
		return nil, err
	}
	return ssh.NewSignerFromSigner(pk)
}

// from net/http/httptest
func newLocalListener() net.Listener {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
			panic(fmt.Sprintf("sstest: failed to listen on a port: %v", err))
		}
	}
	return l
}
<commit_msg>Move related code closer together<commit_after>package job

import (
	"context"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"errors"
	"fmt"
	"net"
	"sync/atomic"
	"testing"
	"time"

	"golang.org/x/crypto/ssh"
)

func expect(t *testing.T, want, got interface{}) {
	if want != got {
		t.Errorf("want <%T>%+v, got: <%T>%+v", want, want, got, got)
	}
}

func TestCreateClient(t *testing.T) {
	const (
		user     = "testUser"
		question = "Password: "
		answer   = "rootroot"
	)

	config := &ssh.ServerConfig{
		KeyboardInteractiveCallback: func(c ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
			a, err := client(user, "", []string{question}, []bool{false})
			expect(t, 1, len(a))
			expect(t, answer, a[0])
			expect(t, nil, err)

			if a[0] != answer {
				return nil, errors.New("invalid answer")
			}

			return nil, nil
		},
	}

	key, err := generateSSHKey()
	if err != nil {
		t.Fatal(err)
	}

	config.AddHostKey(key)

	s, err := newSSHTestServer(config)
	if err != nil {
		t.Fatal("expected nil, got", err)
	}
	defer s.Close()

	client, err := createClient(s.listener.Addr().String(), user, "", "", map[string]string{
		question: answer,
	})
	if client == nil {
		t.Error("expected a client, got nil")
	}
	expect(t, nil, err)
}

type testServer struct {
	successfulConnections int32
	listener              net.Listener
	cancel                context.CancelFunc
}

func (s *testServer) Close() {
	s.cancel()
	s.listener.Close()
}

func newSSHTestServer(config *ssh.ServerConfig) (*testServer, error) {
	s := &testServer{}
	var ctx context.Context
	ctx, s.cancel = context.WithCancel(context.Background())

	s.listener = newLocalListener()

	go func() {
		conn, err := s.listener.Accept()
		if err != nil {
			// log.Println("sshtest: error accepting connection", err)
			return
		}

		_, chans, reqs, err := ssh.NewServerConn(conn, config)
		if err != nil {
			fmt.Println("error opening server conn", err)
			return
		}

		go ssh.DiscardRequests(reqs)

		go func() {
			for {
				select {
				case newChannel, ok := <-chans:
					if !ok {
						fmt.Println("new connection channel close")
						return
					}
					channel, _, err := newChannel.Accept()
					if err != nil {
						fmt.Println("error accepting new channel", err)
					}

					atomic.AddInt32(&s.successfulConnections, 1)
					channel.Close()
				case <-ctx.Done():
					return
				}
			}
		}()
	}()

	return s, nil
}

func generateSSHKey() (ssh.Signer, error) {
	pk, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
	if err != nil {
		return nil, err
	}
	return ssh.NewSignerFromSigner(pk)
}

// from net/http/httptest
func newLocalListener() net.Listener {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
			panic(fmt.Sprintf("sstest: failed to listen on a port: %v", err))
		}
	}
	return l
}

func TestKIHappyPath(t *testing.T) {
	const (
		user     = "user"
		question = "Password: "
		pw       = "123"
	)
	c := keyboardInteractiveChallenge(user, map[string]string{
		question: pw,
	})
	answers, _ := c(user, "", []string{question}, nil)
	expect(t, 1, len(answers))
	expect(t, pw, answers[0])
}

func TestKINoQuestions(t *testing.T) {
	const (
		user     = "user"
		question = "Password: "
		pw       = "123"
	)
	c := keyboardInteractiveChallenge(user, map[string]string{
		question: pw,
	})
	answers, _ := c(user, "", []string{}, nil)
	expect(t, 0, len(answers))
}

func TestConnectionTimeout(t *testing.T) {
	conn := &errorConn{
		c:   make(chan struct{}),
		err: errors.New("errorConn closed"),
	}

	createClient = func(addr, user, keyFile, password string, keyboardInteractive map[string]string) (*sshClient, error) {
		return &sshClient{
			c:       &ssh.Client{Conn: conn},
			trashed: make(chan struct{}),
		}, nil
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	InitializeSSHClientStore(time.Hour * 24 * 365)

	client1, err := newSSHClient(ctx, "", "", "", "", nil)
	expect(t, nil, err)

	if client1 == nil {
		t.Fatalf("Expected client1 to be non-nil")
	}

	close(conn.c)
	<-client1.trashed

	client2, err := newSSHClient(ctx, "", "", "", "", nil)
	expect(t, nil, err)

	if client2 == nil {
		t.Fatalf("Expected client2 to be non-nil")
	}

	if client1 == client2 {
		t.Fatalf("Expected to get a new client, got the old one")
	}
}

type errorConn struct {
	c   chan struct{}
	err error
}

func (e *errorConn) User() string { return "no user" }

func (e *errorConn) SessionID() []byte { return []byte{} }

func (e *errorConn) ClientVersion() []byte { return []byte{} }

func (e *errorConn) ServerVersion() []byte { return []byte{} }

func (e *errorConn) RemoteAddr() net.Addr { panic("") }

func (e *errorConn) LocalAddr() net.Addr { panic("") }

func (e *errorConn) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) {
	return false, []byte{}, nil
}

func (e *errorConn) OpenChannel(name string, data []byte) (ssh.Channel, <-chan *ssh.Request, error) {
	return nil, nil, errors.New("error")
}

func (e *errorConn) Close() error { return nil }

func (e *errorConn) Wait() error {
	<-e.c
	return e.err
}
<|endoftext|>


<commit_before>package restless

import (
   "github.com/gorilla/mux"
   "labix.org/v2/mgo"
   "labix.org/v2/mgo/bson"
   "net/http"
   "fmt"
   "encoding/json"
   log "github.com/zdannar/flogger"
)

func GetAll(c *mgo.Collection, ip interface{}) {
   c.Find(nil).All(ip)
}

func Insert(c *mgo.Collection, i interface{}) (string, error) {
    info, err := c.Upsert(bson.M{"_id" : nil}, i)
    id := info.UpsertedId.(bson.ObjectId)
    return id.Hex(), err
}

func RemoveId(c *mgo.Collection, id bson.ObjectId) error {
   return c.RemoveId(id)
}

func GetId(c *mgo.Collection, i interface{}, id bson.ObjectId) error {
   return c.FindId(id).One(i)
}

func UpdateId(c *mgo.Collection, i interface{}, id bson.ObjectId) error {
   return c.UpdateId(id, i)
}

func GetShapeHandler(s *mgo.Session, dbName string, colName string, cns Constructor) http.HandlerFunc {
   return func(w http.ResponseWriter, r *http.Request) {
       var jdata []byte

       var err error
       ns := s.Clone()
       defer ns.Close()

       col := ns.DB(dbName).C(colName)

       if r.Method == "GET" {
           i := cns.Slice()
           //TODO: Add ability to queary specifics
           GetAll(col, i)
           jdata, _ = json.Marshal(i)
       }

       if r.Method == "POST" {
           i := cns.Single()
           err = r.ParseForm()
           if err != nil {
               http.Error(w, "Unable to parse form", http.StatusNoContent)
           }

           jString := []byte(r.PostForm.Get("json"))
           err = json.Unmarshal(jString, i)
           if err != nil {
               log.Panicf("UnMarshal error : %s", err)
           }

           lastId, err := Insert(col, i)
           if err != nil  {
               log.Panicf("Insert Error : %#v", err)
           }
           jdata, _ = json.Marshal(i)

           w.Header().Add("Location", fmt.Sprintf("%s/%s", r.URL, lastId))
           w.WriteHeader(http.StatusCreated)

       }

       w.Header().Add("Content-Type", "application/json")

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

func GetShapeByIdHandler(s *mgo.Session, dbName string, colName string, cns Constructor) http.HandlerFunc {
   return func (w http.ResponseWriter, r *http.Request) {

       var jdata []byte
       var err error

       ns := s.Clone()
       defer ns.Close()
       vars := mux.Vars(r)
       ids := vars["id"]

       col := ns.DB(dbName).C(colName)

       if !bson.IsObjectIdHex(ids) {
            log.Panicf("ObjectId(%s) is not hex", ids)
       }

       id := bson.ObjectIdHex(ids)

       i := cns.Single()
       //Get Object regardless, Reconsider later
       err = GetId(col, i, id)
       if err != nil {
            log.Panic("Unknown object")
       }

       //TODO: Another error to catch
       jdata, _ = json.Marshal(i)

       if r.Method == "PUT" {
           err := r.ParseForm()
           if err != nil {
               http.Error(w, "Unable to parse form", http.StatusNoContent)
           }
           //TODO: Need error handling
           ijson :=  r.PostForm.Get("json")
           err = json.Unmarshal([]byte(ijson), i)
           if err != nil {
               log.Panicf("UnMarshal error : %s", err)
           }

           //TODO : Need to handle false insert and hand back method
           UpdateId(col, i, id)
       }

       if r.Method == "DELETE" {
            //TODO: Catch Error
            err = RemoveId(col, id)
            if err != nil {
               log.Panicf("Failed to remove id %s; error : %s", id, err)
            }
       }
       w.Header().Add("Content-Type", "application/json")
       fmt.Fprintf(w, "%s", jdata)
       return
    }
}
<commit_msg>Update<commit_after>package restless

import (
   "github.com/gorilla/mux"
   "labix.org/v2/mgo"
   "labix.org/v2/mgo/bson"
   "net/http"
   "fmt"
   "encoding/json"
   log "github.com/zdannar/flogger"
)

func GetAll(c *mgo.Collection, ip interface{}) {
   c.Find(nil).All(ip)
}

func Insert(c *mgo.Collection, i interface{}) (string, error) {
    info, err := c.Upsert(bson.M{"_id" : nil}, i)
    id := info.UpsertedId.(bson.ObjectId)
    return id.Hex(), err
}

func RemoveId(c *mgo.Collection, id bson.ObjectId) error {
   return c.RemoveId(id)
}

func GetId(c *mgo.Collection, i interface{}, id bson.ObjectId) error {
   return c.FindId(id).One(i)
}

func UpdateId(c *mgo.Collection, i interface{}, id bson.ObjectId) error {
   return c.UpdateId(id, i)
}

func GetGenHandler(s *mgo.Session, dbName string, colName string, cns Constructor) http.HandlerFunc {
   return func(w http.ResponseWriter, r *http.Request) {

        var jdata []byte
        var err error

        ns := s.Clone()
        defer ns.Close()

        col := ns.DB(dbName).C(colName)

        switch r.Method {
            //TODO: Add ability to queary specifics
            case "GET":
                i := cns.Slice()
                GetAll(col, i)
                jdata, err = json.Marshal(i)

                w.Header().Add("Content-Type", "application/json")
                fmt.Fprintf(w, "%s", jdata)

            case "PUT":
                var lastId string

                i := cns.Single()
                if err = r.ParseForm(); err != nil {
                    http.Error(w, "Unable to parse form", http.StatusBadRequest)
                    log.Panicf("%s", err)
                }

                jString := []byte(r.PostForm.Get("json"))
                if err = json.Unmarshal(jString, i); err != nil {
                    http.Error(w, "Unable to unmarshal data", http.StatusBadRequest)
                    log.Panicf("UnMarshal error : %s", err)
                }

                if lastId, err := Insert(col, i); err != nil {
                    log.Panicf("Insert Error : %#v", err)
                }

                if jdata, err = json.Marshal(i); err != nil {
                    http.Error(w, "Marshal error", http.StatusInternalServerError)
                }
                w.Header().Add("Location", fmt.Sprintf("%s/%s", r.URL, lastId))
                w.WriteHeader(http.StatusCreated)
        }
        return
}

func GetIdHandler(s *mgo.Session, dbName string, colName string, cns Constructor) http.HandlerFunc {
   return func (w http.ResponseWriter, r *http.Request) {

        var jdata []byte
        var err error
        var ids string

        ns := s.Clone()
        defer ns.Close()

        vars := mux.Vars(r)
        ids = vars["id"]

        col := ns.DB(dbName).C(colName)

        if !bson.IsObjectIdHex(ids) {
            http.Error(w, "Provided ID is unknown", http.StatusNotFound)
            return
        }

        id := bson.ObjectIdHex(ids)
        i := cns.Single()

        if err = GetId(col, i, id); err != nil {
            http.Error(w, "Provided ID is unknown", http.StatusNotFound)
            return
        }

        if jdata, err := json.Marshal(i); err != nil {
            http.Error(w, "", http.StatusBadRequest)
        }

        switch r.Method {
            case "GET":
                w.Header().Add("Content-Type", "application/json")
                fmt.Fprintf(w, "%s", jdata)

            case "PUT":
                if r.ParseForm(); err != nil {
                    http.Error(w, "", http.StatusBadRequest)
                }

                if err = json.Unmarshal([]byte(r.PostForm.Get("json")), i); err != nil {
                    http.Error(w, "", http.StatusBadRequest)
                    log.Panicf("UnMarshal error : %s", err)
                }

                if err = UpdateId(col, i, id); err != nil {
                    http.Error(w, "Failed to update provided ID", http.StatusInternalServerError)
                    log.Panicf("UnMarshal error : %s", err)
                }

            case "DELETE":
                if err = RemoveId(col, id); err != nil {
                    http.Error(w, "Failed to remove provided ID", http.StatusInternalServerError)
                    log.Panicf("Failed to remove id %s; error : %s", id, err)
                }
        }
        return
}
<|endoftext|>


<commit_before>// +build linux,!nonsystemd

package journald

import (
	"context"
	"os"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/coreos/go-systemd/sdjournal"
	"github.com/inconshreveable/log15"
	"github.com/stephane-martin/skewer/model"
	"github.com/stephane-martin/skewer/services/base"
	"github.com/stephane-martin/skewer/utils"
	"github.com/stephane-martin/skewer/utils/eerrors"
)

var Supported = true

type Reader struct {
	journal        *sdjournal.Journal
	stop           context.CancelFunc
	wgroup         sync.WaitGroup
	logger         log15.Logger
	stasher        base.Stasher
	fatalErrorChan chan struct{}
	fatalOnce      sync.Once
}

type Converter func(*sdjournal.JournalEntry) *model.FullMessage

func EntryToSyslog(entry map[string]string) (m *model.SyslogMessage) {
	m = model.CleanFactory()
	properties := map[string]string{}
	for k, v := range entry {
		k = strings.ToLower(k)
		switch k {
		case "syslog_identifier":
		case "_comm":
			m.AppName = v
		case "message":
			m.Message = v
		case "syslog_pid":
		case "_pid":
			m.ProcId = v
		case "priority":
			p, err := strconv.Atoi(v)
			if err == nil {
				m.Severity = model.Severity(p)
			}
		case "syslog_facility":
			f, err := strconv.Atoi(v)
			if err == nil {
				m.Facility = model.Facility(f)
			}
		case "_hostname":
			m.HostName = v
		case "_source_realtime_timestamp": // microseconds
			t, err := strconv.ParseInt(v, 10, 64)
			if err == nil {
				m.TimeReportedNum = t * 1000
			}
		default:
			if strings.HasPrefix(k, "_") {
				properties[k] = v
			}

		}
	}
	if len(m.AppName) == 0 {
		m.AppName = entry["SYSLOG_IDENTIFIER"]
	}
	if len(m.ProcId) == 0 {
		m.ProcId = entry["SYSLOG_PID"]
	}
	m.TimeGeneratedNum = time.Now().UnixNano()
	if m.TimeReportedNum == 0 {
		m.TimeReportedNum = m.TimeGeneratedNum
	}
	m.Priority = model.Priority(int(m.Facility)*8 + int(m.Severity))
	m.ClearDomain("journald")
	m.Properties.Map["journald"].Map = properties
	m.SetProperty("skewer", "client", m.HostName)
	return m
}

func makeMapConverter(coding string, confID utils.MyULID) Converter {
	decoder := utils.SelectDecoder(coding)
	generator := utils.NewGenerator()

	return func(m *sdjournal.JournalEntry) *model.FullMessage {
		dest := make(map[string]string, len(m.Fields))
		for k, v := range m.Fields {
			k2, err := decoder.String(k)
			if err == nil {
				v2, err := decoder.String(v)
				if err == nil {
					dest[k2] = v2
				}
			}
		}
		full := model.FullFactoryFrom(EntryToSyslog(dest))
		full.Uid = generator.Uid()
		full.ConfId = confID
		return full
	}
}

func (r *Reader) FatalError() chan struct{} {
	return r.fatalErrorChan
}

func (r *Reader) dofatal() {
	r.fatalOnce.Do(func() { close(r.fatalErrorChan) })
}

func NewReader(stasher base.Stasher, logger log15.Logger) (*Reader, error) {
	var err error
	r := &Reader{
		logger:         logger,
		stasher:        stasher,
		fatalErrorChan: make(chan struct{}),
	}
	r.journal, err = sdjournal.NewJournal()
	if err != nil {
		return nil, err
	}
	err = r.journal.SeekTail()
	if err != nil {
		r.journal.Close()
		return nil, err
	}
	_, err = r.journal.Previous()
	if err != nil {
		r.journal.Close()
		return nil, err
	}
	return r, nil
}

func wait(ctx context.Context, logger log15.Logger, j *sdjournal.Journal) {
	lctx, lcancel := context.WithCancel(ctx)

	go func() {
		for {
			// Wait() is a blocking call
			ev := j.Wait(time.Second)
			if ev == sdjournal.SD_JOURNAL_APPEND || ev == sdjournal.SD_JOURNAL_INVALIDATE {
				lcancel()
				return
			} else if ev == -int(syscall.EBADF) {
				logger.Debug("journal.Wait returned EBADF") // r.journal was closed
				lcancel()
				return
			} else if ev != 0 {
				// r.logger.Debug("journal.Wait event", "code", ev)
			}
		}
	}()
	<-lctx.Done()
}

func (r *Reader) Start(confID utils.MyULID) {
	var ctx context.Context
	ctx, r.stop = context.WithCancel(context.Background())
	hostname, err := os.Hostname()
	if err != nil {
		hostname = "unknown"
	}
	converter := makeMapConverter("utf8", confID)

	r.wgroup.Add(1)
	go func() {
		defer r.wgroup.Done()

	L:
		for {
			select {
			case <-ctx.Done():
				return
			default:
				nb, err := r.journal.Next()
				if err != nil {
					return
				}
				if nb == 0 {
					wait(ctx, r.logger, r.journal) // wait that journald has more entries
					continue L
				}
				entry, err := r.journal.GetEntry()
				if err != nil {
					return
				}
				err = r.stasher.Stash(converter(entry))
				if eerrors.IsFatal(err) {
					r.logger.Error("Fatal error stashing journal message", "error", err)
					r.dofatal()
					return
				}
				if err != nil {
					r.logger.Warn("Non-fatal error stashing journal message", "error", err)
					continue L
				}
				base.IncomingMsgsCounter.WithLabelValues("journald", hostname, "", "").Inc()

			}
		}

	}()
}

func (r *Reader) WaitFinished() {
	r.wgroup.Wait()
}

func (r *Reader) Stop() {
	if r.stop != nil {
		r.stop()
		r.stop = nil
	}
	r.WaitFinished()
}

func (r *Reader) Shutdown() {
	r.Stop()
	// async close the low level journald reader
	go func() {
		r.journal.Close()
	}()
}
<commit_msg>fix compile on linux<commit_after>// +build linux,!nonsystemd

package journald

import (
	"context"
	"os"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/coreos/go-systemd/sdjournal"
	"github.com/inconshreveable/log15"
	"github.com/stephane-martin/skewer/model"
	"github.com/stephane-martin/skewer/services/base"
	"github.com/stephane-martin/skewer/utils"
	"github.com/stephane-martin/skewer/utils/eerrors"
)

var Supported = true

type Reader struct {
	journal        *sdjournal.Journal
	stop           context.CancelFunc
	wgroup         sync.WaitGroup
	logger         log15.Logger
	stasher        base.Stasher
	fatalErrorChan chan struct{}
	fatalOnce      sync.Once
}

type Converter func(*sdjournal.JournalEntry) *model.FullMessage

func EntryToSyslog(entry map[string]string) *model.SyslogMessage {
	m := model.Factory()
	properties := map[string]string{}
	for k, v := range entry {
		k = strings.ToLower(k)
		switch k {
		case "syslog_identifier":
		case "_comm":
			m.AppName = v
		case "message":
			m.Message = v
		case "syslog_pid":
		case "_pid":
			m.ProcId = v
		case "priority":
			p, err := strconv.Atoi(v)
			if err == nil {
				m.Severity = model.Severity(p)
			}
		case "syslog_facility":
			f, err := strconv.Atoi(v)
			if err == nil {
				m.Facility = model.Facility(f)
			}
		case "_hostname":
			m.HostName = v
		case "_source_realtime_timestamp": // microseconds
			t, err := strconv.ParseInt(v, 10, 64)
			if err == nil {
				m.TimeReportedNum = t * 1000
			}
		default:
			if strings.HasPrefix(k, "_") {
				properties[k] = v
			}

		}
	}
	if len(m.AppName) == 0 {
		m.AppName = entry["SYSLOG_IDENTIFIER"]
	}
	if len(m.ProcId) == 0 {
		m.ProcId = entry["SYSLOG_PID"]
	}
	m.TimeGeneratedNum = time.Now().UnixNano()
	if m.TimeReportedNum == 0 {
		m.TimeReportedNum = m.TimeGeneratedNum
	}
	m.Priority = model.Priority(int(m.Facility)*8 + int(m.Severity))
	m.ClearDomain("journald")
	m.Properties.Map["journald"].Map = properties
	m.SetProperty("skewer", "client", m.HostName)
	return m
}

func makeMapConverter(coding string, confID utils.MyULID) Converter {
	decoder := utils.SelectDecoder(coding)
	generator := utils.NewGenerator()

	return func(m *sdjournal.JournalEntry) *model.FullMessage {
		dest := make(map[string]string, len(m.Fields))
		for k, v := range m.Fields {
			k2, err := decoder.String(k)
			if err == nil {
				v2, err := decoder.String(v)
				if err == nil {
					dest[k2] = v2
				}
			}
		}
		full := model.FullFactoryFrom(EntryToSyslog(dest))
		full.Uid = generator.Uid()
		full.ConfId = confID
		return full
	}
}

func (r *Reader) FatalError() chan struct{} {
	return r.fatalErrorChan
}

func (r *Reader) dofatal() {
	r.fatalOnce.Do(func() { close(r.fatalErrorChan) })
}

func NewReader(stasher base.Stasher, logger log15.Logger) (*Reader, error) {
	var err error
	r := &Reader{
		logger:         logger,
		stasher:        stasher,
		fatalErrorChan: make(chan struct{}),
	}
	r.journal, err = sdjournal.NewJournal()
	if err != nil {
		return nil, err
	}
	err = r.journal.SeekTail()
	if err != nil {
		r.journal.Close()
		return nil, err
	}
	_, err = r.journal.Previous()
	if err != nil {
		r.journal.Close()
		return nil, err
	}
	return r, nil
}

func wait(ctx context.Context, logger log15.Logger, j *sdjournal.Journal) {
	lctx, lcancel := context.WithCancel(ctx)

	go func() {
		for {
			// Wait() is a blocking call
			ev := j.Wait(time.Second)
			if ev == sdjournal.SD_JOURNAL_APPEND || ev == sdjournal.SD_JOURNAL_INVALIDATE {
				lcancel()
				return
			} else if ev == -int(syscall.EBADF) {
				logger.Debug("journal.Wait returned EBADF") // r.journal was closed
				lcancel()
				return
			} else if ev != 0 {
				// r.logger.Debug("journal.Wait event", "code", ev)
			}
		}
	}()
	<-lctx.Done()
}

func (r *Reader) Start(confID utils.MyULID) {
	var ctx context.Context
	ctx, r.stop = context.WithCancel(context.Background())
	hostname, err := os.Hostname()
	if err != nil {
		hostname = "unknown"
	}
	converter := makeMapConverter("utf8", confID)

	r.wgroup.Add(1)
	go func() {
		defer r.wgroup.Done()

	L:
		for {
			select {
			case <-ctx.Done():
				return
			default:
				nb, err := r.journal.Next()
				if err != nil {
					return
				}
				if nb == 0 {
					wait(ctx, r.logger, r.journal) // wait that journald has more entries
					continue L
				}
				entry, err := r.journal.GetEntry()
				if err != nil {
					return
				}
				err = r.stasher.Stash(converter(entry))
				if eerrors.IsFatal(err) {
					r.logger.Error("Fatal error stashing journal message", "error", err)
					r.dofatal()
					return
				}
				if err != nil {
					r.logger.Warn("Non-fatal error stashing journal message", "error", err)
					continue L
				}
				base.IncomingMsgsCounter.WithLabelValues("journald", hostname, "", "").Inc()

			}
		}

	}()
}

func (r *Reader) WaitFinished() {
	r.wgroup.Wait()
}

func (r *Reader) Stop() {
	if r.stop != nil {
		r.stop()
		r.stop = nil
	}
	r.WaitFinished()
}

func (r *Reader) Shutdown() {
	r.Stop()
	// async close the low level journald reader
	go func() {
		r.journal.Close()
	}()
}
<|endoftext|>


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

package parlib

/*
#cgo akaros LDFLAGS: -lpthread -lbenchutil -lm

#include <parlib.h>
#include <uthread.h>
#include <vcore.h>
#include <mcs.h>
#include <futex.h>
#include <sys/stat.h>

int go_parlib_errno(void)
{
	return current_uthread->err_no;
}

char *go_parlib_errstr(void)
{
	return current_uthread->err_str;
}

*/
import "C"
import (
	"unsafe"
	"errors"
)

var Procinfo *ProcinfoType = (*ProcinfoType)(unsafe.Pointer(uintptr(C.UINFO)))

func Futex(uaddr *int32, op int32, val int32,
           timeout *Timespec, uaddr2 *int32, val3 int32) (ret int32) {
	// For now, akaros futexes don't support uaddr2 or val3, so we
	// just 0 them out.
	uaddr2 = nil;
	val3 = 0;
	// Also, the minimum timout is 1ms, so up it to that if it's too small
	if (timeout != nil) {
		if (timeout.Sec == 0) {
			if (timeout.Nsec < 1000000) {
				timeout.Nsec = 1000000;
			}
		}
	}
	return int32(C.futex((*C.int)(unsafe.Pointer(uaddr)),
	                     C.int(op), C.int(val),
	                     (*C.struct_timespec)(unsafe.Pointer(timeout)),
	                     (*C.int)(unsafe.Pointer(uaddr2)), C.int(val3)))
}

func ProcinfoPackArgs(argv []*byte, envp []*byte) (pi ProcinfoType, err error) {
	p_pi := (*_Ctype_struct_procinfo)(unsafe.Pointer(&pi))
    p_argv := (**_Ctype_char)(unsafe.Pointer(&argv[0]))
    p_envp := (**_Ctype_char)(unsafe.Pointer(&envp[0]))

	__err := C.procinfo_pack_args(p_pi, p_argv, p_envp)
	if __err == -1 {
		err = nil
	} else {
		err = errors.New("ProcinfoPackArgs: error packing argv and envp")
	}
	return pi, err
}

func Errno() (int) {
	return int(C.go_parlib_errno())
}

func Errstr() (string) {
	return C.GoString(C.go_parlib_errstr())
}
<commit_msg>Add parlib calls for chmod() and fchmod()<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// +build akaros

package parlib

/*
#cgo akaros LDFLAGS: -lpthread -lbenchutil -lm

#include <parlib.h>
#include <uthread.h>
#include <vcore.h>
#include <mcs.h>
#include <futex.h>
#include <sys/stat.h>

int go_parlib_errno(void)
{
	return current_uthread->err_no;
}

char *go_parlib_errstr(void)
{
	return current_uthread->err_str;
}

*/
import "C"
import (
	"unsafe"
	"errors"
)

var Procinfo *ProcinfoType = (*ProcinfoType)(unsafe.Pointer(uintptr(C.UINFO)))

func Futex(uaddr *int32, op int32, val int32,
           timeout *Timespec, uaddr2 *int32, val3 int32) (ret int32) {
	// For now, akaros futexes don't support uaddr2 or val3, so we
	// just 0 them out.
	uaddr2 = nil;
	val3 = 0;
	// Also, the minimum timout is 1ms, so up it to that if it's too small
	if (timeout != nil) {
		if (timeout.Sec == 0) {
			if (timeout.Nsec < 1000000) {
				timeout.Nsec = 1000000;
			}
		}
	}
	return int32(C.futex((*C.int)(unsafe.Pointer(uaddr)),
	                     C.int(op), C.int(val),
	                     (*C.struct_timespec)(unsafe.Pointer(timeout)),
	                     (*C.int)(unsafe.Pointer(uaddr2)), C.int(val3)))
}

func ProcinfoPackArgs(argv []*byte, envp []*byte) (pi ProcinfoType, err error) {
	p_pi := (*_Ctype_struct_procinfo)(unsafe.Pointer(&pi))
    p_argv := (**_Ctype_char)(unsafe.Pointer(&argv[0]))
    p_envp := (**_Ctype_char)(unsafe.Pointer(&envp[0]))

	__err := C.procinfo_pack_args(p_pi, p_argv, p_envp)
	if __err == -1 {
		err = nil
	} else {
		err = errors.New("ProcinfoPackArgs: error packing argv and envp")
	}
	return pi, err
}

func Errno() (int) {
	return int(C.go_parlib_errno())
}

func Errstr() (string) {
	return C.GoString(C.go_parlib_errstr())
}

func Chmod(path string, mode uint32) (int) {
	return int(C.chmod(C.CString(path), C.__mode_t(mode)))
}

func Fchmod(fd int, mode uint32) (int) {
	return int(C.fchmod(C.int(fd), C.__mode_t(mode)))
}

<|endoftext|>