Skip to content

Instantly share code, notes, and snippets.

@zserge
Created July 21, 2016 07:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zserge/c26d23296c75eadb2658816ff76bf84f to your computer and use it in GitHub Desktop.
Save zserge/c26d23296c75eadb2658816ff76bf84f to your computer and use it in GitHub Desktop.
//
// A simple echo server for SCTP sockets, it creates a socket with a syscall then wraps it into a net.Listener interface
// to make goroutine-safe (otherwise reading or writing would block the whole host thread).
// All it does is echoing back all the received data from the client.
//
package main
import (
"fmt"
"io"
"log"
"net"
"os"
"syscall"
)
const listenBacklog = 10
func ListenSCTP(addr string) (net.Listener, error) {
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
return nil, err
}
var raddr syscall.Sockaddr
if ip6 := tcpAddr.IP.To16(); ip6 != nil {
addr6 := &syscall.SockaddrInet6{Port: tcpAddr.Port}
copy(addr6.Addr[:], ip6[:16])
raddr = addr6
} else if ip4 := tcpAddr.IP.To4(); ip4 != nil {
addr4 := &syscall.SockaddrInet4{Port: tcpAddr.Port}
copy(addr4.Addr[:], ip4[:4])
raddr = addr4
} else {
raddr = &syscall.SockaddrInet4{Port: tcpAddr.Port}
}
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_SCTP)
if err != nil {
return nil, err
}
err = syscall.Bind(fd, raddr)
if err != nil {
syscall.Close(fd)
return nil, err
}
err = syscall.Listen(fd, listenBacklog)
if err != nil {
syscall.Close(fd)
return nil, err
}
f := os.NewFile(uintptr(fd), fmt.Sprintf("socket fd %d", fd))
return net.FileListener(f)
}
func main() {
if len(os.Args) != 2 {
fmt.Printf("USAGE: %s <address>\n", os.Args[0])
os.Exit(0)
}
ln, err := ListenSCTP(os.Args[1])
if err != nil {
log.Fatal("listen failed: ", err)
}
defer ln.Close()
log.Println("listening at", ln.Addr())
for {
conn, err := ln.Accept()
if err == nil {
go func() {
defer conn.Close()
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err != nil {
if err != io.EOF {
log.Println("read error", err)
}
return
}
_, err = conn.Write(buf[:n])
if err != nil {
log.Println("write error", err)
return
}
}
}()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment