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 }