1/*
2 * Copyright (c) 2021-2022 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 "uds_client.h"
17
18#include "util.h"
19
20#undef MMI_LOG_TAG
21#define MMI_LOG_TAG "UDSClient"
22
23namespace OHOS {
24namespace MMI {
25UDSClient::UDSClient()
26{
27    CALL_DEBUG_ENTER;
28}
29
30UDSClient::~UDSClient()
31{
32    CALL_DEBUG_ENTER;
33}
34
35int32_t UDSClient::ConnectTo()
36{
37    CALL_DEBUG_ENTER;
38    if (Socket() < 0) {
39        MMI_HILOGE("Socket failed");
40        return RET_ERR;
41    }
42    OnConnected();
43    return RET_OK;
44}
45
46bool UDSClient::SendMsg(const char *buf, size_t size) const
47{
48    CHKPF(buf);
49    if ((size == 0) || (size > MAX_PACKET_BUF_SIZE)) {
50        MMI_HILOGE("Stream buffer size out of range");
51        return false;
52    }
53    if (fd_ < 0) {
54        MMI_HILOGE("The fd_ is less than 0");
55        return false;
56    }
57
58    int32_t idx = 0;
59    int32_t retryCount = 0;
60    const int32_t bufSize = static_cast<int32_t>(size);
61    int32_t remSize = bufSize;
62    while (remSize > 0 && retryCount < SEND_RETRY_LIMIT) {
63        retryCount += 1;
64        auto count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL);
65        if (count < 0) {
66            if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
67                MMI_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, errno:%{public}d", errno);
68                continue;
69            }
70            MMI_HILOGE("Send return failed,error:%{public}d fd:%{public}d", errno, fd_);
71            return false;
72        }
73        idx += count;
74        remSize -= count;
75        if (remSize > 0) {
76            MMI_HILOGW("Remsize:%{public}d", remSize);
77            usleep(SEND_RETRY_SLEEP_TIME);
78        }
79    }
80    if (retryCount >= SEND_RETRY_LIMIT || remSize != 0) {
81        MMI_HILOGE("Send too many times:%{public}d/%{public}d,size:%{public}d/%{public}d fd:%{public}d",
82            retryCount, SEND_RETRY_LIMIT, idx, bufSize, fd_);
83        return false;
84    }
85    return true;
86}
87
88bool UDSClient::SendMsg(const NetPacket &pkt) const
89{
90    if (pkt.ChkRWError()) {
91        MMI_HILOGE("Read and write status is error");
92        return false;
93    }
94    StreamBuffer buf;
95    pkt.MakeData(buf);
96    return SendMsg(buf.Data(), buf.Size());
97}
98
99bool UDSClient::StartClient(MsgClientFunCallback fun)
100{
101    CALL_DEBUG_ENTER;
102    if (isRunning_ || isConnected_) {
103        MMI_HILOGE("Client is connected or started");
104        return false;
105    }
106    isExit = false;
107    recvFun_ = fun;
108    if (ConnectTo() < 0) {
109        MMI_HILOGW("Client connection failed, Try again later");
110        return false;
111    }
112    return true;
113}
114
115void UDSClient::Stop()
116{
117    CALL_DEBUG_ENTER;
118    isExit = true;
119    isRunning_ = false;
120    Close();
121}
122} // namespace MMI
123} // namespace OHOS