<commit_before>package cert

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"
	"strings"

	"github.com/hashicorp/vault/helper/certutil"
	"github.com/hashicorp/vault/helper/policyutil"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

// ParsedCert is a certificate that has been configured as trusted
type ParsedCert struct {
	Entry        *CertEntry
	Certificates []*x509.Certificate
}

func pathLogin(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "login",
		Fields:  map[string]*framework.FieldSchema{},
		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathLogin,
		},
	}
}

func (b *backend) pathLogin(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

	var matched *ParsedCert
	if verifyResp, resp, err := b.verifyCredentials(req); err != nil {
		return nil, err
	} else if resp != nil {
		return resp, nil
	} else {
		matched = verifyResp
	}

	if matched == nil {
		return nil, nil
	}

	ttl := matched.Entry.TTL
	if ttl == 0 {
		ttl = b.System().DefaultLeaseTTL()
	}

	clientCerts := req.Connection.ConnState.PeerCertificates
	if len(clientCerts) == 0 {
		return logical.ErrorResponse("no client certificate found"), nil
	}
	skid := base64.StdEncoding.EncodeToString(clientCerts[0].SubjectKeyId)
	akid := base64.StdEncoding.EncodeToString(clientCerts[0].AuthorityKeyId)

	// Generate a response
	resp := &logical.Response{
		Auth: &logical.Auth{
			InternalData: map[string]interface{}{
				"subject_key_id":   skid,
				"authority_key_id": akid,
			},
			Policies:    matched.Entry.Policies,
			DisplayName: matched.Entry.DisplayName,
			Metadata: map[string]string{
				"cert_name":        matched.Entry.Name,
				"common_name":      clientCerts[0].Subject.CommonName,
				"subject_key_id":   certutil.GetOctalFormatted(clientCerts[0].SubjectKeyId, ":"),
				"authority_key_id": certutil.GetOctalFormatted(clientCerts[0].AuthorityKeyId, ":"),
			},
			LeaseOptions: logical.LeaseOptions{
				Renewable: true,
				TTL:       ttl,
			},
		},
	}
	return resp, nil
}

func (b *backend) pathLoginRenew(
	req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, err
	}

	if !config.DisableBinding {
		var matched *ParsedCert
		if verifyResp, resp, err := b.verifyCredentials(req); err != nil {
			return nil, err
		} else if resp != nil {
			return resp, nil
		} else {
			matched = verifyResp
		}

		if matched == nil {
			return nil, nil
		}

		clientCerts := req.Connection.ConnState.PeerCertificates
		if len(clientCerts) == 0 {
			return logical.ErrorResponse("no client certificate found"), nil
		}
		skid := base64.StdEncoding.EncodeToString(clientCerts[0].SubjectKeyId)
		akid := base64.StdEncoding.EncodeToString(clientCerts[0].AuthorityKeyId)

		// Certificate should not only match a registered certificate policy.
		// Also, the identity of the certificate presented should match the identity of the certificate used during login
		if req.Auth.InternalData["subject_key_id"] != skid && req.Auth.InternalData["authority_key_id"] != akid {
			return logical.ErrorResponse("client identity during renewal not matching client identity used during login"), nil
		}

	}
	// Get the cert and use its TTL
	cert, err := b.Cert(req.Storage, req.Auth.Metadata["cert_name"])
	if err != nil {
		return nil, err
	}
	if cert == nil {
		// User no longer exists, do not renew
		return nil, nil
	}

	if !policyutil.EquivalentPolicies(cert.Policies, req.Auth.Policies) {
		return logical.ErrorResponse("policies have changed, not renewing"), nil
	}

	return framework.LeaseExtend(cert.TTL, 0, b.System())(req, d)
}

func (b *backend) verifyCredentials(req *logical.Request) (*ParsedCert, *logical.Response, error) {
	// Get the connection state
	if req.Connection == nil || req.Connection.ConnState == nil {
		return nil, logical.ErrorResponse("tls connection required"), nil
	}
	connState := req.Connection.ConnState

	// Load the trusted certificates
	roots, trusted, trustedNonCAs := b.loadTrustedCerts(req.Storage)

	// If trustedNonCAs is not empty it means that client had registered a non-CA cert
	// with the backend.
	if len(trustedNonCAs) != 0 {
		policy := b.matchNonCAPolicy(connState.PeerCertificates[0], trustedNonCAs)
		if policy != nil && !b.checkForChainInCRLs(policy.Certificates) {
			return policy, nil, nil
		}
	}

	// Validate the connection state is trusted
	trustedChains, err := validateConnState(roots, connState)
	if err != nil {
		return nil, nil, err
	}

	// If no trusted chain was found, client is not authenticated
	if len(trustedChains) == 0 {
		return nil, logical.ErrorResponse("invalid certificate or no client certificate supplied"), nil
	}

	validChain := b.checkForValidChain(req.Storage, trustedChains)
	if !validChain {
		return nil, logical.ErrorResponse(
			"no chain containing non-revoked certificates could be found for this login certificate",
		), nil
	}

	// Match the trusted chain with the policy
	return b.matchPolicy(trustedChains, trusted), nil, nil
}

// matchNonCAPolicy is used to match the client cert with the registered non-CA
// policies to establish client identity.
func (b *backend) matchNonCAPolicy(clientCert *x509.Certificate, trustedNonCAs []*ParsedCert) *ParsedCert {
	for _, trustedNonCA := range trustedNonCAs {
		tCert := trustedNonCA.Certificates[0]
		if tCert.SerialNumber.Cmp(clientCert.SerialNumber) == 0 && bytes.Equal(tCert.AuthorityKeyId, clientCert.AuthorityKeyId) {
			return trustedNonCA
		}
	}
	return nil
}

// matchPolicy is used to match the associated policy with the certificate that
// was used to establish the client identity.
func (b *backend) matchPolicy(chains [][]*x509.Certificate, trusted []*ParsedCert) *ParsedCert {
	// There is probably a better way to do this...
	for _, chain := range chains {
		for _, trust := range trusted {
			for _, tCert := range trust.Certificates {
				for _, cCert := range chain {
					if tCert.Equal(cCert) {
						return trust
					}
				}
			}
		}
	}
	return nil
}

// loadTrustedCerts is used to load all the trusted certificates from the backend
func (b *backend) loadTrustedCerts(store logical.Storage) (pool *x509.CertPool, trusted []*ParsedCert, trustedNonCAs []*ParsedCert) {
	pool = x509.NewCertPool()
	names, err := store.List("cert/")
	if err != nil {
		b.Logger().Printf("[ERR] cert: failed to list trusted certs: %v", err)
		return
	}
	for _, name := range names {
		entry, err := b.Cert(store, strings.TrimPrefix(name, "cert/"))
		if err != nil {
			b.Logger().Printf("[ERR] cert: failed to load trusted certs '%s': %v", name, err)
			continue
		}
		parsed := parsePEM([]byte(entry.Certificate))
		if len(parsed) == 0 {
			b.Logger().Printf("[ERR] cert: failed to parse certificate for '%s'", name)
			continue
		}
		if !parsed[0].IsCA {
			trustedNonCAs = append(trustedNonCAs, &ParsedCert{
				Entry:        entry,
				Certificates: parsed,
			})
		} else {
			for _, p := range parsed {
				pool.AddCert(p)
			}

			// Create a ParsedCert entry
			trusted = append(trusted, &ParsedCert{
				Entry:        entry,
				Certificates: parsed,
			})
		}
	}
	return
}

func (b *backend) checkForChainInCRLs(chain []*x509.Certificate) bool {
	badChain := false
	for _, cert := range chain {
		badCRLs := b.findSerialInCRLs(cert.SerialNumber)
		if len(badCRLs) != 0 {
			badChain = true
			break
		}
	}
	return badChain
}

func (b *backend) checkForValidChain(store logical.Storage, chains [][]*x509.Certificate) bool {
	for _, chain := range chains {
		if !b.checkForChainInCRLs(chain) {
			return true
		}
	}
	return false
}

// parsePEM parses a PEM encoded x509 certificate
func parsePEM(raw []byte) (certs []*x509.Certificate) {
	for len(raw) > 0 {
		var block *pem.Block
		block, raw = pem.Decode(raw)
		if block == nil {
			break
		}
		if (block.Type != "CERTIFICATE" && block.Type != "TRUSTED CERTIFICATE") || len(block.Headers) != 0 {
			continue
		}

		cert, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			continue
		}
		certs = append(certs, cert)
	}
	return
}

// validateConnState is used to validate that the TLS client is authorized
// by at trusted certificate. Most of this logic is lifted from the client
// verification logic here:  http://golang.org/src/crypto/tls/handshake_server.go
// The trusted chains are returned.
func validateConnState(roots *x509.CertPool, cs *tls.ConnectionState) ([][]*x509.Certificate, error) {
	opts := x509.VerifyOptions{
		Roots:         roots,
		Intermediates: x509.NewCertPool(),
		KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
	}

	certs := cs.PeerCertificates
	if len(certs) == 0 {
		return nil, nil
	}

	if len(certs) > 1 {
		for _, cert := range certs[1:] {
			opts.Intermediates.AddCert(cert)
		}
	}

	chains, err := certs[0].Verify(opts)
	if err != nil {
		if _, ok := err.(x509.UnknownAuthorityError); ok {
			return nil, nil
		}
		return nil, errors.New("failed to verify client's certificate: " + err.Error())
	}
	return chains, nil
}
<commit_msg>Remove unused param from checkForValidChain<commit_after>package cert

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"
	"strings"

	"github.com/hashicorp/vault/helper/certutil"
	"github.com/hashicorp/vault/helper/policyutil"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

// ParsedCert is a certificate that has been configured as trusted
type ParsedCert struct {
	Entry        *CertEntry
	Certificates []*x509.Certificate
}

func pathLogin(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "login",
		Fields:  map[string]*framework.FieldSchema{},
		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathLogin,
		},
	}
}

func (b *backend) pathLogin(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

	var matched *ParsedCert
	if verifyResp, resp, err := b.verifyCredentials(req); err != nil {
		return nil, err
	} else if resp != nil {
		return resp, nil
	} else {
		matched = verifyResp
	}

	if matched == nil {
		return nil, nil
	}

	ttl := matched.Entry.TTL
	if ttl == 0 {
		ttl = b.System().DefaultLeaseTTL()
	}

	clientCerts := req.Connection.ConnState.PeerCertificates
	if len(clientCerts) == 0 {
		return logical.ErrorResponse("no client certificate found"), nil
	}
	skid := base64.StdEncoding.EncodeToString(clientCerts[0].SubjectKeyId)
	akid := base64.StdEncoding.EncodeToString(clientCerts[0].AuthorityKeyId)

	// Generate a response
	resp := &logical.Response{
		Auth: &logical.Auth{
			InternalData: map[string]interface{}{
				"subject_key_id":   skid,
				"authority_key_id": akid,
			},
			Policies:    matched.Entry.Policies,
			DisplayName: matched.Entry.DisplayName,
			Metadata: map[string]string{
				"cert_name":        matched.Entry.Name,
				"common_name":      clientCerts[0].Subject.CommonName,
				"subject_key_id":   certutil.GetOctalFormatted(clientCerts[0].SubjectKeyId, ":"),
				"authority_key_id": certutil.GetOctalFormatted(clientCerts[0].AuthorityKeyId, ":"),
			},
			LeaseOptions: logical.LeaseOptions{
				Renewable: true,
				TTL:       ttl,
			},
		},
	}
	return resp, nil
}

func (b *backend) pathLoginRenew(
	req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, err
	}

	if !config.DisableBinding {
		var matched *ParsedCert
		if verifyResp, resp, err := b.verifyCredentials(req); err != nil {
			return nil, err
		} else if resp != nil {
			return resp, nil
		} else {
			matched = verifyResp
		}

		if matched == nil {
			return nil, nil
		}

		clientCerts := req.Connection.ConnState.PeerCertificates
		if len(clientCerts) == 0 {
			return logical.ErrorResponse("no client certificate found"), nil
		}
		skid := base64.StdEncoding.EncodeToString(clientCerts[0].SubjectKeyId)
		akid := base64.StdEncoding.EncodeToString(clientCerts[0].AuthorityKeyId)

		// Certificate should not only match a registered certificate policy.
		// Also, the identity of the certificate presented should match the identity of the certificate used during login
		if req.Auth.InternalData["subject_key_id"] != skid && req.Auth.InternalData["authority_key_id"] != akid {
			return logical.ErrorResponse("client identity during renewal not matching client identity used during login"), nil
		}

	}
	// Get the cert and use its TTL
	cert, err := b.Cert(req.Storage, req.Auth.Metadata["cert_name"])
	if err != nil {
		return nil, err
	}
	if cert == nil {
		// User no longer exists, do not renew
		return nil, nil
	}

	if !policyutil.EquivalentPolicies(cert.Policies, req.Auth.Policies) {
		return logical.ErrorResponse("policies have changed, not renewing"), nil
	}

	return framework.LeaseExtend(cert.TTL, 0, b.System())(req, d)
}

func (b *backend) verifyCredentials(req *logical.Request) (*ParsedCert, *logical.Response, error) {
	// Get the connection state
	if req.Connection == nil || req.Connection.ConnState == nil {
		return nil, logical.ErrorResponse("tls connection required"), nil
	}
	connState := req.Connection.ConnState

	// Load the trusted certificates
	roots, trusted, trustedNonCAs := b.loadTrustedCerts(req.Storage)

	// If trustedNonCAs is not empty it means that client had registered a non-CA cert
	// with the backend.
	if len(trustedNonCAs) != 0 {
		policy := b.matchNonCAPolicy(connState.PeerCertificates[0], trustedNonCAs)
		if policy != nil && !b.checkForChainInCRLs(policy.Certificates) {
			return policy, nil, nil
		}
	}

	// Validate the connection state is trusted
	trustedChains, err := validateConnState(roots, connState)
	if err != nil {
		return nil, nil, err
	}

	// If no trusted chain was found, client is not authenticated
	if len(trustedChains) == 0 {
		return nil, logical.ErrorResponse("invalid certificate or no client certificate supplied"), nil
	}

	validChain := b.checkForValidChain(trustedChains)
	if !validChain {
		return nil, logical.ErrorResponse(
			"no chain containing non-revoked certificates could be found for this login certificate",
		), nil
	}

	// Match the trusted chain with the policy
	return b.matchPolicy(trustedChains, trusted), nil, nil
}

// matchNonCAPolicy is used to match the client cert with the registered non-CA
// policies to establish client identity.
func (b *backend) matchNonCAPolicy(clientCert *x509.Certificate, trustedNonCAs []*ParsedCert) *ParsedCert {
	for _, trustedNonCA := range trustedNonCAs {
		tCert := trustedNonCA.Certificates[0]
		if tCert.SerialNumber.Cmp(clientCert.SerialNumber) == 0 && bytes.Equal(tCert.AuthorityKeyId, clientCert.AuthorityKeyId) {
			return trustedNonCA
		}
	}
	return nil
}

// matchPolicy is used to match the associated policy with the certificate that
// was used to establish the client identity.
func (b *backend) matchPolicy(chains [][]*x509.Certificate, trusted []*ParsedCert) *ParsedCert {
	// There is probably a better way to do this...
	for _, chain := range chains {
		for _, trust := range trusted {
			for _, tCert := range trust.Certificates {
				for _, cCert := range chain {
					if tCert.Equal(cCert) {
						return trust
					}
				}
			}
		}
	}
	return nil
}

// loadTrustedCerts is used to load all the trusted certificates from the backend
func (b *backend) loadTrustedCerts(store logical.Storage) (pool *x509.CertPool, trusted []*ParsedCert, trustedNonCAs []*ParsedCert) {
	pool = x509.NewCertPool()
	names, err := store.List("cert/")
	if err != nil {
		b.Logger().Printf("[ERR] cert: failed to list trusted certs: %v", err)
		return
	}
	for _, name := range names {
		entry, err := b.Cert(store, strings.TrimPrefix(name, "cert/"))
		if err != nil {
			b.Logger().Printf("[ERR] cert: failed to load trusted certs '%s': %v", name, err)
			continue
		}
		parsed := parsePEM([]byte(entry.Certificate))
		if len(parsed) == 0 {
			b.Logger().Printf("[ERR] cert: failed to parse certificate for '%s'", name)
			continue
		}
		if !parsed[0].IsCA {
			trustedNonCAs = append(trustedNonCAs, &ParsedCert{
				Entry:        entry,
				Certificates: parsed,
			})
		} else {
			for _, p := range parsed {
				pool.AddCert(p)
			}

			// Create a ParsedCert entry
			trusted = append(trusted, &ParsedCert{
				Entry:        entry,
				Certificates: parsed,
			})
		}
	}
	return
}

func (b *backend) checkForChainInCRLs(chain []*x509.Certificate) bool {
	badChain := false
	for _, cert := range chain {
		badCRLs := b.findSerialInCRLs(cert.SerialNumber)
		if len(badCRLs) != 0 {
			badChain = true
			break
		}
	}
	return badChain
}

func (b *backend) checkForValidChain(chains [][]*x509.Certificate) bool {
	for _, chain := range chains {
		if !b.checkForChainInCRLs(chain) {
			return true
		}
	}
	return false
}

// parsePEM parses a PEM encoded x509 certificate
func parsePEM(raw []byte) (certs []*x509.Certificate) {
	for len(raw) > 0 {
		var block *pem.Block
		block, raw = pem.Decode(raw)
		if block == nil {
			break
		}
		if (block.Type != "CERTIFICATE" && block.Type != "TRUSTED CERTIFICATE") || len(block.Headers) != 0 {
			continue
		}

		cert, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			continue
		}
		certs = append(certs, cert)
	}
	return
}

// validateConnState is used to validate that the TLS client is authorized
// by at trusted certificate. Most of this logic is lifted from the client
// verification logic here:  http://golang.org/src/crypto/tls/handshake_server.go
// The trusted chains are returned.
func validateConnState(roots *x509.CertPool, cs *tls.ConnectionState) ([][]*x509.Certificate, error) {
	opts := x509.VerifyOptions{
		Roots:         roots,
		Intermediates: x509.NewCertPool(),
		KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
	}

	certs := cs.PeerCertificates
	if len(certs) == 0 {
		return nil, nil
	}

	if len(certs) > 1 {
		for _, cert := range certs[1:] {
			opts.Intermediates.AddCert(cert)
		}
	}

	chains, err := certs[0].Verify(opts)
	if err != nil {
		if _, ok := err.(x509.UnknownAuthorityError); ok {
			return nil, nil
		}
		return nil, errors.New("failed to verify client's certificate: " + err.Error())
	}
	return chains, nil
}
<|endoftext|>


<commit_before>/* Mozilla InvestiGator Console

Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

The Initial Developer of the Original Code is
Mozilla Corporation
Portions created by the Initial Developer are Copyright (C) 2014
the Initial Developer. All Rights Reserved.

Contributor(s):
Julien Vehent jvehent@mozilla.com [:ulfr]

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
*/

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"mig"
	"strings"

	"github.com/bobappleyard/readline"
)

// actionReader retrieves an action from the API using its numerical ID
// and enters prompt mode to analyze it
func actionReader(input string, ctx Context) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("actionReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) < 2 {
		panic("wrong order format. must be 'action <actionid>'")
	}
	aid := inputArr[1]
	a, err := getAction(aid, ctx)
	if err != nil {
		panic(err)
	}
	investigators := investigatorsStringFromAction(a.Investigators, 80)

	fmt.Println("Entering action reader mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Action: '%s'.\nLaunched by '%s' on '%s'.\nStatus '%s'.\n",
		a.Name, investigators, a.StartTime, a.Status)
	prompt := "\x1b[31;1maction " + aid[len(aid)-3:len(aid)] + ">\x1b[0m "
	for {
		// completion
		var symbols = []string{"command", "copy", "counters", "details", "exit", "foundsomething",
			"foundnothing", "help", "investigators", "json", "pretty", "r", "times"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(input, " ")
		switch orders[0] {
		case "command":
			err = commandReader(input, ctx)
			if err != nil {
				panic(err)
			}
		case "copy":
			err = actionLauncher(a, ctx)
			if err != nil {
				panic(err)
			}
			goto exit
		case "counters":
			fmt.Printf("Sent:\t\t%d\nReturned:\t%d\nDone:\t\t%d\n"+
				"Cancelled:\t%d\nFailed:\t\t%d\nTimeout:\t%d\n",
				a.Counters.Sent, a.Counters.Returned, a.Counters.Done,
				a.Counters.Cancelled, a.Counters.Failed, a.Counters.TimeOut)
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "foundsomething":
			err = searchFoundAnything(a, true, ctx)
			if err != nil {
				panic(err)
			}
		case "foundnothing":
			err = searchFoundAnything(a, false, ctx)
			if err != nil {
				panic(err)
			}
		case "help":
			fmt.Printf(`The following orders are available:
command <id>	jump to command reader mode for command <id>
copy		enter action launcher mode using current action as template
counters	display the counters of the action
exit		exit this mode
foundsomething	list commands and agents that have found something
foundnothing	list commands and agents that have found nothing
help		show this help
investigators   print the list of investigators that signed the action
json <pretty>	show the json of the action
details		display the details of the action, including status & times
r		refresh the action (get latest version from upstream)
times		show the various timestamps of the action
`)
		case "investigators":
			for _, i := range a.Investigators {
				fmt.Println(i.Name, "- Key ID:", i.PGPFingerprint)
			}
		case "json":
			var ajson []byte
			if len(orders) > 1 {
				if orders[1] == "pretty" {
					ajson, err = json.MarshalIndent(a, "", "  ")
				} else {
					fmt.Printf("Unknown option '%s'\n", orders[1])
				}
			} else {
				ajson, err = json.Marshal(a)
			}
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", ajson)
		case "details":
			fmt.Printf(`
ID             %.0f
Name           %s
Target         %s
Desc           author '%s <%s>'; revision '%.0f';
               url '%s'
Threat         type '%s'; level '%s'; family '%s'; reference '%s'
Status         %s
Times          valid from %s until %s
               started %s; last updated %s; finished %s
               duration: %s
`, a.ID, a.Name, a.Target, a.Description.Author, a.Description.Email, a.Description.Revision,
				a.Description.URL, a.Threat.Type, a.Threat.Level, a.Threat.Family, a.Threat.Ref, a.Status,
				a.ValidFrom, a.ExpireAfter, a.StartTime, a.LastUpdateTime, a.FinishTime, a.LastUpdateTime.Sub(a.StartTime).String())
			fmt.Printf("Investigators  ")
			for _, i := range a.Investigators {
				fmt.Println(i.Name, "- keyid:", i.PGPFingerprint)
			}
			fmt.Printf("Operations     count=%d => ", len(a.Operations))
			for _, op := range a.Operations {
				fmt.Printf("%s; ", op.Module)
			}
			fmt.Printf("\n")
			fmt.Printf("Counters       sent=%d; returned=%d; done=%d\n"+
				"               cancelled=%d; failed=%d; timeout=%d\n",
				a.Counters.Sent, a.Counters.Returned, a.Counters.Done,
				a.Counters.Cancelled, a.Counters.Failed, a.Counters.TimeOut)
		case "r":
			a, err = getAction(aid, ctx)
			if err != nil {
				panic(err)
			}
			fmt.Println("Reload succeeded")
		case "times":
			fmt.Printf("Valid from   '%s' until '%s'\nStarted on   '%s'\n"+
				"Last updated '%s'\nFinished on  '%s'\n",
				a.ValidFrom, a.ExpireAfter, a.StartTime, a.LastUpdateTime, a.FinishTime)
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in action reader mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf("\n")
	return
}

func getAction(aid string, ctx Context) (a mig.Action, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("getAction() -> %v", e)
		}
	}()
	targetURL := ctx.API.URL + "action?actionid=" + aid
	resource, err := getAPIResource(targetURL, ctx)
	if err != nil {
		panic(err)
	}
	if resource.Collection.Items[0].Data[0].Name != "action" {
		panic("API returned something that is not an action... something's wrong.")
	}
	a, err = valueToAction(resource.Collection.Items[0].Data[0].Value)
	if err != nil {
		panic(err)
	}
	return
}

func valueToAction(v interface{}) (a mig.Action, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("valueToAction() -> %v", e)
		}
	}()
	bData, err := json.Marshal(v)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal(bData, &a)
	if err != nil {
		panic(err)
	}
	return
}

func searchFoundAnything(a mig.Action, wantFound bool, ctx Context) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("foundAnything() -> %v", e)
		}
	}()
	foundanything := "false"
	if wantFound {
		foundanything = "true"
	}
	targetURL := ctx.API.URL + "search?type=command&limit=1000000&actionid=" + fmt.Sprintf("%.0f", a.ID) + "&foundanything=" + foundanything
	resource, err := getAPIResource(targetURL, ctx)
	if resource.Collection.Items[0].Data[0].Name != "search results" {
		fmt.Println(targetURL)
		panic("API returned something that is not search results.")
	}
	var results []mig.Command
	bData, err := json.Marshal(resource.Collection.Items[0].Data[0].Value)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal(bData, &results)
	if err != nil {
		panic(err)
	}
	agents := make(map[float64]mig.Command)
	for _, cmd := range results {
		agents[cmd.Agent.ID] = cmd
	}
	if wantFound {
		fmt.Printf("%d agents have found things\n", len(agents))
	} else {
		fmt.Printf("%d agents have not found anything\n", len(agents))
	}
	if len(agents) > 0 {
		fmt.Println("---- Command ID ----    ---- Agent Name & ID----")
		for agtid, cmd := range agents {
			fmt.Printf("%20.0f    %s [%.0f]\n", cmd.ID, cmd.Agent.Name, agtid)
		}
	}
	return
}

func actionPrintShort(data interface{}) (idstr, name, datestr, invs string, err error) {
	a, err := valueToAction(data)
	if err != nil {
		panic(err)
	}
	invs = investigatorsStringFromAction(a.Investigators, 23)

	idstr = fmt.Sprintf("%.0f", a.ID)
	if len(idstr) < 20 {
		for i := len(idstr); i < 20; i++ {
			idstr += " "
		}
	}

	name = a.Name
	if len(name) < 30 {
		for i := len(name); i < 30; i++ {
			name += " "
		}
	}
	if len(name) > 30 {
		name = name[0:27] + "..."
	}

	datestr = a.LastUpdateTime.Format("Mon Jan 2 3:04pm MST")
	if len(datestr) > 20 {
		datestr = datestr[0:20]
	}
	if len(datestr) < 20 {
		for i := len(datestr); i < 20; i++ {
			datestr += " "
		}
	}
	return
}

func investigatorsStringFromAction(invlist []mig.Investigator, strlen int) (investigators string) {
	for ctr, i := range invlist {
		if ctr > 0 {
			investigators += "; "
		}
		investigators += i.Name
	}
	if len(investigators) > strlen {
		investigators = investigators[0:(strlen-3)] + "..."
	}
	return
}
<commit_msg>[minor] fix foundanything console command to match new API format<commit_after>/* Mozilla InvestiGator Console

Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

The Initial Developer of the Original Code is
Mozilla Corporation
Portions created by the Initial Developer are Copyright (C) 2014
the Initial Developer. All Rights Reserved.

Contributor(s):
Julien Vehent jvehent@mozilla.com [:ulfr]

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
*/

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"mig"
	"strings"

	"github.com/bobappleyard/readline"
)

// actionReader retrieves an action from the API using its numerical ID
// and enters prompt mode to analyze it
func actionReader(input string, ctx Context) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("actionReader() -> %v", e)
		}
	}()
	inputArr := strings.Split(input, " ")
	if len(inputArr) < 2 {
		panic("wrong order format. must be 'action <actionid>'")
	}
	aid := inputArr[1]
	a, err := getAction(aid, ctx)
	if err != nil {
		panic(err)
	}
	investigators := investigatorsStringFromAction(a.Investigators, 80)

	fmt.Println("Entering action reader mode. Type \x1b[32;1mexit\x1b[0m or press \x1b[32;1mctrl+d\x1b[0m to leave. \x1b[32;1mhelp\x1b[0m may help.")
	fmt.Printf("Action: '%s'.\nLaunched by '%s' on '%s'.\nStatus '%s'.\n",
		a.Name, investigators, a.StartTime, a.Status)
	prompt := "\x1b[31;1maction " + aid[len(aid)-3:len(aid)] + ">\x1b[0m "
	for {
		// completion
		var symbols = []string{"command", "copy", "counters", "details", "exit", "foundsomething",
			"foundnothing", "help", "investigators", "json", "pretty", "r", "times"}
		readline.Completer = func(query, ctx string) []string {
			var res []string
			for _, sym := range symbols {
				if strings.HasPrefix(sym, query) {
					res = append(res, sym)
				}
			}
			return res
		}

		input, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("error: ", err)
			break
		}
		orders := strings.Split(input, " ")
		switch orders[0] {
		case "command":
			err = commandReader(input, ctx)
			if err != nil {
				panic(err)
			}
		case "copy":
			err = actionLauncher(a, ctx)
			if err != nil {
				panic(err)
			}
			goto exit
		case "counters":
			fmt.Printf("Sent:\t\t%d\nReturned:\t%d\nDone:\t\t%d\n"+
				"Cancelled:\t%d\nFailed:\t\t%d\nTimeout:\t%d\n",
				a.Counters.Sent, a.Counters.Returned, a.Counters.Done,
				a.Counters.Cancelled, a.Counters.Failed, a.Counters.TimeOut)
		case "exit":
			fmt.Printf("exit\n")
			goto exit
		case "foundsomething":
			err = searchFoundAnything(a, true, ctx)
			if err != nil {
				panic(err)
			}
		case "foundnothing":
			err = searchFoundAnything(a, false, ctx)
			if err != nil {
				panic(err)
			}
		case "help":
			fmt.Printf(`The following orders are available:
command <id>	jump to command reader mode for command <id>
copy		enter action launcher mode using current action as template
counters	display the counters of the action
exit		exit this mode
foundsomething	list commands and agents that have found something
foundnothing	list commands and agents that have found nothing
help		show this help
investigators   print the list of investigators that signed the action
json <pretty>	show the json of the action
details		display the details of the action, including status & times
r		refresh the action (get latest version from upstream)
times		show the various timestamps of the action
`)
		case "investigators":
			for _, i := range a.Investigators {
				fmt.Println(i.Name, "- Key ID:", i.PGPFingerprint)
			}
		case "json":
			var ajson []byte
			if len(orders) > 1 {
				if orders[1] == "pretty" {
					ajson, err = json.MarshalIndent(a, "", "  ")
				} else {
					fmt.Printf("Unknown option '%s'\n", orders[1])
				}
			} else {
				ajson, err = json.Marshal(a)
			}
			if err != nil {
				panic(err)
			}
			fmt.Printf("%s\n", ajson)
		case "details":
			fmt.Printf(`
ID             %.0f
Name           %s
Target         %s
Desc           author '%s <%s>'; revision '%.0f';
               url '%s'
Threat         type '%s'; level '%s'; family '%s'; reference '%s'
Status         %s
Times          valid from %s until %s
               started %s; last updated %s; finished %s
               duration: %s
`, a.ID, a.Name, a.Target, a.Description.Author, a.Description.Email, a.Description.Revision,
				a.Description.URL, a.Threat.Type, a.Threat.Level, a.Threat.Family, a.Threat.Ref, a.Status,
				a.ValidFrom, a.ExpireAfter, a.StartTime, a.LastUpdateTime, a.FinishTime, a.LastUpdateTime.Sub(a.StartTime).String())
			fmt.Printf("Investigators  ")
			for _, i := range a.Investigators {
				fmt.Println(i.Name, "- keyid:", i.PGPFingerprint)
			}
			fmt.Printf("Operations     count=%d => ", len(a.Operations))
			for _, op := range a.Operations {
				fmt.Printf("%s; ", op.Module)
			}
			fmt.Printf("\n")
			fmt.Printf("Counters       sent=%d; returned=%d; done=%d\n"+
				"               cancelled=%d; failed=%d; timeout=%d\n",
				a.Counters.Sent, a.Counters.Returned, a.Counters.Done,
				a.Counters.Cancelled, a.Counters.Failed, a.Counters.TimeOut)
		case "r":
			a, err = getAction(aid, ctx)
			if err != nil {
				panic(err)
			}
			fmt.Println("Reload succeeded")
		case "times":
			fmt.Printf("Valid from   '%s' until '%s'\nStarted on   '%s'\n"+
				"Last updated '%s'\nFinished on  '%s'\n",
				a.ValidFrom, a.ExpireAfter, a.StartTime, a.LastUpdateTime, a.FinishTime)
		case "":
			break
		default:
			fmt.Printf("Unknown order '%s'. You are in action reader mode. Try `help`.\n", orders[0])
		}
		readline.AddHistory(input)
	}
exit:
	fmt.Printf("\n")
	return
}

func getAction(aid string, ctx Context) (a mig.Action, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("getAction() -> %v", e)
		}
	}()
	targetURL := ctx.API.URL + "action?actionid=" + aid
	resource, err := getAPIResource(targetURL, ctx)
	if err != nil {
		panic(err)
	}
	if resource.Collection.Items[0].Data[0].Name != "action" {
		panic("API returned something that is not an action... something's wrong.")
	}
	a, err = valueToAction(resource.Collection.Items[0].Data[0].Value)
	if err != nil {
		panic(err)
	}
	return
}

func valueToAction(v interface{}) (a mig.Action, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("valueToAction() -> %v", e)
		}
	}()
	bData, err := json.Marshal(v)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal(bData, &a)
	if err != nil {
		panic(err)
	}
	return
}

func searchFoundAnything(a mig.Action, wantFound bool, ctx Context) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("foundAnything() -> %v", e)
		}
	}()
	targetURL := ctx.API.URL + "search?type=command&limit=1000000&actionid=" + fmt.Sprintf("%.0f", a.ID)
	if wantFound {
		targetURL += "&foundanything=true"
	} else {
		targetURL += "&foundanything=false"
	}
	resource, err := getAPIResource(targetURL, ctx)
	if err != nil {
		panic(err)
	}
	agents := make(map[float64]mig.Command)
	for _, item := range resource.Collection.Items {
		for _, data := range item.Data {
			if data.Name != "command" {
				continue
			}
			cmd, err := valueToCommand(data.Value)
			if err != nil {
				panic(err)
			}
			agents[cmd.Agent.ID] = cmd
		}
	}
	if wantFound {
		fmt.Printf("%d agents have found things\n", len(agents))
	} else {
		fmt.Printf("%d agents have not found anything\n", len(agents))
	}
	if len(agents) > 0 {
		fmt.Println("---- Command ID ----    ---- Agent Name & ID----")
		for agtid, cmd := range agents {
			fmt.Printf("%20.0f    %s [%.0f]\n", cmd.ID, cmd.Agent.Name, agtid)
		}
	}
	return
}

func actionPrintShort(data interface{}) (idstr, name, datestr, invs string, err error) {
	a, err := valueToAction(data)
	if err != nil {
		panic(err)
	}
	invs = investigatorsStringFromAction(a.Investigators, 23)

	idstr = fmt.Sprintf("%.0f", a.ID)
	if len(idstr) < 20 {
		for i := len(idstr); i < 20; i++ {
			idstr += " "
		}
	}

	name = a.Name
	if len(name) < 30 {
		for i := len(name); i < 30; i++ {
			name += " "
		}
	}
	if len(name) > 30 {
		name = name[0:27] + "..."
	}

	datestr = a.LastUpdateTime.Format("Mon Jan 2 3:04pm MST")
	if len(datestr) > 20 {
		datestr = datestr[0:20]
	}
	if len(datestr) < 20 {
		for i := len(datestr); i < 20; i++ {
			datestr += " "
		}
	}
	return
}

func investigatorsStringFromAction(invlist []mig.Investigator, strlen int) (investigators string) {
	for ctr, i := range invlist {
		if ctr > 0 {
			investigators += "; "
		}
		investigators += i.Name
	}
	if len(investigators) > strlen {
		investigators = investigators[0:(strlen-3)] + "..."
	}
	return
}
<|endoftext|>


<commit_before>package gfx

import (
	"fmt"
	gl "github.com/go-gl/gl"
	glfw "github.com/go-gl/glfw3"
)

type Screen struct {
	Width  int
	Height int
	Title  string
	Window glfw.Window
}

func MakeScreen(width int, height int, title string) Screen {
	s := Screen{}
	s.Width = width
	s.Height = height
	s.Title = title
	s.Init()

	return s
}

func (s *Screen) Init() {
	// Setup: Set GL error callback function...
	glfw.SetErrorCallback(s.GFXError)

	if !glfw.Init() { // Init GLFW3...
		panic("GLFW3 failed to initialize!\n")
	}

	// Now, create a window!
	win, err := glfw.CreateWindow(s.Width, s.Height, s.Title, nil, nil)
	if err != nil {
		panic(fmt.Errorf("GLFW could not create window! Error: %v\n", err))
	}

	win.SetKeyCallback(keyCallback)
	win.MakeContextCurrent()
	s.Window = *win

	glfw.SwapInterval(1) // Use videosync. (People say it's good.)

	// Now, init OpenGL.
	if gl.Init() != 0 {
		panic("OpenGL could not initialize!\n")
	}

	gl.ClearColor(0, 0, 0, 0)
	gl.MatrixMode(gl.PROJECTION)

	gl.Ortho(0, 64, 32, 0, 0, 1)
	fmt.Println("screen done init")
}

func (s *Screen) Draw(data [2048]bool) {
	// I have no idea what I'm doing with OpenGL, so
	// this code is adapted from https://github.com/nictuku/chip-8/blob/master/system/video.go

	//gl.Viewport(0, 0, s.Width, s.Height)
	//gl.Clear(gl.COLOR_BUFFER_BIT)

	gl.MatrixMode(gl.POLYGON)
	//gl.Begin(gl.POLYGON)

	for yline := 0; yline < 32; yline++ {
		for xline := 0; xline < 64; xline++ {

			x, y := float32(xline), float32(yline)
			if !data[xline+(yline*64)] { // False = 0.
				fmt.Println("drawing meeeee...")
				gl.Color3f(0, 0, 0)
			} else { // True = 1.
				fmt.Println("drawing youuuuu...")
				gl.Color3f(1, 1, 1)
			}
			gl.Rectf(x, y, x+1, y+1)
		}
	}

	//gl.End()
	s.Window.SwapBuffers()
	glfw.PollEvents()
}

func (s *Screen) Quit() {
	glfw.Terminate()
}

func (s *Screen) GFXError(err glfw.ErrorCode, msg string) {
	panic(fmt.Errorf("GLFW Error: %v: %v\n", err, msg))
}

func keyCallback(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	if key == glfw.KeyEscape && action == glfw.Press {
		w.SetShouldClose(true)
	}
}
<commit_msg>Cleanup of some code in Screen<commit_after>package gfx

import (
	"fmt"
	gl "github.com/go-gl/gl"
	glfw "github.com/go-gl/glfw3"
)

type Screen struct {
	Width     int
	Height    int
	ResWidth  int
	ResHeight int
	Title     string
	Window    glfw.Window
}

func MakeScreen(width int, height int, title string) Screen {
	s := Screen{}
	s.Width = width
	s.Height = height
	s.Title = title

	// Chip8 resolution is hardcoded.
	s.ResWidth = 64
	s.ResHeight = 32

	s.Init()
	return s
}

func (s *Screen) Init() {
	// 1. Initialize GLFW and save window context.
	glfw.SetErrorCallback(s.GFXError)

	if !glfw.Init() { // Init GLFW3...
		panic("GLFW3 failed to initialize!\n")
	}

	win, err := glfw.CreateWindow(s.Width, s.Height, s.Title, nil, nil)
	if err != nil {
		panic(fmt.Errorf("GLFW could not create window! Error: %v\n", err))
	}

	win.SetKeyCallback(keyCallback)
	win.MakeContextCurrent()
	glfw.SwapInterval(1) // Use videosync. (People say it's good.)

	s.Window = *win

	// 2. Initalize OpenGL.
	if gl.Init() != 0 {
		panic("OpenGL failed to initialize!\n")
	}

	// 3. Draw a black screen and set the coordinate system.
	gl.ClearColor(0, 0, 0, 0)
	gl.MatrixMode(gl.PROJECTION)
	gl.Ortho(0, float64(s.ResWidth), float64(s.ResHeight), 0, 0, 1)

	fmt.Println("Screen successfully initialized.")
}

func (s *Screen) Draw(data [64 * 32]bool) {
	// I have no idea what I'm doing with OpenGL, so
	// this code is adapted from
	// https://github.com/nictuku/chip-8/blob/master/system/video.go

	//gl.Viewport(0, 0, s.Width, s.Height)
	//gl.Clear(gl.COLOR_BUFFER_BIT)

	gl.MatrixMode(gl.POLYGON)

	for xline := 0; xline < s.ResWidth; xline++ {
		for yline := 0; yline < s.ResHeight; yline++ {

			if !data[xline+(yline*s.ResWidth)] {
				gl.Color3d(0, 0, 0)
			} else {
				gl.Color3d(1, 1, 1) // Draw white.
			}
			x, y := float64(xline), float64(yline)
			gl.Rectd(x, y, x+1, y+1)
		}
	}

	s.Window.SwapBuffers() // Display what we just drew.
	glfw.PollEvents()
}

func (s *Screen) Quit() {
	glfw.Terminate()
}

func (s *Screen) GFXError(err glfw.ErrorCode, msg string) {
	panic(fmt.Errorf("GLFW Error: %v: %v\n", err, msg))
}

func keyCallback(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	if key == glfw.KeyEscape && action == glfw.Press {
		w.SetShouldClose(true)
	}
}
<|endoftext|>


<commit_before>package installer

func Prepare() error {

	// Make sure our infrastructure is correct
	//// Create required user and folders
	CreateUser("stampzilla")
	CreateDirAsUser("/var/spool/stampzilla", "stampzilla")
	CreateDirAsUser("/var/log/stampzilla", "stampzilla")
	CreateDirAsUser("/home/stampzilla/go", "stampzilla")
	CreateDirAsUser("/etc/stampzilla", "stampzilla")
	CreateDirAsUser("/etc/stampzilla/nodes", "stampzilla")

	c := Config{}
	c.CreateConfig()

	return nil
}
<commit_msg>Fixed missing binary folder<commit_after>package installer

func Prepare() error {

	// Make sure our infrastructure is correct
	//// Create required user and folders
	CreateUser("stampzilla")
	CreateDirAsUser("/var/spool/stampzilla", "stampzilla")
	CreateDirAsUser("/var/log/stampzilla", "stampzilla")
	CreateDirAsUser("/home/stampzilla/go/bin", "stampzilla")
	CreateDirAsUser("/etc/stampzilla", "stampzilla")
	CreateDirAsUser("/etc/stampzilla/nodes", "stampzilla")

	c := Config{}
	c.CreateConfig()

	return nil
}
<|endoftext|>


<commit_before>//go:build !ignore_autogenerated
// +build !ignore_autogenerated

/*
Copyright The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Code generated by fitask. DO NOT EDIT.

package gcetasks

import (
	"k8s.io/kops/upup/pkg/fi"
)

// PoolHealthCheck

var _ fi.HasLifecycle = &PoolHealthCheck{}

// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
func (o *PoolHealthCheck) GetLifecycle() fi.Lifecycle {
	return o.Lifecycle
}

// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
func (o *PoolHealthCheck) SetLifecycle(lifecycle fi.Lifecycle) {
	o.Lifecycle = lifecycle
}

var _ fi.HasName = &PoolHealthCheck{}

// GetName PoolHealthCheck the Name of the object, implementing fi.HasName
func (o *PoolHealthCheck) GetName() *string {
	return o.Name
}

// String is the stringer function for the task, producing readable output using fi.TaskAsString
func (o *PoolHealthCheck) String() string {
	return fi.TaskAsString(o)
}
<commit_msg>codegen<commit_after>//go:build !ignore_autogenerated
// +build !ignore_autogenerated

/*
Copyright The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Code generated by fitask. DO NOT EDIT.

package gcetasks

import (
	"k8s.io/kops/upup/pkg/fi"
)

// PoolHealthCheck

var _ fi.HasLifecycle = &PoolHealthCheck{}

// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
func (o *PoolHealthCheck) GetLifecycle() fi.Lifecycle {
	return o.Lifecycle
}

// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
func (o *PoolHealthCheck) SetLifecycle(lifecycle fi.Lifecycle) {
	o.Lifecycle = lifecycle
}

var _ fi.HasName = &PoolHealthCheck{}

// GetName returns the Name of the object, implementing fi.HasName
func (o *PoolHealthCheck) GetName() *string {
	return o.Name
}

// String is the stringer function for the task, producing readable output using fi.TaskAsString
func (o *PoolHealthCheck) String() string {
	return fi.TaskAsString(o)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"os"
	"sync"
	"sync/atomic"

	gcplogging "github.com/kyma-project/test-infra/development/gcp/pkg/logging"
	"github.com/kyma-project/test-infra/development/github/pkg/client"
	"github.com/kyma-project/test-infra/development/prow"
	log "github.com/sirupsen/logrus"
)

// Example fields for test por in gcp logging.
// logName: "projects/sap-kyma-prow/logs/stdout"
// resource: {
//   labels: {
//     cluster_name: "trusted-workload-kyma-prow"
//     container_name: "test"
//     location: "europe-west3"
//     namespace_name: "default"
//     pod_name: "cbb59657-fa91-11eb-baea-4e9acc7ce5e6"
//     project_id: "sap-kyma-prow"
//   }
//   type: "k8s_container"
// labels: {
//   compute.googleapis.com/resource_name: "gke-trusted-workload-k-high-cpu-16-32-c8294afe-skrq"
//   k8s-pod/created-by-prow: "true"
//   k8s-pod/event-GUID: "cb549a8a-fa91-11eb-80a9-35f1ac609512"
//   k8s-pod/preset-build-main: "true"
//   k8s-pod/preset-cluster-use-ssd: "true"
//   k8s-pod/preset-cluster-version: "true"
//   k8s-pod/preset-debug-commando-oom: "true"
//   k8s-pod/preset-dind-enabled: "true"
//   k8s-pod/preset-docker-push-repository-gke-integration: "true"
//   k8s-pod/preset-gc-compute-envs: "true"
//   k8s-pod/preset-gc-project-env: "true"
//   k8s-pod/preset-gke-upgrade-post-job: "true"
//   k8s-pod/preset-kyma-artifacts-bucket: "true"
//   k8s-pod/preset-kyma-guard-bot-github-token: "true"
//   k8s-pod/preset-log-collector-slack-token: "true"
//   k8s-pod/preset-sa-gke-kyma-integration: "true"
//   k8s-pod/preset-sa-test-gcr-push: "true"
//   k8s-pod/prow_k8s_io/build-id: "1425409012446269440"
//   k8s-pod/prow_k8s_io/context: "post-main-kyma-gke-upgrade"
//   k8s-pod/prow_k8s_io/id: "cbb59657-fa91-11eb-baea-4e9acc7ce5e6"
//   k8s-pod/prow_k8s_io/job: "post-main-kyma-gke-upgrade"
//   k8s-pod/prow_k8s_io/plank-version: "v20210714-62f15287bd"
//   k8s-pod/prow_k8s_io/pubsub_project: "sap-kyma-prow"
//   k8s-pod/prow_k8s_io/pubsub_runID: "post-main-kyma-gke-upgrade"
//   k8s-pod/prow_k8s_io/pubsub_topic: "prowjobs"
//   k8s-pod/prow_k8s_io/refs_base_ref: "main"
//   k8s-pod/prow_k8s_io/refs_org: "kyma-project"
//   k8s-pod/prow_k8s_io/refs_repo: "kyma"
//   k8s-pod/prow_k8s_io/type: "postsubmit"
// }

func main() {
	var exitCode atomic.Value
	defer func() { os.Exit(exitCode.Load().(int)) }()
	ctx := context.Background()
	var wg sync.WaitGroup
	saProwjobGcpLoggingClientKeyPath := os.Getenv("SA_PROWJOB_GCP_LOGGING_CLIENT_KEY_PATH")
	logClient, err := gcplogging.NewProwjobClient(ctx, saProwjobGcpLoggingClientKeyPath)
	if err != nil {
		log.Errorf("creating gcp logging client failed, got error: %v", err)
	}
	logger := logClient.NewProwjobLogger().WithGeneratedTrace()
	defer logger.Flush()
	// provided by preset-bot-github-sap-token
	accessToken := os.Getenv("BOT_GITHUB_SAP_TOKEN")
	contextLogger := logger.WithContext("checking if user exists in users map")
	defer contextLogger.Flush()
	saptoolsClient, err := client.NewSapToolsClient(ctx, accessToken)
	if err != nil {
		contextLogger.LogError(fmt.Sprintf("failed creating sap tools github client, got error: %v", err))
	}
	usersMap, err := saptoolsClient.GetUsersMap(ctx)
	if err != nil {
		contextLogger.LogError(fmt.Sprintf("error when getting users map: got error %v", err))
	}
	authors, err := prow.GetPrAuthorForPresubmit()
	if err != nil {
		if notPresubmit := prow.IsNotPresubmitError(err); *notPresubmit {
			contextLogger.LogInfo(err.Error())
		} else {
			contextLogger.LogError(fmt.Sprintf("error when getting pr author for presubmit: got error %v", err))
		}
	}
	wg.Add(len(authors))
	contextLogger.LogInfo(fmt.Sprintf("found %d authors in job spec env variable", len(authors)))
	for _, author := range authors {
		go func(wg *sync.WaitGroup, author string, exitCode *atomic.Value) {
			defer wg.Done()
			for _, user := range usersMap {
				if user.ComGithubUsername == author {
					contextLogger.LogInfo(fmt.Sprintf("user %s is present in users map", author))
					return
				}
			}
			contextLogger.LogError(fmt.Sprintf("user %s is not present in users map, please add user to users-map.yaml file.", author))
			exitCode.Store(1)
		}(&wg, author, &exitCode)
	}
	wg.Wait()
	if exitCode.Load() == nil {
		contextLogger.LogInfo("all authors present in users map")
		err := contextLogger.Flush()
		if err != nil {
			fmt.Println(err.Error())
		}
		exitCode.Store(1)
	}
}
<commit_msg>fixed setting exitcode on success (#4048)<commit_after>package main

import (
	"context"
	"fmt"
	"os"
	"sync"
	"sync/atomic"

	gcplogging "github.com/kyma-project/test-infra/development/gcp/pkg/logging"
	"github.com/kyma-project/test-infra/development/github/pkg/client"
	"github.com/kyma-project/test-infra/development/prow"
	log "github.com/sirupsen/logrus"
)

// Example fields in gcp logging.
// logName: "projects/sap-kyma-prow/logs/stdout"
// resource: {
//   labels: {
//     cluster_name: "trusted-workload-kyma-prow"
//     container_name: "test"
//     location: "europe-west3"
//     namespace_name: "default"
//     pod_name: "cbb59657-fa91-11eb-baea-4e9acc7ce5e6"
//     project_id: "sap-kyma-prow"
//   }
//   type: "k8s_container"
// labels: {
//   compute.googleapis.com/resource_name: "gke-trusted-workload-k-high-cpu-16-32-c8294afe-skrq"
//   k8s-pod/created-by-prow: "true"
//   k8s-pod/event-GUID: "cb549a8a-fa91-11eb-80a9-35f1ac609512"
//   k8s-pod/preset-build-main: "true"
//   k8s-pod/preset-cluster-use-ssd: "true"
//   k8s-pod/preset-cluster-version: "true"
//   k8s-pod/preset-debug-commando-oom: "true"
//   k8s-pod/preset-dind-enabled: "true"
//   k8s-pod/preset-docker-push-repository-gke-integration: "true"
//   k8s-pod/preset-gc-compute-envs: "true"
//   k8s-pod/preset-gc-project-env: "true"
//   k8s-pod/preset-gke-upgrade-post-job: "true"
//   k8s-pod/preset-kyma-artifacts-bucket: "true"
//   k8s-pod/preset-kyma-guard-bot-github-token: "true"
//   k8s-pod/preset-log-collector-slack-token: "true"
//   k8s-pod/preset-sa-gke-kyma-integration: "true"
//   k8s-pod/preset-sa-test-gcr-push: "true"
//   k8s-pod/prow_k8s_io/build-id: "1425409012446269440"
//   k8s-pod/prow_k8s_io/context: "post-main-kyma-gke-upgrade"
//   k8s-pod/prow_k8s_io/id: "cbb59657-fa91-11eb-baea-4e9acc7ce5e6"
//   k8s-pod/prow_k8s_io/job: "post-main-kyma-gke-upgrade"
//   k8s-pod/prow_k8s_io/plank-version: "v20210714-62f15287bd"
//   k8s-pod/prow_k8s_io/pubsub_project: "sap-kyma-prow"
//   k8s-pod/prow_k8s_io/pubsub_runID: "post-main-kyma-gke-upgrade"
//   k8s-pod/prow_k8s_io/pubsub_topic: "prowjobs"
//   k8s-pod/prow_k8s_io/refs_base_ref: "main"
//   k8s-pod/prow_k8s_io/refs_org: "kyma-project"
//   k8s-pod/prow_k8s_io/refs_repo: "kyma"
//   k8s-pod/prow_k8s_io/type: "postsubmit"
// }

func main() {
	// exitCode holds exit code to report at the end of main execution, it's safe to set it from multiple goroutines.
	var exitCode atomic.Value
	// Set exit code for exec. This will be call last when exiting from main function.
	defer func() { os.Exit(exitCode.Load().(int)) }()
	ctx := context.Background()
	var wg sync.WaitGroup
	// Serviceaccount credentials to access google cloud logging API.
	saProwjobGcpLoggingClientKeyPath := os.Getenv("SA_PROWJOB_GCP_LOGGING_CLIENT_KEY_PATH")
	// Create kyma implementation Google cloud logging client with defaults for logging from prowjobs.
	logClient, err := gcplogging.NewProwjobClient(ctx, saProwjobGcpLoggingClientKeyPath)
	if err != nil {
		log.Errorf("creating gcp logging client failed, got error: %v", err)
	}
	logger := logClient.NewProwjobLogger().WithGeneratedTrace()
	// Flush all buffered messages when exiting from main function.
	defer logger.Flush()
	// Github access token, provided by preset-bot-github-sap-token
	accessToken := os.Getenv("BOT_GITHUB_SAP_TOKEN")
	contextLogger := logger.WithContext("checking if user exists in users map")
	defer contextLogger.Flush()
	// Create SAP tools github client.
	saptoolsClient, err := client.NewSapToolsClient(ctx, accessToken)
	if err != nil {
		contextLogger.LogError(fmt.Sprintf("failed creating sap tools github client, got error: %v", err))
	}
	// Get file with usernames mappings.
	usersMap, err := saptoolsClient.GetUsersMap(ctx)
	if err != nil {
		contextLogger.LogError(fmt.Sprintf("error when getting users map: got error %v", err))
	}
	// Get authors of github pull request.
	authors, err := prow.GetPrAuthorForPresubmit()
	if err != nil {
		if notPresubmit := prow.IsNotPresubmitError(err); *notPresubmit {
			contextLogger.LogInfo(err.Error())
		} else {
			contextLogger.LogError(fmt.Sprintf("error when getting pr author for presubmit: got error %v", err))
		}
	}
	wg.Add(len(authors))
	contextLogger.LogInfo(fmt.Sprintf("found %d authors in job spec env variable", len(authors)))
	// Search entries for authors github usernames.
	for _, author := range authors {
		// Use goroutines.
		go func(wg *sync.WaitGroup, author string, exitCode *atomic.Value) {
			// Notify goroutine is done when exiting from it.
			defer wg.Done()
			for _, user := range usersMap {
				if user.ComGithubUsername == author {
					contextLogger.LogInfo(fmt.Sprintf("user %s is present in users map", author))
					return
				}
			}
			contextLogger.LogError(fmt.Sprintf("user %s is not present in users map, please add user to users-map.yaml file.", author))
			// Set exitcode to 1, to report failed prowjob execution.
			exitCode.Store(1)
		}(&wg, author, &exitCode)
	}
	wg.Wait()
	// If exitcode is nil, that means no errors were reported.
	if exitCode.Load() == nil {
		contextLogger.LogInfo("all authors present in users map")
		err := contextLogger.Flush()
		if err != nil {
			fmt.Println(err.Error())
		}
		// Report successful prowjob execution.
		exitCode.Store(0)
	}
}
<|endoftext|>


<commit_before>// packet is a wrapper for GoPacket and sub packages
package packet

import (
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
)

// Packet holds all layers information
type Packet struct {
	EthType layers.EthernetType
	SrcMAC  net.HardwareAddr
	DstMAC  net.HardwareAddr
	IPv4    *layers.IPv4
	TCP     *layers.TCP
	UDP     *layers.UDP
	SrcHost []string
	DstHost []string
	Payload string
}

var (
	device            = "en0"
	snapLen     int32 = 1024
	promiscuous       = false
	err         error
	timeout     = 100 * time.Nanosecond
	handle      *pcap.Handle
)

// NewPacket creates an empty packet info
func NewPacket() *Packet {
	return &Packet{}
}

// Open is a loop over packets
func (p *Packet) Open() chan *Packet {
	var (
		c    = make(chan *Packet, 1)
		s    = make(chan os.Signal, 1)
		loop = true
	)
	// capture interrupt w/ s channel
	signal.Notify(s, os.Interrupt)

	go func() {
		handle, err = pcap.OpenLive(device, snapLen, promiscuous, timeout)
		if err != nil {
			log.Fatal(err)
		}
		if err := handle.SetBPFFilter(""); err != nil {
			log.Fatal(err)
		}

		defer handle.Close()
		defer close(s)
		defer close(c)

		packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
		for loop {
			packet, err := packetSource.NextPacket()
			if err != nil {
				continue
			}
			select {
			case <-s:
				loop = false
				signal.Stop(s)
			case c <- GetPacketInfo(packet):
			}
		}
	}()
	return c
}

// PrintPretty prints out the captured data
// to the stdout
func (p *Packet) PrintPretty() {
	switch p.EthType {
	case layers.EthernetTypeIPv4:
		p.PrintIPv4()
	case layers.EthernetTypeIPv6:
		println("IPV6")
		p.PrintIPv4()
	case layers.EthernetTypeARP:
		println("ARP")
	default:
		println("unknown")

	}
}

// PrintIPv4 prints IPv4 packets
func (p *Packet) PrintIPv4() {
	//p.SrcHost, _ = net.LookupHost(ip.SrcIP.String())
	//p.DstHost, _ = net.LookupHost(ip.DstIP.String())
	switch {
	case p.IPv4.Protocol == layers.IPProtocolTCP:
		log.Printf("IP %s > %s , %s length: %d\n", p.IPv4.SrcIP, p.IPv4.DstIP, p.IPv4.Protocol, len(p.Payload))
	case p.IPv4.Protocol == layers.IPProtocolUDP:
		log.Printf("IP %s > %s , %s length: %d\n", p.IPv4.SrcIP, p.IPv4.DstIP, p.IPv4.Protocol, len(p.Payload))
	}
}

// GetPacketInfo decodes layers
func GetPacketInfo(packet gopacket.Packet) *Packet {
	var p Packet
	// Ethernet
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
		p.SrcMAC = ethernetPacket.SrcMAC
		p.DstMAC = ethernetPacket.DstMAC
		p.EthType = ethernetPacket.EthernetType
	}
	// IP Address V4
	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer != nil {
		p.IPv4, _ = ipLayer.(*layers.IPv4)
	}

	// TCP
	tcpLayer := packet.Layer(layers.LayerTypeTCP)
	if tcpLayer != nil {
		p.TCP, _ = tcpLayer.(*layers.TCP)
	} else {
		// UDP
		udpLayer := packet.Layer(layers.LayerTypeUDP)
		if udpLayer != nil {
			p.UDP, _ = udpLayer.(*layers.UDP)
		}
	}

	// Application
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer != nil {
		p.Payload = string(applicationLayer.Payload())
	}

	// Check for errors
	if err := packet.ErrorLayer(); err != nil {
		fmt.Println("Error decoding some part of the packet:", err)
	}
	return &p
}
<commit_msg>added ipv6, fixed ethernet layer<commit_after>// packet is a wrapper for GoPacket and sub packages
package packet

import (
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
)

// Packet holds all layers information
type Packet struct {
	Eth     *layers.Ethernet
	IPv4    *layers.IPv4
	IPv6    *layers.IPv6
	TCP     *layers.TCP
	UDP     *layers.UDP
	SrcHost []string
	DstHost []string
	Payload string
}

var (
	device            = "en0"
	snapLen     int32 = 1024
	promiscuous       = false
	err         error
	timeout     = 100 * time.Nanosecond
	handle      *pcap.Handle
)

// NewPacket creates an empty packet info
func NewPacket() *Packet {
	return &Packet{}
}

// Open is a loop over packets
func (p *Packet) Open() chan *Packet {
	var (
		c    = make(chan *Packet, 1)
		s    = make(chan os.Signal, 1)
		loop = true
	)
	// capture interrupt w/ s channel
	signal.Notify(s, os.Interrupt)

	go func() {
		handle, err = pcap.OpenLive(device, snapLen, promiscuous, timeout)
		if err != nil {
			log.Fatal(err)
		}
		if err := handle.SetBPFFilter(""); err != nil {
			log.Fatal(err)
		}

		defer handle.Close()
		defer close(s)
		defer close(c)

		packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
		for loop {
			packet, err := packetSource.NextPacket()
			if err != nil {
				continue
			}
			select {
			case <-s:
				loop = false
				signal.Stop(s)
			case c <- GetPacketInfo(packet):
			}
		}
	}()
	return c
}

// PrintPretty prints out the captured data
// to the stdout
func (p *Packet) PrintPretty() {
	switch p.Eth.EthernetType {
	case layers.EthernetTypeIPv4:
		p.PrintIPv4()
	case layers.EthernetTypeIPv6:
		println("IPV6")
		p.PrintIPv4()
	case layers.EthernetTypeARP:
		println("ARP")
	default:
		println("unknown")

	}
}

// PrintIPv4 prints IPv4 packets
func (p *Packet) PrintIPv4() {
	switch {
	case p.IPv4.Protocol == layers.IPProtocolTCP:
		log.Printf("IP %s > %s , %s length: %d\n", p.IPv4.SrcIP, p.IPv4.DstIP, p.IPv4.Protocol, len(p.Payload))
	case p.IPv4.Protocol == layers.IPProtocolUDP:
		log.Printf("IP %s > %s , %s length: %d\n", p.IPv4.SrcIP, p.IPv4.DstIP, p.IPv4.Protocol, len(p.Payload))
	}
}

// GetPacketInfo decodes layers
func GetPacketInfo(packet gopacket.Packet) *Packet {
	var p Packet
	// Ethernet
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		p.Eth, _ = ethernetLayer.(*layers.Ethernet)
	}

	// IP Address V4
	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer != nil {
		p.IPv4, _ = ipLayer.(*layers.IPv4)
		p.SrcHost, _ = net.LookupHost(p.IPv4.SrcIP.String())
		p.DstHost, _ = net.LookupHost(p.IPv4.DstIP.String())
	} else {
		// IP Address V6
		ipLayer := packet.Layer(layers.LayerTypeIPv6)
		if ipLayer != nil {
			p.IPv6, _ = ipLayer.(*layers.IPv6)
			p.SrcHost, _ = net.LookupHost(p.IPv6.SrcIP.String())
			p.DstHost, _ = net.LookupHost(p.IPv6.DstIP.String())
		}
	}

	// TCP
	tcpLayer := packet.Layer(layers.LayerTypeTCP)
	if tcpLayer != nil {
		p.TCP, _ = tcpLayer.(*layers.TCP)
	} else {
		// UDP
		udpLayer := packet.Layer(layers.LayerTypeUDP)
		if udpLayer != nil {
			p.UDP, _ = udpLayer.(*layers.UDP)
		}
	}

	// Application
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer != nil {
		p.Payload = string(applicationLayer.Payload())
	}

	// Check for errors
	if err := packet.ErrorLayer(); err != nil {
		fmt.Println("Error decoding some part of the packet:", err)
	}
	return &p
}
<|endoftext|>


<commit_before>// Package packet is a wrapper for GoPacket and sub packages
package packet

import (
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"strings"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"

	"github.com/fatih/color"

	"github.com/mehrdadrad/mylg/cli"
)

// Packet holds all layers information
type Packet struct {
	// packet layers data
	Eth    *layers.Ethernet
	IPv4   *layers.IPv4
	IPv6   *layers.IPv6
	TCP    *layers.TCP
	UDP    *layers.UDP
	ICMPv4 *layers.ICMPv4
	ICMPv6 *layers.ICMPv6

	SrcHost []string
	DstHost []string
	Payload string
	// info
	device string
}

// logWriter represents custom writer
type logWriter struct {
}

var (
	snapLen     int32 = 6 * 1024
	promiscuous       = false
	err         error
	timeout     = 100 * time.Nanosecond
	handle      *pcap.Handle
	addrs       = make(map[string]struct{}, 20)
	ifName      string

	noColor bool
	filter  string
	count   int
)

// NewPacket creates an empty packet info
func NewPacket(args string) (*Packet, error) {
	var flag map[string]interface{}

	filter, flag = cli.Flag(args)

	// help
	if _, ok := flag["help"]; ok {
		help()
		return nil, fmt.Errorf("help")
	}

	noColor = cli.SetFlag(flag, "nc", false).(bool)
	count = cli.SetFlag(flag, "c", 1000000).(int)

	if err != nil {
		return nil, err
	}

	log.SetFlags(0)
	log.SetOutput(new(logWriter))

	return &Packet{
		device: cli.SetFlag(flag, "i", "").(string),
	}, nil
}

// Open is a loop over packets
func (p *Packet) Open() chan *Packet {
	var (
		c    = make(chan *Packet, 1)
		s    = make(chan os.Signal, 1)
		loop = true
	)
	// capture interrupt w/ s channel
	signal.Notify(s, os.Interrupt)

	// return first available interface and all ip addresses
	ifName, addrs = lookupDev()
	if p.device == "" {
		p.device = ifName
	}

	go func() {
		var counter int
		defer signal.Stop(s)
		defer close(s)
		defer close(c)

		handle, err = pcap.OpenLive(p.device, snapLen, promiscuous, timeout)
		if err != nil {
			log.Println(err.Error())
			return
		}
		if err := handle.SetBPFFilter(filter); err != nil {
			log.Println(err.Error())
			return
		}

		defer handle.Close()
		packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
		for loop {
			select {
			case packet := <-packetSource.Packets():
				c <- ParsePacketLayers(packet)
				if counter++; counter > count-1 {
					loop = false
				}
			case <-s:
				loop = false
			}
		}
	}()
	return c
}

// PrintPretty prints out the captured data
// to the stdout
func (p *Packet) PrintPretty() {
	switch p.Eth.EthernetType {
	case layers.EthernetTypeIPv4:
		p.PrintIPv4()
	case layers.EthernetTypeIPv6:
		p.PrintIPv6()
	case layers.EthernetTypeARP:
		// todo
	default:
		// todo
	}
}

// PrintIPv4 prints IPv4 packets
func (p *Packet) PrintIPv4() {

	src := czIP(p.IPv4.SrcIP, p.SrcHost, color.Bold)
	dst := czIP(p.IPv4.DstIP, p.DstHost, color.Bold)

	switch {
	case p.IPv4.Protocol == layers.IPProtocolTCP:
		log.Printf("%s %s:%s > %s:%s [%s], win %d, len: %d\n",
			czStr("IPv4/TCP ", color.FgBlack, color.BgWhite),
			src, p.TCP.SrcPort, dst, p.TCP.DstPort,
			czStr(p.flagsString(), color.Bold),
			p.TCP.Window, len(p.Payload))
	case p.IPv4.Protocol == layers.IPProtocolUDP:
		log.Printf("%s %s:%s > %s:%s , len: %d\n",
			czStr("IPv4/UDP ", color.FgBlack, color.BgCyan),
			src, p.UDP.SrcPort, dst, p.UDP.DstPort, len(p.Payload))
	case p.IPv4.Protocol == layers.IPProtocolICMPv4:
		log.Printf("%s %s > %s: %s id %d, seq %d, len: %d\n",
			czStr("IPv4/ICMP", color.FgBlack, color.BgYellow),
			src, dst, p.ICMPv4.TypeCode.String(), p.ICMPv4.Id,
			p.ICMPv4.Seq, len(p.Payload))
	}
}

// flags returns flags string except ack
func (p *Packet) flagsString() string {
	var (
		r     []string
		flags = []bool{p.TCP.FIN, p.TCP.SYN, p.TCP.RST, p.TCP.PSH, p.TCP.URG, p.TCP.ECE, p.TCP.NS}
		sign  = "FSRPUECN"
	)
	for i, flag := range flags {
		if flag {
			r = append(r, string(sign[i]))
		}
	}
	r = append(r, ".")
	return strings.Join(r, "")
}

// PrintIPv6 prints IPv6 packets
func (p *Packet) PrintIPv6() {

	src := czIP(p.IPv6.SrcIP, p.SrcHost, color.Bold)
	dst := czIP(p.IPv6.DstIP, p.DstHost, color.Bold)

	switch {
	case p.IPv6.NextHeader == layers.IPProtocolTCP:
		log.Printf("%s %s:%s > %s:%s, len: %d\n",
			czStr("IPv6/TCP ", color.FgBlack, color.BgHiWhite),
			src, p.TCP.SrcPort, dst, p.TCP.DstPort,
			len(p.Payload))
	case p.IPv6.NextHeader == layers.IPProtocolUDP:
		log.Printf("%s %s:%s > %s:%s, len: %d\n",
			czStr("IPv6/UDP ", color.FgBlack, color.BgHiCyan),
			src, p.UDP.SrcPort, dst, p.UDP.DstPort, len(p.Payload))
	case p.IPv6.NextHeader == layers.IPProtocolICMPv6:
		log.Printf("%s %s > %s: %s, len: %d\n",
			czStr("IPv6/ICMP", color.FgBlack, color.BgYellow),
			src, dst, p.ICMPv6.TypeCode.String(), len(p.Payload))
	}

}

func (writer logWriter) Write(bytes []byte) (int, error) {
	return fmt.Printf("%s %s", time.Now().Format("15:04:05.000"), string(bytes))
}

// ParsePacketLayers decodes layers
func ParsePacketLayers(packet gopacket.Packet) *Packet {
	var p Packet
	// Ethernet
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		p.Eth, _ = ethernetLayer.(*layers.Ethernet)
	}

	// IP Address V4
	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer != nil {
		p.IPv4, _ = ipLayer.(*layers.IPv4)
		p.SrcHost = lookup(p.IPv4.SrcIP)
		p.DstHost = lookup(p.IPv4.DstIP)
	} else {
		// IP Address V6
		ipLayer := packet.Layer(layers.LayerTypeIPv6)
		if ipLayer != nil {
			p.IPv6, _ = ipLayer.(*layers.IPv6)
			p.SrcHost = lookup(p.IPv6.SrcIP)
			p.DstHost = lookup(p.IPv6.DstIP)
		}
	}

	// TCP
	tcpLayer := packet.Layer(layers.LayerTypeTCP)
	if tcpLayer != nil {
		p.TCP, _ = tcpLayer.(*layers.TCP)
	} else {
		// UDP
		udpLayer := packet.Layer(layers.LayerTypeUDP)
		if udpLayer != nil {
			p.UDP, _ = udpLayer.(*layers.UDP)
		}
	}

	// ICMPv4
	icmpLayer := packet.Layer(layers.LayerTypeICMPv4)
	if icmpLayer != nil {
		p.ICMPv4, _ = icmpLayer.(*layers.ICMPv4)
	} else {
		// ICMPv6
		icmpv6Layer := packet.Layer(layers.LayerTypeICMPv6)
		if icmpv6Layer != nil {
			p.ICMPv6, _ = icmpv6Layer.(*layers.ICMPv6)
		}
	}

	// Application
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer != nil {
		p.Payload = string(applicationLayer.Payload())
	}

	// Check for errors
	if err := packet.ErrorLayer(); err != nil {
		//fmt.Println("Error decoding some part of the packet:", err)
		// todo
	}
	return &p
}

// czIP makes colorize IP/Host
func czIP(ip net.IP, host []string, attr ...color.Attribute) string {
	var (
		src string
	)
	if _, ok := addrs[ip.String()]; ok && !noColor {
		if len(host) > 0 {
			src = czStr(host[0], attr...)
		} else {
			src = czStr(ip.String(), attr...)
		}
	} else {
		if len(host) > 0 {
			src = host[0]
		} else {
			src = ip.String()
		}
	}
	return src
}

// czStr makes colorize string
func czStr(i string, attr ...color.Attribute) string {
	c := color.New(attr...).SprintfFunc()
	if !noColor {
		return c(i)
	}
	return i
}

func lookup(ip net.IP) []string {
	host, _ := net.LookupAddr(ip.String())
	return host
}

func lookupDev() (string, map[string]struct{}) {
	var (
		ips    = make(map[string]struct{}, 20)
		ifName = ""
	)
	ifs, _ := net.Interfaces()
	for _, i := range ifs {
		addrs, _ := i.Addrs()
		if i.Flags == 19 && ifName == "" {
			ifName = i.Name
		}
		for _, addr := range addrs {
			ips[strings.Split(addr.String(), "/")[0]] = struct{}{}
		}
	}
	return ifName, ips
}

func help() {
	fmt.Println(`
    usage:
          dump [-c count][-nc]
    options:
          -c count       Stop after receiving count packets (default: 1M)
          -nc            Shows dumps without color
    Example:
          dump tcp and port 443 -c 1000
	`)
}
<commit_msg>added devie table, update help<commit_after>// Package packet is a wrapper for GoPacket and sub packages
package packet

import (
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"strings"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"

	"github.com/fatih/color"
	"github.com/olekukonko/tablewriter"

	"github.com/mehrdadrad/mylg/cli"
)

// Packet holds all layers information
type Packet struct {
	// packet layers data
	Eth    *layers.Ethernet
	IPv4   *layers.IPv4
	IPv6   *layers.IPv6
	TCP    *layers.TCP
	UDP    *layers.UDP
	ICMPv4 *layers.ICMPv4
	ICMPv6 *layers.ICMPv6

	SrcHost []string
	DstHost []string
	Payload string
	// info
	device string
}

// logWriter represents custom writer
type logWriter struct {
}

var (
	snapLen     int32 = 6 * 1024
	promiscuous       = false
	err         error
	timeout     = 100 * time.Nanosecond
	handle      *pcap.Handle
	addrs       = make(map[string]struct{}, 20)
	ifName      string

	noColor, showIf bool
	filter          string
	count           int
)

// NewPacket creates an empty packet info
func NewPacket(args string) (*Packet, error) {
	var flag map[string]interface{}

	filter, flag = cli.Flag(args)

	// help
	if _, ok := flag["help"]; ok {
		help()
		return nil, nil
	}

	noColor = cli.SetFlag(flag, "nc", false).(bool)
	count = cli.SetFlag(flag, "c", 1000000).(int)
	showIf = cli.SetFlag(flag, "d", false).(bool)

	if showIf {
		printDev()
		return nil, nil
	}

	log.SetFlags(0)
	log.SetOutput(new(logWriter))

	return &Packet{
		device: cli.SetFlag(flag, "i", "").(string),
	}, nil
}

// Open is a loop over packets
func (p *Packet) Open() chan *Packet {
	var (
		c    = make(chan *Packet, 1)
		s    = make(chan os.Signal, 1)
		loop = true
	)
	// capture interrupt w/ s channel
	signal.Notify(s, os.Interrupt)

	// return first available interface and all ip addresses
	ifName, addrs = lookupDev()
	if p.device == "" {
		p.device = ifName
	}

	go func() {
		var counter int
		defer signal.Stop(s)
		defer close(s)
		defer close(c)

		handle, err = pcap.OpenLive(p.device, snapLen, promiscuous, timeout)
		if err != nil {
			log.Println(err.Error())
			return
		}
		if err := handle.SetBPFFilter(filter); err != nil {
			log.Println(err.Error())
			return
		}

		defer handle.Close()
		packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
		for loop {
			select {
			case packet := <-packetSource.Packets():
				c <- ParsePacketLayers(packet)
				if counter++; counter > count-1 {
					loop = false
				}
			case <-s:
				loop = false
			}
		}
	}()
	return c
}

// PrintPretty prints out the captured data
// to the stdout
func (p *Packet) PrintPretty() {
	switch p.Eth.EthernetType {
	case layers.EthernetTypeIPv4:
		p.PrintIPv4()
	case layers.EthernetTypeIPv6:
		p.PrintIPv6()
	case layers.EthernetTypeARP:
		// todo
	default:
		// todo
	}
}

// PrintIPv4 prints IPv4 packets
func (p *Packet) PrintIPv4() {

	src := czIP(p.IPv4.SrcIP, p.SrcHost, color.Bold)
	dst := czIP(p.IPv4.DstIP, p.DstHost, color.Bold)

	switch {
	case p.IPv4.Protocol == layers.IPProtocolTCP:
		log.Printf("%s %s:%s > %s:%s [%s], win %d, len: %d\n",
			czStr("IPv4/TCP ", color.FgBlack, color.BgWhite),
			src, p.TCP.SrcPort, dst, p.TCP.DstPort,
			czStr(p.flagsString(), color.Bold),
			p.TCP.Window, len(p.Payload))
	case p.IPv4.Protocol == layers.IPProtocolUDP:
		log.Printf("%s %s:%s > %s:%s , len: %d\n",
			czStr("IPv4/UDP ", color.FgBlack, color.BgCyan),
			src, p.UDP.SrcPort, dst, p.UDP.DstPort, len(p.Payload))
	case p.IPv4.Protocol == layers.IPProtocolICMPv4:
		log.Printf("%s %s > %s: %s id %d, seq %d, len: %d\n",
			czStr("IPv4/ICMP", color.FgBlack, color.BgYellow),
			src, dst, p.ICMPv4.TypeCode.String(), p.ICMPv4.Id,
			p.ICMPv4.Seq, len(p.Payload))
	}
}

// flags returns flags string except ack
func (p *Packet) flagsString() string {
	var (
		r     []string
		flags = []bool{p.TCP.FIN, p.TCP.SYN, p.TCP.RST, p.TCP.PSH, p.TCP.URG, p.TCP.ECE, p.TCP.NS}
		sign  = "FSRPUECN"
	)
	for i, flag := range flags {
		if flag {
			r = append(r, string(sign[i]))
		}
	}
	r = append(r, ".")
	return strings.Join(r, "")
}

// PrintIPv6 prints IPv6 packets
func (p *Packet) PrintIPv6() {

	src := czIP(p.IPv6.SrcIP, p.SrcHost, color.Bold)
	dst := czIP(p.IPv6.DstIP, p.DstHost, color.Bold)

	switch {
	case p.IPv6.NextHeader == layers.IPProtocolTCP:
		log.Printf("%s %s:%s > %s:%s, len: %d\n",
			czStr("IPv6/TCP ", color.FgBlack, color.BgHiWhite),
			src, p.TCP.SrcPort, dst, p.TCP.DstPort,
			len(p.Payload))
	case p.IPv6.NextHeader == layers.IPProtocolUDP:
		log.Printf("%s %s:%s > %s:%s, len: %d\n",
			czStr("IPv6/UDP ", color.FgBlack, color.BgHiCyan),
			src, p.UDP.SrcPort, dst, p.UDP.DstPort, len(p.Payload))
	case p.IPv6.NextHeader == layers.IPProtocolICMPv6:
		log.Printf("%s %s > %s: %s, len: %d\n",
			czStr("IPv6/ICMP", color.FgBlack, color.BgYellow),
			src, dst, p.ICMPv6.TypeCode.String(), len(p.Payload))
	}

}

func (writer logWriter) Write(bytes []byte) (int, error) {
	return fmt.Printf("%s %s", time.Now().Format("15:04:05.000"), string(bytes))
}

// ParsePacketLayers decodes layers
func ParsePacketLayers(packet gopacket.Packet) *Packet {
	var p Packet
	// Ethernet
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		p.Eth, _ = ethernetLayer.(*layers.Ethernet)
	}

	// IP Address V4
	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer != nil {
		p.IPv4, _ = ipLayer.(*layers.IPv4)
		p.SrcHost = lookup(p.IPv4.SrcIP)
		p.DstHost = lookup(p.IPv4.DstIP)
	} else {
		// IP Address V6
		ipLayer := packet.Layer(layers.LayerTypeIPv6)
		if ipLayer != nil {
			p.IPv6, _ = ipLayer.(*layers.IPv6)
			p.SrcHost = lookup(p.IPv6.SrcIP)
			p.DstHost = lookup(p.IPv6.DstIP)
		}
	}

	// TCP
	tcpLayer := packet.Layer(layers.LayerTypeTCP)
	if tcpLayer != nil {
		p.TCP, _ = tcpLayer.(*layers.TCP)
	} else {
		// UDP
		udpLayer := packet.Layer(layers.LayerTypeUDP)
		if udpLayer != nil {
			p.UDP, _ = udpLayer.(*layers.UDP)
		}
	}

	// ICMPv4
	icmpLayer := packet.Layer(layers.LayerTypeICMPv4)
	if icmpLayer != nil {
		p.ICMPv4, _ = icmpLayer.(*layers.ICMPv4)
	} else {
		// ICMPv6
		icmpv6Layer := packet.Layer(layers.LayerTypeICMPv6)
		if icmpv6Layer != nil {
			p.ICMPv6, _ = icmpv6Layer.(*layers.ICMPv6)
		}
	}

	// Application
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer != nil {
		p.Payload = string(applicationLayer.Payload())
	}

	// Check for errors
	if err := packet.ErrorLayer(); err != nil {
		//fmt.Println("Error decoding some part of the packet:", err)
		// todo
	}
	return &p
}

// czIP makes colorize IP/Host
func czIP(ip net.IP, host []string, attr ...color.Attribute) string {
	var (
		src string
	)
	if _, ok := addrs[ip.String()]; ok && !noColor {
		if len(host) > 0 {
			src = czStr(host[0], attr...)
		} else {
			src = czStr(ip.String(), attr...)
		}
	} else {
		if len(host) > 0 {
			src = host[0]
		} else {
			src = ip.String()
		}
	}
	return src
}

// czStr makes colorize string
func czStr(i string, attr ...color.Attribute) string {
	c := color.New(attr...).SprintfFunc()
	if !noColor {
		return c(i)
	}
	return i
}

func lookup(ip net.IP) []string {
	host, _ := net.LookupAddr(ip.String())
	return host
}

func lookupDev() (string, map[string]struct{}) {
	var (
		ips    = make(map[string]struct{}, 20)
		ifName = ""
	)
	ifs, _ := net.Interfaces()
	for _, i := range ifs {
		addrs, _ := i.Addrs()
		if i.Flags == 19 && ifName == "" {
			ifName = i.Name
		}
		for _, addr := range addrs {
			ips[strings.Split(addr.String(), "/")[0]] = struct{}{}
		}
	}
	return ifName, ips
}

func printDev() {
	var (
		status  = "DOWN"
		columns []string
	)

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "MAC", "Status", "MTU", "Multicast", "Broadcast", "PointToPoint", "Loopback"})
	ifs, _ := net.Interfaces()
	for _, i := range ifs {
		if strings.Contains(i.Flags.String(), "up") {
			status = "UP"
		} else {
			status = "DOWN"
		}
		columns = append(columns, i.Name, i.HardwareAddr.String(), status, fmt.Sprintf("%d", i.MTU))
		for _, flag := range []string{"multicast", "broadcast", "pointtopoint", "loopback"} {
			if strings.Contains(i.Flags.String(), flag) {
				columns = append(columns, "\u2713")
			} else {
				columns = append(columns, "")
			}
		}
		table.Append(columns)
		columns = columns[:0]
	}
	table.Render()
}

func help() {
	fmt.Println(`
    usage:
          dump [-c count][-i interface][-nc]
    options:
          -c count       Stop after receiving count packets (default: 1M)
          -i interface   Listen on specified interface (default: first non-loopback)
          -d             Print list of available interfaces
          -nc            Shows dumps without color
    Example:
          dump tcp and port 443 -c 1000
	`)
}
<|endoftext|>


<commit_before>package quic

import (
	"bytes"
	"sync"
	"sync/atomic"

	"github.com/lucas-clemente/quic-go/crypto"
	"github.com/lucas-clemente/quic-go/frames"
	"github.com/lucas-clemente/quic-go/protocol"
	"github.com/lucas-clemente/quic-go/utils"
)

type packedPacket struct {
	number     protocol.PacketNumber
	entropyBit bool
	raw        []byte
	payload    []byte
}

type packetPacker struct {
	connectionID protocol.ConnectionID
	aead         crypto.AEAD

	queuedFrames []frames.Frame
	mutex        sync.Mutex

	lastPacketNumber protocol.PacketNumber
}

func (p *packetPacker) AddFrame(f frames.Frame) {
	p.mutex.Lock()
	p.queuedFrames = append(p.queuedFrames, f)
	p.mutex.Unlock()
}

func (p *packetPacker) PackPacket() (*packedPacket, error) {
	p.mutex.Lock()
	defer p.mutex.Unlock() // TODO: Split up?

	if len(p.queuedFrames) == 0 {
		return nil, nil
	}

	payload, err := p.composeNextPayload()
	if err != nil {
		return nil, err
	}

	entropyBit, err := utils.RandomBit()
	if err != nil {
		return nil, err
	}
	if entropyBit {
		payload[0] = 1
	}

	currentPacketNumber := protocol.PacketNumber(atomic.AddUint64(
		(*uint64)(&p.lastPacketNumber),
		1,
	))
	var raw bytes.Buffer
	responsePublicHeader := PublicHeader{
		ConnectionID: p.connectionID,
		PacketNumber: currentPacketNumber,
	}
	if err := responsePublicHeader.WritePublicHeader(&raw); err != nil {
		return nil, err
	}

	ciphertext := p.aead.Seal(p.lastPacketNumber, raw.Bytes(), payload)
	raw.Write(ciphertext)

	if raw.Len() > protocol.MaxPacketSize {
		panic("internal inconsistency: packet too large")
	}

	return &packedPacket{
		number:     currentPacketNumber,
		entropyBit: entropyBit,
		raw:        raw.Bytes(),
		payload:    payload[1:],
	}, nil
}

func (p *packetPacker) composeNextPayload() ([]byte, error) {
	var payload bytes.Buffer
	payload.WriteByte(0) // The entropy bit is set in sendPayload

	for len(p.queuedFrames) > 0 {
		frame := p.queuedFrames[0]

		if payload.Len()-1 > protocol.MaxFrameSize {
			panic("internal inconsistency: packet payload too large")
		}

		// Does the frame fit into the remaining space?
		if payload.Len()-1+frame.MaxLength() > protocol.MaxFrameSize {
			return payload.Bytes(), nil
		}

		if streamframe, isStreamFrame := frame.(*frames.StreamFrame); isStreamFrame {
			// Split stream frames if necessary
			previousFrame := streamframe.MaybeSplitOffFrame(protocol.MaxFrameSize - (payload.Len() - 1))
			if previousFrame != nil {
				// Don't pop the queue, leave the modified frame in
				frame = previousFrame
			} else {
				p.queuedFrames = p.queuedFrames[1:]
			}
		} else {
			p.queuedFrames = p.queuedFrames[1:]
		}

		if err := frame.Write(&payload); err != nil {
			return nil, err
		}
	}
	return payload.Bytes(), nil
}
<commit_msg>fix a packet packer race<commit_after>package quic

import (
	"bytes"
	"sync"
	"sync/atomic"

	"github.com/lucas-clemente/quic-go/crypto"
	"github.com/lucas-clemente/quic-go/frames"
	"github.com/lucas-clemente/quic-go/protocol"
	"github.com/lucas-clemente/quic-go/utils"
)

type packedPacket struct {
	number     protocol.PacketNumber
	entropyBit bool
	raw        []byte
	payload    []byte
}

type packetPacker struct {
	connectionID protocol.ConnectionID
	aead         crypto.AEAD

	queuedFrames []frames.Frame
	mutex        sync.Mutex

	lastPacketNumber protocol.PacketNumber
}

func (p *packetPacker) AddFrame(f frames.Frame) {
	p.mutex.Lock()
	p.queuedFrames = append(p.queuedFrames, f)
	p.mutex.Unlock()
}

func (p *packetPacker) PackPacket() (*packedPacket, error) {
	p.mutex.Lock()
	defer p.mutex.Unlock() // TODO: Split up?

	if len(p.queuedFrames) == 0 {
		return nil, nil
	}

	payload, err := p.composeNextPayload()
	if err != nil {
		return nil, err
	}

	entropyBit, err := utils.RandomBit()
	if err != nil {
		return nil, err
	}
	if entropyBit {
		payload[0] = 1
	}

	currentPacketNumber := protocol.PacketNumber(atomic.AddUint64(
		(*uint64)(&p.lastPacketNumber),
		1,
	))
	var raw bytes.Buffer
	responsePublicHeader := PublicHeader{
		ConnectionID: p.connectionID,
		PacketNumber: currentPacketNumber,
	}
	if err := responsePublicHeader.WritePublicHeader(&raw); err != nil {
		return nil, err
	}

	ciphertext := p.aead.Seal(currentPacketNumber, raw.Bytes(), payload)
	raw.Write(ciphertext)

	if raw.Len() > protocol.MaxPacketSize {
		panic("internal inconsistency: packet too large")
	}

	return &packedPacket{
		number:     currentPacketNumber,
		entropyBit: entropyBit,
		raw:        raw.Bytes(),
		payload:    payload[1:],
	}, nil
}

func (p *packetPacker) composeNextPayload() ([]byte, error) {
	var payload bytes.Buffer
	payload.WriteByte(0) // The entropy bit is set in sendPayload

	for len(p.queuedFrames) > 0 {
		frame := p.queuedFrames[0]

		if payload.Len()-1 > protocol.MaxFrameSize {
			panic("internal inconsistency: packet payload too large")
		}

		// Does the frame fit into the remaining space?
		if payload.Len()-1+frame.MaxLength() > protocol.MaxFrameSize {
			return payload.Bytes(), nil
		}

		if streamframe, isStreamFrame := frame.(*frames.StreamFrame); isStreamFrame {
			// Split stream frames if necessary
			previousFrame := streamframe.MaybeSplitOffFrame(protocol.MaxFrameSize - (payload.Len() - 1))
			if previousFrame != nil {
				// Don't pop the queue, leave the modified frame in
				frame = previousFrame
			} else {
				p.queuedFrames = p.queuedFrames[1:]
			}
		} else {
			p.queuedFrames = p.queuedFrames[1:]
		}

		if err := frame.Write(&payload); err != nil {
			return nil, err
		}
	}
	return payload.Bytes(), nil
}
<|endoftext|>


<commit_before>package env

import (
	"flag"
	"fmt"
	"os"
)

var (
	appname string
	nodeid  string
)

func init() {
	flag.StringVar(&appname, "appname", "", "AppName of application. e.g. -appname=nekoq")
	flag.StringVar(&nodeid, "node", "", "Unique Node Id of application. e.g. -node=nekoq001")
	flag.Parse()
	if appname == "" {
		fmt.Fprintln(os.Stderr, "Please set AppName using flag '-appname'.")
		os.Exit(-100)
	}
	if nodeid == "" {
		fmt.Fprintln(os.Stderr, "Please set NodeId using flag '-node'.")
		os.Exit(-101)
	}
}
<commit_msg>provide function to force check appname and node flag<commit_after>package env

import (
	"flag"
	"fmt"
	"os"
)

var (
	appname string
	nodeid  string
)

func init() {
	flag.StringVar(&appname, "appname", "", "AppName of application. e.g. -appname=nekoq")
	flag.StringVar(&nodeid, "node", "", "Unique Node Id of application. e.g. -node=nekoq001")
	flag.Parse()
}

func EnsureEnvFlag() {
	if appname == "" {
		fmt.Fprintln(os.Stderr, "Please set AppName using flag '-appname'.")
		os.Exit(-100)
	}
	if nodeid == "" {
		fmt.Fprintln(os.Stderr, "Please set NodeId using flag '-node'.")
		os.Exit(-101)
	}
}
<|endoftext|>


<commit_before>package nodes

// iframe allowlist - set of domains allow to embed iframes in a codelab.
var IframeAllowlist = []string{
	"carto.com",
	"codepen.io",
	"dartlang.org",
	"github.com",
	"glitch.com",
	"google.com",
	"google.dev",
	"observablehq.com",
	"repl.it",
	"web.dev",
}

// NewIframeNode creates a new embedded iframe.
func NewIframeNode(url string) *IframeNode {
	return &IframeNode{
		node: node{typ: NodeIframe},
		URL:  url,
	}
}

// IframeNode is an embeddes iframe.
type IframeNode struct {
	node
	URL string
}

// Empty returns true if iframe's URL field is empty.
func (iframe *IframeNode) Empty() bool {
	return iframe.URL == ""
}
<commit_msg>Add a TODO to iframe.go<commit_after>package nodes

// iframe allowlist - set of domains allow to embed iframes in a codelab.
// TODO make this configurable somehow
var IframeAllowlist = []string{
	"carto.com",
	"codepen.io",
	"dartlang.org",
	"github.com",
	"glitch.com",
	"google.com",
	"google.dev",
	"observablehq.com",
	"repl.it",
	"web.dev",
}

// NewIframeNode creates a new embedded iframe.
func NewIframeNode(url string) *IframeNode {
	return &IframeNode{
		node: node{typ: NodeIframe},
		URL:  url,
	}
}

// IframeNode is an embeddes iframe.
type IframeNode struct {
	node
	URL string
}

// Empty returns true if iframe's URL field is empty.
func (iframe *IframeNode) Empty() bool {
	return iframe.URL == ""
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"go/build"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"

	"golang.org/x/tools/go/vcs"
	"golang.org/x/tools/refactor/importgraph"
)

func get(gopath, repo string) error {
	done := make(chan struct{})
	defer close(done)
	go progressSize("go get", filepath.Join(gopath, "src"), done)

	// As per https://groups.google.com/forum/#!topic/golang-nuts/N5apfenE4m4,
	// the arguments to “go get” are packages, not repositories. Hence, we
	// specify “gopkg/...” in order to cover all packages.
	// As a concrete example, github.com/jacobsa/util is a repository we want
	// to package into a single Debian package, and using “go get -d
	// github.com/jacobsa/util” fails because there are no buildable go files
	// in the top level of that repository.
	cmd := exec.Command("go", "get", "-d", "-t", repo+"/...")
	cmd.Stderr = os.Stderr
	cmd.Env = append([]string{
		"GO111MODULE=off",
		"GOPATH=" + gopath,
	}, passthroughEnv()...)
	return cmd.Run()
}

func removeVendor(gopath string) (found bool, _ error) {
	err := filepath.Walk(filepath.Join(gopath, "src"), func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			return nil // skip non-directories
		}
		if info.Name() != "vendor" {
			return nil
		}
		found = true
		if err := os.RemoveAll(path); err != nil {
			return fmt.Errorf("remove all: %w", err)
		}
		return filepath.SkipDir
	})
	return found, fmt.Errorf("walk: %w", err)
}

func estimate(importpath string) error {
	// construct a separate GOPATH in a temporary directory
	gopath, err := ioutil.TempDir("", "dh-make-golang")
	if err != nil {
		return fmt.Errorf("create temp dir: %w", err)
	}
	defer os.RemoveAll(gopath)

	if err := get(gopath, importpath); err != nil {
		return fmt.Errorf("go get: %w", err)
	}

	found, err := removeVendor(gopath)
	if err != nil {
		return fmt.Errorf("remove vendor: %w", err)
	}

	if found {
		// Fetch un-vendored dependencies
		if err := get(gopath, importpath); err != nil {
			return fmt.Errorf("fetch un-vendored: go get: %w", err)
		}
	}

	// Remove standard lib packages
	cmd := exec.Command("go", "list", "std")
	cmd.Stderr = os.Stderr
	cmd.Env = append([]string{
		"GO111MODULE=off",
		"GOPATH=" + gopath,
	}, passthroughEnv()...)

	out, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("go list std: args: %v; error: %w", cmd.Args, err)
	}
	stdlib := make(map[string]bool)
	for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
		stdlib[line] = true
	}

	stdlib["C"] = true // would fail resolving anyway

	// Filter out all already-packaged ones:
	golangBinaries, err := getGolangBinaries()
	if err != nil {
		return nil
	}

	build.Default.GOPATH = gopath
	forward, _, errors := importgraph.Build(&build.Default)
	if len(errors) > 0 {
		lines := make([]string, 0, len(errors))
		for importPath, err := range errors {
			lines = append(lines, fmt.Sprintf("%s: %v", importPath, err))
		}
		return fmt.Errorf("could not load packages: %v", strings.Join(lines, "\n"))
	}

	var lines []string
	seen := make(map[string]bool)
	rrseen := make(map[string]bool)
	node := func(importPath string, indent int) {
		rr, err := vcs.RepoRootForImportPath(importPath, false)
		if err != nil {
			log.Printf("Could not determine repo path for import path %q: %v\n", importPath, err)
			return
		}
		if rrseen[rr.Root] {
			return
		}
		rrseen[rr.Root] = true
		if _, ok := golangBinaries[rr.Root]; ok {
			return // already packaged in Debian
		}
		lines = append(lines, fmt.Sprintf("%s%s", strings.Repeat("  ", indent), rr.Root))
	}
	var visit func(x string, indent int)
	visit = func(x string, indent int) {
		if seen[x] {
			return
		}
		seen[x] = true
		if !stdlib[x] {
			node(x, indent)
		}
		for y := range forward[x] {
			visit(y, indent+1)
		}
	}

	keys := make([]string, 0, len(forward))
	for key := range forward {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	for _, key := range keys {
		if !strings.HasPrefix(key, importpath) {
			continue
		}
		if seen[key] {
			continue // already covered in a previous visit call
		}
		visit(key, 0)
	}

	if len(lines) == 0 {
		log.Printf("%s is already fully packaged in Debian", importpath)
		return nil
	}
	log.Printf("Bringing %s to Debian requires packaging the following Go packages:", importpath)
	for _, line := range lines {
		fmt.Println(line)
	}

	return nil
}

func execEstimate(args []string) {
	fs := flag.NewFlagSet("estimate", flag.ExitOnError)

	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s estimate <go-package-importpath>\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Estimates the work necessary to bring <go-package-importpath> into Debian\n"+
			"by printing all currently unpacked repositories.\n")
		fmt.Fprintf(os.Stderr, "Example: %s estimate github.com/Debian/dh-make-golang\n", os.Args[0])
	}

	err := fs.Parse(args)
	if err != nil {
		log.Fatalf("parse args: %s", err)
	}

	if fs.NArg() != 1 {
		fs.Usage()
		os.Exit(1)
	}

	// TODO: support the -git_revision flag

	if err := estimate(fs.Arg(0)); err != nil {
		log.Fatalf("estimate: %s", err)
	}
}
<commit_msg>estimate: Revert an error annotation<commit_after>package main

import (
	"flag"
	"fmt"
	"go/build"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"

	"golang.org/x/tools/go/vcs"
	"golang.org/x/tools/refactor/importgraph"
)

func get(gopath, repo string) error {
	done := make(chan struct{})
	defer close(done)
	go progressSize("go get", filepath.Join(gopath, "src"), done)

	// As per https://groups.google.com/forum/#!topic/golang-nuts/N5apfenE4m4,
	// the arguments to “go get” are packages, not repositories. Hence, we
	// specify “gopkg/...” in order to cover all packages.
	// As a concrete example, github.com/jacobsa/util is a repository we want
	// to package into a single Debian package, and using “go get -d
	// github.com/jacobsa/util” fails because there are no buildable go files
	// in the top level of that repository.
	cmd := exec.Command("go", "get", "-d", "-t", repo+"/...")
	cmd.Stderr = os.Stderr
	cmd.Env = append([]string{
		"GO111MODULE=off",
		"GOPATH=" + gopath,
	}, passthroughEnv()...)
	return cmd.Run()
}

func removeVendor(gopath string) (found bool, _ error) {
	err := filepath.Walk(filepath.Join(gopath, "src"), func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			return nil // skip non-directories
		}
		if info.Name() != "vendor" {
			return nil
		}
		found = true
		if err := os.RemoveAll(path); err != nil {
			return fmt.Errorf("remove all: %w", err)
		}
		return filepath.SkipDir
	})
	return found, err
}

func estimate(importpath string) error {
	// construct a separate GOPATH in a temporary directory
	gopath, err := ioutil.TempDir("", "dh-make-golang")
	if err != nil {
		return fmt.Errorf("create temp dir: %w", err)
	}
	defer os.RemoveAll(gopath)

	if err := get(gopath, importpath); err != nil {
		return fmt.Errorf("go get: %w", err)
	}

	found, err := removeVendor(gopath)
	if err != nil {
		return fmt.Errorf("remove vendor: %w", err)
	}

	if found {
		// Fetch un-vendored dependencies
		if err := get(gopath, importpath); err != nil {
			return fmt.Errorf("fetch un-vendored: go get: %w", err)
		}
	}

	// Remove standard lib packages
	cmd := exec.Command("go", "list", "std")
	cmd.Stderr = os.Stderr
	cmd.Env = append([]string{
		"GO111MODULE=off",
		"GOPATH=" + gopath,
	}, passthroughEnv()...)

	out, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("go list std: args: %v; error: %w", cmd.Args, err)
	}
	stdlib := make(map[string]bool)
	for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
		stdlib[line] = true
	}

	stdlib["C"] = true // would fail resolving anyway

	// Filter out all already-packaged ones:
	golangBinaries, err := getGolangBinaries()
	if err != nil {
		return nil
	}

	build.Default.GOPATH = gopath
	forward, _, errors := importgraph.Build(&build.Default)
	if len(errors) > 0 {
		lines := make([]string, 0, len(errors))
		for importPath, err := range errors {
			lines = append(lines, fmt.Sprintf("%s: %v", importPath, err))
		}
		return fmt.Errorf("could not load packages: %v", strings.Join(lines, "\n"))
	}

	var lines []string
	seen := make(map[string]bool)
	rrseen := make(map[string]bool)
	node := func(importPath string, indent int) {
		rr, err := vcs.RepoRootForImportPath(importPath, false)
		if err != nil {
			log.Printf("Could not determine repo path for import path %q: %v\n", importPath, err)
			return
		}
		if rrseen[rr.Root] {
			return
		}
		rrseen[rr.Root] = true
		if _, ok := golangBinaries[rr.Root]; ok {
			return // already packaged in Debian
		}
		lines = append(lines, fmt.Sprintf("%s%s", strings.Repeat("  ", indent), rr.Root))
	}
	var visit func(x string, indent int)
	visit = func(x string, indent int) {
		if seen[x] {
			return
		}
		seen[x] = true
		if !stdlib[x] {
			node(x, indent)
		}
		for y := range forward[x] {
			visit(y, indent+1)
		}
	}

	keys := make([]string, 0, len(forward))
	for key := range forward {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	for _, key := range keys {
		if !strings.HasPrefix(key, importpath) {
			continue
		}
		if seen[key] {
			continue // already covered in a previous visit call
		}
		visit(key, 0)
	}

	if len(lines) == 0 {
		log.Printf("%s is already fully packaged in Debian", importpath)
		return nil
	}
	log.Printf("Bringing %s to Debian requires packaging the following Go packages:", importpath)
	for _, line := range lines {
		fmt.Println(line)
	}

	return nil
}

func execEstimate(args []string) {
	fs := flag.NewFlagSet("estimate", flag.ExitOnError)

	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s estimate <go-package-importpath>\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Estimates the work necessary to bring <go-package-importpath> into Debian\n"+
			"by printing all currently unpacked repositories.\n")
		fmt.Fprintf(os.Stderr, "Example: %s estimate github.com/Debian/dh-make-golang\n", os.Args[0])
	}

	err := fs.Parse(args)
	if err != nil {
		log.Fatalf("parse args: %s", err)
	}

	if fs.NArg() != 1 {
		fs.Usage()
		os.Exit(1)
	}

	// TODO: support the -git_revision flag

	if err := estimate(fs.Arg(0)); err != nil {
		log.Fatalf("estimate: %s", err)
	}
}
<|endoftext|>