• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hilog_base/log_base.h"
17 
18 #include <hilog_common.h>
19 #include <vsnprintf_s_p.h>
20 
21 #include <array>
22 #include <atomic>
23 #include <cstring>
24 #include <iostream>
25 #include <sys/socket.h>
26 #include <sys/time.h>
27 #include <sys/uio.h>
28 #include <sys/un.h>
29 #include <unistd.h>
30 
31 namespace {
32 
33 constexpr int SOCKET_TYPE = SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC;
34 constexpr int INVALID_SOCKET = -1;
35 constexpr sockaddr_un SOCKET_ADDR = {AF_UNIX, SOCKET_FILE_DIR INPUT_SOCKET_NAME};
36 
37 struct SocketHandler {
38     std::atomic_int socketFd {INVALID_SOCKET};
39     std::atomic_bool isConnected {false};
~SocketHandler__anonc223887b0111::SocketHandler40     ~SocketHandler()
41     {
42         int currentFd = socketFd.exchange(INVALID_SOCKET);
43         if (currentFd >= 0) {
44             close(currentFd);
45         }
46     }
47 };
48 
GenerateFD()49 static int GenerateFD()
50 {
51     int tmpFd = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCKET_TYPE, 0));
52     int res = tmpFd;
53     if (tmpFd == 0) {
54         res = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCKET_TYPE, 0));
55         close(tmpFd);
56     }
57     return res;
58 }
59 
CheckSocket(SocketHandler & socketHandler)60 static int CheckSocket(SocketHandler& socketHandler)
61 {
62     int currentFd = socketHandler.socketFd.load();
63     if (currentFd >= 0) {
64         return currentFd;
65     }
66 
67     int fd = GenerateFD();
68     if (fd < 0) {
69         std::cerr << __FILE__ << __LINE__ << " Can't create socket! Errno: " << errno << "\n";
70         return fd;
71     }
72 
73     currentFd = INVALID_SOCKET;
74     if (!socketHandler.socketFd.compare_exchange_strong(currentFd, fd)) {
75         close(fd);
76         return currentFd;
77     }
78     return fd;
79 }
80 
CheckConnection(SocketHandler & socketHandler)81 static int CheckConnection(SocketHandler& socketHandler)
82 {
83     bool isConnected = socketHandler.isConnected.load();
84     if (isConnected) {
85         return 0;
86     }
87 
88     isConnected = socketHandler.isConnected.load();
89     if (isConnected) {
90         return 0;
91     }
92 
93     auto result = TEMP_FAILURE_RETRY(connect(socketHandler.socketFd.load(),
94         reinterpret_cast<const sockaddr*>(&SOCKET_ADDR), sizeof(SOCKET_ADDR)));
95     if (result < 0) {
96         std::cerr << __FILE__ << __LINE__ << " Can't connect to server. Errno: " << errno << "\n";
97         return result;
98     }
99     socketHandler.isConnected.store(true);
100     return 0;
101 }
102 
SendMessage(HilogMsg * header,const char * tag,uint16_t tagLen,const char * fmt,uint16_t fmtLen)103 static int SendMessage(HilogMsg *header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen)
104 {
105     SocketHandler socketHandler;
106     int ret = CheckSocket(socketHandler);
107     if (ret < 0) {
108         return ret;
109     }
110     ret = CheckConnection(socketHandler);
111     if (ret < 0) {
112         return ret;
113     }
114 
115     struct timeval tv = {0};
116     gettimeofday(&tv, nullptr);
117     header->tv_sec = static_cast<uint32_t>(tv.tv_sec);
118     header->tv_nsec = static_cast<uint32_t>(tv.tv_usec * 1000);     // 1000 : usec convert to nsec
119     header->len = sizeof(HilogMsg) + tagLen + fmtLen;
120     header->tag_len = tagLen;
121 
122     std::array<iovec,3> vec;
123     vec[0].iov_base = header;                // 0 : index of hos log header
124     vec[0].iov_len = sizeof(HilogMsg);       // 0 : index of hos log header
125     vec[1].iov_base = (void*)tag;            // 1 : index of log tag
126     vec[1].iov_len = tagLen;                 // 1 : index of log tag
127     vec[2].iov_base = (void*)fmt;            // 2 : index of log content
128     vec[2].iov_len = fmtLen;                 // 2 : index of log content
129     ret = TEMP_FAILURE_RETRY(::writev(socketHandler.socketFd.load(), vec.data(), vec.size()));
130     return ret;
131 }
132 
HiLogBasePrintArgs(const LogType type,const LogLevel level,const unsigned int domain,const char * tag,const char * fmt,va_list ap)133 static int HiLogBasePrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag,
134     const char *fmt, va_list ap)
135 {
136     if (!HiLogBaseIsLoggable(domain, tag, level)) {
137         return -1;
138     }
139 
140     char buf[MAX_LOG_LEN] = {0};
141 
142     vsnprintfp_s(buf, MAX_LOG_LEN, MAX_LOG_LEN - 1, HILOG_DEFAULT_PRIVACY, fmt, ap);
143 
144     auto tagLen = strnlen(tag, MAX_TAG_LEN - 1);
145     auto logLen = strnlen(buf, MAX_LOG_LEN - 1);
146     HilogMsg header = {0};
147     header.type = type;
148     header.level = level;
149 #ifndef __RECV_MSG_WITH_UCRED_
150     header.pid = getpid();
151 #endif
152     header.tid = static_cast<uint32_t>(gettid());
153     header.domain = domain;
154 
155     return SendMessage(&header, tag, tagLen + 1, buf, logLen + 1);
156 }
157 
158 } // namespace
159 
HiLogBasePrint(LogType type,LogLevel level,unsigned int domain,const char * tag,const char * fmt,...)160 int HiLogBasePrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...)
161 {
162     int ret;
163     va_list ap;
164     va_start(ap, fmt);
165     ret = HiLogBasePrintArgs(type, level, domain, tag, fmt, ap);
166     va_end(ap);
167     return ret;
168 }
169 
HiLogBaseIsLoggable(unsigned int domain,const char * tag,LogLevel level)170 bool HiLogBaseIsLoggable(unsigned int domain, const char *tag, LogLevel level)
171 {
172     if ((level <= LOG_LEVEL_MIN) || (level >= LOG_LEVEL_MAX) || tag == nullptr) {
173         return false;
174     }
175     return true;
176 }
177