package net
import _ "unsafe"
import (
"context"
"syscall"
"unsafe"
)
type addrinfoErrno int
func (eai addrinfoErrno ) Error () string { return ( _Cfunc_GoString )(( _Cfunc_gai_strerror )( _Ctype_int (eai ))) }
func (eai addrinfoErrno ) Temporary () bool { return eai == ( _Ciconst_EAI_AGAIN ) }
func (eai addrinfoErrno ) Timeout () bool { return false }
type portLookupResult struct {
port int
err error
}
type ipLookupResult struct {
addrs []IPAddr
cname string
err error
}
type reverseLookupResult struct {
names []string
err error
}
func cgoLookupHost (ctx context .Context , name string ) (hosts []string , err error , completed bool ) {
addrs , err , completed := cgoLookupIP (ctx , "ip" , name )
for _ , addr := range addrs {
hosts = append (hosts , addr .String ())
}
return
}
func cgoLookupPort (ctx context .Context , network , service string ) (port int , err error , completed bool ) {
var hints _Ctype_struct_addrinfo
switch network {
case "" :
case "tcp" , "tcp4" , "tcp6" :
hints .ai_socktype = ( _Ciconst_SOCK_STREAM )
hints .ai_protocol = ( _Ciconst_IPPROTO_TCP )
case "udp" , "udp4" , "udp6" :
hints .ai_socktype = ( _Ciconst_SOCK_DGRAM )
hints .ai_protocol = ( _Ciconst_IPPROTO_UDP )
default :
return 0 , &DNSError {Err : "unknown network" , Name : network + "/" + service }, true
}
switch ipVersion (network ) {
case '4' :
hints .ai_family = ( _Ciconst_AF_INET )
case '6' :
hints .ai_family = ( _Ciconst_AF_INET6 )
}
if ctx .Done () == nil {
port , err := cgoLookupServicePort (&hints , network , service )
return port , err , true
}
result := make (chan portLookupResult , 1 )
go cgoPortLookup (result , &hints , network , service )
select {
case r := <- result :
return r .port , r .err , true
case <- ctx .Done ():
return 0 , mapErr (ctx .Err ()), false
}
}
func cgoLookupServicePort (hints * _Ctype_struct_addrinfo , network , service string ) (port int , err error ) {
cservice := make ([]byte , len (service )+1 )
copy (cservice , service )
for i , b := range cservice [:len (service )] {
cservice [i ] = lowerASCII (b )
}
var res * _Ctype_struct_addrinfo
gerrno , err := func () (_Ctype_int , error ){ var _cgo0 *_Ctype_char = nil ; var _cgo1 *_Ctype_char = (*_Ctype_char )(unsafe .Pointer (&cservice [0 ])); _cgo2 := hints ; _cgoBase3 := &res ; _cgo3 := _cgoBase3 ; _cgoCheckPointer (_cgo2 , nil ); _cgoCheckPointer (_cgoBase3 , 0 == 0 ); return _C2func_getaddrinfo (_cgo0 , _cgo1 , _cgo2 , _cgo3 ); }()
if gerrno != 0 {
isTemporary := false
switch gerrno {
case ( _Ciconst_EAI_SYSTEM ):
if err == nil {
err = syscall .EMFILE
}
default :
err = addrinfoErrno (gerrno )
isTemporary = addrinfoErrno (gerrno ).Temporary ()
}
return 0 , &DNSError {Err : err .Error(), Name : network + "/" + service , IsTemporary : isTemporary }
}
defer func () func () { _cgo0 := res ; return func () { _cgoCheckPointer (_cgo0 , nil ); _Cfunc_freeaddrinfo (_cgo0 ); }}()()
for r := res ; r != nil ; r = r .ai_next {
switch r .ai_family {
case ( _Ciconst_AF_INET ):
sa := (*syscall .RawSockaddrInet4 )(unsafe .Pointer (r .ai_addr ))
p := (*[2 ]byte )(unsafe .Pointer (&sa .Port ))
return int (p [0 ])<<8 | int (p [1 ]), nil
case ( _Ciconst_AF_INET6 ):
sa := (*syscall .RawSockaddrInet6 )(unsafe .Pointer (r .ai_addr ))
p := (*[2 ]byte )(unsafe .Pointer (&sa .Port ))
return int (p [0 ])<<8 | int (p [1 ]), nil
}
}
return 0 , &DNSError {Err : "unknown port" , Name : network + "/" + service }
}
func cgoPortLookup (result chan <- portLookupResult , hints * _Ctype_struct_addrinfo , network , service string ) {
port , err := cgoLookupServicePort (hints , network , service )
result <- portLookupResult {port , err }
}
func cgoLookupIPCNAME (network , name string ) (addrs []IPAddr , cname string , err error ) {
acquireThread ()
defer releaseThread ()
var hints _Ctype_struct_addrinfo
hints .ai_flags = cgoAddrInfoFlags
hints .ai_socktype = ( _Ciconst_SOCK_STREAM )
hints .ai_family = ( _Ciconst_AF_UNSPEC )
switch ipVersion (network ) {
case '4' :
hints .ai_family = ( _Ciconst_AF_INET )
case '6' :
hints .ai_family = ( _Ciconst_AF_INET6 )
}
h := make ([]byte , len (name )+1 )
copy (h , name )
var res * _Ctype_struct_addrinfo
gerrno , err := func () (_Ctype_int , error ){ var _cgo0 *_Ctype_char = (*_Ctype_char )(unsafe .Pointer (&h [0 ])); var _cgo1 *_Ctype_char = nil ; _cgoBase2 := &hints ; _cgo2 := _cgoBase2 ; _cgoBase3 := &res ; _cgo3 := _cgoBase3 ; _cgoCheckPointer (_cgoBase2 , 0 == 0 ); _cgoCheckPointer (_cgoBase3 , 0 == 0 ); return _C2func_getaddrinfo (_cgo0 , _cgo1 , _cgo2 , _cgo3 ); }()
if gerrno != 0 {
isErrorNoSuchHost := false
isTemporary := false
switch gerrno {
case ( _Ciconst_EAI_SYSTEM ):
if err == nil {
err = syscall .EMFILE
}
case ( _Ciconst_EAI_NONAME ):
err = errNoSuchHost
isErrorNoSuchHost = true
default :
err = addrinfoErrno (gerrno )
isTemporary = addrinfoErrno (gerrno ).Temporary ()
}
return nil , "" , &DNSError {Err : err .Error(), Name : name , IsNotFound : isErrorNoSuchHost , IsTemporary : isTemporary }
}
defer func () func () { _cgo0 := res ; return func () { _cgoCheckPointer (_cgo0 , nil ); _Cfunc_freeaddrinfo (_cgo0 ); }}()()
if res != nil {
cname = ( _Cfunc_GoString )(res .ai_canonname )
if cname == "" {
cname = name
}
if len (cname ) > 0 && cname [len (cname )-1 ] != '.' {
cname += "."
}
}
for r := res ; r != nil ; r = r .ai_next {
if r .ai_socktype != ( _Ciconst_SOCK_STREAM ) {
continue
}
switch r .ai_family {
case ( _Ciconst_AF_INET ):
sa := (*syscall .RawSockaddrInet4 )(unsafe .Pointer (r .ai_addr ))
addr := IPAddr {IP : copyIP (sa .Addr [:])}
addrs = append (addrs , addr )
case ( _Ciconst_AF_INET6 ):
sa := (*syscall .RawSockaddrInet6 )(unsafe .Pointer (r .ai_addr ))
addr := IPAddr {IP : copyIP (sa .Addr [:]), Zone : zoneCache .name (int (sa .Scope_id ))}
addrs = append (addrs , addr )
}
}
return addrs , cname , nil
}
func cgoIPLookup (result chan <- ipLookupResult , network , name string ) {
addrs , cname , err := cgoLookupIPCNAME (network , name )
result <- ipLookupResult {addrs , cname , err }
}
func cgoLookupIP (ctx context .Context , network , name string ) (addrs []IPAddr , err error , completed bool ) {
if ctx .Done () == nil {
addrs , _, err = cgoLookupIPCNAME (network , name )
return addrs , err , true
}
result := make (chan ipLookupResult , 1 )
go cgoIPLookup (result , network , name )
select {
case r := <- result :
return r .addrs , r .err , true
case <- ctx .Done ():
return nil , mapErr (ctx .Err ()), false
}
}
func cgoLookupCNAME (ctx context .Context , name string ) (cname string , err error , completed bool ) {
if ctx .Done () == nil {
_, cname , err = cgoLookupIPCNAME ("ip" , name )
return cname , err , true
}
result := make (chan ipLookupResult , 1 )
go cgoIPLookup (result , "ip" , name )
select {
case r := <- result :
return r .cname , r .err , true
case <- ctx .Done ():
return "" , mapErr (ctx .Err ()), false
}
}
const (
nameinfoLen = 64
maxNameinfoLen = 4096
)
func cgoLookupPTR (ctx context .Context , addr string ) (names []string , err error , completed bool ) {
var zone string
ip := parseIPv4 (addr )
if ip == nil {
ip , zone = parseIPv6Zone (addr )
}
if ip == nil {
return nil , &DNSError {Err : "invalid address" , Name : addr }, true
}
sa , salen := cgoSockaddr (ip , zone )
if sa == nil {
return nil , &DNSError {Err : "invalid address " + ip .String (), Name : addr }, true
}
if ctx .Done () == nil {
names , err := cgoLookupAddrPTR (addr , sa , salen )
return names , err , true
}
result := make (chan reverseLookupResult , 1 )
go cgoReverseLookup (result , addr , sa , salen )
select {
case r := <- result :
return r .names , r .err , true
case <- ctx .Done ():
return nil , mapErr (ctx .Err ()), false
}
}
func cgoLookupAddrPTR (addr string , sa * _Ctype_struct_sockaddr , salen _Ctype_socklen_t ) (names []string , err error ) {
acquireThread ()
defer releaseThread ()
var gerrno int
var b []byte
for l := nameinfoLen ; l <= maxNameinfoLen ; l *= 2 {
b = make ([]byte , l )
gerrno , err = cgoNameinfoPTR (b , sa , salen )
if gerrno == 0 || gerrno != ( _Ciconst_EAI_OVERFLOW ) {
break
}
}
if gerrno != 0 {
isTemporary := false
switch gerrno {
case ( _Ciconst_EAI_SYSTEM ):
if err == nil {
err = syscall .EMFILE
}
default :
err = addrinfoErrno (gerrno )
isTemporary = addrinfoErrno (gerrno ).Temporary ()
}
return nil , &DNSError {Err : err .Error(), Name : addr , IsTemporary : isTemporary }
}
for i := 0 ; i < len (b ); i ++ {
if b [i ] == 0 {
b = b [:i ]
break
}
}
return []string {absDomainName (b )}, nil
}
func cgoReverseLookup (result chan <- reverseLookupResult , addr string , sa * _Ctype_struct_sockaddr , salen _Ctype_socklen_t ) {
names , err := cgoLookupAddrPTR (addr , sa , salen )
result <- reverseLookupResult {names , err }
}
func cgoSockaddr (ip IP , zone string ) (* _Ctype_struct_sockaddr , _Ctype_socklen_t ) {
if ip4 := ip .To4 (); ip4 != nil {
return cgoSockaddrInet4 (ip4 ), _Ctype_socklen_t (syscall .SizeofSockaddrInet4 )
}
if ip6 := ip .To16 (); ip6 != nil {
return cgoSockaddrInet6 (ip6 , zoneCache .index (zone )), _Ctype_socklen_t (syscall .SizeofSockaddrInet6 )
}
return nil , 0
}
func copyIP (x IP ) IP {
if len (x ) < 16 {
return x .To16 ()
}
y := make (IP , len (x ))
copy (y , x )
return y
}
The pages are generated with Golds v0.3.6 . (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .