// Copyright 2017 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tcp

import (
	
	
	
	
	

	
)

// A Conn represents an end point that uses TCP connection.
// It allows to set non-portable, platform-dependent TCP-level socket
// options.
type Conn struct {
	net.Conn
	c syscall.RawConn
}

func ( *Conn) () bool { return  != nil && .Conn != nil && .c != nil }

func ( *Conn) (,  int,  []byte) error {
	var  error
	 := func( uintptr) {
		 = setsockopt(, , , )
	}
	if  := .c.Control();  != nil {
		return 
	}
	return os.NewSyscallError("setsockopt", )
}

func ( *Conn) (,  int,  []byte) (int, error) {
	var  error
	var  int
	 := func( uintptr) {
		,  = getsockopt(, , , )
	}
	if  := .c.Control();  != nil {
		return 0, 
	}
	return , os.NewSyscallError("getsockopt", )
}

func ( *Conn) () int {
	var  error
	var  int
	 := func( uintptr) {
		var  [4]byte
		 = ioctl(, options[soBuffered].name, [:])
		if  != nil {
			return
		}
		 = int(nativeEndian.Uint32([:]))
	}
	 := .c.Control()
	if  != nil ||  != nil {
		return -1
	}
	return 
}

func ( *Conn) () int {
	var  error
	var  int
	 := func( uintptr) {
		var  [4]byte
		if runtime.GOOS == "darwin" {
			_,  = getsockopt(, options[soAvailable].level, options[soAvailable].name, [:])
		} else {
			 = ioctl(, options[soAvailable].name, [:])
		}
		if  != nil {
			return
		}
		 = int(nativeEndian.Uint32([:]))
		if runtime.GOOS == "darwin" || runtime.GOOS == "linux" {
			var  tcpopt.SendBuffer
			_,  = getsockopt(, .Level(), .Name(), [:])
			if  != nil {
				return
			}
			 = int(nativeEndian.Uint32([:])) - 
		}
	}
	 := .c.Control()
	if  != nil ||  != nil {
		return -1
	}
	return 
}

// NewConn returns a new end point.
func ( net.Conn) (*Conn, error) {
	type  interface {
		() (syscall.RawConn, error)
		(int) error
	}
	var   = &net.TCPConn{}
	 := &Conn{Conn: }
	switch c := .(type) {
	case :
		var  error
		.c,  = .()
		if  != nil {
			return nil, 
		}
		return , nil
	default:
		return nil, errors.New("unknown connection type")
	}
}