1a34a8711Sopenharmony_ci/*
2a34a8711Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3a34a8711Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a34a8711Sopenharmony_ci * you may not use this file except in compliance with the License.
5a34a8711Sopenharmony_ci * You may obtain a copy of the License at
6a34a8711Sopenharmony_ci *
7a34a8711Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a34a8711Sopenharmony_ci *
9a34a8711Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a34a8711Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a34a8711Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a34a8711Sopenharmony_ci * See the License for the specific language governing permissions and
13a34a8711Sopenharmony_ci * limitations under the License.
14a34a8711Sopenharmony_ci */
15a34a8711Sopenharmony_ci
16a34a8711Sopenharmony_ci#include "rpc_session_handle.h"
17a34a8711Sopenharmony_ci
18a34a8711Sopenharmony_ci#include <stdlib.h>
19a34a8711Sopenharmony_ci#include <errno.h>
20a34a8711Sopenharmony_ci#include <sys/time.h>
21a34a8711Sopenharmony_ci
22a34a8711Sopenharmony_ci#include "rpc_log.h"
23a34a8711Sopenharmony_ci#include "rpc_errno.h"
24a34a8711Sopenharmony_ci
25a34a8711Sopenharmony_cistatic int32_t GetWaitTime(struct timespec *waitTime)
26a34a8711Sopenharmony_ci{
27a34a8711Sopenharmony_ci#define USECTONSEC 1000
28a34a8711Sopenharmony_ci    struct timeval now;
29a34a8711Sopenharmony_ci    if (gettimeofday(&now, NULL) != 0) {
30a34a8711Sopenharmony_ci        RPC_LOG_ERROR("gettimeofday failed");
31a34a8711Sopenharmony_ci        return ERR_FAILED;
32a34a8711Sopenharmony_ci    }
33a34a8711Sopenharmony_ci    waitTime->tv_sec = now.tv_sec + CONNECT_WAIT_TIME_SECONDS;
34a34a8711Sopenharmony_ci    waitTime->tv_nsec = now.tv_usec * USECTONSEC;
35a34a8711Sopenharmony_ci
36a34a8711Sopenharmony_ci    return ERR_NONE;
37a34a8711Sopenharmony_ci}
38a34a8711Sopenharmony_ci
39a34a8711Sopenharmony_cistatic SessionIdList *FindOrNewSessionIdObject(SessionIdList *sessionIdList, int32_t sessionId)
40a34a8711Sopenharmony_ci{
41a34a8711Sopenharmony_ci    RPC_LOG_INFO("FindOrNewSessionIdObject sessionId=%d", sessionId);
42a34a8711Sopenharmony_ci    if (sessionIdList == NULL) {
43a34a8711Sopenharmony_ci        RPC_LOG_ERROR("FindOrNewSessionIdObject sessionIdList is null");
44a34a8711Sopenharmony_ci        return NULL;
45a34a8711Sopenharmony_ci    }
46a34a8711Sopenharmony_ci    pthread_mutex_lock(&sessionIdList->mutex);
47a34a8711Sopenharmony_ci    SessionIdList *node = NULL;
48a34a8711Sopenharmony_ci    UTILS_DL_LIST_FOR_EACH_ENTRY(node, &sessionIdList->idList, SessionIdList, idList)
49a34a8711Sopenharmony_ci    {
50a34a8711Sopenharmony_ci        if (node->sessionId == sessionId) {
51a34a8711Sopenharmony_ci            RPC_LOG_INFO("find sessionId in sessionIdList");
52a34a8711Sopenharmony_ci            pthread_mutex_unlock(&sessionIdList->mutex);
53a34a8711Sopenharmony_ci            return node;
54a34a8711Sopenharmony_ci        }
55a34a8711Sopenharmony_ci    }
56a34a8711Sopenharmony_ci
57a34a8711Sopenharmony_ci    node = (SessionIdList *)malloc(sizeof(SessionIdList));
58a34a8711Sopenharmony_ci    if (node == NULL) {
59a34a8711Sopenharmony_ci        RPC_LOG_ERROR("FindOrNewSessionIdObject malloc failed");
60a34a8711Sopenharmony_ci        pthread_mutex_unlock(&sessionIdList->mutex);
61a34a8711Sopenharmony_ci        return NULL;
62a34a8711Sopenharmony_ci    }
63a34a8711Sopenharmony_ci    memset_s(node, sizeof(SessionIdList), 0, sizeof(SessionIdList));
64a34a8711Sopenharmony_ci    (void)pthread_mutex_init(&node->mutex, NULL);
65a34a8711Sopenharmony_ci    (void)pthread_cond_init(&node->condition, NULL);
66a34a8711Sopenharmony_ci    node->sessionId = sessionId;
67a34a8711Sopenharmony_ci    node->isReady = false;
68a34a8711Sopenharmony_ci
69a34a8711Sopenharmony_ci    UtilsListAdd(&sessionIdList->idList, &node->idList);
70a34a8711Sopenharmony_ci    pthread_mutex_unlock(&sessionIdList->mutex);
71a34a8711Sopenharmony_ci    return node;
72a34a8711Sopenharmony_ci}
73a34a8711Sopenharmony_ci
74a34a8711Sopenharmony_ciint32_t WaitForSessionIdReady(SessionIdList *sessionIdList, int32_t sessionId)
75a34a8711Sopenharmony_ci{
76a34a8711Sopenharmony_ci    if (sessionIdList == NULL) {
77a34a8711Sopenharmony_ci        RPC_LOG_ERROR("WaitForSessionIdReady sessionIdList is null");
78a34a8711Sopenharmony_ci        return ERR_FAILED;
79a34a8711Sopenharmony_ci    }
80a34a8711Sopenharmony_ci    if (sessionId <= 0) {
81a34a8711Sopenharmony_ci        RPC_LOG_ERROR("invalid sessionid %d", sessionId);
82a34a8711Sopenharmony_ci        return ERR_FAILED;
83a34a8711Sopenharmony_ci    }
84a34a8711Sopenharmony_ci    SessionIdList *sessionIdObject = FindOrNewSessionIdObject(sessionIdList, sessionId);
85a34a8711Sopenharmony_ci    if (sessionIdObject == NULL) {
86a34a8711Sopenharmony_ci        RPC_LOG_ERROR("FindOrNewSessionIdObject return null");
87a34a8711Sopenharmony_ci        return ERR_FAILED;
88a34a8711Sopenharmony_ci    }
89a34a8711Sopenharmony_ci    pthread_mutex_lock(&sessionIdObject->mutex);
90a34a8711Sopenharmony_ci    if (sessionIdObject->isReady) {
91a34a8711Sopenharmony_ci        pthread_mutex_unlock(&sessionIdObject->mutex);
92a34a8711Sopenharmony_ci        return ERR_NONE;
93a34a8711Sopenharmony_ci    }
94a34a8711Sopenharmony_ci
95a34a8711Sopenharmony_ci    struct timespec waitTime;
96a34a8711Sopenharmony_ci    if (GetWaitTime(&waitTime) != ERR_NONE) {
97a34a8711Sopenharmony_ci        pthread_mutex_unlock(&sessionIdObject->mutex);
98a34a8711Sopenharmony_ci        return ERR_FAILED;
99a34a8711Sopenharmony_ci    }
100a34a8711Sopenharmony_ci
101a34a8711Sopenharmony_ci    if (pthread_cond_timedwait(&sessionIdObject->condition,
102a34a8711Sopenharmony_ci        &sessionIdObject->mutex, &waitTime) == ETIMEDOUT) {
103a34a8711Sopenharmony_ci        RPC_LOG_ERROR("WaitForSessionIdReady timeout");
104a34a8711Sopenharmony_ci        pthread_mutex_unlock(&sessionIdObject->mutex);
105a34a8711Sopenharmony_ci        return ERR_FAILED;
106a34a8711Sopenharmony_ci    }
107a34a8711Sopenharmony_ci
108a34a8711Sopenharmony_ci    RPC_LOG_INFO("WaitForSessionIdReady wakeup!");
109a34a8711Sopenharmony_ci    int32_t ret = sessionIdObject->isReady ? ERR_NONE : ERR_FAILED;
110a34a8711Sopenharmony_ci    pthread_mutex_unlock(&sessionIdObject->mutex);
111a34a8711Sopenharmony_ci    return ret;
112a34a8711Sopenharmony_ci}
113a34a8711Sopenharmony_ci
114a34a8711Sopenharmony_ciint32_t HandleNewConnection(SessionIdList *sessionIdList, int32_t sessionId)
115a34a8711Sopenharmony_ci{
116a34a8711Sopenharmony_ci    if (sessionIdList == NULL) {
117a34a8711Sopenharmony_ci        RPC_LOG_ERROR("HandleNewConnection sessionIdList is null");
118a34a8711Sopenharmony_ci        return ERR_FAILED;
119a34a8711Sopenharmony_ci    }
120a34a8711Sopenharmony_ci    if (sessionId <= 0) {
121a34a8711Sopenharmony_ci        return ERR_FAILED;
122a34a8711Sopenharmony_ci    }
123a34a8711Sopenharmony_ci
124a34a8711Sopenharmony_ci    SessionIdList *sessionIdObject = FindOrNewSessionIdObject(sessionIdList, sessionId);
125a34a8711Sopenharmony_ci    if (sessionIdObject == NULL) {
126a34a8711Sopenharmony_ci        RPC_LOG_ERROR("HandleNewConnection get sessionIdObject null");
127a34a8711Sopenharmony_ci        return ERR_FAILED;
128a34a8711Sopenharmony_ci    }
129a34a8711Sopenharmony_ci
130a34a8711Sopenharmony_ci    pthread_mutex_lock(&sessionIdObject->mutex);
131a34a8711Sopenharmony_ci    if (!sessionIdObject->isReady) {
132a34a8711Sopenharmony_ci        sessionIdObject->isReady = true;
133a34a8711Sopenharmony_ci        pthread_cond_broadcast(&sessionIdObject->condition);
134a34a8711Sopenharmony_ci        RPC_LOG_INFO("HandleNewConnection broadcast thread, sessionId=%d", sessionId);
135a34a8711Sopenharmony_ci    }
136a34a8711Sopenharmony_ci    pthread_mutex_unlock(&sessionIdObject->mutex);
137a34a8711Sopenharmony_ci    return ERR_NONE;
138a34a8711Sopenharmony_ci}