• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "client.h"
17 #include <pthread.h>
18 #include <securec.h>
19 #include <signal.h>
20 #include <string.h>
21 #include <sys/un.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include "common.h"
25 #include "log.h"
26 #include "net.h"
27 
28 #undef LOG_TAG
29 #define LOG_TAG "WifiRpcClient"
30 
31 const int FD_CHECK_TIMEOUT = 1000; /* poll wait time, units: ms */
32 const int CLIENT_STATE_IDLE = 0;
33 const int CLIENT_STATE_DEAL_REPLY = 1;
34 const int CLIENT_STATE_EXIT = 2;
35 
36 #define TMP_BUFF_SIZE 16
37 
38 static void *RpcClientThreadDeal(void *arg);
39 
RpcClientReadMsg(RpcClient * client)40 static char *RpcClientReadMsg(RpcClient *client)
41 {
42     if (client == NULL) {
43         return NULL;
44     }
45 
46     char *buff = ContextGetReadRecord(client->context);
47     while (buff == NULL && client->threadRunFlag) {
48         int ret = WaitFdEvent(client->context->fd, READ_EVENT, FD_CHECK_TIMEOUT);
49         if (ret < 0) {
50             LOGE("wait server reply message failed!");
51             client->threadRunFlag = 0;
52             return NULL;
53         } else if (ret == 0) {
54             continue;
55         }
56         ret = ContextReadNet(client->context);
57         if (ret < 0) {
58             LOGE("read server reply message failed!");
59             client->threadRunFlag = 0;
60             return NULL;
61         }
62         buff = ContextGetReadRecord(client->context);
63     }
64     if (!client->threadRunFlag) {
65         if (buff != NULL) {
66             free(buff);
67             buff = NULL;
68         }
69         return NULL;
70     }
71     return buff;
72 }
73 
RpcClientDealReadMsg(RpcClient * client,char * buff)74 static void RpcClientDealReadMsg(RpcClient *client, char *buff)
75 {
76     if (client == NULL) {
77         return;
78     }
79 
80     char szTmp[TMP_BUFF_SIZE] = {0};
81     if (snprintf_s(szTmp, sizeof(szTmp), sizeof(szTmp) - 1, "N%c", client->context->cSplit) < 0) {
82         return;
83     }
84     if (strncmp(buff, szTmp, strlen(szTmp)) == 0) { /* deal reply message */
85         pthread_mutex_lock(&client->mutex);
86         client->waitReply = CLIENT_STATE_DEAL_REPLY;
87         client->context->oneProcess = buff;
88         client->context->nPos = strlen(szTmp);
89         client->context->nSize = strlen(buff);
90         pthread_cond_signal(&client->condW);
91         pthread_mutex_unlock(&client->mutex);
92     } else { /* deal callback message */
93         pthread_mutex_lock(&client->mutex);
94         while (client->waitReply == CLIENT_STATE_DEAL_REPLY) {
95             pthread_cond_wait(&client->condW, &client->mutex);
96         }
97         pthread_mutex_unlock(&client->mutex);
98         client->context->oneProcess = buff;
99         client->context->nPos = strlen(szTmp);
100         client->context->nSize = strlen(buff);
101         OnTransact(client->context);
102         free(buff);
103         buff = NULL;
104     }
105     return;
106 }
107 
RpcClientThreadDeal(void * arg)108 static void *RpcClientThreadDeal(void *arg)
109 {
110     RpcClient *client = (RpcClient *)arg;
111     if (client == NULL) {
112         return NULL;
113     }
114 
115     while (client->threadRunFlag) {
116         char *buff = RpcClientReadMsg(client);
117         if (buff == NULL) {
118             continue;
119         }
120         RpcClientDealReadMsg(client, buff);
121     }
122     pthread_mutex_lock(&client->mutex);
123     client->waitReply = CLIENT_STATE_EXIT;
124     pthread_cond_signal(&client->condW);
125     pthread_mutex_unlock(&client->mutex);
126     LOGI("Client read message thread exiting!");
127     return NULL;
128 }
129 
CreateRpcClient(const char * path)130 RpcClient *CreateRpcClient(const char *path)
131 {
132     int fd = ConnectUnixServer(path);
133     if (fd < 0) {
134         return NULL;
135     }
136     SetNonBlock(fd, 1);
137     RpcClient *client = (RpcClient *)calloc(1, sizeof(RpcClient));
138     if (client == NULL) {
139         close(fd);
140         return NULL;
141     }
142     client->context = CreateContext(CONTEXT_BUFFER_MIN_SIZE);
143     if (client->context == NULL) {
144         close(fd);
145         free(client);
146         client = NULL;
147         return NULL;
148     }
149     client->context->fd = fd;
150     client->threadRunFlag = 1;
151     client->threadId = 0;
152     client->waitReply = CLIENT_STATE_IDLE;
153     client->callLockFlag = 0;
154     pthread_mutex_init(&client->mutex, NULL);
155     pthread_cond_init(&client->condW, NULL);
156     pthread_mutex_init(&client->lockMutex, NULL);
157     pthread_cond_init(&client->lockCond, NULL);
158     int ret = pthread_create(&client->threadId, NULL, RpcClientThreadDeal, client);
159     if (ret) {
160         pthread_cond_destroy(&client->condW);
161         pthread_mutex_destroy(&client->mutex);
162         pthread_cond_destroy(&client->lockCond);
163         pthread_mutex_destroy(&client->lockMutex);
164         ReleaseContext(client->context);
165         close(fd);
166         free(client);
167         client = NULL;
168         return NULL;
169     }
170     signal(SIGPIPE, SIG_IGN);
171     return client;
172 }
173 
ReleaseRpcClient(RpcClient * client)174 void ReleaseRpcClient(RpcClient *client)
175 {
176     if (client != NULL) {
177         if (client->threadId != 0) {
178             client->threadRunFlag = 0;
179             pthread_join(client->threadId, NULL);
180         }
181         pthread_cond_destroy(&client->condW);
182         pthread_mutex_destroy(&client->mutex);
183         pthread_cond_destroy(&client->lockCond);
184         pthread_mutex_destroy(&client->lockMutex);
185         close(client->context->fd);
186         ReleaseContext(client->context);
187         free(client);
188         client = NULL;
189     }
190     return;
191 }
192 
RemoteCall(RpcClient * client)193 int RemoteCall(RpcClient *client)
194 {
195     if (client == NULL) {
196         return -1;
197     }
198     if (client->waitReply == CLIENT_STATE_EXIT) {
199         return -1;
200     }
201     int ret = 0;
202     Context *context = client->context;
203     while (context->wBegin != context->wEnd && ret >= 0) {
204         ret = ContextWriteNet(context);
205     }
206     if (ret < 0) {
207         return ret;
208     }
209     ret = 0; /* reset ret value */
210     pthread_mutex_lock(&client->mutex);
211     while (client->waitReply != CLIENT_STATE_DEAL_REPLY && client->waitReply != CLIENT_STATE_EXIT) {
212         pthread_cond_wait(&client->condW, &client->mutex);
213     }
214     if (client->waitReply == CLIENT_STATE_EXIT) {
215         ret = -1;
216     }
217     pthread_mutex_unlock(&client->mutex);
218     return ret;
219 }
220 
ReadClientEnd(RpcClient * client)221 void ReadClientEnd(RpcClient *client)
222 {
223     if (client == NULL) {
224         return;
225     }
226 
227     pthread_mutex_lock(&client->mutex);
228     free(client->context->oneProcess);
229     client->context->oneProcess = NULL;
230     if (client->waitReply == CLIENT_STATE_DEAL_REPLY) {
231         client->waitReply = CLIENT_STATE_IDLE;
232     }
233     pthread_cond_signal(&client->condW);
234     pthread_mutex_unlock(&client->mutex);
235     return;
236 }
237 
LockRpcClient(RpcClient * client)238 void LockRpcClient(RpcClient *client)
239 {
240     if (client == NULL) {
241         return;
242     }
243 
244     pthread_mutex_lock(&client->lockMutex);
245     while (client->callLockFlag != 0) {
246         pthread_cond_wait(&client->lockCond, &client->lockMutex);
247     }
248     client->callLockFlag = 1;
249     pthread_mutex_unlock(&client->lockMutex);
250     return;
251 }
252 
UnlockRpcClient(RpcClient * client)253 void UnlockRpcClient(RpcClient *client)
254 {
255     if (client == NULL) {
256         return;
257     }
258 
259     pthread_mutex_lock(&client->lockMutex);
260     client->callLockFlag = 0;
261     pthread_cond_signal(&client->lockCond);
262     pthread_mutex_unlock(&client->lockMutex);
263     return;
264 }
265