<commit_before>// Copyright 2013 Alexandre Fiori
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"bytes"
	"database/sql"
	"encoding/binary"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"github.com/bradfitz/gomemcache/memcache"
	"github.com/fiorix/go-web/http"
	"github.com/fiorix/go-web/mux"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"net"
	"path/filepath"
	"strconv"
	"time"
)

const (
	// API limits
	maxRequestsPerIP = 10000
	expirySeconds    = 3600

	// Server settings
	debug          = true
	listenOn       = ":8080"
	memcacheServer = "127.0.0.1:11211"
	staticPath     = "./static"
	databaseFile   = "./db/ipdb.sqlite"
)

type GeoIP struct {
	XMLName     xml.Name `json:"-" xml:"Response"`
	Ip          string   `json:"ip"`
	CountryCode string   `json:"country_code"`
	CountryName string   `json:"country_name"`
	RegionCode  string   `json:"region_code"`
	RegionName  string   `json:"region_name"`
	CityName    string   `json:"city" xml:"City"`
	ZipCode     string   `json:"zipcode"`
	Latitude    float32  `json:"latitude"`
	Longitude   float32  `json:"longitude"`
	MetroCode   string   `json:"metro_code"`
	AreaCode    string   `json:"areacode"`
}

// http://en.wikipedia.org/wiki/Reserved_IP_addresses
var reservedIPs = []net.IPNet{
	{net.IPv4(0, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(0, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(10, 0, 0, 0), net.IPv4Mask(255, 192, 0, 0)},
	{net.IPv4(100, 64, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(127, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(169, 254, 0, 0), net.IPv4Mask(255, 255, 0, 0)},
	{net.IPv4(172, 16, 0, 0), net.IPv4Mask(255, 240, 0, 0)},
	{net.IPv4(192, 0, 0, 0), net.IPv4Mask(255, 255, 255, 248)},
	{net.IPv4(192, 0, 2, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(192, 88, 99, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(192, 168, 0, 0), net.IPv4Mask(255, 255, 0, 0)},
	{net.IPv4(198, 18, 0, 0), net.IPv4Mask(255, 254, 0, 0)},
	{net.IPv4(198, 51, 100, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(203, 0, 113, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(224, 0, 0, 0), net.IPv4Mask(240, 0, 0, 0)},
	{net.IPv4(240, 0, 0, 0), net.IPv4Mask(240, 0, 0, 0)},
	{net.IPv4(255, 255, 255, 255), net.IPv4Mask(255, 255, 255, 255)},
}

func Lookup(w http.ResponseWriter, req *http.Request, db *sql.DB) {
	format, addr := req.Vars[0], req.Vars[1]
	if addr == "" {
		addr = req.RemoteAddr // port number previously removed
	} else {
		addrs, err := net.LookupHost(addr)
		if err != nil {
			http.Error(w, http.StatusText(404), 404)
			return
		}
		addr = addrs[0]
	}
	IP := net.ParseIP(addr)
	reserved := false
	for _, net := range reservedIPs {
		if net.Contains(IP) {
			reserved = true
			break
		}
	}
	geoip := GeoIP{Ip: addr}
	if reserved {
		geoip.CountryCode = "RD"
		geoip.CountryName = "Reserved"
	} else {
		q := "SELECT " +
			"  city_location.country_code, country_blocks.country_name, " +
			"  city_location.region_code, region_names.region_name, " +
			"  city_location.city_name, city_location.postal_code, " +
			"  city_location.latitude, city_location.longitude, " +
			"  city_location.metro_code, city_location.area_code " +
			"FROM city_blocks " +
			"  NATURAL JOIN city_location " +
			"  INNER JOIN country_blocks ON " +
			"    city_location.country_code = country_blocks.country_code " +
			"  INNER JOIN region_names ON " +
			"    city_location.country_code = region_names.country_code " +
			"    AND " +
			"    city_location.region_code = region_names.region_code " +
			"WHERE city_blocks.ip_start <= ? " +
			"ORDER BY city_blocks.ip_start DESC LIMIT 1"
		stmt, err := db.Prepare(q)
		if err != nil {
			if debug {
				log.Println("[debug] SQLite", err.Error())
			}
			http.Error(w, http.StatusText(500), 500)
			return
		}
		defer stmt.Close()
		var uintIP uint32
		b := bytes.NewBuffer(IP.To4())
		binary.Read(b, binary.BigEndian, &uintIP)
		err = stmt.QueryRow(uintIP).Scan(
			&geoip.CountryCode,
			&geoip.CountryName,
			&geoip.RegionCode,
			&geoip.RegionName,
			&geoip.CityName,
			&geoip.ZipCode,
			&geoip.Latitude,
			&geoip.Longitude,
			&geoip.MetroCode,
			&geoip.AreaCode)
		if err != nil {
			http.Error(w, http.StatusText(404), 404)
			return
		}
	}
	switch format[0] {
	case 'c':
		w.Header().Set("Content-Type", "application/csv")
		fmt.Fprintf(w, `"%s","%s","%s","%s","%s","%s",`+
			`"%s","%0.4f","%0.4f","%s","%s"`+"\r\n",
			geoip.Ip,
			geoip.CountryCode, geoip.CountryName,
			geoip.RegionCode, geoip.RegionName,
			geoip.CityName, geoip.ZipCode,
			geoip.Latitude, geoip.Longitude,
			geoip.MetroCode, geoip.AreaCode)
	case 'j':
		resp, err := json.Marshal(geoip)
		if err != nil {
			if debug {
				log.Println("[debug] JSON", err.Error())
			}
			http.Error(w, http.StatusText(404), 404)
			return
		}
		callback := req.FormValue("callback")
		if callback != "" {
			w.Header().Set("Content-Type", "text/javascript")
			fmt.Fprintf(w, "%s(%s);\n", callback, resp)
		} else {
			w.Header().Set("Content-Type", "application/json")
			fmt.Fprintf(w, "%s\n", resp)
		}
	case 'x':
		w.Header().Set("Content-Type", "application/xml")
		resp, err := xml.MarshalIndent(geoip, "", " ")
		if err != nil {
			if debug {
				log.Println("[debug] XML", err.Error())
			}
			http.Error(w, http.StatusText(500), 500)
			return
		}
		fmt.Fprintf(w, xml.Header+"%s\n", resp)
	}
}

func trimPort(s string) string {
	for i := len(s) - 1; i > 0; i-- {
		if s[i] == ':' {
			return s[:i]
		}
	}
	return s
}

func makeHandler() http.HandlerFunc {
	db, err := sql.Open("sqlite3", databaseFile)
	if err != nil {
		panic(err)
	}
	mc := memcache.New(memcacheServer)
	return func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		req.RemoteAddr = trimPort(req.RemoteAddr)
		// Check quota
		el, err := mc.Get(req.RemoteAddr)
		if err == memcache.ErrCacheMiss {
			err = mc.Set(&memcache.Item{
				Key: req.RemoteAddr, Value: []byte("1"),
				Expiration: expirySeconds})
		}
		if err != nil {
			// Service Unavailable
			if debug {
				log.Println("[debug] memcache", err.Error())
			}
			http.Error(w, http.StatusText(503), 503)
			return
		}
		if el != nil {
			count, _ := strconv.Atoi(string(el.Value))
			if count < maxRequestsPerIP {
				mc.Increment(req.RemoteAddr, 1)
			} else {
				// Out of quota
				http.Error(w, http.StatusText(403), 403)
				return
			}
		}
		Lookup(w, req, db)
	}
}

func IndexHandler(w http.ResponseWriter, req *http.Request) {
	http.ServeFile(w, req, filepath.Join(staticPath, "index.html"))
}

func StaticHandler(w http.ResponseWriter, req *http.Request) {
	http.ServeFile(w, req, filepath.Join(staticPath, req.Vars[0]))
}

func logger(w http.ResponseWriter, req *http.Request) {
	log.Printf("HTTP %d %s %s (%s) :: %s",
		w.Status(),
		req.Method,
		req.URL.Path,
		req.RemoteAddr,
		time.Since(req.Created))
}

func main() {
	mux.HandleFunc("^/$", IndexHandler)
	mux.HandleFunc("^/static/(.*)$", StaticHandler)
	mux.HandleFunc("^/(crossdomain.xml)$", StaticHandler)
	mux.HandleFunc("^/(csv|json|xml)/(.*)$", makeHandler())
	server := http.Server{
		Addr:         listenOn,
		Handler:      mux.DefaultServeMux,
		Logger:       logger,
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 15 * time.Second,
	}
	log.Println("FreeGeoIP server starting")
	if e := server.ListenAndServe(); e != nil {
		log.Println(e.Error())
	}
}
<commit_msg>mux->remux<commit_after>// Copyright 2013 Alexandre Fiori
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"bytes"
	"database/sql"
	"encoding/binary"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"github.com/bradfitz/gomemcache/memcache"
	"github.com/fiorix/go-web/http"
	"github.com/fiorix/go-web/remux"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"net"
	"path/filepath"
	"strconv"
	"time"
)

const (
	// API limits
	maxRequestsPerIP = 10000
	expirySeconds    = 3600

	// Server settings
	debug          = true
	listenOn       = ":8080"
	memcacheServer = "127.0.0.1:11211"
	staticPath     = "./static"
	databaseFile   = "./db/ipdb.sqlite"
)

type GeoIP struct {
	XMLName     xml.Name `json:"-" xml:"Response"`
	Ip          string   `json:"ip"`
	CountryCode string   `json:"country_code"`
	CountryName string   `json:"country_name"`
	RegionCode  string   `json:"region_code"`
	RegionName  string   `json:"region_name"`
	CityName    string   `json:"city" xml:"City"`
	ZipCode     string   `json:"zipcode"`
	Latitude    float32  `json:"latitude"`
	Longitude   float32  `json:"longitude"`
	MetroCode   string   `json:"metro_code"`
	AreaCode    string   `json:"areacode"`
}

// http://en.wikipedia.org/wiki/Reserved_IP_addresses
var reservedIPs = []net.IPNet{
	{net.IPv4(0, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(0, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(10, 0, 0, 0), net.IPv4Mask(255, 192, 0, 0)},
	{net.IPv4(100, 64, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(127, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(169, 254, 0, 0), net.IPv4Mask(255, 255, 0, 0)},
	{net.IPv4(172, 16, 0, 0), net.IPv4Mask(255, 240, 0, 0)},
	{net.IPv4(192, 0, 0, 0), net.IPv4Mask(255, 255, 255, 248)},
	{net.IPv4(192, 0, 2, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(192, 88, 99, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(192, 168, 0, 0), net.IPv4Mask(255, 255, 0, 0)},
	{net.IPv4(198, 18, 0, 0), net.IPv4Mask(255, 254, 0, 0)},
	{net.IPv4(198, 51, 100, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(203, 0, 113, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(224, 0, 0, 0), net.IPv4Mask(240, 0, 0, 0)},
	{net.IPv4(240, 0, 0, 0), net.IPv4Mask(240, 0, 0, 0)},
	{net.IPv4(255, 255, 255, 255), net.IPv4Mask(255, 255, 255, 255)},
}

func Lookup(w http.ResponseWriter, req *http.Request, db *sql.DB) {
	format, addr := req.Vars[0], req.Vars[1]
	if addr == "" {
		addr = req.RemoteAddr // port number previously removed
	} else {
		addrs, err := net.LookupHost(addr)
		if err != nil {
			http.Error(w, http.StatusText(404), 404)
			return
		}
		addr = addrs[0]
	}
	IP := net.ParseIP(addr)
	reserved := false
	for _, net := range reservedIPs {
		if net.Contains(IP) {
			reserved = true
			break
		}
	}
	geoip := GeoIP{Ip: addr}
	if reserved {
		geoip.CountryCode = "RD"
		geoip.CountryName = "Reserved"
	} else {
		q := "SELECT " +
			"  city_location.country_code, country_blocks.country_name, " +
			"  city_location.region_code, region_names.region_name, " +
			"  city_location.city_name, city_location.postal_code, " +
			"  city_location.latitude, city_location.longitude, " +
			"  city_location.metro_code, city_location.area_code " +
			"FROM city_blocks " +
			"  NATURAL JOIN city_location " +
			"  INNER JOIN country_blocks ON " +
			"    city_location.country_code = country_blocks.country_code " +
			"  INNER JOIN region_names ON " +
			"    city_location.country_code = region_names.country_code " +
			"    AND " +
			"    city_location.region_code = region_names.region_code " +
			"WHERE city_blocks.ip_start <= ? " +
			"ORDER BY city_blocks.ip_start DESC LIMIT 1"
		stmt, err := db.Prepare(q)
		if err != nil {
			if debug {
				log.Println("[debug] SQLite", err.Error())
			}
			http.Error(w, http.StatusText(500), 500)
			return
		}
		defer stmt.Close()
		var uintIP uint32
		b := bytes.NewBuffer(IP.To4())
		binary.Read(b, binary.BigEndian, &uintIP)
		err = stmt.QueryRow(uintIP).Scan(
			&geoip.CountryCode,
			&geoip.CountryName,
			&geoip.RegionCode,
			&geoip.RegionName,
			&geoip.CityName,
			&geoip.ZipCode,
			&geoip.Latitude,
			&geoip.Longitude,
			&geoip.MetroCode,
			&geoip.AreaCode)
		if err != nil {
			http.Error(w, http.StatusText(404), 404)
			return
		}
	}
	switch format[0] {
	case 'c':
		w.Header().Set("Content-Type", "application/csv")
		fmt.Fprintf(w, `"%s","%s","%s","%s","%s","%s",`+
			`"%s","%0.4f","%0.4f","%s","%s"`+"\r\n",
			geoip.Ip,
			geoip.CountryCode, geoip.CountryName,
			geoip.RegionCode, geoip.RegionName,
			geoip.CityName, geoip.ZipCode,
			geoip.Latitude, geoip.Longitude,
			geoip.MetroCode, geoip.AreaCode)
	case 'j':
		resp, err := json.Marshal(geoip)
		if err != nil {
			if debug {
				log.Println("[debug] JSON", err.Error())
			}
			http.Error(w, http.StatusText(404), 404)
			return
		}
		callback := req.FormValue("callback")
		if callback != "" {
			w.Header().Set("Content-Type", "text/javascript")
			fmt.Fprintf(w, "%s(%s);\n", callback, resp)
		} else {
			w.Header().Set("Content-Type", "application/json")
			fmt.Fprintf(w, "%s\n", resp)
		}
	case 'x':
		w.Header().Set("Content-Type", "application/xml")
		resp, err := xml.MarshalIndent(geoip, "", " ")
		if err != nil {
			if debug {
				log.Println("[debug] XML", err.Error())
			}
			http.Error(w, http.StatusText(500), 500)
			return
		}
		fmt.Fprintf(w, xml.Header+"%s\n", resp)
	}
}

func trimPort(s string) string {
	for i := len(s) - 1; i > 0; i-- {
		if s[i] == ':' {
			return s[:i]
		}
	}
	return s
}

func makeHandler() http.HandlerFunc {
	db, err := sql.Open("sqlite3", databaseFile)
	if err != nil {
		panic(err)
	}
	mc := memcache.New(memcacheServer)
	return func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		req.RemoteAddr = trimPort(req.RemoteAddr)
		// Check quota
		el, err := mc.Get(req.RemoteAddr)
		if err == memcache.ErrCacheMiss {
			err = mc.Set(&memcache.Item{
				Key: req.RemoteAddr, Value: []byte("1"),
				Expiration: expirySeconds})
		}
		if err != nil {
			// Service Unavailable
			if debug {
				log.Println("[debug] memcache", err.Error())
			}
			http.Error(w, http.StatusText(503), 503)
			return
		}
		if el != nil {
			count, _ := strconv.Atoi(string(el.Value))
			if count < maxRequestsPerIP {
				mc.Increment(req.RemoteAddr, 1)
			} else {
				// Out of quota
				http.Error(w, http.StatusText(403), 403)
				return
			}
		}
		Lookup(w, req, db)
	}
}

func IndexHandler(w http.ResponseWriter, req *http.Request) {
	http.ServeFile(w, req, filepath.Join(staticPath, "index.html"))
}

func StaticHandler(w http.ResponseWriter, req *http.Request) {
	http.ServeFile(w, req, filepath.Join(staticPath, req.Vars[0]))
}

func logger(w http.ResponseWriter, req *http.Request) {
	log.Printf("HTTP %d %s %s (%s) :: %s",
		w.Status(),
		req.Method,
		req.URL.Path,
		req.RemoteAddr,
		time.Since(req.Created))
}

func main() {
	remux.HandleFunc("^/$", IndexHandler)
	remux.HandleFunc("^/static/(.*)$", StaticHandler)
	remux.HandleFunc("^/(crossdomain.xml)$", StaticHandler)
	remux.HandleFunc("^/(csv|json|xml)/(.*)$", makeHandler())
	server := http.Server{
		Addr:         listenOn,
		Handler:      remux.DefaultServeMux,
		Logger:       logger,
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 15 * time.Second,
	}
	log.Println("FreeGeoIP server starting")
	if e := server.ListenAndServe(); e != nil {
		log.Println(e.Error())
	}
}
<|endoftext|>


<commit_before>package rex

import (
	"path"

	"github.com/goanywhere/env"
	"github.com/goanywhere/fs"
)

func init() {
	var basedir = fs.Getcd(2)
	env.Set("basedir", basedir)
	env.Load(path.Join(basedir, ".env"))
}
<commit_msg>shortcut for map<commit_after>package rex

import (
	"path"

	"github.com/goanywhere/env"
	"github.com/goanywhere/fs"
)

// Shortcut for string based map.
type M map[string]interface{}

func init() {
	var basedir = fs.Getcd(2)
	env.Set("basedir", basedir)
	env.Load(path.Join(basedir, ".env"))
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "fmt"
    "encoding/json"
    "github.com/toke/golang-callmon"
)

func handleMessages(msgchan <-chan fritzbox.FbEvent){
  for {
      ev := <- msgchan

      jsonm,_ := json.Marshal(&ev)
      fmt.Printf("Some JSON: %s\n", jsonm)

      if ev.EventName == fritzbox.CALL {
        fmt.Printf("%s Event: %s->%s\n", ev.EventName, ev.Source, ev.Destination)
      } else if ev.EventName == fritzbox.RING {
        fmt.Printf("%s Event: %s->%s\n", ev.EventName, ev.Source, ev.Destination)
      } else {
          fmt.Printf("! %s\n", ev)
      }
  }
}

func mainloop(host string) {
  c := new(fritzbox.CallmonHandler).Connect(host)

  defer c.Close()

  if c.Connected {
    recv := make(chan fritzbox.FbEvent)
    go handleMessages(recv)

    // Inject a test message
    f := c.Parse("06.08.14 14:52:26;CALL;1;10;50000001;012344567;SIP1;")
    recv <- f

    c.Loop(recv)
  }
}

func main() {
  arg := os.Args

  host := "fritz.box"
  if (len(arg) > 1 && arg[1] != "") {
    host = arg[1]
  }

  mainloop(host)
  fmt.Println("NEVER EVER GONNA GIVE YOU UP")
}
<commit_msg>fixed imports<commit_after>package main

import (
    "os"
    "fmt"
    "encoding/json"
    "github.com/toke/golang-callmon/fritzbox"
)

func handleMessages(msgchan <-chan fritzbox.FbEvent){
  for {
      ev := <- msgchan

      jsonm,_ := json.Marshal(&ev)
      fmt.Printf("Some JSON: %s\n", jsonm)

      if ev.EventName == fritzbox.CALL {
        fmt.Printf("%s Event: %s->%s\n", ev.EventName, ev.Source, ev.Destination)
      } else if ev.EventName == fritzbox.RING {
        fmt.Printf("%s Event: %s->%s\n", ev.EventName, ev.Source, ev.Destination)
      } else {
          fmt.Printf("! %s\n", ev)
      }
  }
}

func mainloop(host string) {
  c := new(fritzbox.CallmonHandler).Connect(host)

  defer c.Close()

  if c.Connected {
    recv := make(chan fritzbox.FbEvent)
    go handleMessages(recv)

    // Inject a test message
    f := c.Parse("06.08.14 14:52:26;CALL;1;10;50000001;012344567;SIP1;")
    recv <- f

    c.Loop(recv)
  }
}

func main() {
  arg := os.Args

  host := "fritz.box"
  if (len(arg) > 1 && arg[1] != "") {
    host = arg[1]
  }

  mainloop(host)
  fmt.Println("NEVER EVER GONNA GIVE YOU UP")
}
<|endoftext|>


<commit_before>// Copyright ©2012 The bíogo.bam 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 bam_test

import (
	"fmt"

	"code.google.com/p/biogo.bam"
)

func min(a, b int) int {
	if a > b {
		return b
	}
	return a
}

func max(a, b int) int {
	if a < b {
		return b
	}
	return a
}

// Overlap returns the length of the overlap between the alignment
// of the BAM record and the interval specified.
func Overlap(r *bam.Record, start, end int) int {
	var overlap, o int
	pos := r.Pos
	for _, co := range r.Cigar {
		t, l := co.Type(), co.Len()
		if t.Consumes().Query && t.Consumes().Reference {
			o = min(pos+l, end) - max(pos, start)
			if o > 0 {
				overlap += o
			}
		}
		if t.Consumes().Query || t.Consumes().Reference {
			pos += l
		}
	}

	return overlap
}

func ExampleConsume() {
	// Example alignments from the SAM specification:
	//
	// @HD	VN:1.5	SO:coordinate
	// @SQ	SN:ref	LN:45
	// @CO	--------------------------------------------------------
	// @CO	Coor     12345678901234  5678901234567890123456789012345
	// @CO	ref      AGCATGTTAGATAA**GATAGCTGTGCTAGTAGGCAGTCAGCGCCAT
	// @CO	--------------------------------------------------------
	// @CO	+r001/1        TTAGATAAAGGATA*CTG
	// @CO	+r002         aaaAGATAA*GGATA
	// @CO	+r003       gcctaAGCTAA
	// @CO	+r004                     ATAGCT..............TCAGC
	// @CO	-r003                            ttagctTAGGC
	// @CO	-r001/2                                        CAGCGGCAT
	// @CO	--------------------------------------------------------
	// r001	99	ref	7	30	8M2I4M1D3M	=	37	39	TTAGATAAAGGATACTG	*
	// r002	0	ref	9	30	3S6M1P1I4M	*	0	0	AAAAGATAAGGATA	*
	// r003	0	ref	9	30	5S6M	*	0	0	GCCTAAGCTAA	*	SA:Z:ref,29,-,6H5M,17,0;
	// r004	0	ref	16	30	6M14N5M	*	0	0	ATAGCTTCAGC	*
	// r003	2064	ref	29	17	6H5M	*	0	0	TAGGC	*	SA:Z:ref,9,+,5S6M,30,1;
	// r001	147	ref	37	30	9M	=	7	-39	CAGCGGCAT	*	NM:i:1

	const (
		refStart = 0
		refEnd   = 45
	)

	records := []*bam.Record{
		{Name: "r001/1", Pos: 6, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarMatch, 8),
			bam.NewCigarOp(bam.CigarInsertion, 2),
			bam.NewCigarOp(bam.CigarMatch, 4),
			bam.NewCigarOp(bam.CigarDeletion, 1),
			bam.NewCigarOp(bam.CigarMatch, 3),
		}},
		{Name: "r002", Pos: 8, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarSoftClipped, 3),
			bam.NewCigarOp(bam.CigarMatch, 6),
			bam.NewCigarOp(bam.CigarPadded, 1),
			bam.NewCigarOp(bam.CigarInsertion, 1),
			bam.NewCigarOp(bam.CigarMatch, 4),
		}},
		{Name: "r003", Pos: 8, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarSoftClipped, 5),
			bam.NewCigarOp(bam.CigarMatch, 6),
		}},
		{Name: "r004", Pos: 15, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarMatch, 6),
			bam.NewCigarOp(bam.CigarSkipped, 14),
			bam.NewCigarOp(bam.CigarMatch, 5),
		}},
		{Name: "r003", Pos: 28, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarHardClipped, 6),
			bam.NewCigarOp(bam.CigarMatch, 5),
		}},
		{Name: "r001/2", Pos: 36, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarMatch, 9),
		}},
	}

	for _, r := range records {
		fmt.Printf("%q overlaps reference by %d letters\n", r.Name, Overlap(r, refStart, refEnd))
	}

	// Output:
	//
	// "r001/1" overlaps reference by 15 letters
	// "r002" overlaps reference by 10 letters
	// "r003" overlaps reference by 6 letters
	// "r004" overlaps reference by 11 letters
	// "r003" overlaps reference by 5 letters
	// "r001/2" overlaps reference by 9 letters
}
<commit_msg>Add warning about CigarBack<commit_after>// Copyright ©2012 The bíogo.bam 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 bam_test

import (
	"fmt"

	"code.google.com/p/biogo.bam"
)

func min(a, b int) int {
	if a > b {
		return b
	}
	return a
}

func max(a, b int) int {
	if a < b {
		return b
	}
	return a
}

// Overlap returns the length of the overlap between the alignment
// of the BAM record and the interval specified.
//
// Note that this does not correctly handle the CigarBack operation
// which is poorly specified.
func Overlap(r *bam.Record, start, end int) int {
	var overlap, o int
	pos := r.Pos
	for _, co := range r.Cigar {
		t, l := co.Type(), co.Len()
		if t.Consumes().Query && t.Consumes().Reference {
			o = min(pos+l, end) - max(pos, start)
			if o > 0 {
				overlap += o
			}
		}
		if t.Consumes().Query || t.Consumes().Reference {
			pos += l
		}
	}

	return overlap
}

func ExampleConsume() {
	// Example alignments from the SAM specification:
	//
	// @HD	VN:1.5	SO:coordinate
	// @SQ	SN:ref	LN:45
	// @CO	--------------------------------------------------------
	// @CO	Coor     12345678901234  5678901234567890123456789012345
	// @CO	ref      AGCATGTTAGATAA**GATAGCTGTGCTAGTAGGCAGTCAGCGCCAT
	// @CO	--------------------------------------------------------
	// @CO	+r001/1        TTAGATAAAGGATA*CTG
	// @CO	+r002         aaaAGATAA*GGATA
	// @CO	+r003       gcctaAGCTAA
	// @CO	+r004                     ATAGCT..............TCAGC
	// @CO	-r003                            ttagctTAGGC
	// @CO	-r001/2                                        CAGCGGCAT
	// @CO	--------------------------------------------------------
	// r001	99	ref	7	30	8M2I4M1D3M	=	37	39	TTAGATAAAGGATACTG	*
	// r002	0	ref	9	30	3S6M1P1I4M	*	0	0	AAAAGATAAGGATA	*
	// r003	0	ref	9	30	5S6M	*	0	0	GCCTAAGCTAA	*	SA:Z:ref,29,-,6H5M,17,0;
	// r004	0	ref	16	30	6M14N5M	*	0	0	ATAGCTTCAGC	*
	// r003	2064	ref	29	17	6H5M	*	0	0	TAGGC	*	SA:Z:ref,9,+,5S6M,30,1;
	// r001	147	ref	37	30	9M	=	7	-39	CAGCGGCAT	*	NM:i:1

	const (
		refStart = 0
		refEnd   = 45
	)

	records := []*bam.Record{
		{Name: "r001/1", Pos: 6, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarMatch, 8),
			bam.NewCigarOp(bam.CigarInsertion, 2),
			bam.NewCigarOp(bam.CigarMatch, 4),
			bam.NewCigarOp(bam.CigarDeletion, 1),
			bam.NewCigarOp(bam.CigarMatch, 3),
		}},
		{Name: "r002", Pos: 8, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarSoftClipped, 3),
			bam.NewCigarOp(bam.CigarMatch, 6),
			bam.NewCigarOp(bam.CigarPadded, 1),
			bam.NewCigarOp(bam.CigarInsertion, 1),
			bam.NewCigarOp(bam.CigarMatch, 4),
		}},
		{Name: "r003", Pos: 8, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarSoftClipped, 5),
			bam.NewCigarOp(bam.CigarMatch, 6),
		}},
		{Name: "r004", Pos: 15, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarMatch, 6),
			bam.NewCigarOp(bam.CigarSkipped, 14),
			bam.NewCigarOp(bam.CigarMatch, 5),
		}},
		{Name: "r003", Pos: 28, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarHardClipped, 6),
			bam.NewCigarOp(bam.CigarMatch, 5),
		}},
		{Name: "r001/2", Pos: 36, Cigar: []bam.CigarOp{
			bam.NewCigarOp(bam.CigarMatch, 9),
		}},
	}

	for _, r := range records {
		fmt.Printf("%q overlaps reference by %d letters\n", r.Name, Overlap(r, refStart, refEnd))
	}

	// Output:
	//
	// "r001/1" overlaps reference by 15 letters
	// "r002" overlaps reference by 10 letters
	// "r003" overlaps reference by 6 letters
	// "r004" overlaps reference by 11 letters
	// "r003" overlaps reference by 5 letters
	// "r001/2" overlaps reference by 9 letters
}
<|endoftext|>


<commit_before>package autonat

import (
	"context"
	"errors"
	"math/rand"
	"sync"
	"time"

	pb "github.com/libp2p/go-libp2p-autonat/pb"
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/peerstore"

	"github.com/libp2p/go-msgio/protoio"
	ma "github.com/multiformats/go-multiaddr"
)

var streamTimeout = 60 * time.Second

// AutoNATService provides NAT autodetection services to other peers
type autoNATService struct {
	instanceLock      sync.Mutex
	instance          context.CancelFunc
	backgroundRunning chan struct{} // closed when background exits

	config *config

	// rate limiter
	mx         sync.Mutex
	reqs       map[peer.ID]int
	globalReqs int
}

// NewAutoNATService creates a new AutoNATService instance attached to a host
func newAutoNATService(c *config) (*autoNATService, error) {
	if c.dialer == nil {
		return nil, errors.New("cannot create NAT service without a network")
	}
	return &autoNATService{
		config: c,
		reqs:   make(map[peer.ID]int),
	}, nil
}

func (as *autoNATService) handleStream(s network.Stream) {
	s.SetDeadline(time.Now().Add(streamTimeout))
	defer s.Close()

	pid := s.Conn().RemotePeer()
	log.Debugf("New stream from %s", pid.Pretty())

	r := protoio.NewDelimitedReader(s, network.MessageSizeMax)
	w := protoio.NewDelimitedWriter(s)

	var req pb.Message
	var res pb.Message

	err := r.ReadMsg(&req)
	if err != nil {
		log.Debugf("Error reading message from %s: %s", pid.Pretty(), err.Error())
		s.Reset()
		return
	}

	t := req.GetType()
	if t != pb.Message_DIAL {
		log.Debugf("Unexpected message from %s: %s (%d)", pid.Pretty(), t.String(), t)
		s.Reset()
		return
	}

	dr := as.handleDial(pid, s.Conn().RemoteMultiaddr(), req.GetDial().GetPeer())
	res.Type = pb.Message_DIAL_RESPONSE.Enum()
	res.DialResponse = dr

	err = w.WriteMsg(&res)
	if err != nil {
		log.Debugf("Error writing response to %s: %s", pid.Pretty(), err.Error())
		s.Reset()
		return
	}
}

func (as *autoNATService) handleDial(p peer.ID, obsaddr ma.Multiaddr, mpi *pb.Message_PeerInfo) *pb.Message_DialResponse {
	if mpi == nil {
		return newDialResponseError(pb.Message_E_BAD_REQUEST, "missing peer info")
	}

	mpid := mpi.GetId()
	if mpid != nil {
		mp, err := peer.IDFromBytes(mpid)
		if err != nil {
			return newDialResponseError(pb.Message_E_BAD_REQUEST, "bad peer id")
		}

		if mp != p {
			return newDialResponseError(pb.Message_E_BAD_REQUEST, "peer id mismatch")
		}
	}

	addrs := make([]ma.Multiaddr, 0, as.config.maxPeerAddresses)
	seen := make(map[string]struct{})

	// Don't even try to dial peers with blocked remote addresses. In order to dial a peer, we
	// need to know their public IP address, and it needs to be different from our public IP
	// address.
	if as.config.dialPolicy.skipDial(obsaddr) {
		return newDialResponseError(pb.Message_E_DIAL_ERROR, "refusing to dial peer with blocked observed address")
	}

	// Determine the peer's IP address.
	hostIP, _ := ma.SplitFirst(obsaddr)
	switch hostIP.Protocol().Code {
	case ma.P_IP4, ma.P_IP6:
	default:
		// This shouldn't be possible as we should skip all addresses that don't include
		// public IP addresses.
		return newDialResponseError(pb.Message_E_INTERNAL_ERROR, "expected an IP address")
	}

	// add observed addr to the list of addresses to dial
	addrs = append(addrs, obsaddr)
	seen[obsaddr.String()] = struct{}{}

	for _, maddr := range mpi.GetAddrs() {
		addr, err := ma.NewMultiaddrBytes(maddr)
		if err != nil {
			log.Debugf("Error parsing multiaddr: %s", err.Error())
			continue
		}

		// For security reasons, we _only_ dial the observed IP address.
		// Replace other IP addresses with the observed one so we can still try the
		// requested ports/transports.
		if ip, rest := ma.SplitFirst(addr); !ip.Equal(hostIP) {
			// Make sure it's an IP address
			switch ip.Protocol().Code {
			case ma.P_IP4, ma.P_IP6:
			default:
				continue
			}
			addr = hostIP
			if rest != nil {
				addr = addr.Encapsulate(rest)
			}
		}

		// Make sure we're willing to dial the rest of the address (e.g., not a circuit
		// address).
		if as.config.dialPolicy.skipDial(addr) {
			continue
		}

		str := addr.String()
		_, ok := seen[str]
		if ok {
			continue
		}

		addrs = append(addrs, addr)
		seen[str] = struct{}{}

		if len(addrs) >= as.config.maxPeerAddresses {
			break
		}
	}

	if len(addrs) == 0 {
		return newDialResponseError(pb.Message_E_DIAL_ERROR, "no dialable addresses")
	}

	return as.doDial(peer.AddrInfo{ID: p, Addrs: addrs})
}

func (as *autoNATService) doDial(pi peer.AddrInfo) *pb.Message_DialResponse {
	// rate limit check
	as.mx.Lock()
	count := as.reqs[pi.ID]
	if count >= as.config.throttlePeerMax || (as.config.throttleGlobalMax > 0 &&
		as.globalReqs >= as.config.throttleGlobalMax) {
		as.mx.Unlock()
		return newDialResponseError(pb.Message_E_DIAL_REFUSED, "too many dials")
	}
	as.reqs[pi.ID] = count + 1
	as.globalReqs++
	as.mx.Unlock()

	ctx, cancel := context.WithTimeout(context.Background(), as.config.dialTimeout)
	defer cancel()

	as.config.dialer.Peerstore().ClearAddrs(pi.ID)

	as.config.dialer.Peerstore().AddAddrs(pi.ID, pi.Addrs, peerstore.TempAddrTTL)
	conn, err := as.config.dialer.DialPeer(ctx, pi.ID)
	if err != nil {
		log.Debugf("error dialing %s: %s", pi.ID.Pretty(), err.Error())
		// wait for the context to timeout to avoid leaking timing information
		// this renders the service ineffective as a port scanner
		<-ctx.Done()
		return newDialResponseError(pb.Message_E_DIAL_ERROR, "dial failed")
	}

	ra := conn.RemoteMultiaddr()
	as.config.dialer.ClosePeer(pi.ID)
	return newDialResponseOK(ra)
}

// Enable the autoNAT service if it is not running.
func (as *autoNATService) Enable() {
	as.instanceLock.Lock()
	defer as.instanceLock.Unlock()
	if as.instance != nil {
		return
	}
	ctx, cancel := context.WithCancel(context.Background())
	as.instance = cancel
	as.backgroundRunning = make(chan struct{})

	go as.background(ctx)
}

// Disable the autoNAT service if it is running.
func (as *autoNATService) Disable() {
	as.instanceLock.Lock()
	defer as.instanceLock.Unlock()
	if as.instance != nil {
		as.instance()
		as.instance = nil
		<-as.backgroundRunning
	}
}

func (as *autoNATService) background(ctx context.Context) {
	defer close(as.backgroundRunning)
	as.config.host.SetStreamHandler(AutoNATProto, as.handleStream)

	timer := time.NewTimer(as.config.throttleResetPeriod)
	defer timer.Stop()

	for {
		select {
		case <-timer.C:
			as.mx.Lock()
			as.reqs = make(map[peer.ID]int)
			as.globalReqs = 0
			as.mx.Unlock()
			jitter := rand.Float32() * float32(as.config.throttleResetJitter)
			timer.Reset(as.config.throttleResetPeriod + time.Duration(int64(jitter)))
		case <-ctx.Done():
			as.config.host.RemoveStreamHandler(AutoNATProto)
			return
		}
	}
}
<commit_msg>clean up dialer peerstore after each dial<commit_after>package autonat

import (
	"context"
	"errors"
	"math/rand"
	"sync"
	"time"

	pb "github.com/libp2p/go-libp2p-autonat/pb"
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/peerstore"

	"github.com/libp2p/go-msgio/protoio"
	ma "github.com/multiformats/go-multiaddr"
)

var streamTimeout = 60 * time.Second

// AutoNATService provides NAT autodetection services to other peers
type autoNATService struct {
	instanceLock      sync.Mutex
	instance          context.CancelFunc
	backgroundRunning chan struct{} // closed when background exits

	config *config

	// rate limiter
	mx         sync.Mutex
	reqs       map[peer.ID]int
	globalReqs int
}

// NewAutoNATService creates a new AutoNATService instance attached to a host
func newAutoNATService(c *config) (*autoNATService, error) {
	if c.dialer == nil {
		return nil, errors.New("cannot create NAT service without a network")
	}
	return &autoNATService{
		config: c,
		reqs:   make(map[peer.ID]int),
	}, nil
}

func (as *autoNATService) handleStream(s network.Stream) {
	s.SetDeadline(time.Now().Add(streamTimeout))
	defer s.Close()

	pid := s.Conn().RemotePeer()
	log.Debugf("New stream from %s", pid.Pretty())

	r := protoio.NewDelimitedReader(s, network.MessageSizeMax)
	w := protoio.NewDelimitedWriter(s)

	var req pb.Message
	var res pb.Message

	err := r.ReadMsg(&req)
	if err != nil {
		log.Debugf("Error reading message from %s: %s", pid.Pretty(), err.Error())
		s.Reset()
		return
	}

	t := req.GetType()
	if t != pb.Message_DIAL {
		log.Debugf("Unexpected message from %s: %s (%d)", pid.Pretty(), t.String(), t)
		s.Reset()
		return
	}

	dr := as.handleDial(pid, s.Conn().RemoteMultiaddr(), req.GetDial().GetPeer())
	res.Type = pb.Message_DIAL_RESPONSE.Enum()
	res.DialResponse = dr

	err = w.WriteMsg(&res)
	if err != nil {
		log.Debugf("Error writing response to %s: %s", pid.Pretty(), err.Error())
		s.Reset()
		return
	}
}

func (as *autoNATService) handleDial(p peer.ID, obsaddr ma.Multiaddr, mpi *pb.Message_PeerInfo) *pb.Message_DialResponse {
	if mpi == nil {
		return newDialResponseError(pb.Message_E_BAD_REQUEST, "missing peer info")
	}

	mpid := mpi.GetId()
	if mpid != nil {
		mp, err := peer.IDFromBytes(mpid)
		if err != nil {
			return newDialResponseError(pb.Message_E_BAD_REQUEST, "bad peer id")
		}

		if mp != p {
			return newDialResponseError(pb.Message_E_BAD_REQUEST, "peer id mismatch")
		}
	}

	addrs := make([]ma.Multiaddr, 0, as.config.maxPeerAddresses)
	seen := make(map[string]struct{})

	// Don't even try to dial peers with blocked remote addresses. In order to dial a peer, we
	// need to know their public IP address, and it needs to be different from our public IP
	// address.
	if as.config.dialPolicy.skipDial(obsaddr) {
		return newDialResponseError(pb.Message_E_DIAL_ERROR, "refusing to dial peer with blocked observed address")
	}

	// Determine the peer's IP address.
	hostIP, _ := ma.SplitFirst(obsaddr)
	switch hostIP.Protocol().Code {
	case ma.P_IP4, ma.P_IP6:
	default:
		// This shouldn't be possible as we should skip all addresses that don't include
		// public IP addresses.
		return newDialResponseError(pb.Message_E_INTERNAL_ERROR, "expected an IP address")
	}

	// add observed addr to the list of addresses to dial
	addrs = append(addrs, obsaddr)
	seen[obsaddr.String()] = struct{}{}

	for _, maddr := range mpi.GetAddrs() {
		addr, err := ma.NewMultiaddrBytes(maddr)
		if err != nil {
			log.Debugf("Error parsing multiaddr: %s", err.Error())
			continue
		}

		// For security reasons, we _only_ dial the observed IP address.
		// Replace other IP addresses with the observed one so we can still try the
		// requested ports/transports.
		if ip, rest := ma.SplitFirst(addr); !ip.Equal(hostIP) {
			// Make sure it's an IP address
			switch ip.Protocol().Code {
			case ma.P_IP4, ma.P_IP6:
			default:
				continue
			}
			addr = hostIP
			if rest != nil {
				addr = addr.Encapsulate(rest)
			}
		}

		// Make sure we're willing to dial the rest of the address (e.g., not a circuit
		// address).
		if as.config.dialPolicy.skipDial(addr) {
			continue
		}

		str := addr.String()
		_, ok := seen[str]
		if ok {
			continue
		}

		addrs = append(addrs, addr)
		seen[str] = struct{}{}

		if len(addrs) >= as.config.maxPeerAddresses {
			break
		}
	}

	if len(addrs) == 0 {
		return newDialResponseError(pb.Message_E_DIAL_ERROR, "no dialable addresses")
	}

	return as.doDial(peer.AddrInfo{ID: p, Addrs: addrs})
}

func (as *autoNATService) doDial(pi peer.AddrInfo) *pb.Message_DialResponse {
	// rate limit check
	as.mx.Lock()
	count := as.reqs[pi.ID]
	if count >= as.config.throttlePeerMax || (as.config.throttleGlobalMax > 0 &&
		as.globalReqs >= as.config.throttleGlobalMax) {
		as.mx.Unlock()
		return newDialResponseError(pb.Message_E_DIAL_REFUSED, "too many dials")
	}
	as.reqs[pi.ID] = count + 1
	as.globalReqs++
	as.mx.Unlock()

	ctx, cancel := context.WithTimeout(context.Background(), as.config.dialTimeout)
	defer cancel()

	as.config.dialer.Peerstore().ClearAddrs(pi.ID)

	as.config.dialer.Peerstore().AddAddrs(pi.ID, pi.Addrs, peerstore.TempAddrTTL)

	defer func() {
		as.config.dialer.Peerstore().ClearAddrs(pi.ID)
		as.config.dialer.Peerstore().RemovePeer(pi.ID)
	}()

	conn, err := as.config.dialer.DialPeer(ctx, pi.ID)
	if err != nil {
		log.Debugf("error dialing %s: %s", pi.ID.Pretty(), err.Error())
		// wait for the context to timeout to avoid leaking timing information
		// this renders the service ineffective as a port scanner
		<-ctx.Done()
		return newDialResponseError(pb.Message_E_DIAL_ERROR, "dial failed")
	}

	ra := conn.RemoteMultiaddr()
	as.config.dialer.ClosePeer(pi.ID)
	return newDialResponseOK(ra)
}

// Enable the autoNAT service if it is not running.
func (as *autoNATService) Enable() {
	as.instanceLock.Lock()
	defer as.instanceLock.Unlock()
	if as.instance != nil {
		return
	}
	ctx, cancel := context.WithCancel(context.Background())
	as.instance = cancel
	as.backgroundRunning = make(chan struct{})

	go as.background(ctx)
}

// Disable the autoNAT service if it is running.
func (as *autoNATService) Disable() {
	as.instanceLock.Lock()
	defer as.instanceLock.Unlock()
	if as.instance != nil {
		as.instance()
		as.instance = nil
		<-as.backgroundRunning
	}
}

func (as *autoNATService) background(ctx context.Context) {
	defer close(as.backgroundRunning)
	as.config.host.SetStreamHandler(AutoNATProto, as.handleStream)

	timer := time.NewTimer(as.config.throttleResetPeriod)
	defer timer.Stop()

	for {
		select {
		case <-timer.C:
			as.mx.Lock()
			as.reqs = make(map[peer.ID]int)
			as.globalReqs = 0
			as.mx.Unlock()
			jitter := rand.Float32() * float32(as.config.throttleResetJitter)
			timer.Reset(as.config.throttleResetPeriod + time.Duration(int64(jitter)))
		case <-ctx.Done():
			as.config.host.RemoveStreamHandler(AutoNATProto)
			return
		}
	}
}
<|endoftext|>


<commit_before>package blankhost

import (
	"context"
	"io"

	"github.com/libp2p/go-libp2p-core/connmgr"
	"github.com/libp2p/go-libp2p-core/host"
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/peerstore"
	"github.com/libp2p/go-libp2p-core/protocol"

	logging "github.com/ipfs/go-log"

	ma "github.com/multiformats/go-multiaddr"
	mstream "github.com/multiformats/go-multistream"
)

var log = logging.Logger("blankhost")

// BlankHost is the thinnest implementation of the host.Host interface
type BlankHost struct {
	n    network.Network
	mux  *mstream.MultistreamMuxer
	cmgr connmgr.ConnManager
}

func NewBlankHost(n network.Network) *BlankHost {
	bh := &BlankHost{
		n:    n,
		cmgr: &connmgr.NullConnMgr{},
		mux:  mstream.NewMultistreamMuxer(),
	}

	n.SetStreamHandler(bh.newStreamHandler)
	return bh
}

var _ host.Host = (*BlankHost)(nil)

func (bh *BlankHost) Addrs() []ma.Multiaddr {
	addrs, err := bh.n.InterfaceListenAddresses()
	if err != nil {
		log.Debug("error retrieving network interface addrs: ", err)
		return nil
	}

	return addrs
}

func (bh *BlankHost) Close() error {
	return bh.n.Close()
}

func (bh *BlankHost) Connect(ctx context.Context, ai peer.AddrInfo) error {
	// absorb addresses into peerstore
	bh.Peerstore().AddAddrs(ai.ID, ai.Addrs, peerstore.TempAddrTTL)

	cs := bh.n.ConnsToPeer(ai.ID)
	if len(cs) > 0 {
		return nil
	}

	_, err := bh.Network().DialPeer(ctx, ai.ID)
	return err
}

func (bh *BlankHost) Peerstore() peerstore.Peerstore {
	return bh.n.Peerstore()
}

func (bh *BlankHost) ID() peer.ID {
	return bh.n.LocalPeer()
}

func (bh *BlankHost) NewStream(ctx context.Context, p peer.ID, protos ...protocol.ID) (network.Stream, error) {
	s, err := bh.n.NewStream(ctx, p)
	if err != nil {
		return nil, err
	}

	var protoStrs []string
	for _, pid := range protos {
		protoStrs = append(protoStrs, string(pid))
	}

	selected, err := mstream.SelectOneOf(protoStrs, s)
	if err != nil {
		s.Close()
		return nil, err
	}

	selpid := protocol.ID(selected)
	s.SetProtocol(selpid)
	bh.Peerstore().AddProtocols(p, selected)

	return s, nil
}

func (bh *BlankHost) RemoveStreamHandler(p protocol.ID) {
	bh.Mux().RemoveHandler(string(p))
}

func (bh *BlankHost) SetStreamHandler(pid protocol.ID, handler network.StreamHandler) {
	bh.Mux().AddHandler(string(pid), func(p string, rwc io.ReadWriteCloser) error {
		is := rwc.(network.Stream)
		is.SetProtocol(protocol.ID(p))
		handler(is)
		return nil
	})
}

func (bh *BlankHost) SetStreamHandlerMatch(pid protocol.ID, m func(string) bool, handler network.StreamHandler) {
	bh.Mux().AddHandlerWithFunc(string(pid), m, func(p string, rwc io.ReadWriteCloser) error {
		is := rwc.(network.Stream)
		is.SetProtocol(protocol.ID(p))
		handler(is)
		return nil
	})
}

// newStreamHandler is the remote-opened stream handler for network.Network
func (bh *BlankHost) newStreamHandler(s network.Stream) {

	protoID, handle, err := bh.Mux().Negotiate(s)
	if err != nil {
		log.Warning("protocol mux failed: %s", err)
		s.Close()
		return
	}

	s.SetProtocol(protocol.ID(protoID))

	go handle(protoID, s)
}

// TODO: i'm not sure this really needs to be here
func (bh *BlankHost) Mux() protocol.Switch {
	return bh.mux
}

// TODO: also not sure this fits... Might be better ways around this (leaky abstractions)
func (bh *BlankHost) Network() network.Network {
	return bh.n
}

func (bh *BlankHost) ConnManager() connmgr.ConnManager {
	return bh.cmgr
}
<commit_msg>integrate the event bus into host implementations (#23)<commit_after>package blankhost

import (
	"context"
	"io"

	"github.com/libp2p/go-libp2p-core/connmgr"
	"github.com/libp2p/go-libp2p-core/event"
	"github.com/libp2p/go-libp2p-core/host"
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/peerstore"
	"github.com/libp2p/go-libp2p-core/protocol"

	"github.com/libp2p/go-eventbus"

	logging "github.com/ipfs/go-log"

	ma "github.com/multiformats/go-multiaddr"
	mstream "github.com/multiformats/go-multistream"
)

var log = logging.Logger("blankhost")

// BlankHost is the thinnest implementation of the host.Host interface
type BlankHost struct {
	n        network.Network
	mux      *mstream.MultistreamMuxer
	cmgr     connmgr.ConnManager
	eventbus event.Bus
	emitters struct {
		evtLocalProtocolsUpdated event.Emitter
	}
}

func NewBlankHost(n network.Network) *BlankHost {
	bh := &BlankHost{
		n:        n,
		cmgr:     &connmgr.NullConnMgr{},
		mux:      mstream.NewMultistreamMuxer(),
		eventbus: eventbus.NewBus(),
	}

	var err error
	if bh.emitters.evtLocalProtocolsUpdated, err = bh.eventbus.Emitter(&event.EvtLocalProtocolsUpdated{}); err != nil {
		return nil
	}

	n.SetStreamHandler(bh.newStreamHandler)
	return bh
}

var _ host.Host = (*BlankHost)(nil)

func (bh *BlankHost) Addrs() []ma.Multiaddr {
	addrs, err := bh.n.InterfaceListenAddresses()
	if err != nil {
		log.Debug("error retrieving network interface addrs: ", err)
		return nil
	}

	return addrs
}

func (bh *BlankHost) Close() error {
	return bh.n.Close()
}

func (bh *BlankHost) Connect(ctx context.Context, ai peer.AddrInfo) error {
	// absorb addresses into peerstore
	bh.Peerstore().AddAddrs(ai.ID, ai.Addrs, peerstore.TempAddrTTL)

	cs := bh.n.ConnsToPeer(ai.ID)
	if len(cs) > 0 {
		return nil
	}

	_, err := bh.Network().DialPeer(ctx, ai.ID)
	return err
}

func (bh *BlankHost) Peerstore() peerstore.Peerstore {
	return bh.n.Peerstore()
}

func (bh *BlankHost) ID() peer.ID {
	return bh.n.LocalPeer()
}

func (bh *BlankHost) NewStream(ctx context.Context, p peer.ID, protos ...protocol.ID) (network.Stream, error) {
	s, err := bh.n.NewStream(ctx, p)
	if err != nil {
		return nil, err
	}

	var protoStrs []string
	for _, pid := range protos {
		protoStrs = append(protoStrs, string(pid))
	}

	selected, err := mstream.SelectOneOf(protoStrs, s)
	if err != nil {
		s.Close()
		return nil, err
	}

	selpid := protocol.ID(selected)
	s.SetProtocol(selpid)
	bh.Peerstore().AddProtocols(p, selected)

	return s, nil
}

func (bh *BlankHost) RemoveStreamHandler(pid protocol.ID) {
	bh.Mux().RemoveHandler(string(pid))
	bh.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{
		Removed: []protocol.ID{pid},
	})
}

func (bh *BlankHost) SetStreamHandler(pid protocol.ID, handler network.StreamHandler) {
	bh.Mux().AddHandler(string(pid), func(p string, rwc io.ReadWriteCloser) error {
		is := rwc.(network.Stream)
		is.SetProtocol(protocol.ID(p))
		handler(is)
		return nil
	})
	bh.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{
		Added: []protocol.ID{pid},
	})
}

func (bh *BlankHost) SetStreamHandlerMatch(pid protocol.ID, m func(string) bool, handler network.StreamHandler) {
	bh.Mux().AddHandlerWithFunc(string(pid), m, func(p string, rwc io.ReadWriteCloser) error {
		is := rwc.(network.Stream)
		is.SetProtocol(protocol.ID(p))
		handler(is)
		return nil
	})
	bh.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{
		Added: []protocol.ID{pid},
	})
}

// newStreamHandler is the remote-opened stream handler for network.Network
func (bh *BlankHost) newStreamHandler(s network.Stream) {
	protoID, handle, err := bh.Mux().Negotiate(s)
	if err != nil {
		log.Warning("protocol mux failed: %s", err)
		s.Close()
		return
	}

	s.SetProtocol(protocol.ID(protoID))

	go handle(protoID, s)
}

// TODO: i'm not sure this really needs to be here
func (bh *BlankHost) Mux() protocol.Switch {
	return bh.mux
}

// TODO: also not sure this fits... Might be better ways around this (leaky abstractions)
func (bh *BlankHost) Network() network.Network {
	return bh.n
}

func (bh *BlankHost) ConnManager() connmgr.ConnManager {
	return bh.cmgr
}

func (bh *BlankHost) EventBus() event.Bus {
	return bh.eventbus
}
<|endoftext|>


<commit_before>package wallet

import (
	"bytes"
	"crypto/rand"
	"errors"
	"path/filepath"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/persist"
	"github.com/NebulousLabs/Sia/types"
)

const (
	// The header for all siag files. Do not change. Because siag was created
	// early in development, compatibility with siag requires manually handling
	// the headers and version instead of using the persist package.
	SiagFileHeader    = "siag"
	SiagFileExtension = ".siakey"
	SiagFileVersion   = "1.0"
)

var (
	ErrInconsistentKeys = errors.New("keyfiles provided that are for different addresses")
	ErrInsufficientKeys = errors.New("not enough keys provided to spend the siafunds")
	ErrNoKeyfile        = errors.New("no keyfile has been presented")
	ErrUnknownHeader    = errors.New("file contains the wrong header")
	ErrUnknownVersion   = errors.New("file has an unknown version number")

	errAllDuplicates         = errors.New("old wallet has no new seeds")
	errDuplicateSpendableKey = errors.New("key has already been loaded into the wallet")
)

// A SiagKeyPair is the struct representation of the bytes that get saved to
// disk by siag when a new keyfile is created.
type SiagKeyPair struct {
	Header           string
	Version          string
	Index            int // should be uint64 - too late now
	SecretKey        crypto.SecretKey
	UnlockConditions types.UnlockConditions
}

// SavedKey033x is the persist structure that was used to save and load private
// keys in versions v0.3.3.x for siad.
type SavedKey033x struct {
	SecretKey        crypto.SecretKey
	UnlockConditions types.UnlockConditions
	Visible          bool
}

// initUnseededKeys loads all of the unseeded keys into the wallet after the
// wallet gets unlocked.
func (w *Wallet) initUnseededKeys(masterKey crypto.TwofishKey) error {
	for _, uk := range w.persist.UnseededKeys {
		// Verify that the decryption key is correct.
		encKey := uidEncryptionKey(masterKey, uk.UID)
		expectedDecryptedVerification := make([]byte, crypto.EntropySize)
		decryptedVerification, err := encKey.DecryptBytes(uk.EncryptionVerification)
		if err != nil {
			return err
		}
		if !bytes.Equal(expectedDecryptedVerification, decryptedVerification) {
			return modules.ErrBadEncryptionKey
		}

		// Decrypt the spendable key and add it to the wallet.
		encodedKey, err := encKey.DecryptBytes(uk.SpendableKey)
		if err != nil {
			return err
		}
		var sk spendableKey
		err = encoding.Unmarshal(encodedKey, &sk)
		if err != nil {
			return err
		}
		w.keys[sk.UnlockConditions.UnlockHash()] = sk
	}
	return nil
}

// loadSpendableKey loads a spendable key into the wallet's persist structure.
func (w *Wallet) loadSpendableKey(masterKey crypto.TwofishKey, sk spendableKey) error {
	// Duplication is detected by looking at the set of unlock conditions. If
	// the wallet is locked, correct deduplication is uncertain.
	if !w.unlocked {
		return modules.ErrLockedWallet
	}

	// Check for duplicates.
	_, exists := w.keys[sk.UnlockConditions.UnlockHash()]
	if exists {
		return errDuplicateSpendableKey
	}

	// TODO: Check that the key is actually spendable.

	// Create a UID and encryption verification.
	var skf SpendableKeyFile
	_, err := rand.Read(skf.UID[:])
	if err != nil {
		return err
	}
	encryptionKey := uidEncryptionKey(masterKey, skf.UID)
	plaintextVerification := make([]byte, encryptionVerificationLen)
	skf.EncryptionVerification, err = encryptionKey.EncryptBytes(plaintextVerification)
	if err != nil {
		return err
	}

	// Encrypt and save the key.
	skf.SpendableKey, err = encryptionKey.EncryptBytes(encoding.Marshal(sk))
	if err != nil {
		return err
	}
	w.persist.UnseededKeys = append(w.persist.UnseededKeys, skf)
	w.keys[sk.UnlockConditions.UnlockHash()] = sk
	return nil
}

// loadSiagKeys loads a set of siag keyfiles into the wallet, so that the
// wallet may spend the siafunds.
func (w *Wallet) loadSiagKeys(masterKey crypto.TwofishKey, keyfiles []string) error {
	// Load the keyfiles from disk.
	if len(keyfiles) < 1 {
		return ErrNoKeyfile
	}
	skps := make([]SiagKeyPair, len(keyfiles))
	for i, keyfile := range keyfiles {
		err := encoding.ReadFile(keyfile, &skps[i])
		if err != nil {
			return err
		}

		if skps[i].Header != SiagFileHeader {
			return ErrUnknownHeader
		}
		if skps[i].Version != SiagFileVersion {
			return ErrUnknownVersion
		}
	}

	// Check that all of the loaded files have the same address, and that there
	// are enough to create the transaction.
	baseUnlockHash := skps[0].UnlockConditions.UnlockHash()
	for _, skp := range skps {
		if skp.UnlockConditions.UnlockHash() != baseUnlockHash {
			return ErrInconsistentKeys
		}
	}
	if uint64(len(skps)) < skps[0].UnlockConditions.SignaturesRequired {
		return ErrInsufficientKeys
	}
	// Drop all unneeded keys.
	skps = skps[0:skps[0].UnlockConditions.SignaturesRequired]

	// Merge the keys into a single spendableKey and save it to the wallet.
	var sk spendableKey
	sk.UnlockConditions = skps[0].UnlockConditions
	for _, skp := range skps {
		sk.SecretKeys = append(sk.SecretKeys, skp.SecretKey)
	}
	err := w.loadSpendableKey(masterKey, sk)
	if err != nil {
		return err
	}
	err = w.saveSettings()
	if err != nil {
		return err
	}
	return w.createBackup(filepath.Join(w.persistDir, "Sia Wallet Encrypted Backup - "+persist.RandomSuffix()+settingsFileSuffix))
}

// LoadSiagKeys loads a set of siag-generated keys into the wallet.
func (w *Wallet) LoadSiagKeys(masterKey crypto.TwofishKey, keyfiles []string) error {
	lockID := w.mu.Lock()
	defer w.mu.Unlock(lockID)
	err := w.checkMasterKey(masterKey)
	if err != nil {
		return err
	}
	return w.loadSiagKeys(masterKey, keyfiles)
}

// Load033xWallet loads a v0.3.3.x wallet as an unseeded key, such that the
// funds become spendable to the current wallet.
func (w *Wallet) Load033xWallet(masterKey crypto.TwofishKey, filepath033x string) error {
	lockID := w.mu.Lock()
	defer w.mu.Unlock(lockID)
	err := w.checkMasterKey(masterKey)
	if err != nil {
		return err
	}

	var savedKeys []SavedKey033x
	err = encoding.ReadFile(filepath033x, &savedKeys)
	if err != nil {
		return err
	}
	var seedsLoaded int
	for _, savedKey := range savedKeys {
		spendKey := spendableKey{
			UnlockConditions: savedKey.UnlockConditions,
			SecretKeys:       []crypto.SecretKey{savedKey.SecretKey},
		}
		err = w.loadSpendableKey(masterKey, spendKey)
		if err != nil && err != errDuplicateSpendableKey {
			return err
		}
		if err == nil {
			seedsLoaded++
		}
	}
	err = w.saveSettings()
	if err != nil {
		return err
	}
	if seedsLoaded != 0 {
		return w.createBackup(filepath.Join(w.persistDir, "Sia Wallet Encrypted Backup - "+persist.RandomSuffix()+settingsFileSuffix))
	}
	return errAllDuplicates
}
<commit_msg>disable db corrupting deduplication effort<commit_after>package wallet

import (
	"bytes"
	"crypto/rand"
	"errors"
	"path/filepath"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/persist"
	"github.com/NebulousLabs/Sia/types"
)

const (
	// The header for all siag files. Do not change. Because siag was created
	// early in development, compatibility with siag requires manually handling
	// the headers and version instead of using the persist package.
	SiagFileHeader    = "siag"
	SiagFileExtension = ".siakey"
	SiagFileVersion   = "1.0"
)

var (
	ErrInconsistentKeys = errors.New("keyfiles provided that are for different addresses")
	ErrInsufficientKeys = errors.New("not enough keys provided to spend the siafunds")
	ErrNoKeyfile        = errors.New("no keyfile has been presented")
	ErrUnknownHeader    = errors.New("file contains the wrong header")
	ErrUnknownVersion   = errors.New("file has an unknown version number")

	errAllDuplicates         = errors.New("old wallet has no new seeds")
	errDuplicateSpendableKey = errors.New("key has already been loaded into the wallet")
)

// A SiagKeyPair is the struct representation of the bytes that get saved to
// disk by siag when a new keyfile is created.
type SiagKeyPair struct {
	Header           string
	Version          string
	Index            int // should be uint64 - too late now
	SecretKey        crypto.SecretKey
	UnlockConditions types.UnlockConditions
}

// SavedKey033x is the persist structure that was used to save and load private
// keys in versions v0.3.3.x for siad.
type SavedKey033x struct {
	SecretKey        crypto.SecretKey
	UnlockConditions types.UnlockConditions
	Visible          bool
}

// initUnseededKeys loads all of the unseeded keys into the wallet after the
// wallet gets unlocked.
func (w *Wallet) initUnseededKeys(masterKey crypto.TwofishKey) error {
	for _, uk := range w.persist.UnseededKeys {
		// Verify that the decryption key is correct.
		encKey := uidEncryptionKey(masterKey, uk.UID)
		expectedDecryptedVerification := make([]byte, crypto.EntropySize)
		decryptedVerification, err := encKey.DecryptBytes(uk.EncryptionVerification)
		if err != nil {
			return err
		}
		if !bytes.Equal(expectedDecryptedVerification, decryptedVerification) {
			return modules.ErrBadEncryptionKey
		}

		// Decrypt the spendable key and add it to the wallet.
		encodedKey, err := encKey.DecryptBytes(uk.SpendableKey)
		if err != nil {
			return err
		}
		var sk spendableKey
		err = encoding.Unmarshal(encodedKey, &sk)
		if err != nil {
			return err
		}
		w.keys[sk.UnlockConditions.UnlockHash()] = sk
	}
	return nil
}

// loadSpendableKey loads a spendable key into the wallet's persist structure.
func (w *Wallet) loadSpendableKey(masterKey crypto.TwofishKey, sk spendableKey) error {
	// Duplication is detected by looking at the set of unlock conditions. If
	// the wallet is locked, correct deduplication is uncertain.
	if !w.unlocked {
		return modules.ErrLockedWallet
	}

	// Check for duplicates.
	_, exists := w.keys[sk.UnlockConditions.UnlockHash()]
	if exists {
		return errDuplicateSpendableKey
	}

	// TODO: Check that the key is actually spendable.

	// Create a UID and encryption verification.
	var skf SpendableKeyFile
	_, err := rand.Read(skf.UID[:])
	if err != nil {
		return err
	}
	encryptionKey := uidEncryptionKey(masterKey, skf.UID)
	plaintextVerification := make([]byte, encryptionVerificationLen)
	skf.EncryptionVerification, err = encryptionKey.EncryptBytes(plaintextVerification)
	if err != nil {
		return err
	}

	// Encrypt and save the key.
	skf.SpendableKey, err = encryptionKey.EncryptBytes(encoding.Marshal(sk))
	if err != nil {
		return err
	}
	w.persist.UnseededKeys = append(w.persist.UnseededKeys, skf)
	// w.keys[sk.UnlockConditions.UnlockHash()] = sk -> aids with duplicate
	// detection, but causes db inconsistency. Rescanning is probably the
	// solution.
	return nil
}

// loadSiagKeys loads a set of siag keyfiles into the wallet, so that the
// wallet may spend the siafunds.
func (w *Wallet) loadSiagKeys(masterKey crypto.TwofishKey, keyfiles []string) error {
	// Load the keyfiles from disk.
	if len(keyfiles) < 1 {
		return ErrNoKeyfile
	}
	skps := make([]SiagKeyPair, len(keyfiles))
	for i, keyfile := range keyfiles {
		err := encoding.ReadFile(keyfile, &skps[i])
		if err != nil {
			return err
		}

		if skps[i].Header != SiagFileHeader {
			return ErrUnknownHeader
		}
		if skps[i].Version != SiagFileVersion {
			return ErrUnknownVersion
		}
	}

	// Check that all of the loaded files have the same address, and that there
	// are enough to create the transaction.
	baseUnlockHash := skps[0].UnlockConditions.UnlockHash()
	for _, skp := range skps {
		if skp.UnlockConditions.UnlockHash() != baseUnlockHash {
			return ErrInconsistentKeys
		}
	}
	if uint64(len(skps)) < skps[0].UnlockConditions.SignaturesRequired {
		return ErrInsufficientKeys
	}
	// Drop all unneeded keys.
	skps = skps[0:skps[0].UnlockConditions.SignaturesRequired]

	// Merge the keys into a single spendableKey and save it to the wallet.
	var sk spendableKey
	sk.UnlockConditions = skps[0].UnlockConditions
	for _, skp := range skps {
		sk.SecretKeys = append(sk.SecretKeys, skp.SecretKey)
	}
	err := w.loadSpendableKey(masterKey, sk)
	if err != nil {
		return err
	}
	err = w.saveSettings()
	if err != nil {
		return err
	}
	return w.createBackup(filepath.Join(w.persistDir, "Sia Wallet Encrypted Backup - "+persist.RandomSuffix()+settingsFileSuffix))
}

// LoadSiagKeys loads a set of siag-generated keys into the wallet.
func (w *Wallet) LoadSiagKeys(masterKey crypto.TwofishKey, keyfiles []string) error {
	lockID := w.mu.Lock()
	defer w.mu.Unlock(lockID)
	err := w.checkMasterKey(masterKey)
	if err != nil {
		return err
	}
	return w.loadSiagKeys(masterKey, keyfiles)
}

// Load033xWallet loads a v0.3.3.x wallet as an unseeded key, such that the
// funds become spendable to the current wallet.
func (w *Wallet) Load033xWallet(masterKey crypto.TwofishKey, filepath033x string) error {
	lockID := w.mu.Lock()
	defer w.mu.Unlock(lockID)
	err := w.checkMasterKey(masterKey)
	if err != nil {
		return err
	}

	var savedKeys []SavedKey033x
	err = encoding.ReadFile(filepath033x, &savedKeys)
	if err != nil {
		return err
	}
	var seedsLoaded int
	for _, savedKey := range savedKeys {
		spendKey := spendableKey{
			UnlockConditions: savedKey.UnlockConditions,
			SecretKeys:       []crypto.SecretKey{savedKey.SecretKey},
		}
		err = w.loadSpendableKey(masterKey, spendKey)
		if err != nil && err != errDuplicateSpendableKey {
			return err
		}
		if err == nil {
			seedsLoaded++
		}
	}
	err = w.saveSettings()
	if err != nil {
		return err
	}
	if seedsLoaded != 0 {
		return w.createBackup(filepath.Join(w.persistDir, "Sia Wallet Encrypted Backup - "+persist.RandomSuffix()+settingsFileSuffix))
	}
	return errAllDuplicates
}
<|endoftext|>


<commit_before>// Copyright 2012 The Walk 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 main

import (
	"fmt"
	"os"
	"strings"
)

import "github.com/lxn/walk"

type EnvItem struct {
	varName string
	value   string
}

type EnvModel struct{
	walk.ListModelBase
	envItems []EnvItem
	itemsResetPublisher  walk.EventPublisher
	itemChangedPublisher walk.IntEventPublisher
}

func NewEnvModel() *EnvModel{
	em := &EnvModel{}
	em.envItems = make([]EnvItem, 0)
	return em
}

func (em *EnvModel) ItemCount()int{
	return len(em.envItems)
}

func (em *EnvModel) Value( index int) interface{} {
	return em.envItems[index].varName
}

func main() {
	walk.Initialize(walk.InitParams{PanicOnError: true})
	defer walk.Shutdown()

	myWindow, _ := walk.NewMainWindow()

	myWindow.SetLayout(walk.NewVBoxLayout())
	myWindow.SetTitle("Go GUI example")

	myButton1, _ := walk.NewPushButton(myWindow)
	myButton1.SetText("XXXX")

	lb, _ := walk.NewListBox(myWindow)

	em := NewEnvModel()

	for _, env := range os.Environ() {
		i := strings.Index(env, "=")
		if i == 0 {
			continue
		}
		varName := env[0:i]
		value := env[i+1:]
		envItem := EnvItem{varName, value}

		em.envItems = append(em.envItems, envItem)
	}

	fmt.Println("The len of Model", em.ItemCount())
	lb.SetModel(em)
	lb.CurrentIndexChanged().Attach(func() {
		if curVar, ok := em.Value(lb.CurrentIndex()).(string); ok {
			myButton1.SetText(curVar)
			fmt.Println("CurrentIndex:", lb.CurrentIndex())
			fmt.Println("CurrentEnvVarName:",curVar)
		}
	})
	lb.DblClicked().Attach(func() {
		value := em.envItems[lb.CurrentIndex()].value
		walk.MsgBox(myWindow, "About", value, walk.MsgBoxOK|walk.MsgBoxIconInformation)
	})
	myWindow.Show()
	myWindow.SetMinMaxSize(walk.Size{320, 240}, walk.Size{})
	myWindow.SetSize(walk.Size{400, 500})
	myWindow.Run()
}
<commit_msg>show the env value<commit_after>// Copyright 2012 The Walk 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 main

import (
	"fmt"
	"os"
	"strings"
)

import "github.com/lxn/walk"

type EnvItem struct {
	varName string
	value   string
}

type EnvModel struct{
	walk.ListModelBase
	envItems []EnvItem
	itemsResetPublisher  walk.EventPublisher
	itemChangedPublisher walk.IntEventPublisher
}

func NewEnvModel() *EnvModel{
	em := &EnvModel{}
	em.envItems = make([]EnvItem, 0)
	return em
}

func (em *EnvModel) ItemCount()int{
	return len(em.envItems)
}

func (em *EnvModel) Value( index int) interface{} {
	return em.envItems[index].varName
}

func main() {
	walk.Initialize(walk.InitParams{PanicOnError: true})
	defer walk.Shutdown()

	myWindow, _ := walk.NewMainWindow()

	myWindow.SetLayout(walk.NewVBoxLayout())
	myWindow.SetTitle("Go GUI example")

	splitter, _ := walk.NewSplitter(myWindow)
	splitter.SetOrientation(walk.Vertical)

	lb, _ := walk.NewListBox(splitter)
	//lb.SetHeight(100)

	valueEdit, _ := walk.NewTextEdit(splitter)
	valueEdit.SetReadOnly(true)
	//valueEdit.SetHeight(300)

	buttonCompositor, _ := walk.NewComposite(splitter)
	hbox := walk.NewHBoxLayout()
	buttonCompositor.SetLayout(hbox)

	myButton1, _ := walk.NewPushButton(buttonCompositor)
	myButton1.SetText("New")

	myButton2, _ := walk.NewPushButton(buttonCompositor)
	myButton2.SetText("Edit")

	myButton3, _ := walk.NewPushButton(buttonCompositor)
	myButton3.SetText("Delete")

	//env model
	em := NewEnvModel()

	for _, env := range os.Environ() {
		i := strings.Index(env, "=")
		if i == 0 {
			continue
		}
		varName := env[0:i]
		value := env[i+1:]
		envItem := EnvItem{varName, value}

		em.envItems = append(em.envItems, envItem)
	}

	fmt.Println("The len of Model", em.ItemCount())
	lb.SetModel(em)
	lb.CurrentIndexChanged().Attach(func() {
		if curVar, ok := em.Value(lb.CurrentIndex()).(string); ok {
			value := em.envItems[lb.CurrentIndex()].value
			value = strings.Replace(value, ";", "\r\n", -1)
			valueEdit.SetText(value)
			fmt.Println("CurrentIndex:", lb.CurrentIndex())
			fmt.Println("CurrentEnvVarName:",curVar)
		}
	})
	lb.DblClicked().Attach(func() {
		value := em.envItems[lb.CurrentIndex()].value
		value = strings.Replace(value, ";", "\r\n", -1)
		valueEdit.SetText(value)
		walk.MsgBox(myWindow, "About", value, walk.MsgBoxOK|walk.MsgBoxIconInformation)
	})
	myWindow.Show()
	myWindow.SetMinMaxSize(walk.Size{320, 240}, walk.Size{})
	myWindow.SetSize(walk.Size{400, 500})
	myWindow.Run()
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "net/http"
  "github.com/pilu/traffic"
)

type PingMiddleware struct {}

// If the request path is "/ping", it writes PONG in the response and returns without calling the next middleware
// Otherwise it sets the variable "PING" with PONG as value and calls the next  middleware.
// The next middleware can
func (c *PingMiddleware) ServeHTTP(w traffic.ResponseWriter, r *http.Request, next traffic.NextMiddlewareFunc) (traffic.ResponseWriter, *http.Request) {
  if r.URL.Path == "/ping" {
    fmt.Fprint(w, "pong\n")

    return w, r
  }

  if nextMiddleware := next(); nextMiddleware != nil {
    w.SetVar("ping", "pong")
    w, r = nextMiddleware.ServeHTTP(w, r, next)
  }

  return w, r
}

func root(w traffic.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Router var foo: %v.\n", w.GetVar("foo"))
  fmt.Fprintf(w, "Middleware var ping: %v\n", w.GetVar("ping"))
}

func main() {
  t := traffic.New()
  // Add PingMiddleware
  t.AddMiddleware(&PingMiddleware{})
  // Set router var "foo"
  t.SetVar("foo", "bar")
  // Add root handler
  t.Get("/", root)

  t.Run()
}
<commit_msg>fixed middleware example comments<commit_after>package main

import (
  "fmt"
  "net/http"
  "github.com/pilu/traffic"
)

type PingMiddleware struct {}

// If the request path is "/ping", it writes PONG in the response and returns without calling the next middleware
// Otherwise it sets the variable "PING" with PONG as value and calls the next  middleware.
// The next middleware and the final handler can get that variable with:
//   w.GetVar("ping")
func (c *PingMiddleware) ServeHTTP(w traffic.ResponseWriter, r *http.Request, next traffic.NextMiddlewareFunc) (traffic.ResponseWriter, *http.Request) {
  if r.URL.Path == "/ping" {
    fmt.Fprint(w, "pong\n")

    return w, r
  }

  if nextMiddleware := next(); nextMiddleware != nil {
    w.SetVar("ping", "pong")
    w, r = nextMiddleware.ServeHTTP(w, r, next)
  }

  return w, r
}

func root(w traffic.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Router var foo: %v.\n", w.GetVar("foo"))
  fmt.Fprintf(w, "Middleware var ping: %v\n", w.GetVar("ping"))
}

func main() {
  t := traffic.New()
  // Add PingMiddleware
  t.AddMiddleware(&PingMiddleware{})
  // Set router var "foo"
  t.SetVar("foo", "bar")
  // Add root handler
  t.Get("/", root)

  t.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"delay"

	"stm32/hal/gpio"
	"stm32/hal/system"
	"stm32/hal/system/timer/systick"
)

var led gpio.Pin

func init() {
	system.SetupPLL(8, 1, 72/8)
	systick.Setup(2e6)

	gpio.A.EnableClock(false)
	led = gpio.A.Pin(5)

	led.Setup(&gpio.Config{Mode: gpio.Out, Speed: gpio.Low})
}

func wait() {
	delay.Millisec(250)
}

func main() {
	for {
		led.Set()
		wait()
		led.Clear()
		wait()
	}
}
<commit_msg>examples/nucleo-f303re/blinky: Test new RCC code.<commit_after>package main

import (
	"delay"

	"stm32/hal/gpio"
	"stm32/hal/system"
	"stm32/hal/system/timer/systick"
)

var led gpio.Pin

func init() {
	system.SetupPLL(8, 1, 72/8)
	systick.Setup(2e6)

	gpio.A.EnableClock(false)
	led = gpio.A.Pin(5)

	led.Setup(&gpio.Config{Mode: gpio.Out, Speed: gpio.Low})
}

func wait() {

}

func main() {
	for {
		led.Set()
		delay.Millisec(100)
		led.Clear()
		delay.Millisec(900)
	}
}
<|endoftext|>


<commit_before><commit_msg>最大索引堆优化<commit_after><|endoftext|>


<commit_before>package helpers

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

	"github.com/matrix-org/dendrite/roomserver/api"
	"github.com/matrix-org/dendrite/roomserver/auth"
	"github.com/matrix-org/dendrite/roomserver/state"
	"github.com/matrix-org/dendrite/roomserver/storage"
	"github.com/matrix-org/dendrite/roomserver/storage/shared"
	"github.com/matrix-org/dendrite/roomserver/types"
	"github.com/matrix-org/gomatrixserverlib"
	"github.com/matrix-org/util"
)

// TODO: temporary package which has helper functions used by both internal/perform packages.
// Move these to a more sensible place.

func UpdateToInviteMembership(
	mu *shared.MembershipUpdater, add *gomatrixserverlib.Event, updates []api.OutputEvent,
	roomVersion gomatrixserverlib.RoomVersion,
) ([]api.OutputEvent, error) {
	// We may have already sent the invite to the user, either because we are
	// reprocessing this event, or because the we received this invite from a
	// remote server via the federation invite API. In those cases we don't need
	// to send the event.
	needsSending, err := mu.SetToInvite(*add)
	if err != nil {
		return nil, err
	}
	if needsSending {
		// We notify the consumers using a special event even though we will
		// notify them about the change in current state as part of the normal
		// room event stream. This ensures that the consumers only have to
		// consider a single stream of events when determining whether a user
		// is invited, rather than having to combine multiple streams themselves.
		onie := api.OutputNewInviteEvent{
			Event:       add.Headered(roomVersion),
			RoomVersion: roomVersion,
		}
		updates = append(updates, api.OutputEvent{
			Type:           api.OutputTypeNewInviteEvent,
			NewInviteEvent: &onie,
		})
	}
	return updates, nil
}

func IsServerCurrentlyInRoom(ctx context.Context, db storage.Database, serverName gomatrixserverlib.ServerName, roomID string) (bool, error) {
	info, err := db.RoomInfo(ctx, roomID)
	if err != nil {
		return false, err
	}
	if info == nil {
		return false, fmt.Errorf("unknown room %s", roomID)
	}

	eventNIDs, err := db.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, true, false)
	if err != nil {
		return false, err
	}

	events, err := db.Events(ctx, eventNIDs)
	if err != nil {
		return false, err
	}
	gmslEvents := make([]gomatrixserverlib.Event, len(events))
	for i := range events {
		gmslEvents[i] = events[i].Event
	}
	return auth.IsAnyUserOnServerWithMembership(serverName, gmslEvents, gomatrixserverlib.Join), nil
}

func IsInvitePending(
	ctx context.Context, db storage.Database,
	roomID, userID string,
) (bool, string, string, error) {
	// Look up the room NID for the supplied room ID.
	info, err := db.RoomInfo(ctx, roomID)
	if err != nil {
		return false, "", "", fmt.Errorf("r.DB.RoomInfo: %w", err)
	}
	if info == nil {
		return false, "", "", fmt.Errorf("cannot get RoomInfo: unknown room ID %s", roomID)
	}

	// Look up the state key NID for the supplied user ID.
	targetUserNIDs, err := db.EventStateKeyNIDs(ctx, []string{userID})
	if err != nil {
		return false, "", "", fmt.Errorf("r.DB.EventStateKeyNIDs: %w", err)
	}
	targetUserNID, targetUserFound := targetUserNIDs[userID]
	if !targetUserFound {
		return false, "", "", fmt.Errorf("missing NID for user %q (%+v)", userID, targetUserNIDs)
	}

	// Let's see if we have an event active for the user in the room. If
	// we do then it will contain a server name that we can direct the
	// send_leave to.
	senderUserNIDs, eventIDs, err := db.GetInvitesForUser(ctx, info.RoomNID, targetUserNID)
	if err != nil {
		return false, "", "", fmt.Errorf("r.DB.GetInvitesForUser: %w", err)
	}
	if len(senderUserNIDs) == 0 {
		return false, "", "", nil
	}
	userNIDToEventID := make(map[types.EventStateKeyNID]string)
	for i, nid := range senderUserNIDs {
		userNIDToEventID[nid] = eventIDs[i]
	}

	// Look up the user ID from the NID.
	senderUsers, err := db.EventStateKeys(ctx, senderUserNIDs)
	if err != nil {
		return false, "", "", fmt.Errorf("r.DB.EventStateKeys: %w", err)
	}
	if len(senderUsers) == 0 {
		return false, "", "", fmt.Errorf("no senderUsers")
	}

	senderUser, senderUserFound := senderUsers[senderUserNIDs[0]]
	if !senderUserFound {
		return false, "", "", fmt.Errorf("missing user for NID %d (%+v)", senderUserNIDs[0], senderUsers)
	}

	return true, senderUser, userNIDToEventID[senderUserNIDs[0]], nil
}

// GetMembershipsAtState filters the state events to
// only keep the "m.room.member" events with a "join" membership. These events are returned.
// Returns an error if there was an issue fetching the events.
func GetMembershipsAtState(
	ctx context.Context, db storage.Database, stateEntries []types.StateEntry, joinedOnly bool,
) ([]types.Event, error) {

	var eventNIDs []types.EventNID
	for _, entry := range stateEntries {
		// Filter the events to retrieve to only keep the membership events
		if entry.EventTypeNID == types.MRoomMemberNID {
			eventNIDs = append(eventNIDs, entry.EventNID)
		}
	}

	// Get all of the events in this state
	stateEvents, err := db.Events(ctx, eventNIDs)
	if err != nil {
		return nil, err
	}

	if !joinedOnly {
		return stateEvents, nil
	}

	// Filter the events to only keep the "join" membership events
	var events []types.Event
	for _, event := range stateEvents {
		membership, err := event.Membership()
		if err != nil {
			return nil, err
		}

		if membership == gomatrixserverlib.Join {
			events = append(events, event)
		}
	}

	return events, nil
}

func StateBeforeEvent(ctx context.Context, db storage.Database, info types.RoomInfo, eventNID types.EventNID) ([]types.StateEntry, error) {
	roomState := state.NewStateResolution(db, info)
	// Lookup the event NID
	eIDs, err := db.EventIDs(ctx, []types.EventNID{eventNID})
	if err != nil {
		return nil, err
	}
	eventIDs := []string{eIDs[eventNID]}

	prevState, err := db.StateAtEventIDs(ctx, eventIDs)
	if err != nil {
		return nil, err
	}

	// Fetch the state as it was when this event was fired
	return roomState.LoadCombinedStateAfterEvents(ctx, prevState)
}

func LoadEvents(
	ctx context.Context, db storage.Database, eventNIDs []types.EventNID,
) ([]gomatrixserverlib.Event, error) {
	stateEvents, err := db.Events(ctx, eventNIDs)
	if err != nil {
		return nil, err
	}

	result := make([]gomatrixserverlib.Event, len(stateEvents))
	for i := range stateEvents {
		result[i] = stateEvents[i].Event
	}
	return result, nil
}

func LoadStateEvents(
	ctx context.Context, db storage.Database, stateEntries []types.StateEntry,
) ([]gomatrixserverlib.Event, error) {
	eventNIDs := make([]types.EventNID, len(stateEntries))
	for i := range stateEntries {
		eventNIDs[i] = stateEntries[i].EventNID
	}
	return LoadEvents(ctx, db, eventNIDs)
}

func CheckServerAllowedToSeeEvent(
	ctx context.Context, db storage.Database, info types.RoomInfo, eventID string, serverName gomatrixserverlib.ServerName, isServerInRoom bool,
) (bool, error) {
	roomState := state.NewStateResolution(db, info)
	stateEntries, err := roomState.LoadStateAtEvent(ctx, eventID)
	if err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return false, nil
		}
		return false, err
	}

	// TODO: We probably want to make it so that we don't have to pull
	// out all the state if possible.
	stateAtEvent, err := LoadStateEvents(ctx, db, stateEntries)
	if err != nil {
		return false, err
	}

	return auth.IsServerAllowed(serverName, isServerInRoom, stateAtEvent), nil
}

// TODO: Remove this when we have tests to assert correctness of this function
// nolint:gocyclo
func ScanEventTree(
	ctx context.Context, db storage.Database, info types.RoomInfo, front []string, visited map[string]bool, limit int,
	serverName gomatrixserverlib.ServerName,
) ([]types.EventNID, error) {
	var resultNIDs []types.EventNID
	var err error
	var allowed bool
	var events []types.Event
	var next []string
	var pre string

	// TODO: add tests for this function to ensure it meets the contract that callers expect (and doc what that is supposed to be)
	// Currently, callers like PerformBackfill will call scanEventTree with a pre-populated `visited` map, assuming that by doing
	// so means that the events in that map will NOT be returned from this function. That is not currently true, resulting in
	// duplicate events being sent in response to /backfill requests.
	initialIgnoreList := make(map[string]bool, len(visited))
	for k, v := range visited {
		initialIgnoreList[k] = v
	}

	resultNIDs = make([]types.EventNID, 0, limit)

	var checkedServerInRoom bool
	var isServerInRoom bool

	// Loop through the event IDs to retrieve the requested events and go
	// through the whole tree (up to the provided limit) using the events'
	// "prev_event" key.
BFSLoop:
	for len(front) > 0 {
		// Prevent unnecessary allocations: reset the slice only when not empty.
		if len(next) > 0 {
			next = make([]string, 0)
		}
		// Retrieve the events to process from the database.
		events, err = db.EventsFromIDs(ctx, front)
		if err != nil {
			return resultNIDs, err
		}

		if !checkedServerInRoom && len(events) > 0 {
			// It's nasty that we have to extract the room ID from an event, but many federation requests
			// only talk in event IDs, no room IDs at all (!!!)
			ev := events[0]
			isServerInRoom, err = IsServerCurrentlyInRoom(ctx, db, serverName, ev.RoomID())
			if err != nil {
				util.GetLogger(ctx).WithError(err).Error("Failed to check if server is currently in room, assuming not.")
			}
			checkedServerInRoom = true
		}

		for _, ev := range events {
			// Break out of the loop if the provided limit is reached.
			if len(resultNIDs) == limit {
				break BFSLoop
			}

			if !initialIgnoreList[ev.EventID()] {
				// Update the list of events to retrieve.
				resultNIDs = append(resultNIDs, ev.EventNID)
			}
			// Loop through the event's parents.
			for _, pre = range ev.PrevEventIDs() {
				// Only add an event to the list of next events to process if it
				// hasn't been seen before.
				if !visited[pre] {
					visited[pre] = true
					allowed, err = CheckServerAllowedToSeeEvent(ctx, db, info, pre, serverName, isServerInRoom)
					if err != nil {
						util.GetLogger(ctx).WithField("server", serverName).WithField("event_id", pre).WithError(err).Error(
							"Error checking if allowed to see event",
						)
						return resultNIDs, err
					}

					// If the event hasn't been seen before and the HS
					// requesting to retrieve it is allowed to do so, add it to
					// the list of events to retrieve.
					if allowed {
						next = append(next, pre)
					} else {
						util.GetLogger(ctx).WithField("server", serverName).WithField("event_id", pre).Info("Not allowed to see event")
					}
				}
			}
		}
		// Repeat the same process with the parent events we just processed.
		front = next
	}

	return resultNIDs, err
}

func QueryLatestEventsAndState(
	ctx context.Context, db storage.Database,
	request *api.QueryLatestEventsAndStateRequest,
	response *api.QueryLatestEventsAndStateResponse,
) error {
	roomInfo, err := db.RoomInfo(ctx, request.RoomID)
	if err != nil {
		return err
	}
	if roomInfo == nil || roomInfo.IsStub {
		response.RoomExists = false
		return nil
	}

	roomState := state.NewStateResolution(db, *roomInfo)
	response.RoomExists = true
	response.RoomVersion = roomInfo.RoomVersion

	var currentStateSnapshotNID types.StateSnapshotNID
	response.LatestEvents, currentStateSnapshotNID, response.Depth, err =
		db.LatestEventIDs(ctx, roomInfo.RoomNID)
	if err != nil {
		return err
	}

	var stateEntries []types.StateEntry
	if len(request.StateToFetch) == 0 {
		// Look up all room state.
		stateEntries, err = roomState.LoadStateAtSnapshot(
			ctx, currentStateSnapshotNID,
		)
	} else {
		// Look up the current state for the requested tuples.
		stateEntries, err = roomState.LoadStateAtSnapshotForStringTuples(
			ctx, currentStateSnapshotNID, request.StateToFetch,
		)
	}
	if err != nil {
		return err
	}

	stateEvents, err := LoadStateEvents(ctx, db, stateEntries)
	if err != nil {
		return err
	}

	for _, event := range stateEvents {
		response.StateEvents = append(response.StateEvents, event.Headered(roomInfo.RoomVersion))
	}

	return nil
}
<commit_msg>Return what we have when we encounter missing events when servicing backfill/gme (#1499)<commit_after>package helpers

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

	"github.com/matrix-org/dendrite/roomserver/api"
	"github.com/matrix-org/dendrite/roomserver/auth"
	"github.com/matrix-org/dendrite/roomserver/state"
	"github.com/matrix-org/dendrite/roomserver/storage"
	"github.com/matrix-org/dendrite/roomserver/storage/shared"
	"github.com/matrix-org/dendrite/roomserver/types"
	"github.com/matrix-org/gomatrixserverlib"
	"github.com/matrix-org/util"
)

// TODO: temporary package which has helper functions used by both internal/perform packages.
// Move these to a more sensible place.

func UpdateToInviteMembership(
	mu *shared.MembershipUpdater, add *gomatrixserverlib.Event, updates []api.OutputEvent,
	roomVersion gomatrixserverlib.RoomVersion,
) ([]api.OutputEvent, error) {
	// We may have already sent the invite to the user, either because we are
	// reprocessing this event, or because the we received this invite from a
	// remote server via the federation invite API. In those cases we don't need
	// to send the event.
	needsSending, err := mu.SetToInvite(*add)
	if err != nil {
		return nil, err
	}
	if needsSending {
		// We notify the consumers using a special event even though we will
		// notify them about the change in current state as part of the normal
		// room event stream. This ensures that the consumers only have to
		// consider a single stream of events when determining whether a user
		// is invited, rather than having to combine multiple streams themselves.
		onie := api.OutputNewInviteEvent{
			Event:       add.Headered(roomVersion),
			RoomVersion: roomVersion,
		}
		updates = append(updates, api.OutputEvent{
			Type:           api.OutputTypeNewInviteEvent,
			NewInviteEvent: &onie,
		})
	}
	return updates, nil
}

func IsServerCurrentlyInRoom(ctx context.Context, db storage.Database, serverName gomatrixserverlib.ServerName, roomID string) (bool, error) {
	info, err := db.RoomInfo(ctx, roomID)
	if err != nil {
		return false, err
	}
	if info == nil {
		return false, fmt.Errorf("unknown room %s", roomID)
	}

	eventNIDs, err := db.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, true, false)
	if err != nil {
		return false, err
	}

	events, err := db.Events(ctx, eventNIDs)
	if err != nil {
		return false, err
	}
	gmslEvents := make([]gomatrixserverlib.Event, len(events))
	for i := range events {
		gmslEvents[i] = events[i].Event
	}
	return auth.IsAnyUserOnServerWithMembership(serverName, gmslEvents, gomatrixserverlib.Join), nil
}

func IsInvitePending(
	ctx context.Context, db storage.Database,
	roomID, userID string,
) (bool, string, string, error) {
	// Look up the room NID for the supplied room ID.
	info, err := db.RoomInfo(ctx, roomID)
	if err != nil {
		return false, "", "", fmt.Errorf("r.DB.RoomInfo: %w", err)
	}
	if info == nil {
		return false, "", "", fmt.Errorf("cannot get RoomInfo: unknown room ID %s", roomID)
	}

	// Look up the state key NID for the supplied user ID.
	targetUserNIDs, err := db.EventStateKeyNIDs(ctx, []string{userID})
	if err != nil {
		return false, "", "", fmt.Errorf("r.DB.EventStateKeyNIDs: %w", err)
	}
	targetUserNID, targetUserFound := targetUserNIDs[userID]
	if !targetUserFound {
		return false, "", "", fmt.Errorf("missing NID for user %q (%+v)", userID, targetUserNIDs)
	}

	// Let's see if we have an event active for the user in the room. If
	// we do then it will contain a server name that we can direct the
	// send_leave to.
	senderUserNIDs, eventIDs, err := db.GetInvitesForUser(ctx, info.RoomNID, targetUserNID)
	if err != nil {
		return false, "", "", fmt.Errorf("r.DB.GetInvitesForUser: %w", err)
	}
	if len(senderUserNIDs) == 0 {
		return false, "", "", nil
	}
	userNIDToEventID := make(map[types.EventStateKeyNID]string)
	for i, nid := range senderUserNIDs {
		userNIDToEventID[nid] = eventIDs[i]
	}

	// Look up the user ID from the NID.
	senderUsers, err := db.EventStateKeys(ctx, senderUserNIDs)
	if err != nil {
		return false, "", "", fmt.Errorf("r.DB.EventStateKeys: %w", err)
	}
	if len(senderUsers) == 0 {
		return false, "", "", fmt.Errorf("no senderUsers")
	}

	senderUser, senderUserFound := senderUsers[senderUserNIDs[0]]
	if !senderUserFound {
		return false, "", "", fmt.Errorf("missing user for NID %d (%+v)", senderUserNIDs[0], senderUsers)
	}

	return true, senderUser, userNIDToEventID[senderUserNIDs[0]], nil
}

// GetMembershipsAtState filters the state events to
// only keep the "m.room.member" events with a "join" membership. These events are returned.
// Returns an error if there was an issue fetching the events.
func GetMembershipsAtState(
	ctx context.Context, db storage.Database, stateEntries []types.StateEntry, joinedOnly bool,
) ([]types.Event, error) {

	var eventNIDs []types.EventNID
	for _, entry := range stateEntries {
		// Filter the events to retrieve to only keep the membership events
		if entry.EventTypeNID == types.MRoomMemberNID {
			eventNIDs = append(eventNIDs, entry.EventNID)
		}
	}

	// Get all of the events in this state
	stateEvents, err := db.Events(ctx, eventNIDs)
	if err != nil {
		return nil, err
	}

	if !joinedOnly {
		return stateEvents, nil
	}

	// Filter the events to only keep the "join" membership events
	var events []types.Event
	for _, event := range stateEvents {
		membership, err := event.Membership()
		if err != nil {
			return nil, err
		}

		if membership == gomatrixserverlib.Join {
			events = append(events, event)
		}
	}

	return events, nil
}

func StateBeforeEvent(ctx context.Context, db storage.Database, info types.RoomInfo, eventNID types.EventNID) ([]types.StateEntry, error) {
	roomState := state.NewStateResolution(db, info)
	// Lookup the event NID
	eIDs, err := db.EventIDs(ctx, []types.EventNID{eventNID})
	if err != nil {
		return nil, err
	}
	eventIDs := []string{eIDs[eventNID]}

	prevState, err := db.StateAtEventIDs(ctx, eventIDs)
	if err != nil {
		return nil, err
	}

	// Fetch the state as it was when this event was fired
	return roomState.LoadCombinedStateAfterEvents(ctx, prevState)
}

func LoadEvents(
	ctx context.Context, db storage.Database, eventNIDs []types.EventNID,
) ([]gomatrixserverlib.Event, error) {
	stateEvents, err := db.Events(ctx, eventNIDs)
	if err != nil {
		return nil, err
	}

	result := make([]gomatrixserverlib.Event, len(stateEvents))
	for i := range stateEvents {
		result[i] = stateEvents[i].Event
	}
	return result, nil
}

func LoadStateEvents(
	ctx context.Context, db storage.Database, stateEntries []types.StateEntry,
) ([]gomatrixserverlib.Event, error) {
	eventNIDs := make([]types.EventNID, len(stateEntries))
	for i := range stateEntries {
		eventNIDs[i] = stateEntries[i].EventNID
	}
	return LoadEvents(ctx, db, eventNIDs)
}

func CheckServerAllowedToSeeEvent(
	ctx context.Context, db storage.Database, info types.RoomInfo, eventID string, serverName gomatrixserverlib.ServerName, isServerInRoom bool,
) (bool, error) {
	roomState := state.NewStateResolution(db, info)
	stateEntries, err := roomState.LoadStateAtEvent(ctx, eventID)
	if err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return false, nil
		}
		return false, err
	}

	// TODO: We probably want to make it so that we don't have to pull
	// out all the state if possible.
	stateAtEvent, err := LoadStateEvents(ctx, db, stateEntries)
	if err != nil {
		return false, err
	}

	return auth.IsServerAllowed(serverName, isServerInRoom, stateAtEvent), nil
}

// TODO: Remove this when we have tests to assert correctness of this function
// nolint:gocyclo
func ScanEventTree(
	ctx context.Context, db storage.Database, info types.RoomInfo, front []string, visited map[string]bool, limit int,
	serverName gomatrixserverlib.ServerName,
) ([]types.EventNID, error) {
	var resultNIDs []types.EventNID
	var err error
	var allowed bool
	var events []types.Event
	var next []string
	var pre string

	// TODO: add tests for this function to ensure it meets the contract that callers expect (and doc what that is supposed to be)
	// Currently, callers like PerformBackfill will call scanEventTree with a pre-populated `visited` map, assuming that by doing
	// so means that the events in that map will NOT be returned from this function. That is not currently true, resulting in
	// duplicate events being sent in response to /backfill requests.
	initialIgnoreList := make(map[string]bool, len(visited))
	for k, v := range visited {
		initialIgnoreList[k] = v
	}

	resultNIDs = make([]types.EventNID, 0, limit)

	var checkedServerInRoom bool
	var isServerInRoom bool

	// Loop through the event IDs to retrieve the requested events and go
	// through the whole tree (up to the provided limit) using the events'
	// "prev_event" key.
BFSLoop:
	for len(front) > 0 {
		// Prevent unnecessary allocations: reset the slice only when not empty.
		if len(next) > 0 {
			next = make([]string, 0)
		}
		// Retrieve the events to process from the database.
		events, err = db.EventsFromIDs(ctx, front)
		if err != nil {
			return resultNIDs, err
		}

		if !checkedServerInRoom && len(events) > 0 {
			// It's nasty that we have to extract the room ID from an event, but many federation requests
			// only talk in event IDs, no room IDs at all (!!!)
			ev := events[0]
			isServerInRoom, err = IsServerCurrentlyInRoom(ctx, db, serverName, ev.RoomID())
			if err != nil {
				util.GetLogger(ctx).WithError(err).Error("Failed to check if server is currently in room, assuming not.")
			}
			checkedServerInRoom = true
		}

		for _, ev := range events {
			// Break out of the loop if the provided limit is reached.
			if len(resultNIDs) == limit {
				break BFSLoop
			}

			if !initialIgnoreList[ev.EventID()] {
				// Update the list of events to retrieve.
				resultNIDs = append(resultNIDs, ev.EventNID)
			}
			// Loop through the event's parents.
			for _, pre = range ev.PrevEventIDs() {
				// Only add an event to the list of next events to process if it
				// hasn't been seen before.
				if !visited[pre] {
					visited[pre] = true
					allowed, err = CheckServerAllowedToSeeEvent(ctx, db, info, pre, serverName, isServerInRoom)
					if err != nil {
						util.GetLogger(ctx).WithField("server", serverName).WithField("event_id", pre).WithError(err).Error(
							"Error checking if allowed to see event",
						)
						// drop the error, as we will often error at the DB level if we don't have the prev_event itself. Let's
						// just return what we have.
						return resultNIDs, nil
					}

					// If the event hasn't been seen before and the HS
					// requesting to retrieve it is allowed to do so, add it to
					// the list of events to retrieve.
					if allowed {
						next = append(next, pre)
					} else {
						util.GetLogger(ctx).WithField("server", serverName).WithField("event_id", pre).Info("Not allowed to see event")
					}
				}
			}
		}
		// Repeat the same process with the parent events we just processed.
		front = next
	}

	return resultNIDs, err
}

func QueryLatestEventsAndState(
	ctx context.Context, db storage.Database,
	request *api.QueryLatestEventsAndStateRequest,
	response *api.QueryLatestEventsAndStateResponse,
) error {
	roomInfo, err := db.RoomInfo(ctx, request.RoomID)
	if err != nil {
		return err
	}
	if roomInfo == nil || roomInfo.IsStub {
		response.RoomExists = false
		return nil
	}

	roomState := state.NewStateResolution(db, *roomInfo)
	response.RoomExists = true
	response.RoomVersion = roomInfo.RoomVersion

	var currentStateSnapshotNID types.StateSnapshotNID
	response.LatestEvents, currentStateSnapshotNID, response.Depth, err =
		db.LatestEventIDs(ctx, roomInfo.RoomNID)
	if err != nil {
		return err
	}

	var stateEntries []types.StateEntry
	if len(request.StateToFetch) == 0 {
		// Look up all room state.
		stateEntries, err = roomState.LoadStateAtSnapshot(
			ctx, currentStateSnapshotNID,
		)
	} else {
		// Look up the current state for the requested tuples.
		stateEntries, err = roomState.LoadStateAtSnapshotForStringTuples(
			ctx, currentStateSnapshotNID, request.StateToFetch,
		)
	}
	if err != nil {
		return err
	}

	stateEvents, err := LoadStateEvents(ctx, db, stateEntries)
	if err != nil {
		return err
	}

	for _, event := range stateEvents {
		response.StateEvents = append(response.StateEvents, event.Headered(roomInfo.RoomVersion))
	}

	return nil
}
<|endoftext|>