<commit_before>package cli

import (
	"encoding/json"
	"fmt"
	"os"
	"os/user"
	"reflect"
	"strconv"
	"strings"
)

var defaultConfig = `{
	"ping" : {
		"timeout" : "2s",
		"interval": "1s",
		"count":	4
	},
	"hping" : {
		"timeout"  : "2s",
		"method"   : "HEAD",
		"data"	   : "mylg",
		"count"	   : 5
	},
	"web" : {
		"port"	   : 8080,
		"address"  : "127.0.0.1"
	},
	"scan" : {
		"port"     : "1-500"
	}
}`

// Config represents configuration
type Config struct {
	Ping  Ping  `json:"ping"`
	Hping HPing `json:"hping"`
	Web   Web   `json:"web"`
	Scan  Scan  `json:"scan"`
}

// Ping represents ping command options
type Ping struct {
	Timeout  string `json:"timeout"`
	Interval string `json:"interval"`
	Count    int    `json:"count"`
}

// HPing represents ping command options
type HPing struct {
	Timeout string `json:"timeout"`
	Method  string `json:"method"`
	Data    string `json:"data"`
	Count   int    `json:"count"`
}

// Web represents web command options
type Web struct {
	Port    int    `json:port`
	Address string `json:address`
}

// Scan represents scan command options
type Scan struct {
	Port string `json:port`
}

// UpdateConfig
func WriteConfig(cfg Config) error {
	f, err := cfgFile()
	if err != nil {
		return err
	}

	h, err := os.Create(f)
	if err != nil {
		return err
	}

	b, err := json.Marshal(cfg)
	if err != nil {
		return err
	}
	_, err = h.Write(b)
	if err != nil {
		return err
	}
	h.Close()

	return nil
}

// UpgradeConfig adds / removes new command(s)/option(s)
func UpgradeConfig() {
	// TODO
	var conf map[string]interface{}
	b := make([]byte, 2048)
	f, err := cfgFile()
	if err != nil {

	}
	h, err := os.Open(f)
	n, _ := h.Read(b)
	b = b[:n]

	json.Unmarshal(b, &conf)
	if v, ok := conf["ping"].(interface{}); ok {
		if _, ok = v.(map[string]interface{})["timeout"]; !ok {
			// there is new option
		}
	} else {
		// there is new command
	}

}

// LoadConfig loads configuration
func LoadConfig() Config {
	var cfg Config

	cfg = ReadConfig()

	return cfg
}

// InitConfig creates new config file
func InitConfig(f string) ([]byte, error) {
	h, err := os.Create(f)
	if err != nil {
		return []byte(""), err
	}

	h.Chmod(os.FileMode(int(0600)))
	h.WriteString(defaultConfig)
	h.Close()

	return []byte(defaultConfig), nil
}

// ReadConfig reads configuration from existing
// or default configuration
func ReadConfig() Config {
	var (
		b    = make([]byte, 2048)
		conf Config
		err  error
	)
	f, err := cfgFile()
	if err != nil {

	}

	h, err := os.Open(f)

	if err != nil {
		switch {
		case os.IsNotExist(err):
			if b, err = InitConfig(f); err != nil {
				println(err.Error())
			}
		case os.IsPermission(err):
			println("cannot read configuration file due to insufficient permissions")
			b = []byte(defaultConfig)
		default:
			println(err.Error())
			b = []byte(defaultConfig)
		}
	} else {
		n, _ := h.Read(b)
		b = b[:n]
	}

	err = json.Unmarshal(b, &conf)
	if err != nil {
		println(err.Error())
		b = []byte(defaultConfig)
		json.Unmarshal(b, &conf)
	}

	return conf
}

// ReadDefaultConfig returns default configuration
func ReadDefaultConfig() (Config, error) {
	var (
		b    = make([]byte, 2048)
		conf Config
	)
	b = []byte(defaultConfig)
	err := json.Unmarshal(b, &conf)
	return conf, err
}

// cfgFile returns config file
func cfgFile() (string, error) {
	user, err := user.Current()
	if err != nil {
		return "", err
	}
	return user.HomeDir + "/.mylg.config", nil
}

// SetConfig handles update option's value
func SetConfig(args string, s *Config) {
	var (
		v     reflect.Value
		i     int64
		float float64
		err   error
	)

	args = strings.ToLower(args)
	f := strings.Fields(args)
	if len(f) < 1 {
		helpSet()
		return
	}

	v = reflect.ValueOf(s)
	v = reflect.Indirect(v)
	v = v.FieldByName(strings.Title(f[0]))

	if v.IsValid() {
		if i, err = strconv.ParseInt(f[2], 10, 64); err == nil {
			// integer
			err = SetValue(v.Addr(), strings.Title(f[1]), i)
		} else if float, err = strconv.ParseFloat(f[2], 64); err == nil {
			// float
			err = SetValue(v.Addr(), strings.Title(f[1]), float)
		} else {
			// string
			err = SetValue(v.Addr(), strings.Title(f[1]), f[2])
		}
	} else {
		err = fmt.Errorf("invalid")
	}

	if err != nil {
		println(err.Error())
	} else {
		if err = WriteConfig(*s); err != nil {
			println(err.Error())
		}
	}

}

// SetConfig set optioni's value
func SetValue(v reflect.Value, rec string, val interface{}) error {

	if v.Kind() != reflect.Ptr {
		return fmt.Errorf("not a pointer value")
	}

	v = reflect.Indirect(v)
	switch v.Kind() {
	case reflect.Int:
		if value, ok := val.(int64); ok {
			v.SetInt(value)
		} else {
			return fmt.Errorf("the value should be integer")
		}
	case reflect.Float64:
		if value, ok := val.(float64); ok {
			v.SetFloat(value)
		} else {
			return fmt.Errorf("the value should be float")
		}
	case reflect.String:
		if value, ok := val.(string); ok {
			v.SetString(value)
		} else {
			return fmt.Errorf("the value shouldn't be number")
		}
	case reflect.Struct:
		for i := 0; i < v.NumField(); i++ {
			if v.Type().Field(i).Name == rec {
				err := SetValue(v.Field(i).Addr(), rec, val)
				if err != nil {
					return err
				}
			}
		}
	}
	return nil
}

// ShowConfig prints the configuration
func ShowConfig(s *Config) {
	var v reflect.Value

	v = reflect.ValueOf(s)
	v = reflect.Indirect(v)

	for i := 0; i < v.NumField(); i++ {
		cmd := v.Type().Field(i).Name
		cmd = strings.ToLower(cmd)

		vv := v.Field(i).Addr()
		vv = reflect.Indirect(vv)

		for j := 0; j < vv.NumField(); j++ {
			subCmd := vv.Type().Field(j).Name
			subCmd = strings.ToLower(subCmd)
			value := vv.Field(j)
			fmt.Printf("set %-8s %-10s %v\n", cmd, subCmd, value)
		}
	}
}

// helpSet shows set command
func helpSet() {
	println(`
          usage:
               set command option value
          example:
               set ping timeout 2s
	`)

}
<commit_msg>upgrade config<commit_after>package cli

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"os/user"
	"reflect"
	"strconv"
	"strings"
)

var defaultConfig = `{
	"ping" : {
		"timeout" : "2s",
		"interval": "1s",
		"count":	4
	},
	"hping" : {
		"timeout"  : "2s",
		"method"   : "HEAD",
		"data"	   : "mylg",
		"count"	   : 5
	},
	"web" : {
		"port"	   : 8080,
		"address"  : "127.0.0.1"
	},
	"scan" : {
		"port"     : "1-500"
	}
}`

// Config represents configuration
type Config struct {
	Ping  Ping  `json:"ping"`
	Hping HPing `json:"hping"`
	Web   Web   `json:"web"`
	Scan  Scan  `json:"scan"`
}

// Ping represents ping command options
type Ping struct {
	Timeout  string `json:"timeout"`
	Interval string `json:"interval"`
	Count    int    `json:"count"`
}

// HPing represents ping command options
type HPing struct {
	Timeout string `json:"timeout"`
	Method  string `json:"method"`
	Data    string `json:"data"`
	Count   int    `json:"count"`
}

// Web represents web command options
type Web struct {
	Port    int    `json:port`
	Address string `json:address`
}

// Scan represents scan command options
type Scan struct {
	Port string `json:port`
}

// UpdateConfig
func WriteConfig(cfg Config) error {
	f, err := cfgFile()
	if err != nil {
		return err
	}

	h, err := os.Create(f)
	if err != nil {
		return err
	}

	b, err := json.Marshal(cfg)
	if err != nil {
		return err
	}
	_, err = h.Write(bytes.ToLower(b))
	if err != nil {
		return err
	}
	h.Close()

	return nil
}

// GetOptions returns option(s)/value(s) for specific command
func GetOptions(s interface{}, key string) ([]string, []interface{}) {
	var (
		opts []string
		vals []interface{}
	)
	v := reflect.ValueOf(s)
	t := v.Type()

	for i := 0; i < v.NumField(); i++ {
		if t.Field(i).Name == key {
			f := v.Field(i)
			ft := f.Type()
			for j := 0; j < f.NumField(); j++ {
				vals = append(vals, f.Field(j))
				opts = append(opts, ft.Field(j).Name)
			}
			break
		}
	}
	return opts, vals
}

// GetCMDNames returns command line names
func GetCMDNames(s interface{}) []string {
	var fields []string

	v := reflect.ValueOf(s)
	t := v.Type()

	for i := 0; i < t.NumField(); i++ {
		fields = append(fields, t.Field(i).Name)
	}
	return fields
}

// UpgradeConfig adds / removes new command(s)/option(s)
func UpgradeConfig(cfg *Config) {
	var (
		conf  map[string]interface{}
		cConf Config
	)
	b := make([]byte, 2048)
	f, err := cfgFile()
	if err != nil {

	}
	h, err := os.Open(f)
	n, _ := h.Read(b)
	b = b[:n]
	// load saved/old config to conf
	json.Unmarshal(b, &conf)
	// load default config to cConf
	json.Unmarshal([]byte(defaultConfig), &cConf)

	for _, cmd := range GetCMDNames(cConf) {
		opts, vals := GetOptions(cConf, cmd)
		for i, opt := range opts {
			if v, ok := conf[strings.ToLower(cmd)].(interface{}); ok {
				if _, ok = v.(map[string]interface{})[strings.ToLower(opt)]; !ok {
					args := fmt.Sprintf("%s %s %v", cmd, opt, vals[i])
					SetConfig(args, cfg)
				}
			} else {
				//TODO:
				// there is new command
			}
		}
	}
}

// LoadConfig loads configuration
func LoadConfig() Config {
	var cfg Config

	cfg = ReadConfig()
	UpgradeConfig(&cfg)
	return cfg
}

// InitConfig creates new config file
func InitConfig(f string) ([]byte, error) {
	h, err := os.Create(f)
	if err != nil {
		return []byte(""), err
	}

	h.Chmod(os.FileMode(int(0600)))
	h.WriteString(defaultConfig)
	h.Close()

	return []byte(defaultConfig), nil
}

// ReadConfig reads configuration from existing
// or default configuration
func ReadConfig() Config {
	var (
		b    = make([]byte, 2048)
		conf Config
		err  error
	)
	f, err := cfgFile()
	if err != nil {

	}

	h, err := os.Open(f)

	if err != nil {
		switch {
		case os.IsNotExist(err):
			if b, err = InitConfig(f); err != nil {
				println(err.Error())
			}
		case os.IsPermission(err):
			println("cannot read configuration file due to insufficient permissions")
			b = []byte(defaultConfig)
		default:
			println(err.Error())
			b = []byte(defaultConfig)
		}
	} else {
		n, _ := h.Read(b)
		b = b[:n]
	}

	err = json.Unmarshal(b, &conf)
	if err != nil {
		println(err.Error())
		b = []byte(defaultConfig)
		json.Unmarshal(b, &conf)
	}

	return conf
}

// ReadDefaultConfig returns default configuration
func ReadDefaultConfig() (Config, error) {
	var (
		b    = make([]byte, 2048)
		conf Config
	)
	b = []byte(defaultConfig)
	err := json.Unmarshal(b, &conf)
	return conf, err
}

// cfgFile returns config file
func cfgFile() (string, error) {
	user, err := user.Current()
	if err != nil {
		return "", err
	}
	return user.HomeDir + "/.mylg.config", nil
}

// SetConfig handles update option's value
func SetConfig(args string, s *Config) {
	var (
		v     reflect.Value
		i     int64
		float float64
		err   error
	)

	args = strings.ToLower(args)
	f := strings.Fields(args)
	if len(f) < 1 {
		helpSet()
		return
	}

	v = reflect.ValueOf(s)
	v = reflect.Indirect(v)
	v = v.FieldByName(strings.Title(f[0]))

	if v.IsValid() {
		if i, err = strconv.ParseInt(f[2], 10, 64); err == nil {
			// integer
			err = SetValue(v.Addr(), strings.Title(f[1]), i)
		} else if float, err = strconv.ParseFloat(f[2], 64); err == nil {
			// float
			err = SetValue(v.Addr(), strings.Title(f[1]), float)
		} else {
			// string
			err = SetValue(v.Addr(), strings.Title(f[1]), f[2])
		}
	} else {
		err = fmt.Errorf("invalid")
	}

	if err != nil {
		println(err.Error())
	} else {
		if err = WriteConfig(*s); err != nil {
			println(err.Error())
		}
	}

}

// SetConfig set optioni's value
func SetValue(v reflect.Value, rec string, val interface{}) error {

	if v.Kind() != reflect.Ptr {
		return fmt.Errorf("not a pointer value")
	}

	v = reflect.Indirect(v)
	switch v.Kind() {
	case reflect.Int:
		if value, ok := val.(int64); ok {
			v.SetInt(value)
		} else {
			return fmt.Errorf("the value should be integer")
		}
	case reflect.Float64:
		if value, ok := val.(float64); ok {
			v.SetFloat(value)
		} else {
			return fmt.Errorf("the value should be float")
		}
	case reflect.String:
		if value, ok := val.(string); ok {
			v.SetString(value)
		} else {
			return fmt.Errorf("the value shouldn't be number")
		}
	case reflect.Struct:
		for i := 0; i < v.NumField(); i++ {
			if v.Type().Field(i).Name == rec {
				err := SetValue(v.Field(i).Addr(), rec, val)
				if err != nil {
					return err
				}
			}
		}
	}
	return nil
}

// ShowConfig prints the configuration
func ShowConfig(s *Config) {
	var v reflect.Value

	v = reflect.ValueOf(s)
	v = reflect.Indirect(v)

	for i := 0; i < v.NumField(); i++ {
		cmd := v.Type().Field(i).Name
		cmd = strings.ToLower(cmd)

		vv := v.Field(i).Addr()
		vv = reflect.Indirect(vv)

		for j := 0; j < vv.NumField(); j++ {
			subCmd := vv.Type().Field(j).Name
			subCmd = strings.ToLower(subCmd)
			value := vv.Field(j)
			fmt.Printf("set %-8s %-10s %v\n", cmd, subCmd, value)
		}
	}
}

// helpSet shows set command
func helpSet() {
	println(`
          usage:
               set command option value
          example:
               set ping timeout 2s
	`)

}
<|endoftext|>


<commit_before>package lint

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/golang/protobuf/v2/reflect/protoreflect"
	descriptorpb "github.com/golang/protobuf/v2/types/descriptor"
)

var (
	// ErrPathNotFound is the returned error when a path is not found.
	ErrPathNotFound = errors.New("source: path not found")
	// ErrSourceInfoNotAvailable is the returned error when creating a source
	// but the source information is not available.
	ErrSourceInfoNotAvailable = errors.New("source: source information is not available")
)

// Comments describes a collection of comments associate with an element,
// which contains leading, trailing, and leading-detached comments, in a
// source code file.
type Comments struct {
	LeadingComments         string
	TrailingComments        string
	LeadingDetachedComments []string
}

const sep = ","

// locPath represents a path in the SourceCodeInfo_Location,
// and this serves as a map key.
// It's a string representation of a slice because slices
// cannot be map keys.
// Representation: integers separated by commas. No spaces.
// Example: [4, 3, 2, 7] --> "4,3,2,7"
// See descriptor.proto for more explanation of semantics.
type locPath string

// newLocPath return a locPath from a list of index.
func newLocPath(p ...int) locPath {
	a := []string{}
	for _, i := range p {
		a = append(a, strconv.Itoa(i))
	}
	return locPath(strings.Join(a, sep))
}

// buildLocPathMap creates a map of locPath to *descriptorpb.SourceCodeInfo_Location
// from *descriptorpb.SourceCodeInfo.
func buildLocPathMap(sci *descriptorpb.SourceCodeInfo) map[locPath]*descriptorpb.SourceCodeInfo_Location {
	m := make(map[locPath]*descriptorpb.SourceCodeInfo_Location)
	if sci == nil {
		return m
	}

	for _, loc := range sci.GetLocation() {
		var path []int
		for _, v := range loc.GetPath() {
			path = append(path, int(v))
		}
		m[newLocPath(path...)] = loc
	}
	return m
}

// DescriptorSource represents a map of locPath to *descriptorpb.SourceCodeInfo_Location.
type DescriptorSource struct {
	m map[locPath]*descriptorpb.SourceCodeInfo_Location
}

// newDescriptorSource creates a new DescriptorSource from a FileDescriptorProto.
// If source code information is not available, returns (nil, ErrSourceInfoNotAvailable).
func newDescriptorSource(f *descriptorpb.FileDescriptorProto) (DescriptorSource, error) {
	if f.GetSourceCodeInfo() == nil {
		return DescriptorSource{}, ErrSourceInfoNotAvailable
	}
	return DescriptorSource{m: buildLocPathMap(f.GetSourceCodeInfo())}, nil
}

// findLocationByPath returns a `Location` if found in the map,
// and (nil, ErrPathNotFound) if not found.
func (s DescriptorSource) findLocationByPath(path []int) (*Location, error) {
	l := s.m[newLocPath(path...)]
	if l == nil {
		return nil, ErrPathNotFound
	}
	return newLocationFromSpan(l.GetSpan())
}

// findCommentsByPath returns a `Comments` for the path. If not found, returns
// (nil, ErrCommentsNotFound).
func (s DescriptorSource) findCommentsByPath(path []int) (Comments, error) {
	l := s.m[newLocPath(path...)]
	if l == nil {
		return Comments{}, ErrPathNotFound
	}
	return Comments{
		LeadingComments:         l.GetLeadingComments(),
		TrailingComments:        l.GetTrailingComments(),
		LeadingDetachedComments: l.GetLeadingDetachedComments(),
	}, nil
}

func newLocationFromSpan(span []int32) (*Location, error) {
	if len(span) == 4 {
		start := NewPosition(int(span[0]), int(span[1]))
		end := NewPosition(int(span[2]), int(span[3]))
		return NewLocation(start, end), nil
	}

	if len(span) == 3 {
		start := NewPosition(int(span[0]), int(span[1]))
		end := NewPosition(int(span[0]), int(span[2]))
		return NewLocation(start, end), nil
	}

	return nil, fmt.Errorf("source: %v is not a valid span to create a Location", span)
}

// SyntaxLocation returns the location of the syntax definition.
func (s DescriptorSource) SyntaxLocation() (*Location, error) {
	return s.findLocationByPath([]int{syntaxTag})
}

// SyntaxComments returns the comments of the syntax definition.
func (s DescriptorSource) SyntaxComments() (Comments, error) {
	return s.findCommentsByPath([]int{syntaxTag})
}

// DescriptorLocation returns a `Location` for the given descriptor.
// If not found, returns (nil, ErrPathNotFound).
func (s DescriptorSource) DescriptorLocation(d protoreflect.Descriptor) (*Location, error) {
	return s.findLocationByPath(getPath(d))
}

func getPath(d protoreflect.Descriptor) []int {
	path := []int{}
	for p := d; !isFileDescriptor(p); p, _ = p.Parent() {
		path = append(path, p.Index(), getDescriptorTag(p))
	}
	reverseInts(path)
	return path
}

const syntaxTag = 12

var enumTagInFile = 5
var enumTagInMessage = 4
var enumValueTag = 2
var fieldTag = 2
var extensionTagInFile = 7
var extensionTagInMessage = 6
var messageTagInFile = 4
var nestedMessageTag = 3
var oneofTag = 8
var serviceTag = 6
var methodTag = 2

func getDescriptorTag(d protoreflect.Descriptor) int {
	switch d.(type) {
	case protoreflect.EnumDescriptor:
		if isTopLevelDescriptor(d) {
			return enumTagInFile
		}
		return enumTagInMessage
	case protoreflect.EnumValueDescriptor:
		return enumValueTag
	case protoreflect.FieldDescriptor:
		if isFieldExtension(d) {
			if isTopLevelDescriptor(d) {
				return extensionTagInFile
			}
			return extensionTagInMessage
		}
		return fieldTag
	case protoreflect.MessageDescriptor:
		if isTopLevelDescriptor(d) {
			return messageTagInFile
		}
		return nestedMessageTag
	case protoreflect.MethodDescriptor:
		return methodTag
	case protoreflect.OneofDescriptor:
		return oneofTag
	case protoreflect.ServiceDescriptor:
		return serviceTag
	default:
		return 0
	}
}

func isFieldExtension(d protoreflect.Descriptor) bool {
	f, ok := d.(protoreflect.FieldDescriptor)
	return ok && f.ExtendedType() != nil
}

func isFileDescriptor(d protoreflect.Descriptor) bool {
	_, ok := d.(protoreflect.FileDescriptor)
	return ok
}

func isTopLevelDescriptor(d protoreflect.Descriptor) bool {
	p, _ := d.Parent()
	_, ok := p.(protoreflect.FileDescriptor)
	return ok
}

// DescriptorComments returns a `Comments` for the given descriptor.
// If not found, returns (nil, ErrCommentsNotFound).
func (s DescriptorSource) DescriptorComments(d protoreflect.Descriptor) (Comments, error) {
	return s.findCommentsByPath(getPath(d))
}

func reverseInts(a []int) {
	for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
		a[left], a[right] = a[right], a[left]
	}
}

// IsRuleDisabled check if a rule is disabled for a descriptor
// in the comments.
func (s DescriptorSource) IsRuleDisabled(name RuleName, d protoreflect.Descriptor) bool {
	comments, err := s.DescriptorComments(d)
	if err != nil {
		return true
	}

	commentsToCheck := []string{
		comments.LeadingComments,
		comments.TrailingComments,
	}
	commentsToCheck = append(commentsToCheck, s.fileComments().LeadingDetachedComments...)

	return stringsContains(commentsToCheck, ruleDisablingComment(name))
}

func stringsContains(comments []string, s string) bool {
	for _, c := range comments {
		if strings.Contains(c, s) {
			return true
		}
	}
	return false
}

func ruleDisablingComment(name RuleName) string {
	return fmt.Sprintf("(-- api-linter: %v =disabled --)", name)
}

func (s DescriptorSource) fileComments() Comments {
	comments, _ := s.SyntaxComments()
	return comments
}
<commit_msg>Fixed format string<commit_after>package lint

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/golang/protobuf/v2/reflect/protoreflect"
	descriptorpb "github.com/golang/protobuf/v2/types/descriptor"
)

var (
	// ErrPathNotFound is the returned error when a path is not found.
	ErrPathNotFound = errors.New("source: path not found")
	// ErrSourceInfoNotAvailable is the returned error when creating a source
	// but the source information is not available.
	ErrSourceInfoNotAvailable = errors.New("source: source information is not available")
)

// Comments describes a collection of comments associate with an element,
// which contains leading, trailing, and leading-detached comments, in a
// source code file.
type Comments struct {
	LeadingComments         string
	TrailingComments        string
	LeadingDetachedComments []string
}

const sep = ","

// locPath represents a path in the SourceCodeInfo_Location,
// and this serves as a map key.
// It's a string representation of a slice because slices
// cannot be map keys.
// Representation: integers separated by commas. No spaces.
// Example: [4, 3, 2, 7] --> "4,3,2,7"
// See descriptor.proto for more explanation of semantics.
type locPath string

// newLocPath return a locPath from a list of index.
func newLocPath(p ...int) locPath {
	a := []string{}
	for _, i := range p {
		a = append(a, strconv.Itoa(i))
	}
	return locPath(strings.Join(a, sep))
}

// buildLocPathMap creates a map of locPath to *descriptorpb.SourceCodeInfo_Location
// from *descriptorpb.SourceCodeInfo.
func buildLocPathMap(sci *descriptorpb.SourceCodeInfo) map[locPath]*descriptorpb.SourceCodeInfo_Location {
	m := make(map[locPath]*descriptorpb.SourceCodeInfo_Location)
	if sci == nil {
		return m
	}

	for _, loc := range sci.GetLocation() {
		var path []int
		for _, v := range loc.GetPath() {
			path = append(path, int(v))
		}
		m[newLocPath(path...)] = loc
	}
	return m
}

// DescriptorSource represents a map of locPath to *descriptorpb.SourceCodeInfo_Location.
type DescriptorSource struct {
	m map[locPath]*descriptorpb.SourceCodeInfo_Location
}

// newDescriptorSource creates a new DescriptorSource from a FileDescriptorProto.
// If source code information is not available, returns (nil, ErrSourceInfoNotAvailable).
func newDescriptorSource(f *descriptorpb.FileDescriptorProto) (DescriptorSource, error) {
	if f.GetSourceCodeInfo() == nil {
		return DescriptorSource{}, ErrSourceInfoNotAvailable
	}
	return DescriptorSource{m: buildLocPathMap(f.GetSourceCodeInfo())}, nil
}

// findLocationByPath returns a `Location` if found in the map,
// and (nil, ErrPathNotFound) if not found.
func (s DescriptorSource) findLocationByPath(path []int) (*Location, error) {
	l := s.m[newLocPath(path...)]
	if l == nil {
		return nil, ErrPathNotFound
	}
	return newLocationFromSpan(l.GetSpan())
}

// findCommentsByPath returns a `Comments` for the path. If not found, returns
// (nil, ErrCommentsNotFound).
func (s DescriptorSource) findCommentsByPath(path []int) (Comments, error) {
	l := s.m[newLocPath(path...)]
	if l == nil {
		return Comments{}, ErrPathNotFound
	}
	return Comments{
		LeadingComments:         l.GetLeadingComments(),
		TrailingComments:        l.GetTrailingComments(),
		LeadingDetachedComments: l.GetLeadingDetachedComments(),
	}, nil
}

func newLocationFromSpan(span []int32) (*Location, error) {
	if len(span) == 4 {
		start := NewPosition(int(span[0]), int(span[1]))
		end := NewPosition(int(span[2]), int(span[3]))
		return NewLocation(start, end), nil
	}

	if len(span) == 3 {
		start := NewPosition(int(span[0]), int(span[1]))
		end := NewPosition(int(span[0]), int(span[2]))
		return NewLocation(start, end), nil
	}

	return nil, fmt.Errorf("source: %v is not a valid span to create a Location", span)
}

// SyntaxLocation returns the location of the syntax definition.
func (s DescriptorSource) SyntaxLocation() (*Location, error) {
	return s.findLocationByPath([]int{syntaxTag})
}

// SyntaxComments returns the comments of the syntax definition.
func (s DescriptorSource) SyntaxComments() (Comments, error) {
	return s.findCommentsByPath([]int{syntaxTag})
}

// DescriptorLocation returns a `Location` for the given descriptor.
// If not found, returns (nil, ErrPathNotFound).
func (s DescriptorSource) DescriptorLocation(d protoreflect.Descriptor) (*Location, error) {
	return s.findLocationByPath(getPath(d))
}

func getPath(d protoreflect.Descriptor) []int {
	path := []int{}
	for p := d; !isFileDescriptor(p); p, _ = p.Parent() {
		path = append(path, p.Index(), getDescriptorTag(p))
	}
	reverseInts(path)
	return path
}

const syntaxTag = 12

var enumTagInFile = 5
var enumTagInMessage = 4
var enumValueTag = 2
var fieldTag = 2
var extensionTagInFile = 7
var extensionTagInMessage = 6
var messageTagInFile = 4
var nestedMessageTag = 3
var oneofTag = 8
var serviceTag = 6
var methodTag = 2

func getDescriptorTag(d protoreflect.Descriptor) int {
	switch d.(type) {
	case protoreflect.EnumDescriptor:
		if isTopLevelDescriptor(d) {
			return enumTagInFile
		}
		return enumTagInMessage
	case protoreflect.EnumValueDescriptor:
		return enumValueTag
	case protoreflect.FieldDescriptor:
		if isFieldExtension(d) {
			if isTopLevelDescriptor(d) {
				return extensionTagInFile
			}
			return extensionTagInMessage
		}
		return fieldTag
	case protoreflect.MessageDescriptor:
		if isTopLevelDescriptor(d) {
			return messageTagInFile
		}
		return nestedMessageTag
	case protoreflect.MethodDescriptor:
		return methodTag
	case protoreflect.OneofDescriptor:
		return oneofTag
	case protoreflect.ServiceDescriptor:
		return serviceTag
	default:
		return 0
	}
}

func isFieldExtension(d protoreflect.Descriptor) bool {
	f, ok := d.(protoreflect.FieldDescriptor)
	return ok && f.ExtendedType() != nil
}

func isFileDescriptor(d protoreflect.Descriptor) bool {
	_, ok := d.(protoreflect.FileDescriptor)
	return ok
}

func isTopLevelDescriptor(d protoreflect.Descriptor) bool {
	p, _ := d.Parent()
	_, ok := p.(protoreflect.FileDescriptor)
	return ok
}

// DescriptorComments returns a `Comments` for the given descriptor.
// If not found, returns (nil, ErrCommentsNotFound).
func (s DescriptorSource) DescriptorComments(d protoreflect.Descriptor) (Comments, error) {
	return s.findCommentsByPath(getPath(d))
}

func reverseInts(a []int) {
	for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
		a[left], a[right] = a[right], a[left]
	}
}

// IsRuleDisabled check if a rule is disabled for a descriptor
// in the comments.
func (s DescriptorSource) IsRuleDisabled(name RuleName, d protoreflect.Descriptor) bool {
	comments, err := s.DescriptorComments(d)
	if err != nil {
		return true
	}

	commentsToCheck := []string{
		comments.LeadingComments,
		comments.TrailingComments,
	}
	commentsToCheck = append(commentsToCheck, s.fileComments().LeadingDetachedComments...)

	return stringsContains(commentsToCheck, ruleDisablingComment(name))
}

func stringsContains(comments []string, s string) bool {
	for _, c := range comments {
		if strings.Contains(c, s) {
			return true
		}
	}
	return false
}

func ruleDisablingComment(name RuleName) string {
	return fmt.Sprintf("(-- api-linter: %s=disabled --)", name)
}

func (s DescriptorSource) fileComments() Comments {
	comments, _ := s.SyntaxComments()
	return comments
}
<|endoftext|>


<commit_before>// Copyright 2011 Alexander Orlov <alexander.orlov@loxal.net>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package test

import (
    "flag" // replace by a post release.58.1 version and check whether flag.Init() exists
           //   then test whether flag.Init("name", 0) works
	"fmt"
	"http"
	"math"
)

func test1(w http.ResponseWriter) (func(int) int) {
    fmt.Fprintf(w, "Hello From MON\n
")
    fmt.Fprintf(w, "POST-TEXTYPE-MON")
    var x int
    return func(delta int) int {
        x += delta
        return x
    }
}

func TestFlag(w http.ResponseWriter){
//    var test flag.FlagSet
var myFlag string
//flagSetPointer.StringVar(&myFlag, "g", "value of String", "usage of string")
//var myFlag *string = flag.String("g", "value of String", "usage of string")
//flag.StringVar(&myFlag, "nameOFString", "value of String", "usage of string")
//flag.Parse()
flagSetPointer := flag.NewFlagSet("", flag.ContinueOnError)
//var myFlag *string = flagSetPointer.String("f", "v", "u")
//var myFlag = flagSetPointer.String("f", "", "u")
flagSetPointer.StringVar(&myFlag, "f", "v", "u")
//args:= []string{"g", "-g", "-g=g", "-g g", "-g u", *myFlag}
args:= []string{"-f", "FEST"}
//flagSetPointer.Usage = func() {}
//otherArgs := flagSetPointer.Args()

  if err := flagSetPointer.Parse(args); err != nil {
            fmt.Fprintf(w, " error
 %v", err)
//            return
    }
fmt.Fprint(w, " test ")

//    fmt.Fprintf(w, "Arg: %v ", flagSetPointer.NArg());
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(0));
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(1));
    fmt.Fprintf(w, "Arg: %q ", myFlag);
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(3));
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(4));
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(5));
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(6));
//    fmt.Fprintf(w, "Other: %v ", otherArgs);
}

type Point struct { x, y float64 }
// A method on *Point
func (p *Point) Abs() float64 {
    return math.Sqrt(p.x*p.x + p.y*p.y)
}

<commit_msg>improved flag pkg example<commit_after>// Copyright 2011 Alexander Orlov <alexander.orlov@loxal.net>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package test

import (
    "flag" // replace by a post release.58.1 version and check whether flag.Init() exists
           //   then test whether flag.Init("name", 0) works
	"fmt"
	"http"
	"math"
)

func test1(w http.ResponseWriter) (func(int) int) {
    fmt.Fprintf(w, "Hello From MON\n
")
    fmt.Fprintf(w, "POST-TEXTYPE-MON")
    var x int
    return func(delta int) int {
        x += delta
        return x
    }
}

func TestFlag(w http.ResponseWriter){
//    var test flag.FlagSet
var myFlag string
var myFlag1 *string
var myFlag2 string
//flagSetPointer.StringVar(&myFlag, "g", "value of String", "usage of string")
//var myFlag *string = flag.String("g", "value of String", "usage of string")
//flag.StringVar(&myFlag, "nameOFString", "value of String", "usage of string")
//flag.Parse()
flagSetPointer := flag.NewFlagSet("google", flag.ContinueOnError)
//var myFlag *string = flagSetPointer.String("f", "v", "u")
//var myFlag = flagSetPointer.String("f", "", "u")
flagSetPointer.StringVar(&myFlag, "flag", "v", "usage")
myFlag1 = flagSetPointer.String("flag1", "v", "u")
flagSetPointer.StringVar(&myFlag2, "mon", "DEFAULT VALUE", "u")
//args:= []string{"g", "-g", "-g=g", "-g g", "-g u", *myFlag}
args:= []string{"-flag", "value", "-flag1", "flag1 Value", "-f", "vom"}
flagSetPointer.Usage = func() {
    fmt.Fprintln(w, "[MY USAGE]")
}
//otherArgs := flagSetPointer.Args()
 f:=flagSetPointer.Lookup("flag")
 fmt.Fprintln(w, f.Usage)

  flagSetPointer.PrintDefaults()
  if err := flagSetPointer.Parse(args); err != nil {
            fmt.Fprintf(w, " [MY ERROR]
 %v", err)
//            fmt.Fprintf(w, " error
 %v", &myFlag2.Usage)
//            return
    }
fmt.Fprint(w, " BAL ")

//    fmt.Fprintf(w, "Arg: %v ", flagSetPointer.NArg());
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(0));
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(1));
    fmt.Fprintf(w, "Arg: %q ", myFlag);
    fmt.Fprintf(w, "Arg: %q ", *myFlag1);
    fmt.Fprintf(w, "Arg: %q ", myFlag2);
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(3));
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(4));
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(5));
//    fmt.Fprintf(w, "Arg: %q ", flagSetPointer.Arg(6));
//    fmt.Fprintf(w, "Other: %v ", otherArgs);
}

type Point struct { x, y float64 }
// A method on *Point
func (p *Point) Abs() float64 {
    return math.Sqrt(p.x*p.x + p.y*p.y)
}

<|endoftext|>


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

package header

import (
	"encoding/binary"

	"github.com/google/netstack/tcpip"
)

const (
	versIHL  = 0
	tos      = 1
	totalLen = 2
	id       = 4
	flagsFO  = 6
	ttl      = 8
	protocol = 9
	checksum = 10
	srcAddr  = 12
	dstAddr  = 16
)

// IPv4Fields contains the fields of an IPv4 packet. It is used to describe the
// fields of a packet that needs to be encoded.
type IPv4Fields struct {
	// IHL is the "internet header length" field of an IPv4 packet.
	IHL uint8

	// TOS is the "type of service" field of an IPv4 packet.
	TOS uint8

	// TotalLength is the "total length" field of an IPv4 packet.
	TotalLength uint16

	// ID is the "identification" field of an IPv4 packet.
	ID uint16

	// Flags is the "flags" field of an IPv4 packet.
	Flags uint8

	// FragmentOffset is the "fragment offset" field of an IPv4 packet.
	FragmentOffset uint16

	// TTL is the "time to live" field of an IPv4 packet.
	TTL uint8

	// Protocol is the "protocol" field of an IPv4 packet.
	Protocol uint8

	// Checksum is the "checksum" field of an IPv4 packet.
	Checksum uint16

	// SrcAddr is the "source ip address" of an IPv4 packet.
	SrcAddr tcpip.Address

	// DstAddr is the "destination ip address" of an IPv4 packet.
	DstAddr tcpip.Address
}

// IPv4 represents an ipv4 header stored in a byte array.
// Most of the methods of IPv4 access to the underlying slice without
// checking the boundaries and could panic because of 'index out of range'.
// Always call IsValid() to validate an instance of IPv4 before using other methods.
type IPv4 []byte

const (
	// IPv4MinimumSize is the minimum size of a valid IPv4 packet.
	IPv4MinimumSize = 20

	// IPv4MaximumHeaderSize is the maximum size of an IPv4 header. Given
	// that there are only 4 bits to represents the header length in 32-bit
	// units, the header cannot exceed 15*4 = 60 bytes.
	IPv4MaximumHeaderSize = 60

	// IPv4AddressSize is the size, in bytes, of an IPv4 address.
	IPv4AddressSize = 4

	// IPv4ProtocolNumber is IPv4's network protocol number.
	IPv4ProtocolNumber tcpip.NetworkProtocolNumber = 0x0800

	// IPv4Version is the version of the ipv4 procotol.
	IPv4Version = 4
)

// Flags that may be set in an IPv4 packet.
const (
	IPv4FlagMoreFragments = 1 << iota
	IPv4FlagDontFragment
)

// IPVersion returns the version of IP used in the given packet. It returns -1
// if the packet is not large enough to contain the version field.
func IPVersion(b []byte) int {
	// Length must be at least offset+length of version field.
	if len(b) < versIHL+1 {
		return -1
	}
	return int(b[versIHL] >> 4)
}

// HeaderLength returns the value of the "header length" field of the ipv4
// header.
func (b IPv4) HeaderLength() uint8 {
	return (b[versIHL] & 0xf) * 4
}

// ID returns the value of the identifier field of the ipv4 header.
func (b IPv4) ID() uint16 {
	return binary.BigEndian.Uint16(b[id:])
}

// Protocol returns the value of the protocol field of the ipv4 header.
func (b IPv4) Protocol() uint8 {
	return b[protocol]
}

// Flags returns the "flags" field of the ipv4 header.
func (b IPv4) Flags() uint8 {
	return uint8(binary.BigEndian.Uint16(b[flagsFO:]) >> 13)
}

// TTL returns the "TTL" field of the ipv4 header.
func (b IPv4) TTL() uint8 {
	return b[ttl]
}

// FragmentOffset returns the "fragment offset" field of the ipv4 header.
func (b IPv4) FragmentOffset() uint16 {
	return binary.BigEndian.Uint16(b[flagsFO:]) << 3
}

// TotalLength returns the "total length" field of the ipv4 header.
func (b IPv4) TotalLength() uint16 {
	return binary.BigEndian.Uint16(b[totalLen:])
}

// Checksum returns the checksum field of the ipv4 header.
func (b IPv4) Checksum() uint16 {
	return binary.BigEndian.Uint16(b[checksum:])
}

// SourceAddress returns the "source address" field of the ipv4 header.
func (b IPv4) SourceAddress() tcpip.Address {
	return tcpip.Address(b[srcAddr : srcAddr+IPv4AddressSize])
}

// DestinationAddress returns the "destination address" field of the ipv4
// header.
func (b IPv4) DestinationAddress() tcpip.Address {
	return tcpip.Address(b[dstAddr : dstAddr+IPv4AddressSize])
}

// TransportProtocol implements Network.TransportProtocol.
func (b IPv4) TransportProtocol() tcpip.TransportProtocolNumber {
	return tcpip.TransportProtocolNumber(b.Protocol())
}

// Payload implements Network.Payload.
func (b IPv4) Payload() []byte {
	return b[b.HeaderLength():][:b.PayloadLength()]
}

// PayloadLength returns the length of the payload portion of the ipv4 packet.
func (b IPv4) PayloadLength() uint16 {
	return b.TotalLength() - uint16(b.HeaderLength())
}

// TOS returns the "type of service" field of the ipv4 header.
func (b IPv4) TOS() (uint8, uint32) {
	return b[tos], 0
}

// SetTOS sets the "type of service" field of the ipv4 header.
func (b IPv4) SetTOS(v uint8, _ uint32) {
	b[tos] = v
}

// SetTotalLength sets the "total length" field of the ipv4 header.
func (b IPv4) SetTotalLength(totalLength uint16) {
	binary.BigEndian.PutUint16(b[totalLen:], totalLength)
}

// SetChecksum sets the checksum field of the ipv4 header.
func (b IPv4) SetChecksum(v uint16) {
	binary.BigEndian.PutUint16(b[checksum:], v)
}

// SetFlagsFragmentOffset sets the "flags" and "fragment offset" fields of the
// ipv4 header.
func (b IPv4) SetFlagsFragmentOffset(flags uint8, offset uint16) {
	v := (uint16(flags) << 13) | (offset >> 3)
	binary.BigEndian.PutUint16(b[flagsFO:], v)
}

// SetSourceAddress sets the "source address" field of the ipv4 header.
func (b IPv4) SetSourceAddress(addr tcpip.Address) {
	copy(b[srcAddr:srcAddr+IPv4AddressSize], addr)
}

// SetDestinationAddress sets the "destination address" field of the ipv4
// header.
func (b IPv4) SetDestinationAddress(addr tcpip.Address) {
	copy(b[dstAddr:dstAddr+IPv4AddressSize], addr)
}

// CalculateChecksum calculates the checksum of the ipv4 header.
func (b IPv4) CalculateChecksum() uint16 {
	return Checksum(b[:b.HeaderLength()], 0)
}

// Encode encodes all the fields of the ipv4 header.
func (b IPv4) Encode(i *IPv4Fields) {
	b[versIHL] = (4 << 4) | ((i.IHL / 4) & 0xf)
	b[tos] = i.TOS
	b.SetTotalLength(i.TotalLength)
	binary.BigEndian.PutUint16(b[id:], i.ID)
	b.SetFlagsFragmentOffset(i.Flags, i.FragmentOffset)
	b[ttl] = i.TTL
	b[protocol] = i.Protocol
	b.SetChecksum(i.Checksum)
	copy(b[srcAddr:srcAddr+IPv4AddressSize], i.SrcAddr)
	copy(b[dstAddr:dstAddr+IPv4AddressSize], i.DstAddr)
}

// EncodePartial updates the total length and checksum fields of ipv4 header,
// taking in the partial checksum, which is the checksum of the header without
// the total length and checksum fields. It is useful in cases when similar
// packets are produced.
func (b IPv4) EncodePartial(partialChecksum, totalLength uint16) {
	b.SetTotalLength(totalLength)
	checksum := Checksum(b[totalLen:totalLen+2], partialChecksum)
	b.SetChecksum(^checksum)
}

// IsValid performs basic validation on the packet.
func (b IPv4) IsValid(pktSize int) bool {
	if len(b) < IPv4MinimumSize {
		return false
	}

	hlen := int(b.HeaderLength())
	tlen := int(b.TotalLength())
	if hlen > tlen || tlen > pktSize {
		return false
	}

	return true
}
<commit_msg>Fix misspellings<commit_after>// Copyright 2016 The Netstack Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package header

import (
	"encoding/binary"

	"github.com/google/netstack/tcpip"
)

const (
	versIHL  = 0
	tos      = 1
	totalLen = 2
	id       = 4
	flagsFO  = 6
	ttl      = 8
	protocol = 9
	checksum = 10
	srcAddr  = 12
	dstAddr  = 16
)

// IPv4Fields contains the fields of an IPv4 packet. It is used to describe the
// fields of a packet that needs to be encoded.
type IPv4Fields struct {
	// IHL is the "internet header length" field of an IPv4 packet.
	IHL uint8

	// TOS is the "type of service" field of an IPv4 packet.
	TOS uint8

	// TotalLength is the "total length" field of an IPv4 packet.
	TotalLength uint16

	// ID is the "identification" field of an IPv4 packet.
	ID uint16

	// Flags is the "flags" field of an IPv4 packet.
	Flags uint8

	// FragmentOffset is the "fragment offset" field of an IPv4 packet.
	FragmentOffset uint16

	// TTL is the "time to live" field of an IPv4 packet.
	TTL uint8

	// Protocol is the "protocol" field of an IPv4 packet.
	Protocol uint8

	// Checksum is the "checksum" field of an IPv4 packet.
	Checksum uint16

	// SrcAddr is the "source ip address" of an IPv4 packet.
	SrcAddr tcpip.Address

	// DstAddr is the "destination ip address" of an IPv4 packet.
	DstAddr tcpip.Address
}

// IPv4 represents an ipv4 header stored in a byte array.
// Most of the methods of IPv4 access to the underlying slice without
// checking the boundaries and could panic because of 'index out of range'.
// Always call IsValid() to validate an instance of IPv4 before using other methods.
type IPv4 []byte

const (
	// IPv4MinimumSize is the minimum size of a valid IPv4 packet.
	IPv4MinimumSize = 20

	// IPv4MaximumHeaderSize is the maximum size of an IPv4 header. Given
	// that there are only 4 bits to represents the header length in 32-bit
	// units, the header cannot exceed 15*4 = 60 bytes.
	IPv4MaximumHeaderSize = 60

	// IPv4AddressSize is the size, in bytes, of an IPv4 address.
	IPv4AddressSize = 4

	// IPv4ProtocolNumber is IPv4's network protocol number.
	IPv4ProtocolNumber tcpip.NetworkProtocolNumber = 0x0800

	// IPv4Version is the version of the ipv4 protocol.
	IPv4Version = 4
)

// Flags that may be set in an IPv4 packet.
const (
	IPv4FlagMoreFragments = 1 << iota
	IPv4FlagDontFragment
)

// IPVersion returns the version of IP used in the given packet. It returns -1
// if the packet is not large enough to contain the version field.
func IPVersion(b []byte) int {
	// Length must be at least offset+length of version field.
	if len(b) < versIHL+1 {
		return -1
	}
	return int(b[versIHL] >> 4)
}

// HeaderLength returns the value of the "header length" field of the ipv4
// header.
func (b IPv4) HeaderLength() uint8 {
	return (b[versIHL] & 0xf) * 4
}

// ID returns the value of the identifier field of the ipv4 header.
func (b IPv4) ID() uint16 {
	return binary.BigEndian.Uint16(b[id:])
}

// Protocol returns the value of the protocol field of the ipv4 header.
func (b IPv4) Protocol() uint8 {
	return b[protocol]
}

// Flags returns the "flags" field of the ipv4 header.
func (b IPv4) Flags() uint8 {
	return uint8(binary.BigEndian.Uint16(b[flagsFO:]) >> 13)
}

// TTL returns the "TTL" field of the ipv4 header.
func (b IPv4) TTL() uint8 {
	return b[ttl]
}

// FragmentOffset returns the "fragment offset" field of the ipv4 header.
func (b IPv4) FragmentOffset() uint16 {
	return binary.BigEndian.Uint16(b[flagsFO:]) << 3
}

// TotalLength returns the "total length" field of the ipv4 header.
func (b IPv4) TotalLength() uint16 {
	return binary.BigEndian.Uint16(b[totalLen:])
}

// Checksum returns the checksum field of the ipv4 header.
func (b IPv4) Checksum() uint16 {
	return binary.BigEndian.Uint16(b[checksum:])
}

// SourceAddress returns the "source address" field of the ipv4 header.
func (b IPv4) SourceAddress() tcpip.Address {
	return tcpip.Address(b[srcAddr : srcAddr+IPv4AddressSize])
}

// DestinationAddress returns the "destination address" field of the ipv4
// header.
func (b IPv4) DestinationAddress() tcpip.Address {
	return tcpip.Address(b[dstAddr : dstAddr+IPv4AddressSize])
}

// TransportProtocol implements Network.TransportProtocol.
func (b IPv4) TransportProtocol() tcpip.TransportProtocolNumber {
	return tcpip.TransportProtocolNumber(b.Protocol())
}

// Payload implements Network.Payload.
func (b IPv4) Payload() []byte {
	return b[b.HeaderLength():][:b.PayloadLength()]
}

// PayloadLength returns the length of the payload portion of the ipv4 packet.
func (b IPv4) PayloadLength() uint16 {
	return b.TotalLength() - uint16(b.HeaderLength())
}

// TOS returns the "type of service" field of the ipv4 header.
func (b IPv4) TOS() (uint8, uint32) {
	return b[tos], 0
}

// SetTOS sets the "type of service" field of the ipv4 header.
func (b IPv4) SetTOS(v uint8, _ uint32) {
	b[tos] = v
}

// SetTotalLength sets the "total length" field of the ipv4 header.
func (b IPv4) SetTotalLength(totalLength uint16) {
	binary.BigEndian.PutUint16(b[totalLen:], totalLength)
}

// SetChecksum sets the checksum field of the ipv4 header.
func (b IPv4) SetChecksum(v uint16) {
	binary.BigEndian.PutUint16(b[checksum:], v)
}

// SetFlagsFragmentOffset sets the "flags" and "fragment offset" fields of the
// ipv4 header.
func (b IPv4) SetFlagsFragmentOffset(flags uint8, offset uint16) {
	v := (uint16(flags) << 13) | (offset >> 3)
	binary.BigEndian.PutUint16(b[flagsFO:], v)
}

// SetSourceAddress sets the "source address" field of the ipv4 header.
func (b IPv4) SetSourceAddress(addr tcpip.Address) {
	copy(b[srcAddr:srcAddr+IPv4AddressSize], addr)
}

// SetDestinationAddress sets the "destination address" field of the ipv4
// header.
func (b IPv4) SetDestinationAddress(addr tcpip.Address) {
	copy(b[dstAddr:dstAddr+IPv4AddressSize], addr)
}

// CalculateChecksum calculates the checksum of the ipv4 header.
func (b IPv4) CalculateChecksum() uint16 {
	return Checksum(b[:b.HeaderLength()], 0)
}

// Encode encodes all the fields of the ipv4 header.
func (b IPv4) Encode(i *IPv4Fields) {
	b[versIHL] = (4 << 4) | ((i.IHL / 4) & 0xf)
	b[tos] = i.TOS
	b.SetTotalLength(i.TotalLength)
	binary.BigEndian.PutUint16(b[id:], i.ID)
	b.SetFlagsFragmentOffset(i.Flags, i.FragmentOffset)
	b[ttl] = i.TTL
	b[protocol] = i.Protocol
	b.SetChecksum(i.Checksum)
	copy(b[srcAddr:srcAddr+IPv4AddressSize], i.SrcAddr)
	copy(b[dstAddr:dstAddr+IPv4AddressSize], i.DstAddr)
}

// EncodePartial updates the total length and checksum fields of ipv4 header,
// taking in the partial checksum, which is the checksum of the header without
// the total length and checksum fields. It is useful in cases when similar
// packets are produced.
func (b IPv4) EncodePartial(partialChecksum, totalLength uint16) {
	b.SetTotalLength(totalLength)
	checksum := Checksum(b[totalLen:totalLen+2], partialChecksum)
	b.SetChecksum(^checksum)
}

// IsValid performs basic validation on the packet.
func (b IPv4) IsValid(pktSize int) bool {
	if len(b) < IPv4MinimumSize {
		return false
	}

	hlen := int(b.HeaderLength())
	tlen := int(b.TotalLength())
	if hlen > tlen || tlen > pktSize {
		return false
	}

	return true
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 Tamás Gulácsi
// See LICENSE.txt
// Translated from cx_Oracle ((c) Anthony Tuininga) by Tamás Gulácsi
package goracle

/*
#cgo CFLAGS: -I/usr/include/oracle/11.2/client64
#cgo LDFLAGS: -lclntsh -L/usr/lib/oracle/11.2/client64/lib

#include <stdlib.h>
#include <oci.h>
*/
import "C"

import (
	// "unsafe"
	"errors"
	"fmt"
)

// Initialize the variable.
func stringVar_Initialize(v *Variable, cur *Cursor) error {
	v.actualLength = make([]C.ub2, v.allocatedElements)
	return nil
}

// Set the value of the variable.
func stringVar_SetValue(v *Variable, pos uint, value interface{}) error {
	var (
		text   string
		buf    []byte
		ok     bool
		length int
	)
	if text, ok = value.(string); !ok {
		if buf, ok = value.([]byte); !ok {
			return fmt.Errorf("string or []byte required, got %T", value)
		} else {
			if v.typ.isCharData {
				text = string(buf)
				length = len(text)
			} else {
				length = len(buf)
			}
		}
	} else {
		if v.typ.isCharData {
			length = len(text)
		} else {
			length = len(buf)
		}
		buf = []byte(text)
	}
	if v.typ.isCharData && length > MAX_STRING_CHARS {
		return errors.New("string data too large")
	} else if !v.typ.isCharData && length > MAX_BINARY_BYTES {
		return errors.New("binary data too large")
	}

	// ensure that the buffer is large enough
	if length > int(v.bufferSize) {
		if err := v.resize(uint(length)); err != nil {
			return err
		}
	}

	// keep a copy of the string
	v.actualLength[pos] = C.ub2(length)
	if length > 0 {
		copy(v.dataBytes[int(v.bufferSize*pos):], buf)
	}

	return nil
}

// Returns the value stored at the given array position.
func stringVar_GetValue(v *Variable, pos uint) (interface{}, error) {
	buf := v.dataBytes[int(v.bufferSize*pos) : int(v.bufferSize*pos)+int(v.actualLength[pos])]
	if v.typ == BinaryVarType {
		return buf, nil
	}
	return v.environment.FromEncodedString(buf), nil
	/*
		#if PY_MAJOR_VERSION < 3
		    if (var->type == &vt_FixedNationalChar
		            || var->type == &vt_NationalCharString)
		        return PyUnicode_Decode(data, var->actualLength[pos],
		                var->environment->nencoding, NULL);
		#endif
	*/
}

/*
#if PY_MAJOR_VERSION < 3
//-----------------------------------------------------------------------------
// StringVar_PostDefine()
//   Set the character set information when values are fetched from this
// variable.
//-----------------------------------------------------------------------------
static int StringVar_PostDefine(
    udt_StringVar *var)                 // variable to initialize
{
    sword status;

    status = OCIAttrSet(var->defineHandle, OCI_HTYPE_DEFINE,
            &var->type->charsetForm, 0, OCI_ATTR_CHARSET_FORM,
            var->environment->errorHandle);
    if (Environment_CheckForError(var->environment, status,
            "StringVar_PostDefine(): setting charset form") < 0)
        return -1;

    return 0;
}
#endif
*/

// Returns the buffer size to use for the variable.
func stringVar_GetBufferSize(v *Variable) uint {
	if v.typ.isCharData {
		return v.size * v.environment.maxBytesPerCharacter
	}
	return uint(v.size)
}

var (
	StringVarType, FixedCharVarType *VariableType
	BinaryVarType, RowidVarType     *VariableType
)

func init() {
	StringVarType = &VariableType{
		Name:             "String",
		isVariableLength: true,
		initialize:       stringVar_Initialize,
		setValue:         stringVar_SetValue,
		getValue:         stringVar_GetValue,
		getBufferSize:    stringVar_GetBufferSize,
		oracleType:       C.SQLT_CHR,       // Oracle type
		charsetForm:      C.SQLCS_IMPLICIT, // charset form
		size:             MAX_STRING_CHARS, // element length (default)
		isCharData:       true,             // is character data
		canBeCopied:      true,             // can be copied
		canBeInArray:     true,             // can be in array
	}

	FixedCharVarType = &VariableType{
		Name:             "FixedChar",
		initialize:       stringVar_Initialize,
		setValue:         stringVar_SetValue,
		getValue:         stringVar_GetValue,
		getBufferSize:    stringVar_GetBufferSize,
		oracleType:       C.SQLT_AFC,       // Oracle type
		charsetForm:      C.SQLCS_IMPLICIT, // charset form
		size:             2000,             // element length (default)
		isCharData:       true,             // is character data
		isVariableLength: true,             // is variable length
		canBeCopied:      true,             // can be copied
		canBeInArray:     true,             // can be in array
	}

	RowidVarType = &VariableType{
		Name:             "Rowid",
		initialize:       stringVar_Initialize,
		setValue:         stringVar_SetValue,
		getValue:         stringVar_GetValue,
		getBufferSize:    stringVar_GetBufferSize,
		oracleType:       C.SQLT_CHR,       // Oracle type
		charsetForm:      C.SQLCS_IMPLICIT, // charset form
		size:             18,               // element length (default)
		isCharData:       true,             // is character data
		isVariableLength: false,            // is variable length
		canBeCopied:      true,             // can be copied
		canBeInArray:     true,             // can be in array
	}

	BinaryVarType = &VariableType{
		Name:             "Binary",
		initialize:       stringVar_Initialize,
		setValue:         stringVar_SetValue,
		getValue:         stringVar_GetValue,
		oracleType:       C.SQLT_BIN,       // Oracle type
		charsetForm:      C.SQLCS_IMPLICIT, // charset form
		size:             MAX_BINARY_BYTES, // element length (default)
		isCharData:       false,            // is character data
		isVariableLength: true,             // is variable length
		canBeCopied:      true,             // can be copied
		canBeInArray:     true,             // can be in array
	}
}
<commit_msg>stringvar still contained license<commit_after>package goracle

/*
#cgo CFLAGS: -I/usr/include/oracle/11.2/client64
#cgo LDFLAGS: -lclntsh -L/usr/lib/oracle/11.2/client64/lib

#include <stdlib.h>
#include <oci.h>
*/
import "C"

import (
	// "unsafe"
	"errors"
	"fmt"
)

// Initialize the variable.
func stringVar_Initialize(v *Variable, cur *Cursor) error {
	v.actualLength = make([]C.ub2, v.allocatedElements)
	return nil
}

// Set the value of the variable.
func stringVar_SetValue(v *Variable, pos uint, value interface{}) error {
	var (
		text   string
		buf    []byte
		ok     bool
		length int
	)
	if text, ok = value.(string); !ok {
		if buf, ok = value.([]byte); !ok {
			return fmt.Errorf("string or []byte required, got %T", value)
		} else {
			if v.typ.isCharData {
				text = string(buf)
				length = len(text)
			} else {
				length = len(buf)
			}
		}
	} else {
		if v.typ.isCharData {
			length = len(text)
		} else {
			length = len(buf)
		}
		buf = []byte(text)
	}
	if v.typ.isCharData && length > MAX_STRING_CHARS {
		return errors.New("string data too large")
	} else if !v.typ.isCharData && length > MAX_BINARY_BYTES {
		return errors.New("binary data too large")
	}

	// ensure that the buffer is large enough
	if length > int(v.bufferSize) {
		if err := v.resize(uint(length)); err != nil {
			return err
		}
	}

	// keep a copy of the string
	v.actualLength[pos] = C.ub2(length)
	if length > 0 {
		copy(v.dataBytes[int(v.bufferSize*pos):], buf)
	}

	return nil
}

// Returns the value stored at the given array position.
func stringVar_GetValue(v *Variable, pos uint) (interface{}, error) {
	buf := v.dataBytes[int(v.bufferSize*pos) : int(v.bufferSize*pos)+int(v.actualLength[pos])]
	if v.typ == BinaryVarType {
		return buf, nil
	}
	return v.environment.FromEncodedString(buf), nil
	/*
		#if PY_MAJOR_VERSION < 3
		    if (var->type == &vt_FixedNationalChar
		            || var->type == &vt_NationalCharString)
		        return PyUnicode_Decode(data, var->actualLength[pos],
		                var->environment->nencoding, NULL);
		#endif
	*/
}

/*
#if PY_MAJOR_VERSION < 3
//-----------------------------------------------------------------------------
// StringVar_PostDefine()
//   Set the character set information when values are fetched from this
// variable.
//-----------------------------------------------------------------------------
static int StringVar_PostDefine(
    udt_StringVar *var)                 // variable to initialize
{
    sword status;

    status = OCIAttrSet(var->defineHandle, OCI_HTYPE_DEFINE,
            &var->type->charsetForm, 0, OCI_ATTR_CHARSET_FORM,
            var->environment->errorHandle);
    if (Environment_CheckForError(var->environment, status,
            "StringVar_PostDefine(): setting charset form") < 0)
        return -1;

    return 0;
}
#endif
*/

// Returns the buffer size to use for the variable.
func stringVar_GetBufferSize(v *Variable) uint {
	if v.typ.isCharData {
		return v.size * v.environment.maxBytesPerCharacter
	}
	return uint(v.size)
}

var (
	StringVarType, FixedCharVarType *VariableType
	BinaryVarType, RowidVarType     *VariableType
)

func init() {
	StringVarType = &VariableType{
		Name:             "String",
		isVariableLength: true,
		initialize:       stringVar_Initialize,
		setValue:         stringVar_SetValue,
		getValue:         stringVar_GetValue,
		getBufferSize:    stringVar_GetBufferSize,
		oracleType:       C.SQLT_CHR,       // Oracle type
		charsetForm:      C.SQLCS_IMPLICIT, // charset form
		size:             MAX_STRING_CHARS, // element length (default)
		isCharData:       true,             // is character data
		canBeCopied:      true,             // can be copied
		canBeInArray:     true,             // can be in array
	}

	FixedCharVarType = &VariableType{
		Name:             "FixedChar",
		initialize:       stringVar_Initialize,
		setValue:         stringVar_SetValue,
		getValue:         stringVar_GetValue,
		getBufferSize:    stringVar_GetBufferSize,
		oracleType:       C.SQLT_AFC,       // Oracle type
		charsetForm:      C.SQLCS_IMPLICIT, // charset form
		size:             2000,             // element length (default)
		isCharData:       true,             // is character data
		isVariableLength: true,             // is variable length
		canBeCopied:      true,             // can be copied
		canBeInArray:     true,             // can be in array
	}

	RowidVarType = &VariableType{
		Name:             "Rowid",
		initialize:       stringVar_Initialize,
		setValue:         stringVar_SetValue,
		getValue:         stringVar_GetValue,
		getBufferSize:    stringVar_GetBufferSize,
		oracleType:       C.SQLT_CHR,       // Oracle type
		charsetForm:      C.SQLCS_IMPLICIT, // charset form
		size:             18,               // element length (default)
		isCharData:       true,             // is character data
		isVariableLength: false,            // is variable length
		canBeCopied:      true,             // can be copied
		canBeInArray:     true,             // can be in array
	}

	BinaryVarType = &VariableType{
		Name:             "Binary",
		initialize:       stringVar_Initialize,
		setValue:         stringVar_SetValue,
		getValue:         stringVar_GetValue,
		oracleType:       C.SQLT_BIN,       // Oracle type
		charsetForm:      C.SQLCS_IMPLICIT, // charset form
		size:             MAX_BINARY_BYTES, // element length (default)
		isCharData:       false,            // is character data
		isVariableLength: true,             // is variable length
		canBeCopied:      true,             // can be copied
		canBeInArray:     true,             // can be in array
	}
}
<|endoftext|>


<commit_before>package web

import "gopkg.in/webnice/debug.v1"
import "gopkg.in/webnice/log.v2"
import (
	"crypto/tls"
	"net"
	"os"
)

// Wait while web server is running
func (wsv *web) Wait() Interface { wsv.doCloseDone.Wait(); return wsv }

// ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections
func (wsv *web) ListenAndServe(addr string) Interface {
	var conf *Configuration

	if conf, wsv.err = parseAddress(addr); wsv.err != nil {
		return wsv
	}

	return wsv.ListenAndServeWithConfig(conf)
}

// ListenAndServeTLS listens on the TCP network address address with TLS and then calls Serve with handler
// to handle requests on incoming connections
func (wsv *web) ListenAndServeTLS(addr string, certFile string, keyFile string, tlsConfig *tls.Config) Interface {
	var conf *Configuration

	if conf, wsv.err = parseAddress(addr); wsv.err != nil {
		return wsv
	}
	conf.TLSPublicKeyPEM, conf.TLSPrivateKeyPEM = certFile, keyFile

	return wsv.ListenAndServeTLSWithConfig(conf, tlsConfig)
}

// ListenAndServeWithConfig Fully configurable web server listens and then calls Serve on incoming connections
func (wsv *web) ListenAndServeWithConfig(conf *Configuration) Interface {
	if conf == nil {
		wsv.err = ErrNoConfiguration()
		return wsv
	}
	wsv.conf = conf

	return wsv.Listen(nil)
}

// ListenAndServeTLSWithConfig Fully configurable web server listens and then calls Serve on incoming connections
func (wsv *web) ListenAndServeTLSWithConfig(conf *Configuration, tlsConfig *tls.Config) Interface {
	if conf == nil {
		wsv.err = ErrNoConfiguration()
		return wsv
	}
	wsv.conf = conf
	if tlsConfig == nil {
		if tlsConfig, wsv.err = wsv.tlsConfigDefault(conf.TLSPublicKeyPEM, conf.TLSPrivateKeyPEM); wsv.err != nil {
			return wsv
		}
	}

	return wsv.Listen(tlsConfig)
}

// NewListener Make new listener from web server configuration
func (wsv *web) NewListener(conf *Configuration) (ret net.Listener, err error) {
	var (
		lstWithNames map[string][]net.Listener
		listeners    []net.Listener
		ok           bool
	)

	defaultConfiguration(conf)
	switch conf.Mode {
	case netSystemd:
		if conf.Socket != "" {
			// Имена сокетов указаны
			if lstWithNames, err = wsv.ListenersSystemdWithNames(false); err != nil {
				return
			}

			log.Debug(debug.DumperString(lstWithNames, listeners, os.Environ(), conf.Socket, conf))

			// Выбор сокета по имени
			if listeners, ok = lstWithNames[conf.Socket]; !ok {
				err = ErrListenSystemdNotFound()
				return
			}
		} else {
			// Имена сокетов не указаны
			if listeners, err = wsv.ListenersSystemdWithoutNames(false); err != nil {
				return
			}
		}
		if len(listeners) == 0 {
			err = ErrListenSystemdUnexpectedNumber()
			return
		}
		ret = listeners[0]
	case netUnix, netUnixPacket:
		_ = os.Remove(conf.Socket)
		ret, err = net.Listen(conf.Mode, conf.Socket)
		_ = os.Chmod(conf.Socket, os.FileMode(0666))
	default:
		ret, err = net.Listen(conf.Mode, conf.HostPort)
	}

	return
}

// NewListenerTLS Make new listener with TLS from web server configuration
func (wsv *web) NewListenerTLS(conf *Configuration, tlsConfig *tls.Config) (ret net.Listener, err error) {
	var l net.Listener

	if l, err = wsv.NewListener(conf); err != nil {
		return
	}
	if tlsConfig == nil {
		if tlsConfig, err = wsv.tlsConfigDefault(conf.TLSPublicKeyPEM, conf.TLSPrivateKeyPEM); err != nil {
			return
		}
	}
	ret = tls.NewListener(l, tlsConfig)

	return
}

// Конфигурация TLS по умолчанию
func (wsv *web) tlsConfigDefault(tlsPublicFile string, tlsPrivateFile string) (ret *tls.Config, err error) {
	ret = &tls.Config{
		MinVersion:               tls.VersionTLS12,
		CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
		PreferServerCipherSuites: true,
		CipherSuites: []uint16{
			tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_RSA_WITH_AES_256_CBC_SHA,
		},
		Certificates: make([]tls.Certificate, 1),
	}
	if ret.Certificates[0], err = tls.LoadX509KeyPair(tlsPublicFile, tlsPrivateFile); err != nil {
		return
	}

	return
}

// Listen Begin listen port and web server serve
func (wsv *web) Listen(tlsConfig *tls.Config) Interface {
	var ltn net.Listener

	if wsv.isRun.Load().(bool) {
		wsv.err = ErrAlreadyRunning()
		return wsv
	}
	switch tlsConfig == nil {
	case true:
		ltn, wsv.err = wsv.NewListener(wsv.conf)
	case false:
		ltn, wsv.err = wsv.NewListenerTLS(wsv.conf, tlsConfig)
	}
	if wsv.err != nil {
		return wsv
	}

	return wsv.ServeTLS(ltn, tlsConfig)
}

// Serve accepts incoming connections on the listener, creating a new web server goroutine
func (wsv *web) Serve(ltn net.Listener) Interface { return wsv.ServeTLS(ltn, nil) }

// ServeTLS accepts incoming connections on the listener with TLS configuration, creating a new web server goroutine
func (wsv *web) ServeTLS(ltn net.Listener, tlsConfig *tls.Config) Interface {
	var conf *Configuration

	// TODO: Реализовать поддержку PROXY Protocol через "gopkg.in/webnice/web.v1/proxyp", conf.ProxyProtocol

	if wsv.conf == nil {
		conf, _ = parseAddress(ltn.Addr().String())
		defaultConfiguration(conf)
		wsv.conf = conf
	}
	wsv.listener = ltn
	wsv.isRun.Store(true)
	wsv.doCloseDone.Add(1)
	go wsv.run(tlsConfig)

	return wsv
}

// Goroutine of the web server
func (wsv *web) run(tlsConfig *tls.Config) {
	defer wsv.doCloseDone.Done()
	defer wsv.isRun.Store(false)
	defer func() {
		if wsv.conf.Socket == "" {
			return
		}
		switch wsv.conf.Mode {
		case netSystemd:
			return
		case netUnix, netUnixPacket:
			_ = os.Remove(wsv.conf.Socket)
		}
	}()

	// Configure net/http web server
	if wsv.server = wsv.loadConfiguration(tlsConfig); wsv.err != nil {
		return
	}
	// Configure keepalive of web server
	if wsv.conf.KeepAliveDisable {
		wsv.server.SetKeepAlivesEnabled(false)
	}
	// Begin serve
	if wsv.conf.TLSPrivateKeyPEM == "" || wsv.conf.TLSPublicKeyPEM == "" {
		wsv.err = wsv.server.Serve(wsv.listener)
		return
	}
	wsv.err = wsv.server.ServeTLS(wsv.listener, wsv.conf.TLSPublicKeyPEM, wsv.conf.TLSPrivateKeyPEM)
}
<commit_msg>Debug removed<commit_after>package web

//import "gopkg.in/webnice/debug.v1"
//import "gopkg.in/webnice/log.v2"
import (
	"crypto/tls"
	"net"
	"os"
	"path"
)

// Wait while web server is running
func (wsv *web) Wait() Interface { wsv.doCloseDone.Wait(); return wsv }

// ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections
func (wsv *web) ListenAndServe(addr string) Interface {
	var conf *Configuration

	if conf, wsv.err = parseAddress(addr); wsv.err != nil {
		return wsv
	}

	return wsv.ListenAndServeWithConfig(conf)
}

// ListenAndServeTLS listens on the TCP network address address with TLS and then calls Serve with handler
// to handle requests on incoming connections
func (wsv *web) ListenAndServeTLS(addr string, certFile string, keyFile string, tlsConfig *tls.Config) Interface {
	var conf *Configuration

	if conf, wsv.err = parseAddress(addr); wsv.err != nil {
		return wsv
	}
	conf.TLSPublicKeyPEM, conf.TLSPrivateKeyPEM = certFile, keyFile

	return wsv.ListenAndServeTLSWithConfig(conf, tlsConfig)
}

// ListenAndServeWithConfig Fully configurable web server listens and then calls Serve on incoming connections
func (wsv *web) ListenAndServeWithConfig(conf *Configuration) Interface {
	if conf == nil {
		wsv.err = ErrNoConfiguration()
		return wsv
	}
	wsv.conf = conf

	return wsv.Listen(nil)
}

// ListenAndServeTLSWithConfig Fully configurable web server listens and then calls Serve on incoming connections
func (wsv *web) ListenAndServeTLSWithConfig(conf *Configuration, tlsConfig *tls.Config) Interface {
	if conf == nil {
		wsv.err = ErrNoConfiguration()
		return wsv
	}
	wsv.conf = conf
	if tlsConfig == nil {
		if tlsConfig, wsv.err = wsv.tlsConfigDefault(conf.TLSPublicKeyPEM, conf.TLSPrivateKeyPEM); wsv.err != nil {
			return wsv
		}
	}

	return wsv.Listen(tlsConfig)
}

// NewListener Make new listener from web server configuration
func (wsv *web) NewListener(conf *Configuration) (ret net.Listener, err error) {
	var (
		lstWithNames map[string][]net.Listener
		listeners    []net.Listener
		ok           bool
	)

	defaultConfiguration(conf)
	switch conf.Mode {
	case netSystemd:
		if conf.Socket != "" {
			// Имена сокетов указаны
			if lstWithNames, err = wsv.ListenersSystemdWithNames(false); err != nil {
				return
			}
			// Выбор сокета по имени
			if listeners, ok = lstWithNames[path.Base(conf.Socket)]; !ok {
				err = ErrListenSystemdNotFound()
				return
			}
		} else {
			// Имена сокетов не указаны
			if listeners, err = wsv.ListenersSystemdWithoutNames(false); err != nil {
				return
			}
		}
		if len(listeners) == 0 {
			err = ErrListenSystemdUnexpectedNumber()
			return
		}
		ret = listeners[0]
	case netUnix, netUnixPacket:
		_ = os.Remove(conf.Socket)
		ret, err = net.Listen(conf.Mode, conf.Socket)
		_ = os.Chmod(conf.Socket, os.FileMode(0666))
	default:
		ret, err = net.Listen(conf.Mode, conf.HostPort)
	}

	return
}

// NewListenerTLS Make new listener with TLS from web server configuration
func (wsv *web) NewListenerTLS(conf *Configuration, tlsConfig *tls.Config) (ret net.Listener, err error) {
	var l net.Listener

	if l, err = wsv.NewListener(conf); err != nil {
		return
	}
	if tlsConfig == nil {
		if tlsConfig, err = wsv.tlsConfigDefault(conf.TLSPublicKeyPEM, conf.TLSPrivateKeyPEM); err != nil {
			return
		}
	}
	ret = tls.NewListener(l, tlsConfig)

	return
}

// Конфигурация TLS по умолчанию
func (wsv *web) tlsConfigDefault(tlsPublicFile string, tlsPrivateFile string) (ret *tls.Config, err error) {
	ret = &tls.Config{
		MinVersion:               tls.VersionTLS12,
		CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
		PreferServerCipherSuites: true,
		CipherSuites: []uint16{
			tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_RSA_WITH_AES_256_CBC_SHA,
		},
		Certificates: make([]tls.Certificate, 1),
	}
	if ret.Certificates[0], err = tls.LoadX509KeyPair(tlsPublicFile, tlsPrivateFile); err != nil {
		return
	}

	return
}

// Listen Begin listen port and web server serve
func (wsv *web) Listen(tlsConfig *tls.Config) Interface {
	var ltn net.Listener

	if wsv.isRun.Load().(bool) {
		wsv.err = ErrAlreadyRunning()
		return wsv
	}
	switch tlsConfig == nil {
	case true:
		ltn, wsv.err = wsv.NewListener(wsv.conf)
	case false:
		ltn, wsv.err = wsv.NewListenerTLS(wsv.conf, tlsConfig)
	}
	if wsv.err != nil {
		return wsv
	}

	return wsv.ServeTLS(ltn, tlsConfig)
}

// Serve accepts incoming connections on the listener, creating a new web server goroutine
func (wsv *web) Serve(ltn net.Listener) Interface { return wsv.ServeTLS(ltn, nil) }

// ServeTLS accepts incoming connections on the listener with TLS configuration, creating a new web server goroutine
func (wsv *web) ServeTLS(ltn net.Listener, tlsConfig *tls.Config) Interface {
	var conf *Configuration

	// TODO: Реализовать поддержку PROXY Protocol через "gopkg.in/webnice/web.v1/proxyp", conf.ProxyProtocol

	if wsv.conf == nil {
		conf, _ = parseAddress(ltn.Addr().String())
		defaultConfiguration(conf)
		wsv.conf = conf
	}
	wsv.listener = ltn
	wsv.isRun.Store(true)
	wsv.doCloseDone.Add(1)
	go wsv.run(tlsConfig)

	return wsv
}

// Goroutine of the web server
func (wsv *web) run(tlsConfig *tls.Config) {
	defer wsv.doCloseDone.Done()
	defer wsv.isRun.Store(false)
	defer func() {
		if wsv.conf.Socket == "" {
			return
		}
		switch wsv.conf.Mode {
		case netSystemd:
			return
		case netUnix, netUnixPacket:
			_ = os.Remove(wsv.conf.Socket)
		}
	}()

	// Configure net/http web server
	if wsv.server = wsv.loadConfiguration(tlsConfig); wsv.err != nil {
		return
	}
	// Configure keepalive of web server
	if wsv.conf.KeepAliveDisable {
		wsv.server.SetKeepAlivesEnabled(false)
	}
	// Begin serve
	if wsv.conf.TLSPrivateKeyPEM == "" || wsv.conf.TLSPublicKeyPEM == "" {
		wsv.err = wsv.server.Serve(wsv.listener)
		return
	}
	wsv.err = wsv.server.ServeTLS(wsv.listener, wsv.conf.TLSPublicKeyPEM, wsv.conf.TLSPrivateKeyPEM)
}
<|endoftext|>


<commit_before>package tlsdefaults

import (
	"crypto/tls"
	"fmt"
	"net"
	"os"
	"time"

	"github.com/getlantern/keyman"
)

var (
	tenYearsFromToday = time.Now().AddDate(10, 0, 0)
)

// Listen opens a TLS listener at the given address using the private key and
// certificate PEM files at the given paths. If no files exists, it creates a
// new key and self-signed certificate at those locations.
func Listen(addr, pkfile, certfile string) (net.Listener, error) {
	l, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, fmt.Errorf("Unable to listen for connections at %s: %s\n", addr, err)
	}

	return NewListenerAddr(l, addr, pkfile, certfile)
}

// NewListener creates a TLS listener based on the given listener using the
// private key and certificate PEM files at the given paths. If no files exists,
// it creates a new key and self-signed certificate at those locations.
func NewListener(l net.Listener, pkfile, certfile string) (net.Listener, error) {
	return NewListenerAddr(l, l.Addr().String(), pkfile, certfile)
}

// NewListenerAddr is like NewListener but uses the specified addr to generate
// the cert.
func NewListenerAddr(l net.Listener, addr string, pkfile, certfile string) (net.Listener, error) {
	host, _, err := net.SplitHostPort(addr)
	if err != nil {
		return nil, fmt.Errorf("Unable to split host and port for %v: %v\n", addr, err)
	}

	mypkfile := pkfile
	if mypkfile == "" {
		mypkfile = "key.pem"
	}
	mycertfile := certfile
	if mycertfile == "" {
		mycertfile = "cert.pem"
	}
	ctx := CertContext{
		PKFile:         mypkfile,
		ServerCertFile: mycertfile,
	}
	_, err1 := os.Stat(ctx.ServerCertFile)
	_, err2 := os.Stat(ctx.PKFile)
	if os.IsNotExist(err1) || os.IsNotExist(err2) {
		fmt.Println("At least one of the Key/Cert files is not found -> Generating new key pair")
		err = ctx.initServerCert(host)
		if err != nil {
			return nil, fmt.Errorf("Unable to init server cert: %s\n", err)
		}
	} /* else if *debug {
	    fmt.Println("Using provided Key/Cert files")
	}*/

	tlsConfig := Server()
	cert, err := tls.LoadX509KeyPair(ctx.ServerCertFile, ctx.PKFile)
	if err != nil {
		return nil, fmt.Errorf("Unable to load certificate and key from %s and %s: %s\n", ctx.ServerCertFile, ctx.PKFile, err)
	}
	tlsConfig.Certificates = []tls.Certificate{cert}

	return tls.NewListener(l, tlsConfig), nil
}

// CertContext encapsulates the certificates used by a Server
type CertContext struct {
	PKFile         string
	ServerCertFile string
	PK             *keyman.PrivateKey
	ServerCert     *keyman.Certificate
}

// InitServerCert initializes a PK + cert for use by a server proxy, signed by
// the CA certificate.  We always generate a new certificate just in case.
func (ctx *CertContext) initServerCert(host string) (err error) {
	if ctx.PK, err = keyman.LoadPKFromFile(ctx.PKFile); err != nil {
		if os.IsNotExist(err) {
			fmt.Printf("Creating new PK at: %s\n", ctx.PKFile)
			if ctx.PK, err = keyman.GeneratePK(2048); err != nil {
				return
			}
			if err = ctx.PK.WriteToFile(ctx.PKFile); err != nil {
				return fmt.Errorf("Unable to save private key: %s\n", err)
			}
		} else {
			return fmt.Errorf("Unable to read private key, even though it exists: %s\n", err)
		}
	}

	fmt.Printf("Creating new server cert at: %s\n", ctx.ServerCertFile)
	ctx.ServerCert, err = ctx.PK.TLSCertificateFor("Lantern", host, tenYearsFromToday, true, nil)
	if err != nil {
		return
	}
	err = ctx.ServerCert.WriteToFile(ctx.ServerCertFile)
	if err != nil {
		return
	}
	return nil
}
<commit_msg>Exposed BuildListenerConfig function<commit_after>package tlsdefaults

import (
	"crypto/tls"
	"fmt"
	"net"
	"os"
	"time"

	"github.com/getlantern/keyman"
)

var (
	tenYearsFromToday = time.Now().AddDate(10, 0, 0)
)

// Listen opens a TLS listener at the given address using the private key and
// certificate PEM files at the given paths. If no files exists, it creates a
// new key and self-signed certificate at those locations.
func Listen(addr, pkfile, certfile string) (net.Listener, error) {
	l, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, fmt.Errorf("Unable to listen for connections at %s: %s\n", addr, err)
	}

	return NewListenerAddr(l, addr, pkfile, certfile)
}

// NewListener creates a TLS listener based on the given listener using the
// private key and certificate PEM files at the given paths. If no files exists,
// it creates a new key and self-signed certificate at those locations.
func NewListener(l net.Listener, pkfile, certfile string) (net.Listener, error) {
	return NewListenerAddr(l, l.Addr().String(), pkfile, certfile)
}

// NewListenerAddr is like NewListener but uses the specified addr to generate
// the cert.
func NewListenerAddr(l net.Listener, addr string, pkfile, certfile string) (net.Listener, error) {
	cfg, err := BuildListenerConfig(addr, pkfile, certfile)
	if err != nil {
		return nil, err
	}
	return tls.NewListener(l, cfg), nil
}

// BuildListenerConfig builds a tls.Config for a listener at the given addr
func BuildListenerConfig(addr string, pkfile string, certfile string) (*tls.Config, error) {
	host, _, err := net.SplitHostPort(addr)
	if err != nil {
		return nil, fmt.Errorf("Unable to split host and port for %v: %v\n", addr, err)
	}

	mypkfile := pkfile
	if mypkfile == "" {
		mypkfile = "key.pem"
	}
	mycertfile := certfile
	if mycertfile == "" {
		mycertfile = "cert.pem"
	}
	ctx := CertContext{
		PKFile:         mypkfile,
		ServerCertFile: mycertfile,
	}
	_, err1 := os.Stat(ctx.ServerCertFile)
	_, err2 := os.Stat(ctx.PKFile)
	if os.IsNotExist(err1) || os.IsNotExist(err2) {
		fmt.Println("At least one of the Key/Cert files is not found -> Generating new key pair")
		err = ctx.initServerCert(host)
		if err != nil {
			return nil, fmt.Errorf("Unable to init server cert: %s\n", err)
		}
	} /* else if *debug {
	    fmt.Println("Using provided Key/Cert files")
	}*/

	tlsConfig := Server()
	cert, err := tls.LoadX509KeyPair(ctx.ServerCertFile, ctx.PKFile)
	if err != nil {
		return nil, fmt.Errorf("Unable to load certificate and key from %s and %s: %s\n", ctx.ServerCertFile, ctx.PKFile, err)
	}
	tlsConfig.Certificates = []tls.Certificate{cert}

	return tlsConfig, nil
}

// CertContext encapsulates the certificates used by a Server
type CertContext struct {
	PKFile         string
	ServerCertFile string
	PK             *keyman.PrivateKey
	ServerCert     *keyman.Certificate
}

// InitServerCert initializes a PK + cert for use by a server proxy, signed by
// the CA certificate.  We always generate a new certificate just in case.
func (ctx *CertContext) initServerCert(host string) (err error) {
	if ctx.PK, err = keyman.LoadPKFromFile(ctx.PKFile); err != nil {
		if os.IsNotExist(err) {
			fmt.Printf("Creating new PK at: %s\n", ctx.PKFile)
			if ctx.PK, err = keyman.GeneratePK(2048); err != nil {
				return
			}
			if err = ctx.PK.WriteToFile(ctx.PKFile); err != nil {
				return fmt.Errorf("Unable to save private key: %s\n", err)
			}
		} else {
			return fmt.Errorf("Unable to read private key, even though it exists: %s\n", err)
		}
	}

	fmt.Printf("Creating new server cert at: %s\n", ctx.ServerCertFile)
	ctx.ServerCert, err = ctx.PK.TLSCertificateFor("Lantern", host, tenYearsFromToday, true, nil)
	if err != nil {
		return
	}
	err = ctx.ServerCert.WriteToFile(ctx.ServerCertFile)
	if err != nil {
		return
	}
	return nil
}
<|endoftext|>


<commit_before>package ics

import (
	"encoding/base64"
	"errors"
)

const (
	calscalec        = "CALSCALE"
	methodc          = "METHOD"
	prodidc          = "PRODID"
	versionc         = "VERSION"
	attachc          = "ATTACH"
	categoriesc      = "CATEGORIES"
	classc           = "CLASS"
	commentc         = "COMMENT"
	descriptionc     = "DESCRIPTION"
	geoc             = "GEO"
	locationc        = "LOCATION"
	percentcompletec = "PERCENT-COMPLETE"
	priorityc        = "PRIORITY"
	resourcesc       = "RESOURCES"
	statusc          = "STATUS"
	summaryc         = "SUMMARY"
	completedc       = "COMPLETED"
	dtendc           = "DTEND"
	duec             = "DUE"
	dtstartc         = "DTSTART"
	durationc        = "DURATION"
	freebusyc        = "FREEBUSY"
	transpc          = "TRANSP"
	tzidc            = "TZID"
	tznamec          = "TZNAME"
	tzoffsetfromc    = "TZOFFSETFROM"
	tzoffsettoc      = "TZOFFSETTO"
	tzurlc           = "TZURL"
	attendeec        = "ATTENDEE"
	contactc         = "CONTACT"
	organizerc       = "ORGANIZER"
	recuridc         = "RECURRENCE-ID"
	relatedc         = "RELATED-TO"
	urlc             = "URL"
	uidc             = "UID"
	exdatec          = "EXDATE"
	rdatec           = "RDATE"
	rrulec           = "RRULE"
	actionc          = "ACTION"
	repeatc          = "REPEAT"
	triggerc         = "TRIGGER"
	createdc         = "CREATED"
	dtstampc         = "DTSTAMP"
	lastmodc         = "LAST-MODIFIED"
	seqc             = "SEQUENCE"
)

type component interface{}

type attach struct {
	URI  bool
	Mime string
	Data []byte
}

func (p *parser) readAttachComponent() (component, error) {
	as, err := p.readAttributes(fmttypeparam, encodingparam, valuetypeparam)
	if err != nil {
		return nil, err
	}
	value, err := p.readValue()
	if err != nil {
		return nil, err
	}
	uri := true
	enc, encOK := as[encodingparam]
	val, valOK := as[valuetypeparam]
	var data []byte
	if encOK && valOK {
		uri = false
		if enc.(encoding) != encodingBase64 || val.(value) != valueBinary {
			return nil, ErrUnsupportedValue
		}
		data, err = base64.StdEncoding.DecodeString(value)
		if err != nil {
			return nil, err
		}

	} else if encOK == valOK {
		data = []byte(unescape(value))
	} else {
		return nil, ErrInvalidAttributeCombination
	}
	return attach{
		uri,
		as[fmttypeparam],
		data,
	}, nil
}

type categories struct {
	Language   string
	Categories []string
}

func (p *parser) readCategoriesComponent() (component, error) {
	as, err := p.readAttributes(languageparam)
	if err != nil {
		return nil, err
	}
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	language := ""
	if l, ok := as[languageparam]; ok {
		language = l.String()
	}
	return categories{
		language,
		textSplit(v),
	}, nil
}

const (
	classPublic = iota
	classPrivate
	classConfidential
)

type class struct {
	Value int
}

func (p *parser) readClassComponent() (component, error) {
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	var cv int
	switch v {
	case "PUBLIC":
		cv = classPublic
	case "PRIVATE":
		cv = classPrivate
	case "CONFIDENTIAL":
		cv = classConfidential
	default:
		cv = classPrivate
	}
	return class{cv}, nil
}

type comment struct {
	Altrep, Language string
}

func (p *parser) readCommentComponent() (component, error) {

}

type unknown struct {
	Name   string
	Params []token
	Value  string
}

func (p *parser) readUnknownComponent(name string) (component, error) {
	vs, err := p.readAttributes()
	if err != nil {
		return nil, err
	}
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	return unknown{
		name,
		vs,
		v,
	}, err
}

// Errors

var (
	ErrUnsupportedValue            = errors.New("attribute contained unsupported value")
	ErrInvalidAttributeCombination = errors.New("invalid combination of attributes")
)
<commit_msg>added more component parsing<commit_after>package ics

import (
	"encoding/base64"
	"errors"
)

const (
	calscalec        = "CALSCALE"
	methodc          = "METHOD"
	prodidc          = "PRODID"
	versionc         = "VERSION"
	attachc          = "ATTACH"
	categoriesc      = "CATEGORIES"
	classc           = "CLASS"
	commentc         = "COMMENT"
	descriptionc     = "DESCRIPTION"
	geoc             = "GEO"
	locationc        = "LOCATION"
	percentcompletec = "PERCENT-COMPLETE"
	priorityc        = "PRIORITY"
	resourcesc       = "RESOURCES"
	statusc          = "STATUS"
	summaryc         = "SUMMARY"
	completedc       = "COMPLETED"
	dtendc           = "DTEND"
	duec             = "DUE"
	dtstartc         = "DTSTART"
	durationc        = "DURATION"
	freebusyc        = "FREEBUSY"
	transpc          = "TRANSP"
	tzidc            = "TZID"
	tznamec          = "TZNAME"
	tzoffsetfromc    = "TZOFFSETFROM"
	tzoffsettoc      = "TZOFFSETTO"
	tzurlc           = "TZURL"
	attendeec        = "ATTENDEE"
	contactc         = "CONTACT"
	organizerc       = "ORGANIZER"
	recuridc         = "RECURRENCE-ID"
	relatedc         = "RELATED-TO"
	urlc             = "URL"
	uidc             = "UID"
	exdatec          = "EXDATE"
	rdatec           = "RDATE"
	rrulec           = "RRULE"
	actionc          = "ACTION"
	repeatc          = "REPEAT"
	triggerc         = "TRIGGER"
	createdc         = "CREATED"
	dtstampc         = "DTSTAMP"
	lastmodc         = "LAST-MODIFIED"
	seqc             = "SEQUENCE"
)

type component interface{}

type calscale string

func (p *parser) readCalScaleComponent() (component, error) {
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	return calscale(unescape(v)), nil
}

type method string

func (p *parser) readMethodComponent() (component, error) {
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	return method(unescape(v)), nil
}

type productID string

func (p *parser) readProductIDComponent() (component, error) {
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	return productID(unescape(v)), nil
}

type version struct {
	Min, Max string
}

func (p *parser) readVersionComponent() (component, error) {
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	parts := textSplit(v, ';')
	if len(parts) > 2 {
		return nil, ErrUnsupportedValue
	} else if len(parts) == 2 {
		return version{parts[0], parts[1]}, nil
	} else {
		return version{parts[0], parts[0]}, nil
	}
}

type attach struct {
	URI  bool
	Mime string
	Data []byte
}

func (p *parser) readAttachComponent() (component, error) {
	as, err := p.readAttributes(fmttypeparam, encodingparam, valuetypeparam)
	if err != nil {
		return nil, err
	}
	value, err := p.readValue()
	if err != nil {
		return nil, err
	}
	uri := true
	enc, encOK := as[encodingparam]
	val, valOK := as[valuetypeparam]
	var data []byte
	if encOK && valOK {
		uri = false
		if enc.(encoding) != encodingBase64 || val.(value) != valueBinary {
			return nil, ErrUnsupportedValue
		}
		data, err = base64.StdEncoding.DecodeString(value)
		if err != nil {
			return nil, err
		}

	} else if encOK == valOK {
		data = []byte(unescape(value))
	} else {
		return nil, ErrInvalidAttributeCombination
	}
	return attach{
		uri,
		as[fmttypeparam],
		data,
	}, nil
}

type categories struct {
	Language   string
	Categories []string
}

func (p *parser) readCategoriesComponent() (component, error) {
	as, err := p.readAttributes(languageparam)
	if err != nil {
		return nil, err
	}
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	language := ""
	if l, ok := as[languageparam]; ok {
		language = l.String()
	}
	return categories{
		language,
		textSplit(v, ','),
	}, nil
}

const (
	classPublic = iota
	classPrivate
	classConfidential
)

type class struct {
	Value int
}

func (p *parser) readClassComponent() (component, error) {
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	var cv int
	switch v {
	case "PUBLIC":
		cv = classPublic
	case "PRIVATE":
		cv = classPrivate
	case "CONFIDENTIAL":
		cv = classConfidential
	default:
		cv = classPrivate
	}
	return class{cv}, nil
}

type comment struct {
	Altrep, Language string
}

func (p *parser) readCommentComponent() (component, error) {

}

type unknown struct {
	Name   string
	Params []token
	Value  string
}

func (p *parser) readUnknownComponent(name string) (component, error) {
	vs, err := p.readAttributes()
	if err != nil {
		return nil, err
	}
	v, err := p.readValue()
	if err != nil {
		return nil, err
	}
	return unknown{
		name,
		vs,
		v,
	}, err
}

// Errors

var (
	ErrUnsupportedValue            = errors.New("attribute contained unsupported value")
	ErrInvalidAttributeCombination = errors.New("invalid combination of attributes")
)
<|endoftext|>