1 /*
2 * Copyright (c) 2024 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 "easy_socket_writer.h"
17
18 #include <errno.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <string.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <unistd.h>
25
26 #include "easy_def.h"
27 #include "easy_util.h"
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 static const char SOCKET_PATH[] = "/dev/unix/socket/hisysevent";
34
InitSendBuffer(int socketId)35 static int InitSendBuffer(int socketId)
36 {
37 int sendBuffSize = 384 * 1024; // max buffer of socket is 384K
38 if (setsockopt(socketId, SOL_SOCKET, SO_SNDBUF, (void*)(&sendBuffSize), sizeof(int)) < 0) {
39 return ERR_SET_SOCKET_OPT_FAILED;
40 }
41 return SUCCESS;
42 }
43
InitSocket(struct sockaddr_un* socketAddr)44 static int InitSocket(struct sockaddr_un* socketAddr)
45 {
46 if (socketAddr == NULL) {
47 return ERR_SOCKET_ADDR_INVALID;
48 }
49 int ret = MemoryInit((uint8_t*)(socketAddr), sizeof(struct sockaddr_un));
50 if (ret != SUCCESS) {
51 return ret;
52 }
53 ret = MemoryCopy((uint8_t*)(socketAddr->sun_path), sizeof(socketAddr->sun_path), (uint8_t*)SOCKET_PATH,
54 strlen(SOCKET_PATH));
55 if (ret != SUCCESS) {
56 return ret;
57 }
58 socketAddr->sun_family = AF_UNIX;
59 return SUCCESS;
60 }
61
Write(const uint8_t* data, const size_t dataLen)62 int Write(const uint8_t* data, const size_t dataLen)
63 {
64 if (data == NULL) {
65 return ERR_EVENT_BUF_INVALID;
66 }
67 int socketId = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
68 if (socketId < 0) {
69 close(socketId);
70 return ERR_INIT_SOCKET_FAILED;
71 }
72 int ret = InitSendBuffer(socketId);
73 if (ret != SUCCESS) {
74 close(socketId);
75 return ret;
76 }
77 struct sockaddr_un socketAddr;
78 ret = InitSocket(&socketAddr);
79 if (ret != SUCCESS) {
80 close(socketId);
81 return ret;
82 }
83
84 int sendRet = 0;
85 int retryTimes = 3; // retry 3 times to write socket
86 do {
87 sendRet = sendto(socketId, data, dataLen, 0, (struct sockaddr*)(&socketAddr),
88 sizeof(socketAddr));
89 retryTimes--;
90 } while (sendRet < 0 && retryTimes > 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR));
91 if (sendRet < 0) {
92 close(socketId);
93 return ERR_SOCKET_SEND_ERROR_BASE + errno;
94 }
95 close(socketId);
96 return SUCCESS;
97 }
98
99 #ifdef __cplusplus
100 }
101 #endif