<commit_before>// dulbecco is a IRC bot.
//
// Plugin support through external commands (bash, python, ...).
//
//   most of the code was copied from:
//   - https://github.com/fluffle/goirc
//   - https://github.com/thoj/go-ircevent
package dulbecco

import (
	"bufio"
	"crypto/tls"
	"log"
	"net"
	"strings"
	"sync"
	"time"
)

type Channel struct {
	name  string
	topic string
	names []string
}

type User struct {
	nickname, username, hostname, realname string

	channels map[string]bool
}

func NewUser(nickname string) *User {
	user := &User{
		nickname: nickname,
		channels: make(map[string]bool),
	}
	return user
}

// A connection to the IRC server, also the main data structure of the IRC bot.
type Connection struct {
	// server address+port: "irc.example.com:6667"
	address string

	username, realname, nickname, password string
	altnicknames                           []string
	channels                               []string
	chanmap                                map[string]*Channel
	usermap                                map[string]*User

	// ping frequency
	pingFreq time.Duration

	// enable anti-flood protection
	floodProtection bool
	// anti-flood internal counters
	badness  time.Duration
	lastSent time.Time

	// IO
	sock         net.Conn
	io           *bufio.ReadWriter
	out          chan string
	connected    bool
	tryReconnect bool

	// lock shutdown calls
	mutex sync.Mutex

	// SSL
	useTLS    bool
	sslConfig *tls.Config

	// Control channels
	cWrite chan bool
	cEvent chan bool
	cPing  chan bool
	CQuit  chan bool

	// callbacks
	events map[string]map[string]func(*Message)
}

func NewConnection(srvConfig *ServerType, genConfig *ConfigurationType, quit chan bool) *Connection {
	conn := &Connection{
		address:         srvConfig.Address,
		password:        srvConfig.Password,
		useTLS:          srvConfig.Ssl,
		username:        srvConfig.Username,
		realname:        srvConfig.Realname,
		nickname:        srvConfig.Nickname,
		altnicknames:    srvConfig.Altnicknames,
		channels:        srvConfig.Channels,
		sslConfig:       nil,
		pingFreq:        3 * time.Minute,
		chanmap:         make(map[string]*Channel),
		usermap:         make(map[string]*User),
		connected:       false,
		tryReconnect:    false,
		out:             make(chan string, 32),
		cWrite:          make(chan bool),
		cPing:           make(chan bool),
		floodProtection: true,
		badness:         0,
		lastSent:        time.Now(),
		CQuit:           quit,
	}

	// setup internal callbacks
	conn.SetupCallbacks()
	conn.SetupPlugins(genConfig.Plugins)

	return conn
}

// Connect to the server, launch all internal goroutines.
func (c *Connection) Connect() (err error) {
	var conn net.Conn
	if c.useTLS {
		conn, err = tls.Dial("tcp", c.address, c.sslConfig)
	} else {
		conn, err = net.Dial("tcp", c.address)
	}
	if err != nil {
		return
	}

	c.sock = conn
	log.Println("Connected to:", c.address)
	c.connected = true

	c.io = bufio.NewReadWriter(
		bufio.NewReader(c.sock),
		bufio.NewWriter(c.sock))

	go c.writeLoop()
	go c.readLoop()
	go c.pingLoop()

	c.RunCallbacks(&Message{Cmd: "INIT"})

	return nil
}

func (c *Connection) writeLoop() {
	for {
		select {
		case line := <-c.out:
			err := c.write(line)
			if err != nil {
				log.Println("ERROR writing:", err)
				go c.shutdown()
				return
			}
		case <-c.cWrite:
			return
		}
	}
}

func (c *Connection) readLoop() {
	for {
		line, err := c.io.ReadString('\n')
		if err != nil {
			log.Println("read failed:", err)
			go c.shutdown()
			return
		}

		line = strings.TrimRight(line, "\r\n")
		// log.Println("READ: ", line)

		if message, err := parseMessage(line); err == nil {
			log.Println("message =", message.Dump())
			c.RunCallbacks(message)
		} else {
			log.Printf("parsing failed (%s) for line: %q\n", err, line)
		}
	}
}

func (c *Connection) pingLoop() {
	tick := time.NewTicker(c.pingFreq)

	for {
		select {
		case <-tick.C:
			c.ServerPing()
		case <-c.cPing:
			tick.Stop()
			return
		}
	}
}

func (c *Connection) write(line string) error {
	if !c.floodProtection {
		if t := c.rateLimit(len(line)); t != 0 {
			log.Printf("anti-flood: sleeping for %.2f seconds\n", t.Seconds())
			<-time.After(t)
		}
	}

	if _, err := c.io.WriteString(line); err != nil {
		return err
	}

	if err := c.io.Flush(); err != nil {
		return err
	}
	return nil
}

func (c *Connection) rateLimit(chars int) time.Duration {
	lineTime := 2*time.Second + time.Duration(chars)*time.Second/120
	elapsed := time.Now().Sub(c.lastSent)
	if c.badness += lineTime - elapsed; c.badness < 0 {
		c.badness = 0
	}
	c.lastSent = time.Now()

	if c.badness > 10*time.Second {
		return lineTime
	}

	return 0
}

func (c *Connection) shutdown() {
	c.mutex.Lock()
	log.Println("enter shutdown()")

	if c.connected {
		log.Println("shutting down connection")

		c.connected = false
		c.sock.Close()
		c.cWrite <- true
		c.cPing <- true

		c.io = nil
		c.sock = nil

		c.RunCallbacks(&Message{Cmd: "DISCONNECT"})

		if c.tryReconnect {
			go c.reconnect()
		} else {
			c.CQuit <- true
		}
		log.Println("end of shutdown")
	}
	c.mutex.Unlock()
	log.Println("exit shutdown()")
}

func (c *Connection) reconnect() {
	for {
		log.Println("Sleeping 5 minutes before trying to reconnect")
		time.Sleep(5 * time.Minute)
		if err := c.Connect(); err == nil {
			return
		}
	}
}
<commit_msg>more cleanup<commit_after>// dulbecco is a IRC bot.
//
// Plugin support through external commands (bash, python, ...).
//
//   most of the code was copied from:
//   - https://github.com/fluffle/goirc
//   - https://github.com/thoj/go-ircevent
package dulbecco

import (
	"bufio"
	"crypto/tls"
	"log"
	"net"
	"strings"
	"sync"
	"time"
)

var (
	pingFrequency = 3 * time.Minute
)

type Channel struct {
	name, topic string
	names       []string
}

type User struct {
	nickname, username, hostname, realname string

	channels map[string]bool
}

func NewUser(nickname string) *User {
	user := &User{
		nickname: nickname,
		channels: make(map[string]bool),
	}
	return user
}

// A connection to the IRC server, also the main data structure of the IRC bot.
type Connection struct {
	// server address+port: "irc.example.com:6667"
	address string

	username, realname, nickname, password string

	altnicknames []string
	channels     []string
	chanmap      map[string]*Channel
	usermap      map[string]*User

	// ping frequency
	pingFreq time.Duration

	// enable anti-flood protection
	floodProtection bool
	// anti-flood internal counters
	badness  time.Duration
	lastSent time.Time

	// IO
	sock         net.Conn
	io           *bufio.ReadWriter
	out          chan string
	connected    bool
	tryReconnect bool

	// lock shutdown calls
	mutex sync.Mutex

	// SSL
	useTLS bool

	// Control channels
	cWrite chan bool
	cEvent chan bool
	cPing  chan bool
	CQuit  chan bool

	// callbacks
	events map[string]map[string]func(*Message)
}

func NewConnection(srvConfig *ServerType, genConfig *ConfigurationType, quit chan bool) *Connection {
	conn := &Connection{
		address:         srvConfig.Address,
		password:        srvConfig.Password,
		useTLS:          srvConfig.Ssl,
		username:        srvConfig.Username,
		realname:        srvConfig.Realname,
		nickname:        srvConfig.Nickname,
		altnicknames:    srvConfig.Altnicknames,
		channels:        srvConfig.Channels,
		pingFreq:        pingFrequency,
		chanmap:         make(map[string]*Channel),
		usermap:         make(map[string]*User),
		out:             make(chan string, 32),
		cWrite:          make(chan bool),
		cPing:           make(chan bool),
		floodProtection: true,
		lastSent:        time.Now(),
		CQuit:           quit,
	}

	// setup internal callbacks
	conn.SetupCallbacks()
	conn.SetupPlugins(genConfig.Plugins)

	return conn
}

// Connect to the server, launch all internal goroutines.
func (c *Connection) Connect() (err error) {
	var conn net.Conn
	if c.useTLS {
		// XXX should use a valid tls client configuration insted of nil (default)
		conn, err = tls.Dial("tcp", c.address, nil)
	} else {
		conn, err = net.Dial("tcp", c.address)
	}
	if err != nil {
		return
	}

	c.sock = conn
	log.Println("Connected to:", c.address)
	c.connected = true

	c.io = bufio.NewReadWriter(
		bufio.NewReader(c.sock),
		bufio.NewWriter(c.sock))

	go c.writeLoop()
	go c.readLoop()
	go c.pingLoop()

	c.RunCallbacks(&Message{Cmd: "INIT"})

	return nil
}

func (c *Connection) writeLoop() {
	for {
		select {
		case line := <-c.out:
			err := c.write(line)
			if err != nil {
				log.Println("ERROR writing:", err)
				go c.shutdown()
				return
			}
		case <-c.cWrite:
			return
		}
	}
}

func (c *Connection) readLoop() {
	for {
		line, err := c.io.ReadString('\n')
		if err != nil {
			log.Println("read failed:", err)
			go c.shutdown()
			return
		}

		line = strings.TrimRight(line, "\r\n")
		// log.Println("READ: ", line)

		if message, err := parseMessage(line); err == nil {
			log.Println("message =", message.Dump())
			c.RunCallbacks(message)
		} else {
			log.Printf("parsing failed (%s) for line: %q\n", err, line)
		}
	}
}

func (c *Connection) pingLoop() {
	tick := time.NewTicker(c.pingFreq)

	for {
		select {
		case <-tick.C:
			c.ServerPing()
		case <-c.cPing:
			tick.Stop()
			return
		}
	}
}

func (c *Connection) write(line string) error {
	if !c.floodProtection {
		if t := c.rateLimit(len(line)); t != 0 {
			log.Printf("anti-flood: sleeping for %.2f seconds\n", t.Seconds())
			<-time.After(t)
		}
	}

	if _, err := c.io.WriteString(line); err != nil {
		return err
	}

	if err := c.io.Flush(); err != nil {
		return err
	}
	return nil
}

func (c *Connection) rateLimit(chars int) time.Duration {
	lineTime := 2*time.Second + time.Duration(chars)*time.Second/120
	elapsed := time.Now().Sub(c.lastSent)
	if c.badness += lineTime - elapsed; c.badness < 0 {
		c.badness = 0
	}
	c.lastSent = time.Now()

	if c.badness > 10*time.Second {
		return lineTime
	}

	return 0
}

func (c *Connection) shutdown() {
	c.mutex.Lock()
	log.Println("enter shutdown()")

	if c.connected {
		log.Println("shutting down connection")

		c.connected = false
		c.sock.Close()
		c.cWrite <- true
		c.cPing <- true

		c.io = nil
		c.sock = nil

		c.RunCallbacks(&Message{Cmd: "DISCONNECT"})

		if c.tryReconnect {
			go c.reconnect()
		} else {
			c.CQuit <- true
		}
		log.Println("end of shutdown")
	}
	c.mutex.Unlock()
	log.Println("exit shutdown()")
}

func (c *Connection) reconnect() {
	for {
		log.Println("Sleeping 5 minutes before trying to reconnect")
		time.Sleep(5 * time.Minute)
		if err := c.Connect(); err == nil {
			return
		}
	}
}
<|endoftext|>


<commit_before>/*
 * Provide IRC functionality
 */

package irc

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"strings"
)

type Conn struct {
	Nick  string
	Name  string
	Ident string
	Host  string
	Port  int
	SSL   bool

	connected bool
	conn      net.Conn
	rw        *bufio.ReadWriter
}

// Connect attempts to initialize a connection to a server.
func (c *Conn) Connect() error {
	conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", c.Host, c.Port))
	if err != nil {
		return err
	}

	c.connected = true
	c.conn = conn

	c.rw = bufio.NewReadWriter(bufio.NewReader(c.conn), bufio.NewWriter(c.conn))

	err = c.init()
	if err != nil {
		return err
	}

	return nil
}

// init runs connection initiation (nick, etc)
func (c *Conn) init() error {
	_, err := c.rw.WriteString(fmt.Sprintf("NICK %s\r\n", c.Nick))
	if err != nil {
		return fmt.Errorf("Failed to send NICK: %s", err.Error())
	}

	_, err = c.rw.WriteString(fmt.Sprintf("USER %s 0 * :%s\r\n", c.Ident,
		c.Name))
	if err != nil {
		return fmt.Errorf("Failed to send NICK: %s", err.Error())
	}

	err = c.rw.Flush()
	if err != nil {
		return err
	}

	for {
		line, err := c.rw.ReadString('\n')
		if err != nil {
			return err
		}

		log.Printf("Read line [%s]", line)

		if !strings.HasPrefix(line, ":") {
			continue
		}

		var server string
		var code int
		_, err = fmt.Sscanf(line, ":%s %d ", &server, &code)
		if err == nil {
			if code == 1 {
				return nil
			}
			return fmt.Errorf("No welcome found")
		}
	}
}

// Loop enters a connection loop
func (c *Conn) Loop() error {
	for {
		line, err := c.rw.ReadString('\n')
		if err != nil {
			return err
		}

		log.Printf("Read line [%s]", line)

		if strings.HasPrefix(line, "PING ") {
			var server string
			_, err = fmt.Sscanf(line, "PING :%s", &server)
			if err != nil {
				return fmt.Errorf("Unable to parse PING")
			}

			_, err = c.rw.WriteString(fmt.Sprintf("PONG %s\r\n", server))
			if err != nil {
				return fmt.Errorf("Failed to send PONG: %s", err.Error())
			}

			err = c.rw.Flush()
			if err != nil {
				return err
			}

			log.Printf("Sent PONG.")
		}
	}
}

// Join joins a channel
func (c *Conn) Join(name string) error {
	_, err := c.rw.WriteString(fmt.Sprintf("JOIN %s\r\n", name))
	if err != nil {
		return fmt.Errorf("Failed to send JOIN: %s", err.Error())
	}

	err = c.rw.Flush()
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Prepare for privmsg hook<commit_after>/*
 * Provide IRC functionality
 */

package irc

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"strings"
)

type Conn struct {
	Nick  string
	Name  string
	Ident string
	Host  string
	Port  int
	SSL   bool

	connected bool
	conn      net.Conn
	rw        *bufio.ReadWriter
}

// Connect attempts to initialize a connection to a server.
func (c *Conn) Connect() error {
	conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", c.Host, c.Port))
	if err != nil {
		return err
	}

	c.connected = true
	c.conn = conn

	c.rw = bufio.NewReadWriter(bufio.NewReader(c.conn), bufio.NewWriter(c.conn))

	err = c.init()
	if err != nil {
		return err
	}

	return nil
}

// init runs connection initiation (nick, etc)
func (c *Conn) init() error {
	err := c.write(fmt.Sprintf("NICK %s\r\n", c.Nick))
	if err != nil {
		return fmt.Errorf("Failed to send NICK: %s", err.Error())
	}

	err = c.write(fmt.Sprintf("USER %s 0 * :%s\r\n", c.Ident, c.Name))
	if err != nil {
		return fmt.Errorf("Failed to send NICK: %s", err.Error())
	}

	for {
		line, err := c.rw.ReadString('\n')
		if err != nil {
			return err
		}

		log.Printf("Read line [%s]", line)

		if !strings.HasPrefix(line, ":") {
			continue
		}

		var server string
		var code int
		_, err = fmt.Sscanf(line, ":%s %d ", &server, &code)
		if err == nil {
			if code == 1 {
				return nil
			}
			return fmt.Errorf("No welcome found")
		}
	}
}

// Loop enters a connection loop
func (c *Conn) Loop() error {
	for {
		line, err := c.rw.ReadString('\n')
		if err != nil {
			return err
		}

		log.Printf("Read line [%s]", line)

		if strings.HasPrefix(line, "PING ") {
			var server string
			_, err = fmt.Sscanf(line, "PING :%s", &server)
			if err != nil {
				return fmt.Errorf("Unable to parse PING")
			}

			err = c.write(fmt.Sprintf("PONG %s\r\n", server))
			if err != nil {
				return fmt.Errorf("Failed to send PONG: %s", err.Error())
			}
			log.Printf("Sent PONG.")
			continue
		}

		pieces := strings.Split(line, " ")

		if len(pieces) > 1 {
			if pieces[1] == "PRIVMSG" {
				err = c.privmsg(line, pieces)
				if err != nil {
					return err
				}
				continue
			}
		}
	}
}

// Join joins a channel
func (c *Conn) Join(name string) error {
	return c.write(fmt.Sprintf("JOIN %s\r\n", name))
}

// privmsg fires when a PRIVMSG is seen.
//
// It triggers any hook functions registered for privmsg.
func (c *Conn) privmsg(line string, pieces []string) error {
	log.Printf("privmsg: todo")
	return nil
}

// write writes a string to the connection
func (c *Conn) write(s string) error {
	sz, err := c.rw.WriteString(s)
	if err != nil {
		return err
	}

	if sz != len(s) {
		return fmt.Errorf("Short write")
	}

	err = c.rw.Flush()
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package jit

/*
#cgo CFLAGS: -I./include
#cgo linux,amd64 LDFLAGS: -L./lib -lm -ljit

#include <stdio.h>
#include <jit/jit.h>
#include <jit/jit-dump.h>

extern int on_demand_compile(jit_function_t);

static void SetOnDemandCompileFunction(jit_function_t f) {
    jit_function_set_on_demand_compiler(f, on_demand_compile);
}

static FILE *getStdout(void) { return stdout; }
*/
import "C"
import "unsafe"
import "reflect"

const CDECL = C.jit_abi_cdecl

type Context struct {
	C C.jit_context_t
}

type Type struct {
	C C.jit_type_t
}

type Signature struct {
	C C.jit_type_t
}

type Function struct {
	C         C.jit_function_t
	retType   Type
	paramType []Type
}

type Value struct {
	C C.jit_value_t
}

type Label struct {
	C C.jit_label_t
}

func Int() Type {
	return Type{C.jit_type_int}
}

func UInt() Type {
	return Type{C.jit_type_uint}
}

func Void() Type {
	return Type{C.jit_type_void}
}

func VoidPtr() Type {
	return Type{C.jit_type_void_ptr}
}

func NewContext() *Context {
	return &Context{C.jit_context_create()}
}

func NewSignature(ret Type, params []Type) *Signature {
	if len(params) == 0 {
		signature := C.jit_type_create_signature(C.jit_abi_cdecl,
			ret.C,
			(*C.jit_type_t)(nil),
			C.uint(0), 1)
		return &Signature{signature}
	} else {
		signature := C.jit_type_create_signature(C.jit_abi_cdecl,
			ret.C,
			(*C.jit_type_t)(unsafe.Pointer(&params[0])),
			C.uint(len(params)), 1)
		return &Signature{signature}
	}
}

func NewLabel() *Label {
	return &Label{C.jit_label_undefined}
}

// ========== Context =============

func (c *Context) NewFunction(ret Type, params []Type) *Function {
	signature := NewSignature(ret, params)
	function := C.jit_function_create(c.C, signature.C)
	C.jit_type_free(signature.C)
	return &Function{C: function, retType: ret, paramType: params}
}

func (c *Context) BuildStart() {
	C.jit_context_build_start(c.C)
}

func (c *Context) BuildEnd() {
	C.jit_context_build_end(c.C)
}

func (c *Context) Destroy() {
	C.jit_context_destroy(c.C)
}

// ========== Context =============

// ========== Function =============

func (f *Function) Param(i int) *Value {
	return &Value{C.jit_value_get_param(f.C, C.uint(i))}
}

func (f *Function) Param2() (*Value, *Value) {
	return &Value{C.jit_value_get_param(f.C, C.uint(0))},
		&Value{C.jit_value_get_param(f.C, C.uint(1))}
}

func (f *Function) Param3() (*Value, *Value, *Value) {
	return &Value{C.jit_value_get_param(f.C, C.uint(0))},
		&Value{C.jit_value_get_param(f.C, C.uint(1))},
		&Value{C.jit_value_get_param(f.C, C.uint(2))}
}

func (f *Function) Mul(a, b *Value) *Value {
	return &Value{C.jit_insn_mul(f.C, a.C, b.C)}
}

func (f *Function) Add(a, b *Value) *Value {
	return &Value{C.jit_insn_add(f.C, a.C, b.C)}
}

func (f *Function) Sub(a, b *Value) *Value {
	return &Value{C.jit_insn_sub(f.C, a.C, b.C)}
}

func (f *Function) Return(ret *Value) {
	C.jit_insn_return(f.C, ret.C)
}

func (f *Function) Store(x, y *Value) {
	C.jit_insn_store(f.C, x.C, y.C)
}

func (f *Function) StoreRelative(x *Value, offset int, y *Value) {
	C.jit_insn_store_relative(f.C, x.C, C.jit_nint(offset), y.C)
}

func (f *Function) Eq(a, b *Value) *Value {
	return &Value{C.jit_insn_eq(f.C, a.C, b.C)}
}

func (f *Function) BranchIfNot(v *Value, label *Label) {
	C.jit_insn_branch_if_not(f.C, v.C, (*C.jit_label_t)(unsafe.Pointer(label)))
}

func (f *Function) Label(label *Label) {
	C.jit_insn_label(f.C, (*C.jit_label_t)(unsafe.Pointer(label)))
}

func (f *Function) LessThan(a, b *Value) *Value {
	return &Value{C.jit_insn_lt(f.C, a.C, b.C)}
}

func (f *Function) TailCall(target *Function, values ...*Value) *Value {
	args := make([]C.jit_value_t, len(values))
	for i := range values {
		args[i] = values[i].C
	}
	return &Value{C.jit_insn_call(f.C,
		C.CString("noname"),
		target.C, nil, (*C.jit_value_t)(&args[0]), C.uint(len(args)), C.JIT_CALL_TAIL)}
}

func (f *Function) Call(target *Function, values []*Value) *Value {
	args := make([]C.jit_value_t, len(values))
	for i := range values {
		args[i] = values[i].C
	}
	return &Value{C.jit_insn_call(f.C,
		C.CString("noname"),
		target.C, nil, (*C.jit_value_t)(&args[0]), C.uint(len(args)), C.int(0))}
}

func (f *Function) Call0(name string, target *Function, values ...*Value) *Value {
	args := make([]C.jit_value_t, len(values))
	for i := range values {
		args[i] = values[i].C
	}
	return &Value{C.jit_insn_call(f.C,
		C.CString(name),
		target.C, nil, (*C.jit_value_t)(&args[0]), C.uint(len(args)), C.int(0))}
}

func (f *Function) CallNative(name string, target unsafe.Pointer, sig *Signature, values ...*Value) *Value {
	if len(values) == 0 {
		return &Value{C.jit_insn_call_native(f.C,
			C.CString(name),
			target,
			sig.C, (*C.jit_value_t)(nil),
			C.uint(0), C.JIT_CALL_NOTHROW)}
	} else {
		args := make([]C.jit_value_t, len(values))
		for i := range values {
			args[i] = values[i].C
		}
		return &Value{C.jit_insn_call_native(f.C,
			C.CString(name),
			target,
			sig.C, (*C.jit_value_t)(&args[0]),
			C.uint(len(args)), C.JIT_CALL_NOTHROW)}
	}
}

func (f *Function) Compile() {
	C.jit_function_compile(f.C)
}

func (f *Function) Run(values ...interface{}) interface{} {
	args := make([]unsafe.Pointer, len(values))
	for i := range values {
		switch f.paramType[i].C {
		case C.jit_type_int:
			x := C.jit_int(values[i].(int))
			args[i] = (unsafe.Pointer)(&x)

		case C.jit_type_uint:
			x := C.jit_uint(values[i].(uint))
			args[i] = (unsafe.Pointer)(&x)

		case C.jit_type_void_ptr:
			x := (unsafe.Pointer)(reflect.ValueOf(values[i]).Pointer())
			args[i] = (unsafe.Pointer)(&x)
		}
	}

	switch f.retType.C {
	case C.jit_type_int:
		result := C.jit_int(0)
		C.jit_function_apply(f.C, (*unsafe.Pointer)(&args[0]), unsafe.Pointer(&result))
		return int(result)

	case C.jit_type_uint:
		result := C.jit_uint(0)
		C.jit_function_apply(f.C, (*unsafe.Pointer)(&args[0]), unsafe.Pointer(&result))
		return uint(result)

	case C.jit_type_void:
		C.jit_function_apply(f.C, (*unsafe.Pointer)(&args[0]), unsafe.Pointer(nil))
		return nil

	}

	return nil
}

func (f *Function) Dump(name string) {
	C.jit_dump_function(C.getStdout(), f.C, C.CString(name))
}

func (f *Function) SetRecompilable() {
	C.jit_function_set_recompilable(f.C)
}

type compileFunction struct {
	F           *Function
	compileFunc func(*Function) bool
}

var registry = make(map[C.jit_function_t]*compileFunction)

func (f *Function) SetOnDemandCompiler(function func(f *Function) bool) {
	registry[f.C] = &compileFunction{f, function}
	C.SetOnDemandCompileFunction(f.C)
}

func (f *Function) GetOnDemandCompiler() func(*Function) bool {
	return registry[f.C].compileFunc
}

// ========== Function =============

//export on_demand_compile
func on_demand_compile(f C.jit_function_t) C.int {
	cf := registry[f]
	result := cf.compileFunc(cf.F)
	if result {
		return C.int(1)
	}
	return C.int(0)
}
<commit_msg>optimized value passing<commit_after>package jit

/*
#cgo CFLAGS: -I./include
#cgo linux,amd64 LDFLAGS: -L./lib -lm -ljit

#include <stdio.h>
#include <jit/jit.h>
#include <jit/jit-dump.h>

extern int on_demand_compile(jit_function_t);

static void SetOnDemandCompileFunction(jit_function_t f) {
    jit_function_set_on_demand_compiler(f, on_demand_compile);
}

static FILE *getStdout(void) { return stdout; }
*/
import "C"
import "unsafe"
import "reflect"

const CDECL = C.jit_abi_cdecl

type Context struct {
	C C.jit_context_t
}

type Type struct {
	C C.jit_type_t
}

type Signature struct {
	C C.jit_type_t
}

type Function struct {
	C         C.jit_function_t
	retType   Type
	paramType []Type
}

type Value struct {
	C C.jit_value_t
}

type Label struct {
	C C.jit_label_t
}

func Int() Type {
	return Type{C.jit_type_int}
}

func UInt() Type {
	return Type{C.jit_type_uint}
}

func Void() Type {
	return Type{C.jit_type_void}
}

func VoidPtr() Type {
	return Type{C.jit_type_void_ptr}
}

func NewContext() *Context {
	return &Context{C.jit_context_create()}
}

func NewSignature(ret Type, params []Type) *Signature {
	if len(params) == 0 {
		signature := C.jit_type_create_signature(C.jit_abi_cdecl,
			ret.C,
			(*C.jit_type_t)(nil),
			C.uint(0), 1)
		return &Signature{signature}
	} else {
		signature := C.jit_type_create_signature(C.jit_abi_cdecl,
			ret.C,
			(*C.jit_type_t)(unsafe.Pointer(&params[0])),
			C.uint(len(params)), 1)
		return &Signature{signature}
	}
}

func NewLabel() *Label {
	return &Label{C.jit_label_undefined}
}

// ========== Context =============

func (c *Context) NewFunction(ret Type, params []Type) *Function {
	signature := NewSignature(ret, params)
	function := C.jit_function_create(c.C, signature.C)
	C.jit_type_free(signature.C)
	return &Function{C: function, retType: ret, paramType: params}
}

func (c *Context) BuildStart() {
	C.jit_context_build_start(c.C)
}

func (c *Context) BuildEnd() {
	C.jit_context_build_end(c.C)
}

func (c *Context) Destroy() {
	C.jit_context_destroy(c.C)
}

// ========== Context =============

// ========== Function =============

func (f *Function) Param(i int) *Value {
	return &Value{C.jit_value_get_param(f.C, C.uint(i))}
}

func (f *Function) Param2() (*Value, *Value) {
	return &Value{C.jit_value_get_param(f.C, C.uint(0))},
		&Value{C.jit_value_get_param(f.C, C.uint(1))}
}

func (f *Function) Param3() (*Value, *Value, *Value) {
	return &Value{C.jit_value_get_param(f.C, C.uint(0))},
		&Value{C.jit_value_get_param(f.C, C.uint(1))},
		&Value{C.jit_value_get_param(f.C, C.uint(2))}
}

func (f *Function) Mul(a, b *Value) *Value {
	return &Value{C.jit_insn_mul(f.C, a.C, b.C)}
}

func (f *Function) Add(a, b *Value) *Value {
	return &Value{C.jit_insn_add(f.C, a.C, b.C)}
}

func (f *Function) Sub(a, b *Value) *Value {
	return &Value{C.jit_insn_sub(f.C, a.C, b.C)}
}

func (f *Function) Return(ret *Value) {
	C.jit_insn_return(f.C, ret.C)
}

func (f *Function) Store(x, y *Value) {
	C.jit_insn_store(f.C, x.C, y.C)
}

func (f *Function) StoreRelative(x *Value, offset int, y *Value) {
	C.jit_insn_store_relative(f.C, x.C, C.jit_nint(offset), y.C)
}

func (f *Function) Eq(a, b *Value) *Value {
	return &Value{C.jit_insn_eq(f.C, a.C, b.C)}
}

func (f *Function) BranchIfNot(v *Value, label *Label) {
	C.jit_insn_branch_if_not(f.C, v.C, (*C.jit_label_t)(unsafe.Pointer(label)))
}

func (f *Function) Label(label *Label) {
	C.jit_insn_label(f.C, (*C.jit_label_t)(unsafe.Pointer(label)))
}

func (f *Function) LessThan(a, b *Value) *Value {
	return &Value{C.jit_insn_lt(f.C, a.C, b.C)}
}

func (f *Function) TailCall(target *Function, values ...*Value) *Value {
	if len(values) == 0 {
		return &Value{C.jit_insn_call(f.C,
			C.CString("noname"),
			target.C, nil,
			(*C.jit_value_t)(nil),
			C.uint(0), C.JIT_CALL_TAIL)}
	} else {
		return &Value{C.jit_insn_call(f.C,
			C.CString("noname"),
			target.C, nil,
			(*C.jit_value_t)(unsafe.Pointer(values[0])),
			C.uint(len(values)), C.JIT_CALL_TAIL)}
	}
}

func (f *Function) Call(target *Function, values []*Value) *Value {
	if len(values) == 0 {
		return &Value{C.jit_insn_call(f.C,
			C.CString("noname"),
			target.C, nil,
			(*C.jit_value_t)(nil),
			C.uint(0), C.int(0))}
	} else {
		return &Value{C.jit_insn_call(f.C,
			C.CString("noname"),
			target.C, nil,
			(*C.jit_value_t)(unsafe.Pointer(values[0])),
			C.uint(len(values)), C.int(0))}
	}
}

func (f *Function) Call0(name string, target *Function, values ...*Value) *Value {
	if len(values) == 0 {
		return &Value{C.jit_insn_call(f.C,
			C.CString(name),
			target.C, nil,
			(*C.jit_value_t)(nil),
			C.uint(0), C.int(0))}
	} else {
		return &Value{C.jit_insn_call(f.C,
			C.CString(name),
			target.C, nil,
			(*C.jit_value_t)(unsafe.Pointer(values[0])),
			C.uint(len(values)), C.int(0))}
	}
}

func (f *Function) CallNative(name string, target unsafe.Pointer, sig *Signature, values ...*Value) *Value {
	if len(values) == 0 {
		return &Value{C.jit_insn_call_native(f.C,
			C.CString(name),
			target,
			sig.C, (*C.jit_value_t)(nil),
			C.uint(0), C.JIT_CALL_NOTHROW)}
	} else {
		return &Value{C.jit_insn_call_native(f.C,
			C.CString(name),
			target,
			sig.C, (*C.jit_value_t)(unsafe.Pointer(values[0])),
			C.uint(len(values)), C.JIT_CALL_NOTHROW)}
	}
}

func (f *Function) Compile() {
	C.jit_function_compile(f.C)
}

func (f *Function) Run(values ...interface{}) interface{} {
	args := make([]unsafe.Pointer, len(values))
	for i := range values {
		switch f.paramType[i].C {
		case C.jit_type_int:
			x := C.jit_int(values[i].(int))
			args[i] = (unsafe.Pointer)(&x)

		case C.jit_type_uint:
			x := C.jit_uint(values[i].(uint))
			args[i] = (unsafe.Pointer)(&x)

		case C.jit_type_void_ptr:
			x := (unsafe.Pointer)(reflect.ValueOf(values[i]).Pointer())
			args[i] = (unsafe.Pointer)(&x)
		}
	}

	switch f.retType.C {
	case C.jit_type_int:
		result := C.jit_int(0)
		C.jit_function_apply(f.C, (*unsafe.Pointer)(&args[0]), unsafe.Pointer(&result))
		return int(result)

	case C.jit_type_uint:
		result := C.jit_uint(0)
		C.jit_function_apply(f.C, (*unsafe.Pointer)(&args[0]), unsafe.Pointer(&result))
		return uint(result)

	case C.jit_type_void:
		C.jit_function_apply(f.C, (*unsafe.Pointer)(&args[0]), unsafe.Pointer(nil))
		return nil

	}

	return nil
}

func (f *Function) Dump(name string) {
	C.jit_dump_function(C.getStdout(), f.C, C.CString(name))
}

func (f *Function) SetRecompilable() {
	C.jit_function_set_recompilable(f.C)
}

type compileFunction struct {
	F           *Function
	compileFunc func(*Function) bool
}

var registry = make(map[C.jit_function_t]*compileFunction)

func (f *Function) SetOnDemandCompiler(function func(f *Function) bool) {
	registry[f.C] = &compileFunction{f, function}
	C.SetOnDemandCompileFunction(f.C)
}

func (f *Function) GetOnDemandCompiler() func(*Function) bool {
	return registry[f.C].compileFunc
}

// ========== Function =============

//export on_demand_compile
func on_demand_compile(f C.jit_function_t) C.int {
	cf := registry[f]
	result := cf.compileFunc(cf.F)
	if result {
		return C.int(1)
	}
	return C.int(0)
}
<|endoftext|>


<commit_before>// Package jwt is a barebones JWT implementation that only supports HS256
package jwt

import (
	"crypto/hmac"
	"crypto/sha256"
	"hash"
	"encoding/base64"
	"encoding/json"
	"errors"
	"strings"
	"time"
)

// Header containins important information for encrypting / decryting
type Header struct {
	Typ string // Token Type
	Alg string // Message Authentication Code Algorithm - The issuer can freely set an algorithm to verify the signature on the token. However, some asymmetrical algorithms pose security concerns
	Cty string // Content Type - This claim should always be JWT
}

// Payload contains the claims of the token
type Payload struct {
	//Standard Fields
	Iis string    // Issuer - identifies principal that issued the JWT;
	Sub string    // Subject - identifies the subject of the JWT;
	Aud string    // Audience - The "aud" (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the aud claim when this claim is present, then the JWT MUST be rejected.
	Exp time.Time // Expiration time - The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.
	Nbf time.Time // Not before - Similarly, the not-before time claim identifies the time on which the JWT will start to be accepted for processing.
	Iat time.Time // Issued at - The "iat" (issued at) claim identifies the time at which the JWT was issued.
	Jti string    // JWT ID - case sensitive unique identifier of the token even among different issuers.
}

//HmacSha256 returns the hash for HMAC with SHA256
func HmacSha256(key string) hash.Hash {
	return hmac.New(sha256.New, []byte(key))
}

//Sign signs the token with the given hash, and key
func Sign(signingHash hash.Hash, unsignedToken string) (string, error){
	_, err := signingHash.Write([]byte(unsignedToken))
	if err != nil {
		return "", errors.New("Unable to write to HMAC-SHA256")
	}

	encodedToken := base64.StdEncoding.EncodeToString(signingHash.Sum(nil))
	signingHash.Reset()

	return encodedToken, nil
}

// Encode returns an encoded JWT token from a header, payload, and secret
func Encode(signingHash hash.Hash, header Header, payload Payload) (string, error) {
	jsonTokenHeader, err := json.Marshal(header)
	if err != nil {
		return "", errors.New("unable to marshal header")
	}

	b64TokenHeader := base64.StdEncoding.EncodeToString(jsonTokenHeader)

	jsonTokenPayload, err := json.Marshal(payload)
	if err != nil {
		return "", errors.New("unable to marshal payload")
	}

	b64TokenPayload := base64.StdEncoding.EncodeToString(jsonTokenPayload)

	unsignedSignature := b64TokenHeader + "." + b64TokenPayload

	signature, err := Sign(signingHash, unsignedSignature)
	if err != nil {
		return "", err
	}
	b64Signature := base64.StdEncoding.EncodeToString([]byte(signature))

	token := b64TokenHeader + "." + b64TokenPayload + "." + b64Signature

	return token, nil
}

// Verify verifies if a token is valid,
func Verify(signingHash hash.Hash, encoded string) error {
	encryptedComponents := strings.Split(encoded, ".")

	b64Header := encryptedComponents[0]
	b64Payload := encryptedComponents[1]
	b64Signature := encryptedComponents[2]

	unsignedAttempt := b64Header + "." + b64Payload
	signedAttempt, err := Sign(signingHash, unsignedAttempt)

	if err != nil {
		return err
	}

	b64SignedAttempt := base64.StdEncoding.EncodeToString([]byte(signedAttempt))

	if strings.Compare(b64Signature, b64SignedAttempt) != 0 {
		return errors.New("Invalid Signature Doesn't Match")
	}

	return nil
}
<commit_msg>Refactored api to be cleaner<commit_after>// Package jwt is a barebones JWT implementation that only supports HS256
package jwt

import (
	"crypto/hmac"
	"crypto/sha256"
	"crypto/sha512"
	"hash"
	"encoding/base64"
	"encoding/json"
	"errors"
	"strings"
	"time"
)

//SigningMethod is the algorithm used to sign and validate a token.
type SigningMethod struct {
	signingHash hash.Hash
	algorithm string
}

// NewHeader returns a new Header object.
func (method *SigningMethod) NewHeader() *Header{
	return &Header{
		Typ: "JWT",
		Alg: method.algorithm,
	}
}

// Sum returns the sum of the hash
func (method *SigningMethod) Sum(data []byte) []byte {
	return method.signingHash.Sum(data)
}

// Reset resets the hash
func (method *SigningMethod) Reset(){
	method.signingHash.Reset()
}

// Write writes the specified bytes to the hash
func (method *SigningMethod) Write(data []byte) (int, error){
	return method.signingHash.Write(data)
}

// Header containins important information for encrypting / decryting
type Header struct {
	Typ string // Token Type
	Alg string // Message Authentication Code Algorithm - The issuer can freely set an algorithm to verify the signature on the token. However, some asymmetrical algorithms pose security concerns
	Cty string // Content Type - This claim should always be JWT
}

// Payload contains the claims of the token
type Payload struct {
	//Standard Fields
	Iis string    // Issuer - identifies principal that issued the JWT;
	Sub string    // Subject - identifies the subject of the JWT;
	Aud string    // Audience - The "aud" (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the aud claim when this claim is present, then the JWT MUST be rejected.
	Exp time.Time // Expiration time - The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.
	Nbf time.Time // Not before - Similarly, the not-before time claim identifies the time on which the JWT will start to be accepted for processing.
	Iat time.Time // Issued at - The "iat" (issued at) claim identifies the time at which the JWT was issued.
	Jti string    // JWT ID - case sensitive unique identifier of the token even among different issuers.
}

//HmacSha256 returns the SingingMethod for HMAC with SHA256
func HmacSha256(key string) SigningMethod {
	return SigningMethod{
		algorithm: "HS256",
		signingHash: hmac.New(sha256.New, []byte(key)),
	}
}

//HmacSha512 returns the SigningMethod for HMAC with SHA512
func HmacSha512(key string) SigningMethod {
	return SigningMethod{
		algorithm: "HS512",
		signingHash: hmac.New(sha512.New, []byte(key)),
	}
}

//Sign signs the token with the given hash, and key
func Sign(signingHash SigningMethod, unsignedToken string) (string, error){
	_, err := signingHash.Write([]byte(unsignedToken))
	if err != nil {
		return "", errors.New("Unable to write to HMAC-SHA256")
	}

	encodedToken := base64.StdEncoding.EncodeToString(signingHash.Sum(nil))
	signingHash.Reset()

	return encodedToken, nil
}

// Encode returns an encoded JWT token from a header, payload, and secret
func Encode(signingHash SigningMethod, header Header, payload Payload) (string, error) {
	jsonTokenHeader, err := json.Marshal(header)
	if err != nil {
		return "", errors.New("unable to marshal header")
	}

	b64TokenHeader := base64.StdEncoding.EncodeToString(jsonTokenHeader)

	jsonTokenPayload, err := json.Marshal(payload)
	if err != nil {
		return "", errors.New("unable to marshal payload")
	}

	b64TokenPayload := base64.StdEncoding.EncodeToString(jsonTokenPayload)

	unsignedSignature := b64TokenHeader + "." + b64TokenPayload

	signature, err := Sign(signingHash, unsignedSignature)
	if err != nil {
		return "", err
	}
	b64Signature := base64.StdEncoding.EncodeToString([]byte(signature))

	token := b64TokenHeader + "." + b64TokenPayload + "." + b64Signature

	return token, nil
}

// Verify verifies if a token is valid,
func Verify(signingHash SigningMethod, encoded string) error {
	encryptedComponents := strings.Split(encoded, ".")

	b64Header := encryptedComponents[0]
	b64Payload := encryptedComponents[1]
	b64Signature := encryptedComponents[2]

	unsignedAttempt := b64Header + "." + b64Payload
	signedAttempt, err := Sign(signingHash, unsignedAttempt)

	if err != nil {
		return err
	}

	b64SignedAttempt := base64.StdEncoding.EncodeToString([]byte(signedAttempt))

	if strings.Compare(b64Signature, b64SignedAttempt) != 0 {
		return errors.New("Invalid Signature Doesn't Match")
	}

	return nil
}
<|endoftext|>


<commit_before>// Wrapper over jose utilities that implements JSON Web Signature (JWS) and JSON Web Encryption (JWE).

package jwt

import (
	"crypto/rand"
	"crypto/rsa"
	"fmt"
	"strconv"
	"time"

	"github.com/pkg/errors"
	"gopkg.in/square/go-jose.v2"
	"gopkg.in/square/go-jose.v2/jwt"
)

const (
	prvKeyBits         = 2048
	signatureAlgorithm = jose.PS512
	keyAlgorithm       = jose.RSA_OAEP
	contentAlgorithm   = jose.A128GCM
)

func genKey() (*rsa.PrivateKey, error) {
	return rsa.GenerateKey(rand.Reader, prvKeyBits)
}

// Claims specify registered claim names specified in https://tools.ietf.org/html/rfc7519#section-4.1.
type Claims struct {
	Issuer    string      `json:"iss,omitempty"`
	Subject   string      `json:"sub,omitempty"`
	Audience  []string    `json:"aud,omitempty"`
	Expiry    NumericDate `json:"exp,omitempty"`
	NotBefore NumericDate `json:"nbf,omitempty"`
	IssuedAt  NumericDate `json:"iat,omitempty"`
	ID        string      `json:"jti,omitempty"`

	timeNow func() time.Time
}

// ValidateWithLeeway checks claims in a token against expected values. A custom leeway may be specified for comparing
// time values. You may pass a zero value to check time values with no leeway, but you should note that numeric date
// values are rounded to the nearest second and sub-second precision is not supported.
func (c Claims) ValidateWithLeeway(e Claims, leeway time.Duration) error {
	if e.Issuer != "" && e.Issuer != c.Issuer {
		return fmt.Errorf("Invalid issuer. Expected: %q, got: %q", e.Issuer, c.Issuer)
	}

	if e.Subject != "" && e.Subject != c.Subject {
		return fmt.Errorf("Invalid subject. Expected: %q, got: %q", e.Subject, c.Subject)
	}

	if e.ID != "" && e.ID != c.ID {
		return fmt.Errorf("Invalid ID. Expected: %q, got: %q", e.ID, c.ID)
	}

	if len(e.Audience) != 0 {
		if len(e.Audience) != len(c.Audience) {
			return fmt.Errorf("Invalid Audience. Expected len: %d, got: %d", len(e.Audience), len(c.Audience))
		}

		audienceLookup := map[string]struct{}{}
		for _, v := range c.Audience {
			audienceLookup[v] = struct{}{}
		}

		for _, v := range e.Audience {
			if _, ok := audienceLookup[v]; !ok {
				return fmt.Errorf("Invalid Audience. Expected: %q and  not found.", v)
			}
		}

	}

	if c.timeNow == nil {
		c.timeNow = time.Now
	}

	now := c.timeNow()
	if now.IsZero() {
		return nil
	}

	if now.Add(leeway).Before(c.NotBefore.Time()) {
		return fmt.Errorf("Violated NotBefore. It is before specified time %q", c.NotBefore.Time().String())
	}

	if now.Add(-leeway).After(c.Expiry.Time()) {
		return fmt.Errorf("Exipred claim. Expiration time %q", c.Expiry.Time())

	}

	return nil
}

// jwtPayload defines special claim custom payload.
// Needed to avoid collisions. https://tools.ietf.org/html/rfc7519#section-4.2
type jwtPayload struct {
	Payload interface{} `json:"payload"`
}

// Builder is an builder that is able to construct nested JWT or JWS with custom payload claim or other claims.
// Nested JSON Web Token is token that is signed and encrypted respectively).
type Builder struct {
	*SignedObtainer

	// Private key encryption and signatures used with every JWT handled by this builder.
	prvKey *rsa.PrivateKey

	signer    jose.Signer
	encrypter jose.Encrypter
}

func NewBuilder() (*Builder, error) {
	prvKey, err := genKey()
	if err != nil {
		return nil, fmt.Errorf("JWT Builder: Could not generate RSA key. Err: %v", err)
	}

	signer, err := jose.NewSigner(
		jose.SigningKey{
			Algorithm: signatureAlgorithm,
			Key:       prvKey,
		},
		nil,
	)
	if err != nil {
		return nil, fmt.Errorf("JWT Builder: Could not build signer. Err: %v", err)
	}

	encrypter, err := jose.NewEncrypter(
		contentAlgorithm,
		jose.Recipient{
			Algorithm: keyAlgorithm,
			Key:       &prvKey.PublicKey,
		},
		(&jose.EncrypterOptions{}).WithType("JWT").WithContentType("JWT"),
	)
	if err != nil {
		return nil, fmt.Errorf("JWT Builder: Could not build encrypter. Err: %v", err)
	}

	return &Builder{
		SignedObtainer: NewSignedObtainer(&prvKey.PublicKey),
		prvKey:         prvKey,
		signer:         signer,
		encrypter:      encrypter,
	}, nil
}

// SignedAndEncryptedJWT constructs nested JSON Web Token that is both signed and encrypted respectively
func (j *Builder) SignedAndEncryptedJWT() *BuilderWrapper {
	return &BuilderWrapper{engine: jwt.SignedAndEncrypted(j.signer, j.encrypter)}
}

// JWS constructs JSON Web Token that is only signed.
func (j *Builder) JWS() *BuilderWrapper {
	return &BuilderWrapper{engine: jwt.Signed(j.signer)}
}

// JWE constructs JSON Web Token that is only encrypted.
func (j *Builder) JWE() *BuilderWrapper {
	return &BuilderWrapper{engine: jwt.Encrypted(j.encrypter)}
}

// FromSignedAndEncryptedJWT parsed given token as nested JSON Web Token's and decrypts it.
// Returned ObtainerWrapper can be used to fetch claims. Signature verification is done by ObtainerWrapper.
func (j *Builder) FromSignedAndEncryptedJWT(token string) *ObtainerWrapper {
	nestedJWT, err := jwt.ParseSignedAndEncrypted(token)
	if err != nil {
		return &ObtainerWrapper{err: fmt.Errorf("JWT Builder: Could not parse given token as nested JSON Web Token. Err: %v", err)}
	}

	signedJWT, err := nestedJWT.Decrypt(j.prvKey)
	if err != nil {
		return &ObtainerWrapper{err: fmt.Errorf("JWT Builder: Could not decrypt given nested JSON Web Token. Err: %v", err)}
	}

	return &ObtainerWrapper{parsedToken: signedJWT, key: &j.prvKey.PublicKey}
}

// FromJWS decrypts JSON Web Token's.
// Returned ObtainerWrapper can be used to fetch claims. Decryption is done by ObtainerWrapper.
func (j *Builder) FromJWE(token string) *ObtainerWrapper {
	encrypted, err := jwt.ParseEncrypted(token)
	if err != nil {
		return &ObtainerWrapper{err: fmt.Errorf("JWT Builder: Could not parse given token as encrypted JSON Web Token. Err: %v", err)}
	}

	return &ObtainerWrapper{parsedToken: encrypted, key: j.prvKey}
}

type SignedObtainer struct {
	pubKey *rsa.PublicKey

	timeNow func() time.Time
}

func NewSignedObtainer(publicKey *rsa.PublicKey) *SignedObtainer {
	return &SignedObtainer{
		pubKey:  publicKey,
		timeNow: time.Now,
	}
}

// FromJWS parses given JWS.
// Returned ObtainerWrapper can be used to fetch claims. Signature verification is done by ObtainerWrapper.
func (j *SignedObtainer) FromJWS(token string) *ObtainerWrapper {
	signed, err := jwt.ParseSigned(token)
	if err != nil {
		return &ObtainerWrapper{err: fmt.Errorf("JWT Builder: Could not parse given token as signed JSON Web Token. Err: %v", err)}
	}

	return &ObtainerWrapper{parsedToken: signed, key: j.pubKey}
}

// VerifyClaims verifies standard "iss", "sub", "aud", "exp" claims from JWT RFC (https://tools.ietf.org/html/rfc7519).
func (j *SignedObtainer) VerifyStdClaims(claims Claims, expected Claims) error {
	err := claims.ValidateWithLeeway(expected, 1*time.Second)
	if err != nil {
		return fmt.Errorf("JWT Builder: claims validation failed. Err: %v", err)
	}
	return nil
}

// BuilderWrapper wraps specified engine and enabling packing and serializing claims into single token.
type BuilderWrapper struct {
	engine interface{}
}

// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
// into single JSON object.
func (b *BuilderWrapper) Claims(claims interface{}) *BuilderWrapper {
	switch builder := b.engine.(type) {
	case jwt.Builder:
		b.engine = builder.Claims(claims)
	case jwt.NestedBuilder:
		b.engine = builder.Claims(claims)
	}
	return b
}

// Payload encodes payload into JWE/JWS form in a `payload` field. Multiple calls will override payload.
func (b *BuilderWrapper) Payload(payload interface{}) *BuilderWrapper {
	switch builder := b.engine.(type) {
	case jwt.Builder:
		b.engine = builder.Claims(
			jwtPayload{
				Payload: payload,
			},
		)
	case jwt.NestedBuilder:
		b.engine = builder.Claims(
			jwtPayload{
				Payload: payload,
			},
		)
	}
	return b
}

func (b *BuilderWrapper) CompactSerialize() (string, error) {
	switch builder := b.engine.(type) {
	case jwt.Builder:
		return builder.CompactSerialize()
	case jwt.NestedBuilder:
		return builder.CompactSerialize()
	}
	return "", errors.New("JWT BuildWrapper internal error: Wrong type of wrapped engine.")
}

// ObtainerWrapper wraps token and enables deserialization from token.
type ObtainerWrapper struct {
	err         error
	parsedToken *jwt.JSONWebToken
	key         interface{} // *rsa.PublicKey or rsa.PrivateKey
}

func (o *ObtainerWrapper) Claims(out interface{}) error {
	if o.err != nil {
		return o.err
	}
	err := o.parsedToken.Claims(o.key, &out)
	if err != nil {
		return fmt.Errorf("JWT ObtainerWrapper: Could not deserialize JSON Web Token into given type. Err: %v", err)
	}
	return nil
}

func (o *ObtainerWrapper) Payload(out interface{}) error {
	if o.err != nil {
		return o.err
	}
	payload := jwtPayload{
		Payload: out,
	}
	err := o.parsedToken.Claims(o.key, &payload)
	if err != nil {
		return fmt.Errorf("JWT ObtainerWrapper: Could not deserialize JSON Web Token into given payload type. Err: %v", err)
	}
	return nil
}

func (o *ObtainerWrapper) StdClaims() (Claims, error) {
	if o.err != nil {
		return Claims{}, o.err
	}
	var claims Claims
	err := o.parsedToken.Claims(o.key, &claims)
	if err != nil {
		return Claims{}, fmt.Errorf("JWT ObtainerWrapper: Could not deserialize JSON Web Token into standard claims. Err: %v", err)
	}
	return claims, nil
}

// NumericDate represents date and time as the number of seconds since the
// epoch, including leap seconds. Non-integer values can be represented
// in the serialized format, but we round to the nearest second.
type NumericDate int64

// NewNumericDate constructs NumericDate from time.Time value.
func NewNumericDate(t time.Time) NumericDate {
	if t.IsZero() {
		return NumericDate(0)
	}

	// While RFC 7519 technically states that NumericDate values may be
	// non-integer values, we don't bother serializing timestamps in
	// claims with sub-second accuracy and just round to the nearest
	// second instead.
	return NumericDate(t.Unix())
}

// MarshalJSON serializes the given NumericDate into its JSON representation.
func (n NumericDate) MarshalJSON() ([]byte, error) {
	return []byte(strconv.FormatInt(int64(n), 10)), nil
}

// UnmarshalJSON reads a date from its JSON representation.
func (n *NumericDate) UnmarshalJSON(b []byte) error {
	s := string(b)

	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return fmt.Errorf("Failed to unmarshall NumericDate. Err: %v", err)
	}

	*n = NumericDate(f)
	return nil
}

// Time returns time.Time representation of NumericDate.
func (n NumericDate) Time() time.Time {
	return time.Unix(int64(n), 0)
}
<commit_msg>Changed algorithm to RSA512<commit_after>// Wrapper over jose utilities that implements JSON Web Signature (JWS) and JSON Web Encryption (JWE).

package jwt

import (
	"crypto/rand"
	"crypto/rsa"
	"fmt"
	"strconv"
	"time"

	"github.com/pkg/errors"
	"gopkg.in/square/go-jose.v2"
	"gopkg.in/square/go-jose.v2/jwt"
)

const (
	prvKeyBits         = 2048
	signatureAlgorithm = jose.RS512
	keyAlgorithm       = jose.RSA_OAEP
	contentAlgorithm   = jose.A128GCM
)

func genKey() (*rsa.PrivateKey, error) {
	return rsa.GenerateKey(rand.Reader, prvKeyBits)
}

// Claims specify registered claim names specified in https://tools.ietf.org/html/rfc7519#section-4.1.
type Claims struct {
	Issuer    string      `json:"iss,omitempty"`
	Subject   string      `json:"sub,omitempty"`
	Audience  []string    `json:"aud,omitempty"`
	Expiry    NumericDate `json:"exp,omitempty"`
	NotBefore NumericDate `json:"nbf,omitempty"`
	IssuedAt  NumericDate `json:"iat,omitempty"`
	ID        string      `json:"jti,omitempty"`

	timeNow func() time.Time
}

// ValidateWithLeeway checks claims in a token against expected values. A custom leeway may be specified for comparing
// time values. You may pass a zero value to check time values with no leeway, but you should note that numeric date
// values are rounded to the nearest second and sub-second precision is not supported.
func (c Claims) ValidateWithLeeway(e Claims, leeway time.Duration) error {
	if e.Issuer != "" && e.Issuer != c.Issuer {
		return fmt.Errorf("Invalid issuer. Expected: %q, got: %q", e.Issuer, c.Issuer)
	}

	if e.Subject != "" && e.Subject != c.Subject {
		return fmt.Errorf("Invalid subject. Expected: %q, got: %q", e.Subject, c.Subject)
	}

	if e.ID != "" && e.ID != c.ID {
		return fmt.Errorf("Invalid ID. Expected: %q, got: %q", e.ID, c.ID)
	}

	if len(e.Audience) != 0 {
		if len(e.Audience) != len(c.Audience) {
			return fmt.Errorf("Invalid Audience. Expected len: %d, got: %d", len(e.Audience), len(c.Audience))
		}

		audienceLookup := map[string]struct{}{}
		for _, v := range c.Audience {
			audienceLookup[v] = struct{}{}
		}

		for _, v := range e.Audience {
			if _, ok := audienceLookup[v]; !ok {
				return fmt.Errorf("Invalid Audience. Expected: %q and  not found.", v)
			}
		}

	}

	if c.timeNow == nil {
		c.timeNow = time.Now
	}

	now := c.timeNow()
	if now.IsZero() {
		return nil
	}

	if now.Add(leeway).Before(c.NotBefore.Time()) {
		return fmt.Errorf("Violated NotBefore. It is before specified time %q", c.NotBefore.Time().String())
	}

	if now.Add(-leeway).After(c.Expiry.Time()) {
		return fmt.Errorf("Exipred claim. Expiration time %q", c.Expiry.Time())

	}

	return nil
}

// jwtPayload defines special claim custom payload.
// Needed to avoid collisions. https://tools.ietf.org/html/rfc7519#section-4.2
type jwtPayload struct {
	Payload interface{} `json:"payload"`
}

// Builder is an builder that is able to construct nested JWT or JWS with custom payload claim or other claims.
// Nested JSON Web Token is token that is signed and encrypted respectively).
type Builder struct {
	*SignedObtainer

	// Private key encryption and signatures used with every JWT handled by this builder.
	prvKey *rsa.PrivateKey

	signer    jose.Signer
	encrypter jose.Encrypter
}

func NewBuilder() (*Builder, error) {
	prvKey, err := genKey()
	if err != nil {
		return nil, fmt.Errorf("JWT Builder: Could not generate RSA key. Err: %v", err)
	}

	signer, err := jose.NewSigner(
		jose.SigningKey{
			Algorithm: signatureAlgorithm,
			Key:       prvKey,
		},
		nil,
	)
	if err != nil {
		return nil, fmt.Errorf("JWT Builder: Could not build signer. Err: %v", err)
	}

	encrypter, err := jose.NewEncrypter(
		contentAlgorithm,
		jose.Recipient{
			Algorithm: keyAlgorithm,
			Key:       &prvKey.PublicKey,
		},
		(&jose.EncrypterOptions{}).WithType("JWT").WithContentType("JWT"),
	)
	if err != nil {
		return nil, fmt.Errorf("JWT Builder: Could not build encrypter. Err: %v", err)
	}

	return &Builder{
		SignedObtainer: NewSignedObtainer(&prvKey.PublicKey),
		prvKey:         prvKey,
		signer:         signer,
		encrypter:      encrypter,
	}, nil
}

// SignedAndEncryptedJWT constructs nested JSON Web Token that is both signed and encrypted respectively
func (j *Builder) SignedAndEncryptedJWT() *BuilderWrapper {
	return &BuilderWrapper{engine: jwt.SignedAndEncrypted(j.signer, j.encrypter)}
}

// JWS constructs JSON Web Token that is only signed.
func (j *Builder) JWS() *BuilderWrapper {
	return &BuilderWrapper{engine: jwt.Signed(j.signer)}
}

// JWE constructs JSON Web Token that is only encrypted.
func (j *Builder) JWE() *BuilderWrapper {
	return &BuilderWrapper{engine: jwt.Encrypted(j.encrypter)}
}

// FromSignedAndEncryptedJWT parsed given token as nested JSON Web Token's and decrypts it.
// Returned ObtainerWrapper can be used to fetch claims. Signature verification is done by ObtainerWrapper.
func (j *Builder) FromSignedAndEncryptedJWT(token string) *ObtainerWrapper {
	nestedJWT, err := jwt.ParseSignedAndEncrypted(token)
	if err != nil {
		return &ObtainerWrapper{err: fmt.Errorf("JWT Builder: Could not parse given token as nested JSON Web Token. Err: %v", err)}
	}

	signedJWT, err := nestedJWT.Decrypt(j.prvKey)
	if err != nil {
		return &ObtainerWrapper{err: fmt.Errorf("JWT Builder: Could not decrypt given nested JSON Web Token. Err: %v", err)}
	}

	return &ObtainerWrapper{parsedToken: signedJWT, key: &j.prvKey.PublicKey}
}

// FromJWS decrypts JSON Web Token's.
// Returned ObtainerWrapper can be used to fetch claims. Decryption is done by ObtainerWrapper.
func (j *Builder) FromJWE(token string) *ObtainerWrapper {
	encrypted, err := jwt.ParseEncrypted(token)
	if err != nil {
		return &ObtainerWrapper{err: fmt.Errorf("JWT Builder: Could not parse given token as encrypted JSON Web Token. Err: %v", err)}
	}

	return &ObtainerWrapper{parsedToken: encrypted, key: j.prvKey}
}

type SignedObtainer struct {
	pubKey *rsa.PublicKey

	timeNow func() time.Time
}

func NewSignedObtainer(publicKey *rsa.PublicKey) *SignedObtainer {
	return &SignedObtainer{
		pubKey:  publicKey,
		timeNow: time.Now,
	}
}

// FromJWS parses given JWS.
// Returned ObtainerWrapper can be used to fetch claims. Signature verification is done by ObtainerWrapper.
func (j *SignedObtainer) FromJWS(token string) *ObtainerWrapper {
	signed, err := jwt.ParseSigned(token)
	if err != nil {
		return &ObtainerWrapper{err: fmt.Errorf("JWT Builder: Could not parse given token as signed JSON Web Token. Err: %v", err)}
	}

	return &ObtainerWrapper{parsedToken: signed, key: j.pubKey}
}

// VerifyClaims verifies standard "iss", "sub", "aud", "exp" claims from JWT RFC (https://tools.ietf.org/html/rfc7519).
func (j *SignedObtainer) VerifyStdClaims(claims Claims, expected Claims) error {
	err := claims.ValidateWithLeeway(expected, 1*time.Second)
	if err != nil {
		return fmt.Errorf("JWT Builder: claims validation failed. Err: %v", err)
	}
	return nil
}

// BuilderWrapper wraps specified engine and enabling packing and serializing claims into single token.
type BuilderWrapper struct {
	engine interface{}
}

// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
// into single JSON object.
func (b *BuilderWrapper) Claims(claims interface{}) *BuilderWrapper {
	switch builder := b.engine.(type) {
	case jwt.Builder:
		b.engine = builder.Claims(claims)
	case jwt.NestedBuilder:
		b.engine = builder.Claims(claims)
	}
	return b
}

// Payload encodes payload into JWE/JWS form in a `payload` field. Multiple calls will override payload.
func (b *BuilderWrapper) Payload(payload interface{}) *BuilderWrapper {
	switch builder := b.engine.(type) {
	case jwt.Builder:
		b.engine = builder.Claims(
			jwtPayload{
				Payload: payload,
			},
		)
	case jwt.NestedBuilder:
		b.engine = builder.Claims(
			jwtPayload{
				Payload: payload,
			},
		)
	}
	return b
}

func (b *BuilderWrapper) CompactSerialize() (string, error) {
	switch builder := b.engine.(type) {
	case jwt.Builder:
		return builder.CompactSerialize()
	case jwt.NestedBuilder:
		return builder.CompactSerialize()
	}
	return "", errors.New("JWT BuildWrapper internal error: Wrong type of wrapped engine.")
}

// ObtainerWrapper wraps token and enables deserialization from token.
type ObtainerWrapper struct {
	err         error
	parsedToken *jwt.JSONWebToken
	key         interface{} // *rsa.PublicKey or rsa.PrivateKey
}

func (o *ObtainerWrapper) Claims(out interface{}) error {
	if o.err != nil {
		return o.err
	}
	err := o.parsedToken.Claims(o.key, &out)
	if err != nil {
		return fmt.Errorf("JWT ObtainerWrapper: Could not deserialize JSON Web Token into given type. Err: %v", err)
	}
	return nil
}

func (o *ObtainerWrapper) Payload(out interface{}) error {
	if o.err != nil {
		return o.err
	}
	payload := jwtPayload{
		Payload: out,
	}
	err := o.parsedToken.Claims(o.key, &payload)
	if err != nil {
		return fmt.Errorf("JWT ObtainerWrapper: Could not deserialize JSON Web Token into given payload type. Err: %v", err)
	}
	return nil
}

func (o *ObtainerWrapper) StdClaims() (Claims, error) {
	if o.err != nil {
		return Claims{}, o.err
	}
	var claims Claims
	err := o.parsedToken.Claims(o.key, &claims)
	if err != nil {
		return Claims{}, fmt.Errorf("JWT ObtainerWrapper: Could not deserialize JSON Web Token into standard claims. Err: %v", err)
	}
	return claims, nil
}

// NumericDate represents date and time as the number of seconds since the
// epoch, including leap seconds. Non-integer values can be represented
// in the serialized format, but we round to the nearest second.
type NumericDate int64

// NewNumericDate constructs NumericDate from time.Time value.
func NewNumericDate(t time.Time) NumericDate {
	if t.IsZero() {
		return NumericDate(0)
	}

	// While RFC 7519 technically states that NumericDate values may be
	// non-integer values, we don't bother serializing timestamps in
	// claims with sub-second accuracy and just round to the nearest
	// second instead.
	return NumericDate(t.Unix())
}

// MarshalJSON serializes the given NumericDate into its JSON representation.
func (n NumericDate) MarshalJSON() ([]byte, error) {
	return []byte(strconv.FormatInt(int64(n), 10)), nil
}

// UnmarshalJSON reads a date from its JSON representation.
func (n *NumericDate) UnmarshalJSON(b []byte) error {
	s := string(b)

	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return fmt.Errorf("Failed to unmarshall NumericDate. Err: %v", err)
	}

	*n = NumericDate(f)
	return nil
}

// Time returns time.Time representation of NumericDate.
func (n NumericDate) Time() time.Time {
	return time.Unix(int64(n), 0)
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package saltpack

import (
	"crypto/hmac"
)

// RawBoxKey is the raw byte-representation of what a box key should
// look like, a static 32-byte buffer. Used for NaCl Box.
type RawBoxKey [32]byte

func rawBoxKeyFromSlice(slice []byte) (*RawBoxKey, error) {
	var result RawBoxKey
	if len(slice) != len(result) {
		return nil, ErrBadBoxKey
	}
	copy(result[:], slice)
	return &result, nil
}

// SymmetricKey is a template for a symmetric key, a 32-byte static
// buffer. Used for NaCl SecretBox.
type SymmetricKey [32]byte

func symmetricKeyFromSlice(slice []byte) (*SymmetricKey, error) {
	var result SymmetricKey
	if len(slice) != len(result) {
		return nil, ErrBadSymmetricKey
	}
	copy(result[:], slice)
	return &result, nil
}

// KIDExtractor key types can output a key ID corresponding to the
// key.
type KIDExtractor interface {
	// ToKID outputs the "key ID" that corresponds to this key.
	// You can do whatever you'd like here, but probably it makes sense just
	// to output the public key as is.
	ToKID() []byte
}

// BoxPublicKey is an generic interface to NaCl's public key Box function.
type BoxPublicKey interface {
	KIDExtractor

	// ToRawBoxKeyPointer returns this public key as a *[32]byte,
	// for use with nacl.box.Seal
	ToRawBoxKeyPointer() *RawBoxKey

	// CreateEmphemeralKey creates an ephemeral key of the same type,
	// but totally random.
	CreateEphemeralKey() (BoxSecretKey, error)

	// HideIdentity returns true if we should hide the identity of this
	// key in our output message format.
	HideIdentity() bool
}

// BoxPrecomputedSharedKey results from a Precomputation below.
type BoxPrecomputedSharedKey interface {
	Unbox(nonce *Nonce, msg []byte) ([]byte, error)
	Box(nonce *Nonce, msg []byte) []byte
}

// BoxSecretKey is the secret key corresponding to a BoxPublicKey
type BoxSecretKey interface {

	// Box boxes up data, sent from this secret key, and to the receiver
	// specified.
	Box(receiver BoxPublicKey, nonce *Nonce, msg []byte) []byte

	// Unobx opens up the box, using this secret key as the receiver key
	// abd the give public key as the sender key.
	Unbox(sender BoxPublicKey, nonce *Nonce, msg []byte) ([]byte, error)

	// GetPublicKey gets the public key associated with this secret key.
	GetPublicKey() BoxPublicKey

	// Precompute computes a DH with the given key
	Precompute(sender BoxPublicKey) BoxPrecomputedSharedKey
}

// SigningSecretKey is a secret NaCl key that can sign messages.
type SigningSecretKey interface {
	// Sign signs message with this secret key.
	Sign(message []byte) ([]byte, error)

	// PublicKey gets the public key associated with this secret key.
	PublicKey() SigningPublicKey
}

// SigningPublicKey is a public NaCl key that can verify
// signatures.
type SigningPublicKey interface {
	KIDExtractor

	// Verify verifies that signature is a valid signature of message for
	// this public key.
	Verify(message []byte, signature []byte) error
}

// Keyring is an interface used with decryption; it is called to
// recover public or private keys during the decryption process.
// Calls can block on network action.
type Keyring interface {
	// LookupBoxSecretKey looks in the Keyring for the secret key corresponding
	// to one of the given Key IDs.  Returns the index and the key on success,
	// or -1 and nil on failure.
	LookupBoxSecretKey(kids [][]byte) (int, BoxSecretKey)

	// LookupBoxPublicKey returns a public key given the specified key ID.
	// For most cases, the key ID will be the key itself.
	LookupBoxPublicKey(kid []byte) BoxPublicKey

	// GetAllSecretKeys returns all keys, needed if we want to support
	// "hidden" receivers via trial and error
	GetAllSecretKeys() []BoxSecretKey

	// ImportEphemeralKey imports the ephemeral key into
	// BoxPublicKey format. This key has never been seen before, so
	// will be ephemeral.
	ImportEphemeralKey(kid []byte) BoxPublicKey
}

// SigKeyring is an interface used during verification to find
// the public key for the signer of a message.
type SigKeyring interface {
	// LookupSigningPublicKey returns a public signing key for the specified key ID.
	LookupSigningPublicKey(kid []byte) SigningPublicKey
}

// SecretKeyEqual returns true if the two secret keys are equal.
func SecretKeyEqual(sk1, sk2 BoxSecretKey) bool {
	return PublicKeyEqual(sk1.GetPublicKey(), sk2.GetPublicKey())
}

// PublicKeyEqual returns true if the two public keys are equal.
func PublicKeyEqual(pk1, pk2 BoxPublicKey) bool {
	return KIDEqual(pk1, pk2)
}

// KIDEqual return true if the KIDs for two keys are equal.
func KIDEqual(k1, k2 KIDExtractor) bool {
	return hmac.Equal(k1.ToKID(), k2.ToKID())
}
<commit_msg>delete SecretKeyEqual<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package saltpack

import (
	"crypto/hmac"
)

// RawBoxKey is the raw byte-representation of what a box key should
// look like, a static 32-byte buffer. Used for NaCl Box.
type RawBoxKey [32]byte

func rawBoxKeyFromSlice(slice []byte) (*RawBoxKey, error) {
	var result RawBoxKey
	if len(slice) != len(result) {
		return nil, ErrBadBoxKey
	}
	copy(result[:], slice)
	return &result, nil
}

// SymmetricKey is a template for a symmetric key, a 32-byte static
// buffer. Used for NaCl SecretBox.
type SymmetricKey [32]byte

func symmetricKeyFromSlice(slice []byte) (*SymmetricKey, error) {
	var result SymmetricKey
	if len(slice) != len(result) {
		return nil, ErrBadSymmetricKey
	}
	copy(result[:], slice)
	return &result, nil
}

// KIDExtractor key types can output a key ID corresponding to the
// key.
type KIDExtractor interface {
	// ToKID outputs the "key ID" that corresponds to this key.
	// You can do whatever you'd like here, but probably it makes sense just
	// to output the public key as is.
	ToKID() []byte
}

// BoxPublicKey is an generic interface to NaCl's public key Box function.
type BoxPublicKey interface {
	KIDExtractor

	// ToRawBoxKeyPointer returns this public key as a *[32]byte,
	// for use with nacl.box.Seal
	ToRawBoxKeyPointer() *RawBoxKey

	// CreateEmphemeralKey creates an ephemeral key of the same type,
	// but totally random.
	CreateEphemeralKey() (BoxSecretKey, error)

	// HideIdentity returns true if we should hide the identity of this
	// key in our output message format.
	HideIdentity() bool
}

// BoxPrecomputedSharedKey results from a Precomputation below.
type BoxPrecomputedSharedKey interface {
	Unbox(nonce *Nonce, msg []byte) ([]byte, error)
	Box(nonce *Nonce, msg []byte) []byte
}

// BoxSecretKey is the secret key corresponding to a BoxPublicKey
type BoxSecretKey interface {

	// Box boxes up data, sent from this secret key, and to the receiver
	// specified.
	Box(receiver BoxPublicKey, nonce *Nonce, msg []byte) []byte

	// Unobx opens up the box, using this secret key as the receiver key
	// abd the give public key as the sender key.
	Unbox(sender BoxPublicKey, nonce *Nonce, msg []byte) ([]byte, error)

	// GetPublicKey gets the public key associated with this secret key.
	GetPublicKey() BoxPublicKey

	// Precompute computes a DH with the given key
	Precompute(sender BoxPublicKey) BoxPrecomputedSharedKey
}

// SigningSecretKey is a secret NaCl key that can sign messages.
type SigningSecretKey interface {
	// Sign signs message with this secret key.
	Sign(message []byte) ([]byte, error)

	// PublicKey gets the public key associated with this secret key.
	PublicKey() SigningPublicKey
}

// SigningPublicKey is a public NaCl key that can verify
// signatures.
type SigningPublicKey interface {
	KIDExtractor

	// Verify verifies that signature is a valid signature of message for
	// this public key.
	Verify(message []byte, signature []byte) error
}

// Keyring is an interface used with decryption; it is called to
// recover public or private keys during the decryption process.
// Calls can block on network action.
type Keyring interface {
	// LookupBoxSecretKey looks in the Keyring for the secret key corresponding
	// to one of the given Key IDs.  Returns the index and the key on success,
	// or -1 and nil on failure.
	LookupBoxSecretKey(kids [][]byte) (int, BoxSecretKey)

	// LookupBoxPublicKey returns a public key given the specified key ID.
	// For most cases, the key ID will be the key itself.
	LookupBoxPublicKey(kid []byte) BoxPublicKey

	// GetAllSecretKeys returns all keys, needed if we want to support
	// "hidden" receivers via trial and error
	GetAllSecretKeys() []BoxSecretKey

	// ImportEphemeralKey imports the ephemeral key into
	// BoxPublicKey format. This key has never been seen before, so
	// will be ephemeral.
	ImportEphemeralKey(kid []byte) BoxPublicKey
}

// SigKeyring is an interface used during verification to find
// the public key for the signer of a message.
type SigKeyring interface {
	// LookupSigningPublicKey returns a public signing key for the specified key ID.
	LookupSigningPublicKey(kid []byte) SigningPublicKey
}

// PublicKeyEqual returns true if the two public keys are equal.
func PublicKeyEqual(pk1, pk2 BoxPublicKey) bool {
	return KIDEqual(pk1, pk2)
}

// KIDEqual return true if the KIDs for two keys are equal.
func KIDEqual(k1, k2 KIDExtractor) bool {
	return hmac.Equal(k1.ToKID(), k2.ToKID())
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/stianeikeland/go-rpio"
	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/all"
	"github.com/rs/cors"
	"periph.io/x/periph/conn/gpio"
	"periph.io/x/periph/conn/gpio/gpioreg"
	"periph.io/x/periph/host"
)

var (
	mode     = 0 // 0=go-rpio,1=embd,2=periph
	demoMode = false

	// LEDs
	ledRedPin    = 4
	ledYellowPin = 17
	ledGreenPin  = 27
	ledToColor   = map[int]string{}
	ledMapEmbd   = map[int]embd.DigitalPin{}
	ledMap       = map[int]rpio.Pin{}
	ledMapPeriph = map[int]gpio.PinIO{}

	// Buttons
	buttonPin = 22
	buttonMap = map[int]embd.DigitalPin{}

	// GPIOs
	gpios = map[int]Gpio{}
	demoNum = 26
)

func getLEDString(color string) string {
	return "Toggle " + strings.ToUpper(color)
}

func getToggledValue(pin embd.DigitalPin) int {
	val, _ := pin.Read()
	if val == embd.High {
		return embd.Low
	}
	return embd.High
}

func setGpio(id int, name string, value int) {
	gpios[id] = Gpio{id, name, value}
}

func toggleLEDPeriph(id int, pin gpio.PinIO, color string) {
	fmt.Println(getLEDString(color))
	if !demoMode {
		fmt.Println("Val to write", !pin.Read())
		pin.Out(!pin.Read())
		value := 0
		if pin.Read() == gpio.High {
			value = 1
		}
		setGpio(id, pin.Name(), value)
	}
}

func toggleLEDEmbd(id int, pin embd.DigitalPin, color string) {
	fmt.Println(getLEDString(color))
	if !demoMode {
		toggledValue := getToggledValue(pin)
		fmt.Println("Val to write", toggledValue)
		embd.DigitalWrite(pin.N(), toggledValue)
		value,_ := pin.Read()
		setGpio(id, "GPIO" + strconv.Itoa(pin.N()), value)
	}
}

func toggleLED(id int, pin rpio.Pin, color string) {
	fmt.Println(getLEDString(color))
	if !demoMode {
		fmt.Println("Current value:", pin.Read())
		pin.Toggle()
		value := 0
		if pin.Read() == rpio.High {
			value = 1
		}
		setGpio(id, "GPIO" + "N/A", value)
	}
}

func initButtons() {
	buttonMap[0], _ = embd.NewDigitalPin(buttonPin)
	buttonMap[0].SetDirection(embd.In)
	buttonMap[0].ActiveLow(false)
	quit := make(chan interface{})
	err := buttonMap[0].Watch(embd.EdgeFalling, func(btn embd.DigitalPin) {
		fmt.Println("Pressed", btn)
		quit <- btn
	})
	if err != nil {
		panic(err)
	}
	fmt.Printf("Button %v was pressed.\n", <-quit)
}

func initLEDs() {
	if mode == 1 {
		ledMapEmbd[0], _ = embd.NewDigitalPin(ledRedPin)
		ledMapEmbd[1], _ = embd.NewDigitalPin(ledYellowPin)
		ledMapEmbd[2], _ = embd.NewDigitalPin(ledGreenPin)
		for i := 0; i < len(ledMapEmbd); i++ {
			ledMapEmbd[i].SetDirection(embd.Out)
			embd.DigitalWrite(ledMapEmbd[i].N(), embd.Low)
		}
	} else if mode == 2 {
		ledMapPeriph[0] = gpioreg.ByNumber(ledRedPin)
		ledMapPeriph[1] = gpioreg.ByNumber(ledYellowPin)
		ledMapPeriph[2] = gpioreg.ByNumber(ledGreenPin)
		for i := 0; i < len(ledMapPeriph); i++ {
			ledMapPeriph[i].Out(gpio.Low)
		}
	} else {
		ledMap[0] = rpio.Pin(ledRedPin)
		ledMap[1] = rpio.Pin(ledYellowPin)
		ledMap[2] = rpio.Pin(ledGreenPin)
		for i := 0; i < len(ledMap); i++ {
			ledMap[i].Output()
			ledMap[i].Low()
		}
	}
	initLEDcolors()
}

func initLEDcolors() {
	ledToColor[0] = "red"
	ledToColor[1] = "yellow"
	ledToColor[2] = "green"
}

func initGPIO() error {
	if mode == 1 {
		return embd.InitGPIO()
	} else if mode == 2 {
		_,err := host.Init()
		return err
	}
	return rpio.Open()
}

func doLedToggling(i int) {
	if !demoMode {
		if mode == 1 {
			toggleLEDEmbd(i%3, ledMapEmbd[i%3], ledToColor[i%3])
		} else if mode == 2{
			toggleLEDPeriph(i%3, ledMapPeriph[i%3], ledToColor[i%3])
		} else {
			toggleLED(i%3, ledMap[i%3], ledToColor[i%3])
		}
	} else {
		fmt.Println(getLEDString(ledToColor[i%3]))
		setGpio(i%demoNum, "GPIO" + strconv.Itoa(i%demoNum), i % 2)
	}
	time.Sleep(time.Second)
}

type Gpio struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Value int    `json:"value"`
}

func getGpios(w http.ResponseWriter, r *http.Request) {
	gpiosToJson := make([]Gpio, 0, len(gpios))
	fmt.Printf("Transforming %d GPIOs\n", len(gpios))
	for  _, value := range gpios {
  	gpiosToJson = append(gpiosToJson, value)
	}
	fmt.Printf("Transformed into %d gpios\n", len(gpiosToJson))
	json, err := json.Marshal(gpiosToJson)

	if err != nil {
		panic(err)
	}
	w.Write(json)
}

func initWebServer() {
	mux := http.NewServeMux()
	mux.HandleFunc("/v1/gpios", getGpios)
	handler := cors.Default().Handler(mux)
	http.ListenAndServe(":8080", handler)
}

func main() {
	fmt.Println("Parsing parameters")
	num := flag.Int("num", 3, "number of blinks")
	modeFromCli := flag.Int("mode", 0, "mode")
	button := flag.Bool("button", false, "button mode")
	api := flag.Bool("api", true, "API enabled")
	demo := flag.Bool("demo", false, "Demo mode enabled")
	flag.Parse()

	mode = *modeFromCli
	demoMode = *demo

	if demoMode {
		fmt.Println("Running in demo mode, no physical hw interaction")
	}
	if mode == 1 {
		fmt.Println("Running using Embd.io")
	} else if mode == 2 {
		fmt.Println("Running using periph")
	} else {
		fmt.Println("Running using go-rpio")
	}
	fmt.Println("Number of blinks:", *num)

	if *api {
		go initWebServer()
	}

	if !demoMode {
		var err = initGPIO()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		initLEDs()
		if mode == 1 && *button {
			initButtons()
		}

		if mode == 1 {
			defer embd.CloseGPIO()
		} else {
			defer rpio.Close()
		}
	} else {
		initLEDcolors()
	}

	if !*button {
		if *num == 0 {
			var counter = 0
			for {
				doLedToggling(counter)
				counter++
			}
		} else {
			for i := 0; i < *num; i++ {
				doLedToggling(i)
			}
		}
	}
}
<commit_msg>Logging ws init<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/stianeikeland/go-rpio"
	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/all"
	"github.com/rs/cors"
	"periph.io/x/periph/conn/gpio"
	"periph.io/x/periph/conn/gpio/gpioreg"
	"periph.io/x/periph/host"
)

var (
	mode     = 0 // 0=go-rpio,1=embd,2=periph
	demoMode = false

	// LEDs
	ledRedPin    = 4
	ledYellowPin = 17
	ledGreenPin  = 27
	ledToColor   = map[int]string{}
	ledMapEmbd   = map[int]embd.DigitalPin{}
	ledMap       = map[int]rpio.Pin{}
	ledMapPeriph = map[int]gpio.PinIO{}

	// Buttons
	buttonPin = 22
	buttonMap = map[int]embd.DigitalPin{}

	// GPIOs
	gpios = map[int]Gpio{}
	demoNum = 26
)

func getLEDString(color string) string {
	return "Toggle " + strings.ToUpper(color)
}

func getToggledValue(pin embd.DigitalPin) int {
	val, _ := pin.Read()
	if val == embd.High {
		return embd.Low
	}
	return embd.High
}

func setGpio(id int, name string, value int) {
	gpios[id] = Gpio{id, name, value}
}

func toggleLEDPeriph(id int, pin gpio.PinIO, color string) {
	fmt.Println(getLEDString(color))
	if !demoMode {
		fmt.Println("Val to write", !pin.Read())
		pin.Out(!pin.Read())
		value := 0
		if pin.Read() == gpio.High {
			value = 1
		}
		setGpio(id, pin.Name(), value)
	}
}

func toggleLEDEmbd(id int, pin embd.DigitalPin, color string) {
	fmt.Println(getLEDString(color))
	if !demoMode {
		toggledValue := getToggledValue(pin)
		fmt.Println("Val to write", toggledValue)
		embd.DigitalWrite(pin.N(), toggledValue)
		value,_ := pin.Read()
		setGpio(id, "GPIO" + strconv.Itoa(pin.N()), value)
	}
}

func toggleLED(id int, pin rpio.Pin, color string) {
	fmt.Println(getLEDString(color))
	if !demoMode {
		fmt.Println("Current value:", pin.Read())
		pin.Toggle()
		value := 0
		if pin.Read() == rpio.High {
			value = 1
		}
		setGpio(id, "GPIO" + "N/A", value)
	}
}

func initButtons() {
	buttonMap[0], _ = embd.NewDigitalPin(buttonPin)
	buttonMap[0].SetDirection(embd.In)
	buttonMap[0].ActiveLow(false)
	quit := make(chan interface{})
	err := buttonMap[0].Watch(embd.EdgeFalling, func(btn embd.DigitalPin) {
		fmt.Println("Pressed", btn)
		quit <- btn
	})
	if err != nil {
		panic(err)
	}
	fmt.Printf("Button %v was pressed.\n", <-quit)
}

func initLEDs() {
	if mode == 1 {
		ledMapEmbd[0], _ = embd.NewDigitalPin(ledRedPin)
		ledMapEmbd[1], _ = embd.NewDigitalPin(ledYellowPin)
		ledMapEmbd[2], _ = embd.NewDigitalPin(ledGreenPin)
		for i := 0; i < len(ledMapEmbd); i++ {
			ledMapEmbd[i].SetDirection(embd.Out)
			embd.DigitalWrite(ledMapEmbd[i].N(), embd.Low)
		}
	} else if mode == 2 {
		ledMapPeriph[0] = gpioreg.ByNumber(ledRedPin)
		ledMapPeriph[1] = gpioreg.ByNumber(ledYellowPin)
		ledMapPeriph[2] = gpioreg.ByNumber(ledGreenPin)
		for i := 0; i < len(ledMapPeriph); i++ {
			ledMapPeriph[i].Out(gpio.Low)
		}
	} else {
		ledMap[0] = rpio.Pin(ledRedPin)
		ledMap[1] = rpio.Pin(ledYellowPin)
		ledMap[2] = rpio.Pin(ledGreenPin)
		for i := 0; i < len(ledMap); i++ {
			ledMap[i].Output()
			ledMap[i].Low()
		}
	}
	initLEDcolors()
}

func initLEDcolors() {
	ledToColor[0] = "red"
	ledToColor[1] = "yellow"
	ledToColor[2] = "green"
}

func initGPIO() error {
	if mode == 1 {
		return embd.InitGPIO()
	} else if mode == 2 {
		_,err := host.Init()
		return err
	}
	return rpio.Open()
}

func doLedToggling(i int) {
	if !demoMode {
		if mode == 1 {
			toggleLEDEmbd(i%3, ledMapEmbd[i%3], ledToColor[i%3])
		} else if mode == 2{
			toggleLEDPeriph(i%3, ledMapPeriph[i%3], ledToColor[i%3])
		} else {
			toggleLED(i%3, ledMap[i%3], ledToColor[i%3])
		}
	} else {
		fmt.Println(getLEDString(ledToColor[i%3]))
		setGpio(i%demoNum, "GPIO" + strconv.Itoa(i%demoNum), i % 2)
	}
	time.Sleep(time.Second)
}

type Gpio struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Value int    `json:"value"`
}

func getGpios(w http.ResponseWriter, r *http.Request) {
	gpiosToJson := make([]Gpio, 0, len(gpios))
	fmt.Printf("Transforming %d GPIOs\n", len(gpios))
	for  _, value := range gpios {
  	gpiosToJson = append(gpiosToJson, value)
	}
	fmt.Printf("Transformed into %d gpios\n", len(gpiosToJson))
	json, err := json.Marshal(gpiosToJson)

	if err != nil {
		panic(err)
	}
	w.Write(json)
}

func initWebServer() {
	fmt.Println("Initializing Webserver")
	mux := http.NewServeMux()
	mux.HandleFunc("/v1/gpios", getGpios)
	handler := cors.Default().Handler(mux)
	http.ListenAndServe(":8080", handler)
}

func main() {
	fmt.Println("Parsing parameters")
	num := flag.Int("num", 3, "number of blinks")
	modeFromCli := flag.Int("mode", 0, "mode")
	button := flag.Bool("button", false, "button mode")
	api := flag.Bool("api", true, "API enabled")
	demo := flag.Bool("demo", false, "Demo mode enabled")
	flag.Parse()

	mode = *modeFromCli
	demoMode = *demo

	if demoMode {
		fmt.Println("Running in demo mode, no physical hw interaction")
	}
	if mode == 1 {
		fmt.Println("Running using Embd.io")
	} else if mode == 2 {
		fmt.Println("Running using periph")
	} else {
		fmt.Println("Running using go-rpio")
	}
	fmt.Println("Number of blinks:", *num)

	if *api {
		go initWebServer()
	}

	if !demoMode {
		var err = initGPIO()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		initLEDs()
		if mode == 1 && *button {
			initButtons()
		}

		if mode == 1 {
			defer embd.CloseGPIO()
		} else {
			defer rpio.Close()
		}
	} else {
		initLEDcolors()
	}

	if !*button {
		if *num == 0 {
			var counter = 0
			for {
				doLedToggling(counter)
				counter++
			}
		} else {
			for i := 0; i < *num; i++ {
				doLedToggling(i)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"strings"
	"unicode"
	"unicode/utf8"
)

type stateFn func(*sqlLex) stateFn

type token struct {
	typ int
	src string
}

type sqlLex struct {
	src    string
	start  int
	pos    int
	width  int
	state  stateFn
	tokens chan token
	stmt   *SelectStmt
}

func (x *sqlLex) Lex(yylval *sqlSymType) int {
	for {
		select {
		case token := <-x.tokens:
			yylval.src = token.src
			return token.typ
		default:
			x.state = x.state(x)
			if x.state == nil {
				return eof
			}
		}
	}
}

// The parser calls this method on a parse error.
func (x *sqlLex) Error(s string) {
	log.Printf("parse error: %s at character %d", s, x.start)
}

func NewSqlLexer(src string) *sqlLex {
	return &sqlLex{src: src,
		tokens: make(chan token, 2),
		state:  blankState,
	}
}

func (l *sqlLex) next() (r rune) {
	if l.pos >= len(l.src) {
		l.width = 0 // because backing up from having read eof should read eof again
		return 0
	}

	r, l.width = utf8.DecodeRuneInString(l.src[l.pos:])
	l.pos += l.width

	return r
}

func (l *sqlLex) unnext() {
	l.pos -= l.width
}

func (l *sqlLex) ignore() {
	l.start = l.pos
}

func (l *sqlLex) acceptRunFunc(f func(rune) bool) {
	for f(l.next()) {
	}
	l.unnext()
}

func blankState(l *sqlLex) stateFn {
	switch r := l.next(); {
	case r == 0:
		return nil
	case r == ',' || r == '.' || r == '(' || r == ')':
		return lexSimple
	case r == '\'':
		return lexStringLiteral
	case r == '"':
		return lexQuotedIdentifier
	case isOperator(r):
		return lexOperator
	case unicode.IsDigit(r):
		return lexNumber
	case isWhitespace(r):
		l.skipWhitespace()
		return blankState
	case isAlphanumeric(r):
		return lexAlphanumeric
	}
	return nil
}

func lexNumber(l *sqlLex) stateFn {
	l.acceptRunFunc(unicode.IsDigit)
	t := token{src: l.src[l.start:l.pos], typ: ICONST}
	l.tokens <- t
	l.start = l.pos
	return blankState
}

func lexAlphanumeric(l *sqlLex) stateFn {
	l.acceptRunFunc(isAlphanumeric)

	t := token{src: l.src[l.start:l.pos]}

	if typ, ok := keywords[strings.ToLower(t.src)]; ok {
		t.typ = typ
	} else {
		t.typ = IDENT
	}

	l.tokens <- t
	l.start = l.pos
	return blankState
}

func lexStringLiteral(l *sqlLex) stateFn {
	for {
		var r rune
		r = l.next()
		if r == 0 {
			return nil // error for EOF inside of string literal
		}

		if r == '\'' {
			r = l.next()
			if r != '\'' {
				l.unnext()
				t := token{src: l.src[l.start:l.pos]}
				t.typ = SCONST
				l.tokens <- t
				l.start = l.pos
				return blankState
			}
		}
	}
}

func lexQuotedIdentifier(l *sqlLex) stateFn {
	for {
		var r rune
		r = l.next()
		if r == 0 {
			return nil // error for EOF inside of string literal
		}

		if r == '"' {
			r = l.next()
			if r != '"' {
				l.unnext()
				t := token{src: l.src[l.start:l.pos]}
				t.typ = IDENT
				l.tokens <- t
				l.start = l.pos
				return blankState
			}
		}
	}
}

func lexOperator(l *sqlLex) stateFn {
	l.acceptRunFunc(isOperator)
	l.tokens <- token{OP, l.src[l.start:l.pos]}
	l.start = l.pos
	return blankState
}

func lexSimple(l *sqlLex) stateFn {
	l.tokens <- token{int(l.src[l.start]), l.src[l.start:l.pos]}
	l.start = l.pos
	return blankState
}

func (l *sqlLex) skipWhitespace() {
	var r rune
	for r = l.next(); isWhitespace(r); r = l.next() {
	}

	if r != 0 {
		l.unnext()
	}

	l.ignore()
}

func isWhitespace(r rune) bool {
	return unicode.IsSpace(r)
}

func isAlphanumeric(r rune) bool {
	return r == '_' || unicode.In(r, unicode.Letter, unicode.Digit)
}

func isOperator(r rune) bool {
	return r == '+' || r == '-' || r == '*' || r == '/' || r == '=' || r == '<' || r == '>' || r == '!'
}
<commit_msg>Tokenize input into slice instead of channel<commit_after>package main

import (
	"log"
	"strings"
	"unicode"
	"unicode/utf8"
)

type stateFn func(*sqlLex) stateFn

type token struct {
	typ int
	src string
}

type sqlLex struct {
	src    string
	start  int
	pos    int
	width  int
	state  stateFn
	tokens []token
	stmt   *SelectStmt
}

func (x *sqlLex) Lex(yylval *sqlSymType) int {
	token := x.tokens[0]
	x.tokens = x.tokens[1:]

	yylval.src = token.src
	return token.typ
}

// The parser calls this method on a parse error.
func (x *sqlLex) Error(s string) {
	log.Printf("parse error: %s at character %d", s, x.start)
}

func NewSqlLexer(src string) *sqlLex {
	x := &sqlLex{src: src,
		tokens: make([]token, 0),
		state:  blankState,
	}

	for x.state != nil {
		x.state = x.state(x)
	}

	x.tokens = append(x.tokens, token{typ: eof})

	return x
}

func (l *sqlLex) next() (r rune) {
	if l.pos >= len(l.src) {
		l.width = 0 // because backing up from having read eof should read eof again
		return 0
	}

	r, l.width = utf8.DecodeRuneInString(l.src[l.pos:])
	l.pos += l.width

	return r
}

func (l *sqlLex) unnext() {
	l.pos -= l.width
}

func (l *sqlLex) ignore() {
	l.start = l.pos
}

func (l *sqlLex) acceptRunFunc(f func(rune) bool) {
	for f(l.next()) {
	}
	l.unnext()
}

func blankState(l *sqlLex) stateFn {
	switch r := l.next(); {
	case r == 0:
		return nil
	case r == ',' || r == '.' || r == '(' || r == ')':
		return lexSimple
	case r == '\'':
		return lexStringLiteral
	case r == '"':
		return lexQuotedIdentifier
	case isOperator(r):
		return lexOperator
	case unicode.IsDigit(r):
		return lexNumber
	case isWhitespace(r):
		l.skipWhitespace()
		return blankState
	case isAlphanumeric(r):
		return lexAlphanumeric
	}
	return nil
}

func lexNumber(l *sqlLex) stateFn {
	l.acceptRunFunc(unicode.IsDigit)
	t := token{src: l.src[l.start:l.pos], typ: ICONST}
	l.tokens = append(l.tokens, t)
	l.start = l.pos
	return blankState
}

func lexAlphanumeric(l *sqlLex) stateFn {
	l.acceptRunFunc(isAlphanumeric)

	t := token{src: l.src[l.start:l.pos]}

	if typ, ok := keywords[strings.ToLower(t.src)]; ok {
		t.typ = typ
	} else {
		t.typ = IDENT
	}

	l.tokens = append(l.tokens, t)
	l.start = l.pos
	return blankState
}

func lexStringLiteral(l *sqlLex) stateFn {
	for {
		var r rune
		r = l.next()
		if r == 0 {
			return nil // error for EOF inside of string literal
		}

		if r == '\'' {
			r = l.next()
			if r != '\'' {
				l.unnext()
				t := token{src: l.src[l.start:l.pos]}
				t.typ = SCONST
				l.tokens = append(l.tokens, t)
				l.start = l.pos
				return blankState
			}
		}
	}
}

func lexQuotedIdentifier(l *sqlLex) stateFn {
	for {
		var r rune
		r = l.next()
		if r == 0 {
			return nil // error for EOF inside of string literal
		}

		if r == '"' {
			r = l.next()
			if r != '"' {
				l.unnext()
				t := token{src: l.src[l.start:l.pos]}
				t.typ = IDENT
				l.tokens = append(l.tokens, t)
				l.start = l.pos
				return blankState
			}
		}
	}
}

func lexOperator(l *sqlLex) stateFn {
	l.acceptRunFunc(isOperator)
	l.tokens = append(l.tokens, token{OP, l.src[l.start:l.pos]})
	l.start = l.pos
	return blankState
}

func lexSimple(l *sqlLex) stateFn {
	l.tokens = append(l.tokens, token{int(l.src[l.start]), l.src[l.start:l.pos]})
	l.start = l.pos
	return blankState
}

func (l *sqlLex) skipWhitespace() {
	var r rune
	for r = l.next(); isWhitespace(r); r = l.next() {
	}

	if r != 0 {
		l.unnext()
	}

	l.ignore()
}

func isWhitespace(r rune) bool {
	return unicode.IsSpace(r)
}

func isAlphanumeric(r rune) bool {
	return r == '_' || unicode.In(r, unicode.Letter, unicode.Digit)
}

func isOperator(r rune) bool {
	return r == '+' || r == '-' || r == '*' || r == '/' || r == '=' || r == '<' || r == '>' || r == '!'
}
<|endoftext|>