// +build ! appengine

/*
 *
 * Copyright 2018 gRPC authors. 
 *
 * 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 internal contains credentials-internal code. 
package internal

import (
	"net"
	"syscall"
)

type sysConn = syscall. Conn

// syscallConn keeps reference of rawConn to support syscall. Conn for channelz. 
// SyscallConn() (the method in interface syscall. Conn) is explicitly
// implemented on this type,
//
// Interface syscall. Conn is implemented by most net. Conn implementations (e.g.
// TCPConn, UnixConn), but is not part of net. Conn interface.  So wrapper conns
// that embed net. Conn don't implement syscall. Conn. (Side note: tls. Conn
// doesn't embed net. Conn, so even if syscall. Conn is part of net. Conn, it won't
// help here). 
type syscallConn struct {
	net. Conn
	// sysConn is a type alias of syscall. Conn. It's necessary because the name
	// `Conn` collides with `net. Conn`. 
	sysConn
}

// WrapSyscallConn tries to wrap rawConn and newConn into a net. Conn that
// implements syscall. Conn. rawConn will be used to support syscall, and newConn
// will be used for read/write. 
//
// This function returns newConn if rawConn doesn't implement syscall. Conn.
func WrapSyscallConn(rawConn, newConn net. Conn) net. Conn {
	sysConn, ok := rawConn.(syscall. Conn)
	if ! ok {
		return newConn
	}
	return &syscallConn{
		Conn:    newConn,
		sysConn: sysConn,
	}
}
