* Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
* ubs-comm is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef UBS_COMM_UBSOCKET_CONNECTION_H
#define UBS_COMM_UBSOCKET_CONNECTION_H
#include <sys/socket.h>
#include <chrono>
#include "common/ubsocket_common_includes.h"
#include "include/ubsocket_def.h"
#include "profiling/statistics/statistics_statsmgr.h"
#include "ubsocket_core_types.h"
#include "ubsocket_data_rx.h"
#include "ubsocket_data_tx.h"
#include "ubsocket_event_epoll.h"
#include "ubsocket_socket_acceptor.h"
#include "ubsocket_socket_connector.h"
#include "under_api/dl_libc_api.h"
namespace ock {
namespace ubs {
class SocketBase;
using SocketBasePtr = Ref<SocketBase>;
class SocketBase : public Socket {
public:
static Result Create(int fd, SocketType t, SocketPtr &sock);
static Result GenerateSocketCommOps(const SocketPtr &sock);
public:
SocketBase(int fd, SocketType type) : Socket(fd, type)
{
stats_mgr_.InitStatsMgr();
}
~SocketBase() override
{
if (GlobalSetting::UBS_TRACE_ENABLED) {
Statistics::StatsMgr::SubMConnCount();
if (IsClient()) {
Statistics::StatsMgr::SubMActiveConnCount();
}
}
}
virtual Result Initialize() noexcept = 0;
virtual void UnInitialize() noexcept = 0;
int Accept(const SocketPtr &sock, struct sockaddr *address, socklen_t *address_len);
int Connect(const SocketPtr &sock, const struct sockaddr *address, socklen_t address_len);
int WriteV(const SocketPtr &sock, const struct iovec *iov, int iovcnt);
int ReadV(const SocketPtr &sock, const struct iovec *iov, int iovcnt);
int GetSockOpt(int fd, int level, int optname, void *optval, socklen_t *optlen);
EventPoll *GetAddedEpollFd(epoll_data_t &data) const;
void SetAddedEpollFd(EventPoll *fd, const epoll_data_t &data = {});
int NotifyReadable();
DataRx *GetRx()
{
return &rx_;
}
DataTx *GetTx()
{
return &tx_;
}
Statistics::StatsMgr *GetStatsMgr()
{
return &stats_mgr_;
}
bool IsClient()
{
return connector_->IsClient();
}
protected:
static Result CreateTxOps(SocketType value, const SocketPtr &sock, DataTxOps *&ops);
static Result CreateRxOps(SocketType value, const SocketPtr &sock, DataRxOps *&ops);
static Result CreateAcceptorOps(SocketType value, const SocketPtr &sock, AcceptorOps *&acceptor);
static Result CreateConnectorOps(SocketType value, const SocketPtr &sock, ConnectorOps *&connector);
protected:
DataTx tx_;
DataRx rx_;
Acceptor *acceptor_ = nullptr;
Connector *connector_ = nullptr;
EventPoll *added_epoll_fd_ = nullptr;
epoll_data_t added_epoll_data_ = {};
Statistics::StatsMgr stats_mgr_ = {};
friend class DataTx;
friend class DataRx;
friend class Acceptor;
friend class Connector;
};
ALWAYS_INLINE int SocketBase::Accept(const SocketPtr &sock, struct sockaddr *address, socklen_t *address_len)
{
if (acceptor_ == nullptr) {
errno = EINVAL;
return UBS_ERROR;
}
return acceptor_->Accept(sock, address, address_len);
}
ALWAYS_INLINE int SocketBase::Connect(const SocketPtr &sock, const struct sockaddr *address, socklen_t address_len)
{
if (connector_ == nullptr) {
errno = EINVAL;
return UBS_ERROR;
}
return connector_->Connect(sock, address, address_len);
}
ALWAYS_INLINE int SocketBase::WriteV(const SocketPtr &sock, const struct iovec *iov, int iovcnt)
{
return tx_.WriteV(sock, iov, iovcnt);
}
ALWAYS_INLINE int SocketBase::ReadV(const SocketPtr &sock, const struct iovec *iov, int iovcnt)
{
return rx_.ReadV(sock, iov, iovcnt);
}
ALWAYS_INLINE EventPoll *SocketBase::GetAddedEpollFd(epoll_data_t &data) const
{
data = added_epoll_data_;
return added_epoll_fd_;
}
ALWAYS_INLINE void SocketBase::SetAddedEpollFd(EventPoll *fd, const epoll_data_t &data)
{
added_epoll_fd_ = fd;
added_epoll_data_ = data;
}
ALWAYS_INLINE int SocketBase::NotifyReadable()
{
if (added_epoll_fd_ == nullptr) {
return eventfd_write(event_fd_, 1);
}
if (((AsyncEventPoll *)added_epoll_fd_)->AddReadableEvent(added_epoll_data_) != 0) {
return -1;
}
return ((AsyncEventPoll *)added_epoll_fd_)->SetReadableEventFd();
}
}
}
#endif