Skip to content

Instantly share code, notes, and snippets.

@filinvadim
Created October 24, 2018 21:09
Show Gist options
  • Save filinvadim/cbdea1c46e6f30195a2cb03254b8c6ae to your computer and use it in GitHub Desktop.
Save filinvadim/cbdea1c46e6f30195a2cb03254b8c6ae to your computer and use it in GitHub Desktop.
epoll
func serve() {
ep, err := netpoll.EpollCreate(epollConfig())
if err != nil {
log.Fatal(err)
}
// Create listener on port 4444.
ln, err := listen(4444)
if err != nil {
log.Fatal(err)
}
defer unix.Close(ln)
done := make(chan struct{})
var received bytes.Buffer
// Add listener fd to epoll instance to know when there are new incoming
// connections.
ep.Add(ln, netpoll.EPOLLIN, func(evt netpoll.EpollEvent) {
if evt&_EPOLLCLOSED != 0 {
return
}
// Accept new incoming connection.
nfd, _, err := unix.Accept(ln)
if err != nil {
log.Fatalf("could not accept: %s", err)
}
// Socket must not block read() from it.
unix.SetNonblock(nfd, true)
// Add connection fd to epoll instance to get notifications about
// available data.
ep.Add(
nfd,
netpoll.EPOLLIN|netpoll.EPOLLET|netpoll.EPOLLHUP|netpoll.EPOLLRDHUP,
func(evt netpoll.EpollEvent,
) {
// If EPOLLRDHUP is supported, it will be triggered after conn
// close() or shutdown(). In older versions EPOLLHUP is triggered.
if evt&_EPOLLCLOSED != 0 {
return
}
var buf [128]byte
for {
n, err := unix.Read(nfd, buf[:])
if err != nil {
break
}
if n <= 0 {
break
}
received.Write(buf[:n])
}
bIo := bufio.NewReader(bytes.NewReader(received.Bytes()))
req, err := http.ReadRequest(bIo)
fmt.Println(req, err, "!!!!!!!!!")
received.Reset()
})
})
<- done
if err = ep.Close(); err != nil {
log.Fatal(err)
}
}
func listen(port int) (ln int, err error) {
fmt.Println("start server")
ln, err = unix.Socket(unix.AF_INET, unix.O_NONBLOCK|unix.SOCK_STREAM, 0)
if err != nil {
return
}
// Need for avoid receiving EADDRINUSE error.
// Closed listener could be in TIME_WAIT state some time.
unix.SetsockoptInt(ln, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
addr := &unix.SockaddrInet4{
Port: port,
Addr: [4]byte{0x7f, 0, 0, 1}, // 127.0.0.1
}
if err = unix.Bind(ln, addr); err != nil {
return
}
err = unix.Listen(ln, 4)
return
}
func epollConfig() *netpoll.EpollConfig {
return &netpoll.EpollConfig{
OnWaitError: func(err error) {
log.Fatal(err)
},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment