1 /*
2 * Copyright (C) 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 "rpc_session_handle.h"
17
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <sys/time.h>
21
22 #include "rpc_log.h"
23 #include "rpc_errno.h"
24
GetWaitTime(struct timespec * waitTime)25 static int32_t GetWaitTime(struct timespec *waitTime)
26 {
27 #define USECTONSEC 1000
28 struct timeval now;
29 if (gettimeofday(&now, NULL) != 0) {
30 RPC_LOG_ERROR("gettimeofday failed");
31 return ERR_FAILED;
32 }
33 waitTime->tv_sec = now.tv_sec + CONNECT_WAIT_TIME_SECONDS;
34 waitTime->tv_nsec = now.tv_usec * USECTONSEC;
35
36 return ERR_NONE;
37 }
38
FindOrNewSessionIdObject(SessionIdList * sessionIdList,int32_t sessionId)39 static SessionIdList *FindOrNewSessionIdObject(SessionIdList *sessionIdList, int32_t sessionId)
40 {
41 RPC_LOG_INFO("FindOrNewSessionIdObject sessionId=%d", sessionId);
42 if (sessionIdList == NULL) {
43 RPC_LOG_ERROR("FindOrNewSessionIdObject sessionIdList is null");
44 return NULL;
45 }
46 pthread_mutex_lock(&sessionIdList->mutex);
47 SessionIdList *node = NULL;
48 UTILS_DL_LIST_FOR_EACH_ENTRY(node, &sessionIdList->idList, SessionIdList, idList)
49 {
50 if (node->sessionId == sessionId) {
51 RPC_LOG_INFO("find sessionId in sessionIdList");
52 pthread_mutex_unlock(&sessionIdList->mutex);
53 return node;
54 }
55 }
56
57 node = (SessionIdList *)malloc(sizeof(SessionIdList));
58 if (node == NULL) {
59 RPC_LOG_ERROR("FindOrNewSessionIdObject malloc failed");
60 pthread_mutex_unlock(&sessionIdList->mutex);
61 return NULL;
62 }
63 memset_s(node, sizeof(SessionIdList), 0, sizeof(SessionIdList));
64 (void)pthread_mutex_init(&node->mutex, NULL);
65 (void)pthread_cond_init(&node->condition, NULL);
66 node->sessionId = sessionId;
67 node->isReady = false;
68
69 UtilsListAdd(&sessionIdList->idList, &node->idList);
70 pthread_mutex_unlock(&sessionIdList->mutex);
71 return node;
72 }
73
WaitForSessionIdReady(SessionIdList * sessionIdList,int32_t sessionId)74 int32_t WaitForSessionIdReady(SessionIdList *sessionIdList, int32_t sessionId)
75 {
76 if (sessionIdList == NULL) {
77 RPC_LOG_ERROR("WaitForSessionIdReady sessionIdList is null");
78 return ERR_FAILED;
79 }
80 if (sessionId <= 0) {
81 RPC_LOG_ERROR("invalid sessionid %d", sessionId);
82 return ERR_FAILED;
83 }
84 SessionIdList *sessionIdObject = FindOrNewSessionIdObject(sessionIdList, sessionId);
85 if (sessionIdObject == NULL) {
86 RPC_LOG_ERROR("FindOrNewSessionIdObject return null");
87 return ERR_FAILED;
88 }
89 pthread_mutex_lock(&sessionIdObject->mutex);
90 if (sessionIdObject->isReady) {
91 pthread_mutex_unlock(&sessionIdObject->mutex);
92 return ERR_NONE;
93 }
94
95 struct timespec waitTime;
96 if (GetWaitTime(&waitTime) != ERR_NONE) {
97 pthread_mutex_unlock(&sessionIdObject->mutex);
98 return ERR_FAILED;
99 }
100
101 if (pthread_cond_timedwait(&sessionIdObject->condition,
102 &sessionIdObject->mutex, &waitTime) == ETIMEDOUT) {
103 RPC_LOG_ERROR("WaitForSessionIdReady timeout");
104 pthread_mutex_unlock(&sessionIdObject->mutex);
105 return ERR_FAILED;
106 }
107
108 RPC_LOG_INFO("WaitForSessionIdReady wakeup!");
109 int32_t ret = sessionIdObject->isReady ? ERR_NONE : ERR_FAILED;
110 pthread_mutex_unlock(&sessionIdObject->mutex);
111 return ret;
112 }
113
HandleNewConnection(SessionIdList * sessionIdList,int32_t sessionId)114 int32_t HandleNewConnection(SessionIdList *sessionIdList, int32_t sessionId)
115 {
116 if (sessionIdList == NULL) {
117 RPC_LOG_ERROR("HandleNewConnection sessionIdList is null");
118 return ERR_FAILED;
119 }
120 if (sessionId <= 0) {
121 return ERR_FAILED;
122 }
123
124 SessionIdList *sessionIdObject = FindOrNewSessionIdObject(sessionIdList, sessionId);
125 if (sessionIdObject == NULL) {
126 RPC_LOG_ERROR("HandleNewConnection get sessionIdObject null");
127 return ERR_FAILED;
128 }
129
130 pthread_mutex_lock(&sessionIdObject->mutex);
131 if (!sessionIdObject->isReady) {
132 sessionIdObject->isReady = true;
133 pthread_cond_broadcast(&sessionIdObject->condition);
134 RPC_LOG_INFO("HandleNewConnection broadcast thread, sessionId=%d", sessionId);
135 }
136 pthread_mutex_unlock(&sessionIdObject->mutex);
137 return ERR_NONE;
138 }