55package syscall
66
77import (
8+ "encoding/binary"
89 "runtime"
910 "unsafe"
1011)
1112
1213const (
13- _ = iota
14+ AF_UNSPEC = iota
1415 AF_INET
1516 AF_INET6
1617 AF_UNIX
1718)
1819
1920const (
20- _ = iota
21+ SOCK_ANY = iota
2122 SOCK_DGRAM
2223 SOCK_STREAM
2324)
@@ -34,6 +35,19 @@ const (
3435 SO_BROADCAST
3536)
3637
38+ const (
39+ AI_PASSIVE = 1 << iota
40+ _
41+ AI_NUMERICHOST
42+ AI_NUMERICSERV
43+ )
44+
45+ const (
46+ IPPROTO_IP = iota
47+ IPPROTO_TCP
48+ IPPROTO_UDP
49+ )
50+
3751type Sockaddr interface {
3852 sockaddr () (unsafe.Pointer , error )
3953 sockport () int
@@ -126,6 +140,18 @@ func sock_getlocaladdr(fd int32, addr unsafe.Pointer, port unsafe.Pointer) Errno
126140//go:wasmimport wasi_snapshot_preview1 sock_getpeeraddr
127141func sock_getpeeraddr (fd int32 , addr unsafe.Pointer , port unsafe.Pointer ) Errno
128142
143+ //go:wasmimport wasi_snapshot_preview1 sock_getaddrinfo
144+ func sock_getaddrinfo (
145+ node unsafe.Pointer ,
146+ nodeLen uint32 ,
147+ service unsafe.Pointer ,
148+ serviceLen uint32 ,
149+ hints unsafe.Pointer ,
150+ res unsafe.Pointer ,
151+ maxResLen uint32 ,
152+ resLen unsafe.Pointer ,
153+ ) uint32
154+
129155func Socket (proto , sotype , unused int ) (fd int , err error ) {
130156 var newfd int32
131157 errno := sock_open (int32 (proto ), int32 (sotype ), unsafe .Pointer (& newfd ))
@@ -211,3 +237,112 @@ func anyToSockaddr(rsa *RawSockaddrAny, port int) (Sockaddr, error) {
211237 return nil , ENOTSUP
212238 }
213239}
240+
241+ // https://github.com/WasmEdge/WasmEdge/blob/434e1fb4690/thirdparty/wasi/api.hpp#L1885
242+ type addrInfo struct {
243+ ai_flags uint16
244+ ai_family uint8
245+ ai_socktype uint8
246+ ai_protocol uint32
247+ ai_addrlen uint32
248+ ai_addr uintptr32 // *sockAddr
249+ ai_canonname uintptr32 // null-terminated string
250+ ai_canonnamelen uint32
251+ ai_next uintptr32 // *addrInfo
252+ }
253+
254+ type sockAddr struct {
255+ sa_family uint32
256+ sa_data_len uint32
257+ sa_data uintptr32
258+ _ [4 ]byte
259+ }
260+
261+ type AddrInfo struct {
262+ Flags int
263+ Family int
264+ SocketType int
265+ Protocol int
266+ Address Sockaddr
267+ CanonicalName string
268+
269+ addrInfo
270+ sockAddr
271+ sockData [26 ]byte
272+ cannoname [30 ]byte
273+ inet4addr SockaddrInet4
274+ inet6addr SockaddrInet6
275+ }
276+
277+ func Getaddrinfo (name , service string , hints AddrInfo , results []AddrInfo ) (int , error ) {
278+ // For compatibility with WasmEdge, make sure strings are null-terminated.
279+ if len (name ) > 0 && name [len (name )- 1 ] != 0 {
280+ name = string (append ([]byte (name ), 0 ))
281+ }
282+ if len (service ) > 0 && service [len (service )- 1 ] != 0 {
283+ service = string (append ([]byte (service ), 0 ))
284+ }
285+
286+ hints .addrInfo = addrInfo {
287+ ai_flags : uint16 (hints .Flags ),
288+ ai_family : uint8 (hints .Family ),
289+ ai_socktype : uint8 (hints .SocketType ),
290+ ai_protocol : uint32 (hints .Protocol ),
291+ }
292+ for i := range results {
293+ results [i ].sockAddr = sockAddr {
294+ sa_family : 0 ,
295+ sa_data_len : uint32 (unsafe .Sizeof (AddrInfo {}.sockData )),
296+ sa_data : uintptr32 (uintptr (unsafe .Pointer (& results [i ].sockData ))),
297+ }
298+ results [i ].addrInfo = addrInfo {
299+ ai_flags : 0 ,
300+ ai_family : 0 ,
301+ ai_socktype : 0 ,
302+ ai_protocol : 0 ,
303+ ai_addrlen : uint32 (unsafe .Sizeof (sockAddr {})),
304+ ai_addr : uintptr32 (uintptr (unsafe .Pointer (& results [i ].sockAddr ))),
305+ ai_canonname : uintptr32 (uintptr (unsafe .Pointer (& results [i ].cannoname ))),
306+ ai_canonnamelen : uint32 (unsafe .Sizeof (AddrInfo {}.cannoname )),
307+ }
308+ if i > 0 {
309+ results [i - 1 ].addrInfo .ai_next = uintptr32 (uintptr (unsafe .Pointer (& results [i - 1 ])))
310+ }
311+ }
312+
313+ resPtr := uintptr32 (uintptr (unsafe .Pointer (& results [0 ].addrInfo )))
314+
315+ var n uint32
316+ errno := sock_getaddrinfo (
317+ unsafe .Pointer (unsafe .StringData (name )),
318+ uint32 (len (name )),
319+ unsafe .Pointer (unsafe .StringData (service )),
320+ uint32 (len (service )),
321+ unsafe .Pointer (& hints .addrInfo ),
322+ unsafe .Pointer (& resPtr ),
323+ uint32 (len (results )),
324+ unsafe .Pointer (& n ),
325+ )
326+ if errno != 0 {
327+ return 0 , errnoErr (Errno (errno ))
328+ }
329+
330+ for i := range results [:n ] {
331+ r := & results [i ]
332+ port := binary .BigEndian .Uint16 (results [i ].sockData [:2 ])
333+ switch results [i ].sockAddr .sa_family {
334+ case AF_INET :
335+ r .inet4addr .Port = int (port )
336+ copy (r .inet4addr .Addr [:], results [i ].sockData [2 :])
337+ r .Address = & r .inet4addr
338+ case AF_INET6 :
339+ r .inet6addr .Port = int (port )
340+ r .Address = & r .inet6addr
341+ copy (r .inet4addr .Addr [:], results [i ].sockData [2 :])
342+ default :
343+ r .Address = nil
344+ }
345+ // TODO: canonical names
346+ }
347+ return int (n ), nil
348+ }
0 commit comments