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 25static 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 39static 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 74int32_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 114int32_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}