github.com/dubbogo/gost@v1.14.0/net/conncheck.go (about)

     1  //go:build linux || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || illumos
     2  // +build linux darwin dragonfly freebsd netbsd openbsd solaris illumos
     3  
     4  /*
     5   * Licensed to the Apache Software Foundation (ASF) under one or more
     6   * contributor license agreements.  See the NOTICE file distributed with
     7   * this work for additional information regarding copyright ownership.
     8   * The ASF licenses this file to You under the Apache License, Version 2.0
     9   * (the "License"); you may not use this file except in compliance with
    10   * the License.  You may obtain a copy of the License at
    11   *
    12   *     http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing, software
    15   * distributed under the License is distributed on an "AS IS" BASIS,
    16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    17   * See the License for the specific language governing permissions and
    18   * limitations under the License.
    19   */
    20  
    21  // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
    22  //
    23  // Copyright 2019 The Go-MySQL-Driver Authors. All rights reserved.
    24  //
    25  // This Source Code Form is subject to the terms of the Mozilla Public
    26  // License, v. 2.0. If a copy of the MPL was not distributed with this file,
    27  // You can obtain one at http://mozilla.org/MPL/2.0/.
    28  
    29  package gxnet
    30  
    31  import (
    32  	"errors"
    33  	"io"
    34  	"net"
    35  	"syscall"
    36  )
    37  
    38  var errUnexpectedRead = errors.New("unexpected read from socket")
    39  
    40  func ConnCheck(conn net.Conn) error {
    41  	var sysErr error
    42  
    43  	sysConn, ok := conn.(syscall.Conn)
    44  	if !ok {
    45  		return nil
    46  	}
    47  	rawConn, err := sysConn.SyscallConn()
    48  	if err != nil {
    49  		return err
    50  	}
    51  
    52  	err = rawConn.Read(func(fd uintptr) bool {
    53  		var buf [1]byte
    54  		n, readErr := syscall.Read(int(fd), buf[:])
    55  		switch {
    56  		case n == 0 && readErr == nil:
    57  			sysErr = io.EOF
    58  		case n > 0:
    59  			sysErr = errUnexpectedRead
    60  		case readErr == syscall.EAGAIN || readErr == syscall.EWOULDBLOCK:
    61  			sysErr = nil
    62  		default:
    63  			sysErr = readErr
    64  		}
    65  		return true
    66  	})
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	return sysErr
    72  }