Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] llgo/c/hyper-related c lib #523

Merged
merged 2 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions _demo/netdb/netdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/net"
)

func main() {
var hints net.AddrInfo
hints.AiFamily = net.AF_UNSPEC
hints.AiSockType = net.SOCK_STREAM

host := "httpbin.org"
port := "80"

var result *net.AddrInfo
c.Printf(c.Str("%d\n"), net.Getaddrinfo(c.Str(host), c.Str(port), &hints, &result))

c.Printf(c.Str("%d\n"), net.Freeaddrinfo(result))
}
44 changes: 44 additions & 0 deletions _demo/select/select.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/os"
"github.com/goplus/llgo/c/sys"
"github.com/goplus/llgo/c/syscall"
"unsafe"
)

func main() {

Check failure on line 11 in _demo/select/select.go

View workflow job for this annotation

GitHub Actions / test (macos-latest, 18)

other declaration of main

Check failure on line 11 in _demo/select/select.go

View workflow job for this annotation

GitHub Actions / test (macos-latest, 18)

other declaration of main
var readFds syscall.FdSet

sys.FD_ZERO(&readFds)

sys.FD_SET(0, &readFds)

var tv sys.TimeVal
tv.TvSec = 5
tv.TvUSec = 0

c.Printf(c.Str("Waiting for input on stdin...\n"))
ret := sys.Select(1, &readFds, nil, nil, &tv)
if ret == -1 {
c.Perror(c.Str("select error"))
c.Exit(1)
} else if ret == 0 {
c.Printf(c.Str("Timeout occurred! No data after 5 seconds.\n"))
} else {
if sys.FD_ISSET(0, &readFds) != 0 {
var buffer [100]c.Char
n := os.Read(0, c.Pointer(&buffer[:][0]), unsafe.Sizeof(buffer)-1)
if n == -1 {
c.Perror(c.Str("read error"))
c.Exit(1)
} else if n == 0 {
c.Printf(c.Str("End of file\n"))
} else {
buffer[n] = c.Char(0)
c.Printf(c.Str("Read %ld bytes: %s\n"), n, &buffer[0])
}
}
}
}
87 changes: 87 additions & 0 deletions _demo/select/select2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package main

import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/net"
"github.com/goplus/llgo/c/os"
"github.com/goplus/llgo/c/sys"
"github.com/goplus/llgo/c/syscall"
"unsafe"
)

const (
SERVER_IP = "110.242.68.66" // Get the IP address by ping baidu.com
SERVER_PORT = 80
BUFFER_SIZE = 4096 * 1024
)

func main() {

Check failure on line 18 in _demo/select/select2.go

View workflow job for this annotation

GitHub Actions / test (macos-latest, 18)

main redeclared in this block

Check failure on line 18 in _demo/select/select2.go

View workflow job for this annotation

GitHub Actions / test (macos-latest, 18)

main redeclared in this block
var server net.SockaddrIn

sendBuf := c.Str("GET / HTTP/1.1\r\nHost: baidu.com\r\n\r\n")
var recvBuf [BUFFER_SIZE]c.Char
var bytes_sent, bytes_received c.Int

// create net
sock := net.Socket(net.AF_INET, net.SOCK_STREAM, 0)
if sock < 0 {
c.Perror(c.Str("Socket creation failed"))
return
}

// set server addr
c.Memset(c.Pointer(&server), 0, unsafe.Sizeof(server))
server.Family = net.AF_INET
server.Port = net.Htons(SERVER_PORT)
server.Addr.Addr = net.InetAddr(c.Str(SERVER_IP))

// connect to server
if net.Connect(sock, (*net.SockAddr)(c.Pointer(&server)), c.Uint(unsafe.Sizeof(server))) < 0 {
c.Perror(c.Str("Connect failed"))
return
}

var writefds, readfds syscall.FdSet
var timeout sys.TimeVal

// Monitor socket writes
sys.FD_ZERO(&writefds)
sys.FD_SET(sock, &writefds)
timeout.TvSec = 10
timeout.TvUSec = 0
// Use select to monitor the readiness of writes
if sys.Select(sock+1, nil, &writefds, nil, &timeout) > 0 {
if sys.FD_ISSET(sock, &writefds) != 0 {
bytes_sent = c.Int(net.Send(sock, c.Pointer(sendBuf), c.Strlen(sendBuf), 0))
if bytes_sent < 0 {
c.Perror(c.Str("send failed"))
return
}
}
} else {
c.Perror(c.Str("Select write error"))
return
}

// Monitor socket reads
sys.FD_ZERO(&readfds)
sys.FD_SET(sock, &readfds)

// Use select to monitor the readiness of the read operation
if sys.Select(sock+1, &readfds, nil, nil, &timeout) > 0 {
if sys.FD_ISSET(sock, &writefds) != -1 {
bytes_received = c.Int(net.Recv(sock, c.Pointer(&recvBuf[:][0]), BUFFER_SIZE-1, 0))
if bytes_received < 0 {
c.Perror(c.Str("receive failed"))
return
}
recvBuf[bytes_received] = c.Char(0)
c.Printf(c.Str("Received:\n%s\n"), &recvBuf[0])
}
} else {
c.Perror(c.Str("Select read error"))
return
}

os.Close(sock)
}
14 changes: 7 additions & 7 deletions _demo/socket/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@ import (
"unsafe"

"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/net"
"github.com/goplus/llgo/c/os"
"github.com/goplus/llgo/c/socket"
)

func main() {
sockfd := socket.Socket(socket.AF_INET, socket.SOCK_STREAM, 0)
sockfd := net.Socket(net.AF_INET, net.SOCK_STREAM, 0)
msg := c.Str("Hello, World!")
defer os.Close(sockfd)

server := socket.GetHostByName(c.Str("localhost"))
server := net.GetHostByName(c.Str("localhost"))
if server == nil {
c.Perror(c.Str("hostname get error"))
return
}

servAddr := &socket.SockaddrIn{}
servAddr.Family = socket.AF_INET
servAddr.Port = socket.Htons(uint16(1234))
servAddr := &net.SockaddrIn{}
servAddr.Family = net.AF_INET
servAddr.Port = net.Htons(uint16(1234))
c.Memcpy(unsafe.Pointer(&servAddr.Addr.Addr), unsafe.Pointer(*server.AddrList), uintptr(server.Length))

if res := socket.Connect(sockfd, (*socket.SockAddr)(unsafe.Pointer(servAddr)), c.Uint(16)); res < 0 {
if res := net.Connect(sockfd, (*net.SockAddr)(unsafe.Pointer(servAddr)), c.Uint(16)); res < 0 {
c.Perror(c.Str("connect error"))
return
}
Expand Down
20 changes: 10 additions & 10 deletions _demo/socket/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,36 @@ import (
"unsafe"

"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/net"
"github.com/goplus/llgo/c/os"
"github.com/goplus/llgo/c/socket"
)

func main() {
var buffer [256]c.Char

sockfd := socket.Socket(socket.AF_INET, socket.SOCK_STREAM, 0)
sockfd := net.Socket(net.AF_INET, net.SOCK_STREAM, 0)
defer os.Close(sockfd)

servAddr := &socket.SockaddrIn{
Family: socket.AF_INET,
Port: socket.Htons(uint16(1234)),
Addr: socket.InAddr{Addr: 0x00000000},
servAddr := &net.SockaddrIn{
Family: net.AF_INET,
Port: net.Htons(uint16(1234)),
Addr: net.InAddr{Addr: 0x00000000},
Zero: [8]c.Char{0, 0, 0, 0, 0, 0, 0, 0},
}
if res := socket.Bind(sockfd, servAddr, c.Uint(unsafe.Sizeof(*servAddr))); res < 0 {
if res := net.Bind(sockfd, servAddr, c.Uint(unsafe.Sizeof(*servAddr))); res < 0 {
c.Perror(c.Str("bind error"))
return
}

if socket.Listen(sockfd, 5) < 0 {
if net.Listen(sockfd, 5) < 0 {
c.Printf(c.Str("listen error"))
return
}
c.Printf(c.Str("Listening on port 1234...\n"))

cliAddr, clilen := &socket.SockaddrIn{}, c.Uint(unsafe.Sizeof(servAddr))
cliAddr, clilen := &net.SockaddrIn{}, c.Uint(unsafe.Sizeof(servAddr))

newsockfd := socket.Accept(sockfd, cliAddr, &clilen)
newsockfd := net.Accept(sockfd, cliAddr, &clilen)
defer os.Close(newsockfd)
c.Printf(c.Str("Connection accepted."))

Expand Down
31 changes: 27 additions & 4 deletions c/socket/socket.go → c/net/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package socket
package net

import (
_ "unsafe"
Expand Down Expand Up @@ -101,7 +101,6 @@ type SockAddr struct {
Data [14]c.Char
}

// (TODO) merge to netdb
type Hostent struct {
Name *c.Char // official name of host
Aliases **c.Char // null-terminated array of alternate names for the host
Expand All @@ -110,6 +109,17 @@ type Hostent struct {
AddrList **c.Char // null-terminated array of addresses for the host
}

type AddrInfo struct {
AiFlags c.Int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove Ai prefix

AiFamily c.Int
AiSockType c.Int
AiProtocol c.Int
AiAddrLen c.Uint
AiCanOnName *c.Char
AiAddr *SockAddr
AiNext *AddrInfo
}

//go:linkname Socket C.socket
func Socket(domain c.Int, typ c.Int, protocol c.Int) c.Int

Expand All @@ -125,8 +135,6 @@ func Listen(sockfd c.Int, backlog c.Int) c.Int
//go:linkname Accept C.accept
func Accept(sockfd c.Int, addr *SockaddrIn, addrlen *c.Uint) c.Int

// (TODO) merge to netdb
//
//go:linkname GetHostByName C.gethostbyname
func GetHostByName(name *c.Char) *Hostent

Expand All @@ -142,3 +150,18 @@ func SwapInt16(data uint16) uint16 {
func Htons(x uint16) uint16 {
return SwapInt16(x)
}

//go:linkname InetAddr C.inet_addr
func InetAddr(s *c.Char) c.Uint

//go:linkname Send C.send
func Send(c.Int, c.Pointer, uintptr, c.Int) c.Long

//go:linkname Recv C.recv
func Recv(c.Int, c.Pointer, uintptr, c.Int) c.Long

//go:linkname Getaddrinfo C.getaddrinfo
func Getaddrinfo(host *c.Char, port *c.Char, addrInfo *AddrInfo, result **AddrInfo) c.Int

//go:linkname Freeaddrinfo C.freeaddrinfo
func Freeaddrinfo(addrInfo *AddrInfo) c.Int
4 changes: 4 additions & 0 deletions c/os/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ const (
O_TRUNC = 0x00000400
)

const (
EAGAIN = 35
)

type (
ModeT C.mode_t
UidT C.uid_t
Expand Down
13 changes: 13 additions & 0 deletions c/sys/_wrap/fddef.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <sys/types.h>

int fd_isset(int n, fd_set *fd) {
return FD_ISSET(n, fd);
}

void fdSet(int n, fd_set *fd) {
FD_SET(n, fd);
}

void fd_zero(fd_set *fd) {
FD_ZERO(fd);
}
31 changes: 31 additions & 0 deletions c/sys/select.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package sys

import (
"github.com/goplus/llgo/c/syscall"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put llgo/c/xxx packages together

_ "unsafe"

"github.com/goplus/llgo/c"
)

const (
LLGoFiles = "_wrap/fddef.c"
LLGoPackage = "link"
)

// (TODO) merge to timeval
type TimeVal struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put TimeVal to package llgo/c/time

TvSec c.Long
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove Tv prefix

TvUSec c.Int
}

//go:linkname FD_ZERO C.fd_zero
func FD_ZERO(fdSet *syscall.FdSet)

//go:linkname FD_SET C.fdSet
func FD_SET(fd c.Int, fdSet *syscall.FdSet)

//go:linkname FD_ISSET C.fd_isset
func FD_ISSET(fd c.Int, fdSet *syscall.FdSet) c.Int

//go:linkname Select C.select
func Select(n c.Int, r *syscall.FdSet, w *syscall.FdSet, e *syscall.FdSet, timeout *TimeVal) c.Int