Coverage Report

Created: 2025-12-17 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/butil/fd_utility.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
// Date: Mon. Nov 7 14:47:36 CST 2011
19
20
#include "butil/build_config.h"
21
#include <fcntl.h>                   // fcntl()
22
#include <netinet/in.h>              // IPPROTO_TCP
23
#include <sys/types.h>
24
#include <sys/socket.h>              // setsockopt
25
#include <netinet/tcp.h>             // TCP_NODELAY
26
#include <netinet/tcp.h>
27
#if defined(OS_MACOSX)
28
#include <netinet/tcp_fsm.h>        // TCPS_ESTABLISHED, TCP6S_ESTABLISHED
29
#endif
30
#include "butil/logging.h"
31
32
namespace butil {
33
34
0
bool is_blocking(int fd) {
35
0
    const int flags = fcntl(fd, F_GETFL, 0);
36
0
    return flags >= 0 && !(flags & O_NONBLOCK);
37
0
}
38
39
0
int make_non_blocking(int fd) {
40
0
    const int flags = fcntl(fd, F_GETFL, 0);
41
0
    if (flags < 0) {
42
0
        return flags;
43
0
    }
44
0
    if (flags & O_NONBLOCK) {
45
0
        return 0;
46
0
    }
47
0
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
48
0
}
49
50
0
int make_blocking(int fd) {
51
0
    const int flags = fcntl(fd, F_GETFL, 0);
52
0
    if (flags < 0) {
53
0
        return flags;
54
0
    }
55
0
    if (flags & O_NONBLOCK) {
56
0
        return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
57
0
    }
58
0
    return 0;
59
0
}
60
61
0
int make_close_on_exec(int fd) {
62
0
    return fcntl(fd, F_SETFD, FD_CLOEXEC);
63
0
}
64
65
0
int make_no_delay(int sockfd) {
66
0
    int flag = 1;
67
0
    return setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(flag));
68
0
}
69
70
0
int is_connected(int sockfd) {
71
0
    errno = 0;
72
0
    int err;
73
0
    socklen_t errlen = sizeof(err);
74
0
    if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &errlen) < 0) {
75
0
        PLOG(FATAL) << "Fail to getsockopt";
76
0
        return -1;
77
0
    }
78
0
    if (err != 0) {
79
0
        errno = err;
80
0
        return -1;
81
0
    }
82
83
0
#if defined(OS_LINUX)
84
0
    struct tcp_info ti{};
85
0
    socklen_t len = sizeof(ti);
86
0
    if(getsockopt(sockfd, SOL_TCP, TCP_INFO, &ti, &len) < 0) {
87
0
        PLOG(FATAL) << "Fail to getsockopt";
88
0
        return -1;
89
0
    }
90
0
    if (ti.tcpi_state != TCP_ESTABLISHED) {
91
0
        errno = ENOTCONN;
92
0
        return -1;
93
0
    }
94
#elif defined(OS_MACOSX)
95
    struct tcp_connection_info ti{};
96
    socklen_t len = sizeof(ti);
97
    if (getsockopt(sockfd, IPPROTO_TCP, TCP_CONNECTION_INFO, &ti, &len) < 0) {
98
        PLOG(FATAL) << "Fail to getsockopt";
99
        return -1;
100
    }
101
    if (ti.tcpi_state != TCPS_ESTABLISHED &&
102
        ti.tcpi_state != TCP6S_ESTABLISHED) {
103
        errno = ENOTCONN;
104
        return -1;
105
    }
106
#endif
107
108
0
    return 0;
109
0
}
110
111
}  // namespace butil