github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/internal/iana/gen.go (about)

     1  // Copyright 2013 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build ignore
     6  
     7  //go:generate go run gen.go
     8  
     9  // This program generates internet protocol constants and tables by
    10  // reading IANA protocol registries.
    11  package main
    12  
    13  import (
    14  	"bytes"
    15  	"encoding/xml"
    16  	"fmt"
    17  	"go/format"
    18  	"io"
    19  	"io/ioutil"
    20  	"net/http"
    21  	"os"
    22  	"strconv"
    23  	"strings"
    24  )
    25  
    26  var registries = []struct {
    27  	url   string
    28  	parse func(io.Writer, io.Reader) error
    29  }{
    30  	{
    31  		"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
    32  		parseDSCPRegistry,
    33  	},
    34  	{
    35  		"http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
    36  		parseTOSTCByte,
    37  	},
    38  	{
    39  		"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
    40  		parseProtocolNumbers,
    41  	},
    42  }
    43  
    44  func main() {
    45  	var bb bytes.Buffer
    46  	fmt.Fprintf(&bb, "// go generate gen.go\n")
    47  	fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
    48  	fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
    49  	fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
    50  	for _, r := range registries {
    51  		resp, err := http.Get(r.url)
    52  		if err != nil {
    53  			fmt.Fprintln(os.Stderr, err)
    54  			os.Exit(1)
    55  		}
    56  		defer resp.Body.Close()
    57  		if resp.StatusCode != http.StatusOK {
    58  			fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
    59  			os.Exit(1)
    60  		}
    61  		if err := r.parse(&bb, resp.Body); err != nil {
    62  			fmt.Fprintln(os.Stderr, err)
    63  			os.Exit(1)
    64  		}
    65  		fmt.Fprintf(&bb, "\n")
    66  	}
    67  	b, err := format.Source(bb.Bytes())
    68  	if err != nil {
    69  		fmt.Fprintln(os.Stderr, err)
    70  		os.Exit(1)
    71  	}
    72  	if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
    73  		fmt.Fprintln(os.Stderr, err)
    74  		os.Exit(1)
    75  	}
    76  }
    77  
    78  func parseDSCPRegistry(w io.Writer, r io.Reader) error {
    79  	dec := xml.NewDecoder(r)
    80  	var dr dscpRegistry
    81  	if err := dec.Decode(&dr); err != nil {
    82  		return err
    83  	}
    84  	drs := dr.escape()
    85  	fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
    86  	fmt.Fprintf(w, "const (\n")
    87  	for _, dr := range drs {
    88  		fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
    89  		fmt.Fprintf(w, "// %s\n", dr.OrigName)
    90  	}
    91  	fmt.Fprintf(w, ")\n")
    92  	return nil
    93  }
    94  
    95  type dscpRegistry struct {
    96  	XMLName     xml.Name `xml:"registry"`
    97  	Title       string   `xml:"title"`
    98  	Updated     string   `xml:"updated"`
    99  	Note        string   `xml:"note"`
   100  	RegTitle    string   `xml:"registry>title"`
   101  	PoolRecords []struct {
   102  		Name  string `xml:"name"`
   103  		Space string `xml:"space"`
   104  	} `xml:"registry>record"`
   105  	Records []struct {
   106  		Name  string `xml:"name"`
   107  		Space string `xml:"space"`
   108  	} `xml:"registry>registry>record"`
   109  }
   110  
   111  type canonDSCPRecord struct {
   112  	OrigName string
   113  	Name     string
   114  	Value    int
   115  }
   116  
   117  func (drr *dscpRegistry) escape() []canonDSCPRecord {
   118  	drs := make([]canonDSCPRecord, len(drr.Records))
   119  	sr := strings.NewReplacer(
   120  		"+", "",
   121  		"-", "",
   122  		"/", "",
   123  		".", "",
   124  		" ", "",
   125  	)
   126  	for i, dr := range drr.Records {
   127  		s := strings.TrimSpace(dr.Name)
   128  		drs[i].OrigName = s
   129  		drs[i].Name = sr.Replace(s)
   130  		n, err := strconv.ParseUint(dr.Space, 2, 8)
   131  		if err != nil {
   132  			continue
   133  		}
   134  		drs[i].Value = int(n) << 2
   135  	}
   136  	return drs
   137  }
   138  
   139  func parseTOSTCByte(w io.Writer, r io.Reader) error {
   140  	dec := xml.NewDecoder(r)
   141  	var ttb tosTCByte
   142  	if err := dec.Decode(&ttb); err != nil {
   143  		return err
   144  	}
   145  	trs := ttb.escape()
   146  	fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
   147  	fmt.Fprintf(w, "const (\n")
   148  	for _, tr := range trs {
   149  		fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
   150  		fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
   151  	}
   152  	fmt.Fprintf(w, ")\n")
   153  	return nil
   154  }
   155  
   156  type tosTCByte struct {
   157  	XMLName  xml.Name `xml:"registry"`
   158  	Title    string   `xml:"title"`
   159  	Updated  string   `xml:"updated"`
   160  	Note     string   `xml:"note"`
   161  	RegTitle string   `xml:"registry>title"`
   162  	Records  []struct {
   163  		Binary  string `xml:"binary"`
   164  		Keyword string `xml:"keyword"`
   165  	} `xml:"registry>record"`
   166  }
   167  
   168  type canonTOSTCByteRecord struct {
   169  	OrigKeyword string
   170  	Keyword     string
   171  	Value       int
   172  }
   173  
   174  func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
   175  	trs := make([]canonTOSTCByteRecord, len(ttb.Records))
   176  	sr := strings.NewReplacer(
   177  		"Capable", "",
   178  		"(", "",
   179  		")", "",
   180  		"+", "",
   181  		"-", "",
   182  		"/", "",
   183  		".", "",
   184  		" ", "",
   185  	)
   186  	for i, tr := range ttb.Records {
   187  		s := strings.TrimSpace(tr.Keyword)
   188  		trs[i].OrigKeyword = s
   189  		ss := strings.Split(s, " ")
   190  		if len(ss) > 1 {
   191  			trs[i].Keyword = strings.Join(ss[1:], " ")
   192  		} else {
   193  			trs[i].Keyword = ss[0]
   194  		}
   195  		trs[i].Keyword = sr.Replace(trs[i].Keyword)
   196  		n, err := strconv.ParseUint(tr.Binary, 2, 8)
   197  		if err != nil {
   198  			continue
   199  		}
   200  		trs[i].Value = int(n)
   201  	}
   202  	return trs
   203  }
   204  
   205  func parseProtocolNumbers(w io.Writer, r io.Reader) error {
   206  	dec := xml.NewDecoder(r)
   207  	var pn protocolNumbers
   208  	if err := dec.Decode(&pn); err != nil {
   209  		return err
   210  	}
   211  	prs := pn.escape()
   212  	prs = append([]canonProtocolRecord{{
   213  		Name:  "IP",
   214  		Descr: "IPv4 encapsulation, pseudo protocol number",
   215  		Value: 0,
   216  	}}, prs...)
   217  	fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
   218  	fmt.Fprintf(w, "const (\n")
   219  	for _, pr := range prs {
   220  		if pr.Name == "" {
   221  			continue
   222  		}
   223  		fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
   224  		s := pr.Descr
   225  		if s == "" {
   226  			s = pr.OrigName
   227  		}
   228  		fmt.Fprintf(w, "// %s\n", s)
   229  	}
   230  	fmt.Fprintf(w, ")\n")
   231  	return nil
   232  }
   233  
   234  type protocolNumbers struct {
   235  	XMLName  xml.Name `xml:"registry"`
   236  	Title    string   `xml:"title"`
   237  	Updated  string   `xml:"updated"`
   238  	RegTitle string   `xml:"registry>title"`
   239  	Note     string   `xml:"registry>note"`
   240  	Records  []struct {
   241  		Value string `xml:"value"`
   242  		Name  string `xml:"name"`
   243  		Descr string `xml:"description"`
   244  	} `xml:"registry>record"`
   245  }
   246  
   247  type canonProtocolRecord struct {
   248  	OrigName string
   249  	Name     string
   250  	Descr    string
   251  	Value    int
   252  }
   253  
   254  func (pn *protocolNumbers) escape() []canonProtocolRecord {
   255  	prs := make([]canonProtocolRecord, len(pn.Records))
   256  	sr := strings.NewReplacer(
   257  		"-in-", "in",
   258  		"-within-", "within",
   259  		"-over-", "over",
   260  		"+", "P",
   261  		"-", "",
   262  		"/", "",
   263  		".", "",
   264  		" ", "",
   265  	)
   266  	for i, pr := range pn.Records {
   267  		if strings.Contains(pr.Name, "Deprecated") ||
   268  			strings.Contains(pr.Name, "deprecated") {
   269  			continue
   270  		}
   271  		prs[i].OrigName = pr.Name
   272  		s := strings.TrimSpace(pr.Name)
   273  		switch pr.Name {
   274  		case "ISIS over IPv4":
   275  			prs[i].Name = "ISIS"
   276  		case "manet":
   277  			prs[i].Name = "MANET"
   278  		default:
   279  			prs[i].Name = sr.Replace(s)
   280  		}
   281  		ss := strings.Split(pr.Descr, "\n")
   282  		for i := range ss {
   283  			ss[i] = strings.TrimSpace(ss[i])
   284  		}
   285  		if len(ss) > 1 {
   286  			prs[i].Descr = strings.Join(ss, " ")
   287  		} else {
   288  			prs[i].Descr = ss[0]
   289  		}
   290  		prs[i].Value, _ = strconv.Atoi(pr.Value)
   291  	}
   292  	return prs
   293  }