github.com/iceber/iouring-go@v0.0.0-20230403020409-002cfd2e2a90/examples/echo-with-callback/server.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"os"
     7  	"syscall"
     8  
     9  	"github.com/iceber/iouring-go"
    10  )
    11  
    12  const readSize = 1024
    13  
    14  var (
    15  	iour     *iouring.IOURing
    16  	resulter chan iouring.Result
    17  )
    18  
    19  func main() {
    20  	if len(os.Args) != 2 {
    21  		fmt.Printf("Usage: %s <host:port>\n", os.Args[0])
    22  		return
    23  	}
    24  
    25  	var err error
    26  	iour, err = iouring.New(1024)
    27  	if err != nil {
    28  		panic(err)
    29  	}
    30  	defer iour.Close()
    31  
    32  	resulter = make(chan iouring.Result, 10)
    33  
    34  	fd := listenSocket(os.Args[1])
    35  	prepAccept := iouring.Accept(fd).WithCallback(accept)
    36  	if _, err := iour.SubmitRequest(prepAccept, resulter); err != nil {
    37  		panicf("submit accept request error: %v", err)
    38  	}
    39  
    40  	fmt.Println("echo server running...")
    41  	for result := range resulter {
    42  		result.Callback()
    43  	}
    44  }
    45  
    46  func accept(result iouring.Result) error {
    47  	prepAccept := iouring.Accept(result.Fd()).WithCallback(accept)
    48  	if _, err := iour.SubmitRequest(prepAccept, resulter); err != nil {
    49  		panicf("submit accept request error: %v", err)
    50  	}
    51  
    52  	if err := result.Err(); err != nil {
    53  		panicf("accept error: %v", err)
    54  	}
    55  
    56  	connFd := result.ReturnValue0().(int)
    57  	sockaddr := result.ReturnValue1().(*syscall.SockaddrInet4)
    58  
    59  	clientAddr := fmt.Sprintf("%s:%d", net.IPv4(sockaddr.Addr[0], sockaddr.Addr[1], sockaddr.Addr[2], sockaddr.Addr[3]), sockaddr.Port)
    60  	fmt.Printf("Client Conn: %s\n", clientAddr)
    61  
    62  	buffer := make([]byte, readSize)
    63  	prep := iouring.Read(connFd, buffer).WithInfo(clientAddr).WithCallback(read)
    64  	if _, err := iour.SubmitRequest(prep, resulter); err != nil {
    65  		panicf("submit read request error: %v", err)
    66  	}
    67  	return nil
    68  }
    69  
    70  func read(result iouring.Result) error {
    71  	clientAddr := result.GetRequestInfo().(string)
    72  	if err := result.Err(); err != nil {
    73  		panicf("[%s] read error: %v", clientAddr, err)
    74  	}
    75  
    76  	num := result.ReturnValue0().(int)
    77  	buf, _ := result.GetRequestBuffer()
    78  	content := buf[:num]
    79  
    80  	connPrintf(clientAddr, "read byte: %v\ncontent: %s\n", num, content)
    81  
    82  	prep := iouring.Write(result.Fd(), content).WithInfo(clientAddr).WithCallback(write)
    83  	if _, err := iour.SubmitRequest(prep, resulter); err != nil {
    84  		panicf("[%s] submit write request error: %v", clientAddr, err)
    85  	}
    86  	return nil
    87  }
    88  
    89  func write(result iouring.Result) error {
    90  	clientAddr := result.GetRequestInfo().(string)
    91  	if err := result.Err(); err != nil {
    92  		panicf("[%s] write error: %v", clientAddr, err)
    93  	}
    94  	connPrintf(clientAddr, "write successful\n")
    95  
    96  	prep := iouring.Close(result.Fd()).WithInfo(clientAddr).WithCallback(close)
    97  	if _, err := iour.SubmitRequest(prep, resulter); err != nil {
    98  		panicf("[%s] submit write request error: %v", clientAddr, err)
    99  	}
   100  	return nil
   101  }
   102  
   103  func close(result iouring.Result) error {
   104  	clientAddr := result.GetRequestInfo().(string)
   105  	if err := result.Err(); err != nil {
   106  		panicf("[%s] close error: %v", clientAddr, err)
   107  	}
   108  	connPrintf(clientAddr, "close successful\n")
   109  	return nil
   110  }
   111  
   112  func listenSocket(addr string) int {
   113  	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
   114  	if err != nil {
   115  		panic(err)
   116  	}
   117  
   118  	tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
   119  	if err != nil {
   120  		panic(err)
   121  	}
   122  
   123  	sockaddr := &syscall.SockaddrInet4{Port: tcpAddr.Port}
   124  	copy(sockaddr.Addr[:], tcpAddr.IP.To4())
   125  	if err := syscall.Bind(fd, sockaddr); err != nil {
   126  		panic(err)
   127  	}
   128  
   129  	if err := syscall.Listen(fd, syscall.SOMAXCONN); err != nil {
   130  		panic(err)
   131  	}
   132  	return fd
   133  }
   134  
   135  func panicf(format string, a ...interface{}) {
   136  	panic(fmt.Sprintf(format, a...))
   137  }
   138  
   139  func connPrintf(addr string, format string, a ...interface{}) {
   140  	prefix := fmt.Sprintf("[%s]", addr)
   141  	fmt.Printf(prefix+format, a...)
   142  }