github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/net/port_unix.go (about)

     1  // Copyright 2009 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 darwin dragonfly freebsd linux netbsd openbsd solaris
     6  
     7  // Read system port mappings from /etc/services
     8  
     9  package net
    10  
    11  import "sync"
    12  
    13  // services contains minimal mappings between services names and port
    14  // numbers for platforms that don't have a complete list of port numbers
    15  // (some Solaris distros).
    16  var services = map[string]map[string]int{
    17  	"tcp": {"http": 80},
    18  }
    19  var servicesError error
    20  var onceReadServices sync.Once
    21  
    22  func readServices() {
    23  	var file *file
    24  	if file, servicesError = open("/etc/services"); servicesError != nil {
    25  		return
    26  	}
    27  	for line, ok := file.readLine(); ok; line, ok = file.readLine() {
    28  		// "http 80/tcp www www-http # World Wide Web HTTP"
    29  		if i := byteIndex(line, '#'); i >= 0 {
    30  			line = line[0:i]
    31  		}
    32  		f := getFields(line)
    33  		if len(f) < 2 {
    34  			continue
    35  		}
    36  		portnet := f[1] // "80/tcp"
    37  		port, j, ok := dtoi(portnet, 0)
    38  		if !ok || port <= 0 || j >= len(portnet) || portnet[j] != '/' {
    39  			continue
    40  		}
    41  		netw := portnet[j+1:] // "tcp"
    42  		m, ok1 := services[netw]
    43  		if !ok1 {
    44  			m = make(map[string]int)
    45  			services[netw] = m
    46  		}
    47  		for i := 0; i < len(f); i++ {
    48  			if i != 1 { // f[1] was port/net
    49  				m[f[i]] = port
    50  			}
    51  		}
    52  	}
    53  	file.close()
    54  }
    55  
    56  // goLookupPort is the native Go implementation of LookupPort.
    57  func goLookupPort(network, service string) (port int, err error) {
    58  	onceReadServices.Do(readServices)
    59  
    60  	switch network {
    61  	case "tcp4", "tcp6":
    62  		network = "tcp"
    63  	case "udp4", "udp6":
    64  		network = "udp"
    65  	}
    66  
    67  	if m, ok := services[network]; ok {
    68  		if port, ok = m[service]; ok {
    69  			return
    70  		}
    71  	}
    72  	return 0, &AddrError{"unknown port", network + "/" + service}
    73  }