|
@@ -1,4 +1,18 @@
|
|
|
// +build linux,!386
|
|
|
+// Copyright 2019 Wataru Ishida. All rights reserved.
|
|
|
+//
|
|
|
+// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
+// you may not use this file except in compliance with the License.
|
|
|
+// You may obtain a copy of the License at
|
|
|
+//
|
|
|
+// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
+//
|
|
|
+// Unless required by applicable law or agreed to in writing, software
|
|
|
+// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
|
+// implied.
|
|
|
+// See the License for the specific language governing permissions and
|
|
|
+// limitations under the License.
|
|
|
|
|
|
package sctp
|
|
|
|
|
@@ -40,6 +54,23 @@ func getsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, erro
|
|
|
return r0, r1, nil
|
|
|
}
|
|
|
|
|
|
+type rawConn struct {
|
|
|
+ sockfd int
|
|
|
+}
|
|
|
+
|
|
|
+func (r rawConn) Control(f func(fd uintptr)) error {
|
|
|
+ f(uintptr(r.sockfd))
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (r rawConn) Read(f func(fd uintptr) (done bool)) error {
|
|
|
+ panic("not implemented")
|
|
|
+}
|
|
|
+
|
|
|
+func (r rawConn) Write(f func(fd uintptr) (done bool)) error {
|
|
|
+ panic("not implemented")
|
|
|
+}
|
|
|
+
|
|
|
func (c *SCTPConn) SCTPWrite(b []byte, info *SndRcvInfo) (int, error) {
|
|
|
var cbuf []byte
|
|
|
if info != nil {
|
|
@@ -114,6 +145,22 @@ func (c *SCTPConn) Close() error {
|
|
|
return syscall.EBADF
|
|
|
}
|
|
|
|
|
|
+func (c *SCTPConn) SetWriteBuffer(bytes int) error {
|
|
|
+ return syscall.SetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
|
|
|
+}
|
|
|
+
|
|
|
+func (c *SCTPConn) GetWriteBuffer() (int, error) {
|
|
|
+ return syscall.GetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_SNDBUF)
|
|
|
+}
|
|
|
+
|
|
|
+func (c *SCTPConn) SetReadBuffer(bytes int) error {
|
|
|
+ return syscall.SetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
|
|
|
+}
|
|
|
+
|
|
|
+func (c *SCTPConn) GetReadBuffer() (int, error) {
|
|
|
+ return syscall.GetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_RCVBUF)
|
|
|
+}
|
|
|
+
|
|
|
// ListenSCTP - start listener on specified address/port
|
|
|
func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
|
|
return ListenSCTPExt(net, laddr, InitMsg{NumOstreams: SCTP_MAX_STREAM})
|
|
@@ -121,6 +168,11 @@ func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
|
|
|
|
|
// ListenSCTPExt - start listener on specified address/port with given SCTP options
|
|
|
func ListenSCTPExt(network string, laddr *SCTPAddr, options InitMsg) (*SCTPListener, error) {
|
|
|
+ return listenSCTPExtConfig(network, laddr, options, nil)
|
|
|
+}
|
|
|
+
|
|
|
+// listenSCTPExtConfig - start listener on specified address/port with given SCTP options and socket configuration
|
|
|
+func listenSCTPExtConfig(network string, laddr *SCTPAddr, options InitMsg, control func(network, address string, c syscall.RawConn) error) (*SCTPListener, error) {
|
|
|
af, ipv6only := favoriteAddrFamily(network, laddr, nil, "listen")
|
|
|
sock, err := syscall.Socket(
|
|
|
af,
|
|
@@ -140,6 +192,12 @@ func ListenSCTPExt(network string, laddr *SCTPAddr, options InitMsg) (*SCTPListe
|
|
|
if err = setDefaultSockopts(sock, af, ipv6only); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
+ if control != nil {
|
|
|
+ rc := rawConn{sockfd: sock}
|
|
|
+ if err = control(network, laddr.String(), rc); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ }
|
|
|
err = setInitOpts(sock, options)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
@@ -154,7 +212,7 @@ func ListenSCTPExt(network string, laddr *SCTPAddr, options InitMsg) (*SCTPListe
|
|
|
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv6zero})
|
|
|
}
|
|
|
}
|
|
|
- err := SCTPBind(sock, laddr, SCTP_BINDX_ADD_ADDR)
|
|
|
+ err = SCTPBind(sock, laddr, SCTP_BINDX_ADD_ADDR)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
@@ -191,6 +249,11 @@ func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
|
|
|
|
|
|
// DialSCTPExt - same as DialSCTP but with given SCTP options
|
|
|
func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTPConn, error) {
|
|
|
+ return dialSCTPExtConfig(network, laddr, raddr, options, nil)
|
|
|
+}
|
|
|
+
|
|
|
+// dialSCTPExtConfig - same as DialSCTP but with given SCTP options and socket configuration
|
|
|
+func dialSCTPExtConfig(network string, laddr, raddr *SCTPAddr, options InitMsg, control func(network, address string, c syscall.RawConn) error) (*SCTPConn, error) {
|
|
|
af, ipv6only := favoriteAddrFamily(network, laddr, raddr, "dial")
|
|
|
sock, err := syscall.Socket(
|
|
|
af,
|
|
@@ -210,6 +273,12 @@ func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTP
|
|
|
if err = setDefaultSockopts(sock, af, ipv6only); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
+ if control != nil {
|
|
|
+ rc := rawConn{sockfd: sock}
|
|
|
+ if err = control(network, laddr.String(), rc); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ }
|
|
|
err = setInitOpts(sock, options)
|
|
|
if err != nil {
|
|
|
return nil, err
|