|
|
|
@ -30,161 +30,248 @@
|
|
|
|
|
|
|
|
|
|
namespace srslte {
|
|
|
|
|
|
|
|
|
|
sctp_socket::sctp_socket()
|
|
|
|
|
{
|
|
|
|
|
bzero(&addr_in, sizeof(addr_in));
|
|
|
|
|
bzero(&dest_addr, sizeof(dest_addr));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sctp_socket::sctp_socket(sctp_socket&& other) noexcept
|
|
|
|
|
base_socket_t::base_socket_t(base_socket_t&& other) noexcept
|
|
|
|
|
{
|
|
|
|
|
sockfd = other.sockfd;
|
|
|
|
|
memcpy(&addr_in, &other.addr_in, sizeof(addr_in));
|
|
|
|
|
// reset other without calling close
|
|
|
|
|
other.sockfd = -1;
|
|
|
|
|
other.sockfd = 0;
|
|
|
|
|
bzero(&other.addr_in, sizeof(other.addr_in));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sctp_socket::~sctp_socket()
|
|
|
|
|
base_socket_t::~base_socket_t()
|
|
|
|
|
{
|
|
|
|
|
reset();
|
|
|
|
|
if (sockfd >= 0) {
|
|
|
|
|
close(sockfd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sctp_socket& sctp_socket::operator=(sctp_socket&& other) noexcept
|
|
|
|
|
base_socket_t& base_socket_t::operator=(base_socket_t&& other) noexcept
|
|
|
|
|
{
|
|
|
|
|
if (this == &other) {
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
sockfd = other.sockfd;
|
|
|
|
|
memcpy(&addr_in, &other.addr_in, sizeof(addr_in));
|
|
|
|
|
other.sockfd = -1;
|
|
|
|
|
sockfd = other.sockfd;
|
|
|
|
|
bzero(&other.addr_in, sizeof(other.addr_in));
|
|
|
|
|
other.sockfd = 0;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sctp_socket::reset()
|
|
|
|
|
void base_socket_t::reset_()
|
|
|
|
|
{
|
|
|
|
|
if (sockfd >= 0) {
|
|
|
|
|
close(sockfd);
|
|
|
|
|
}
|
|
|
|
|
bzero(&addr_in, sizeof(addr_in));
|
|
|
|
|
bzero(&dest_addr, sizeof(dest_addr));
|
|
|
|
|
addr_in = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sctp_socket::listen_addr(const char* bind_addr_str, int port)
|
|
|
|
|
int base_socket_t::bind_addr(const char* bind_addr_str, int port)
|
|
|
|
|
{
|
|
|
|
|
if (sockfd < 0) {
|
|
|
|
|
if (create_socket()) {
|
|
|
|
|
if (create_socket() != 0) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr_in.sin_family = AF_INET;
|
|
|
|
|
addr_in.sin_port = (port != 0) ? htons(port) : 0;
|
|
|
|
|
if (inet_pton(AF_INET, bind_addr_str, &(addr_in.sin_addr)) != 1) {
|
|
|
|
|
perror("inet_pton");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bind(sockfd, (struct sockaddr*)&addr_in, sizeof(addr_in)) != 0) {
|
|
|
|
|
perror("bind()");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int base_socket_t::connect_to(struct sockaddr_in* dest_addr, const char* dest_addr_str, int dest_port)
|
|
|
|
|
{
|
|
|
|
|
dest_addr->sin_family = AF_INET;
|
|
|
|
|
dest_addr->sin_port = htons(dest_port);
|
|
|
|
|
if (inet_pton(AF_INET, dest_addr_str, &(dest_addr->sin_addr)) != 1) {
|
|
|
|
|
perror("inet_pton()");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (connect(sockfd, (struct sockaddr*)dest_addr, sizeof(*dest_addr)) == -1) {
|
|
|
|
|
perror("connect()");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
|
* SCTP socket
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
|
|
void sctp_socket_t::reset()
|
|
|
|
|
{
|
|
|
|
|
reset_();
|
|
|
|
|
dest_addr = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sctp_socket_t::listen_addr(const char* bind_addr_str, int port)
|
|
|
|
|
{
|
|
|
|
|
if (sockfd < 0 and create_socket() != 0) {
|
|
|
|
|
reset();
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sets the data_io_event to be able to use sendrecv_info
|
|
|
|
|
// Subscribes to the SCTP_SHUTDOWN event, to handle graceful shutdown
|
|
|
|
|
struct sctp_event_subscribe evnts;
|
|
|
|
|
bzero(&evnts, sizeof(evnts));
|
|
|
|
|
struct sctp_event_subscribe evnts = {};
|
|
|
|
|
evnts.sctp_data_io_event = 1;
|
|
|
|
|
evnts.sctp_shutdown_event = 1;
|
|
|
|
|
if (setsockopt(sockfd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts))) {
|
|
|
|
|
if (setsockopt(sockfd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts)) != 0) {
|
|
|
|
|
perror("setsockopt");
|
|
|
|
|
reset();
|
|
|
|
|
return -1;
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// bind addr
|
|
|
|
|
if (bind_addr(bind_addr_str, port)) {
|
|
|
|
|
if (bind_addr(bind_addr_str, port) != 0) {
|
|
|
|
|
reset();
|
|
|
|
|
return -1;
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Listen for connections
|
|
|
|
|
if (listen(sockfd, SOMAXCONN)) {
|
|
|
|
|
if (listen(sockfd, SOMAXCONN) != 0) {
|
|
|
|
|
perror("listen");
|
|
|
|
|
reset();
|
|
|
|
|
return -1;
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sctp_socket::connect_addr(const char* bind_addr_str, const char* dest_addr_str, int dest_port)
|
|
|
|
|
int sctp_socket_t::connect_addr(const char* bind_addr_str, const char* dest_addr_str, int dest_port)
|
|
|
|
|
{
|
|
|
|
|
if (sockfd < 0) {
|
|
|
|
|
if (bind_addr(bind_addr_str, 0)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (sockfd < 0 and bind_addr(bind_addr_str, 0) != 0) {
|
|
|
|
|
reset();
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dest_addr.sin_family = AF_INET;
|
|
|
|
|
dest_addr.sin_port = htons(dest_port);
|
|
|
|
|
if (inet_pton(AF_INET, dest_addr_str, &(dest_addr.sin_addr)) != 1) {
|
|
|
|
|
perror("inet_pton()");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (connect(sockfd, (struct sockaddr*)&dest_addr, sizeof(dest_addr)) == -1) {
|
|
|
|
|
perror("connect()");
|
|
|
|
|
return -1;
|
|
|
|
|
if (connect_to(&dest_addr, dest_addr_str, dest_port) != 0) {
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sctp_socket::read(void* buf,
|
|
|
|
|
ssize_t nbytes,
|
|
|
|
|
int sctp_socket_t::read_from(void* buf,
|
|
|
|
|
size_t nbytes,
|
|
|
|
|
struct sockaddr_in* from,
|
|
|
|
|
socklen_t fromlen,
|
|
|
|
|
socklen_t* fromlen,
|
|
|
|
|
struct sctp_sndrcvinfo* sinfo,
|
|
|
|
|
int msg_flags)
|
|
|
|
|
int msg_flags) const
|
|
|
|
|
{
|
|
|
|
|
int rd_sz = sctp_recvmsg(sockfd, buf, nbytes, (struct sockaddr*)from, &fromlen, sinfo, &msg_flags);
|
|
|
|
|
if (rd_sz <= 0) {
|
|
|
|
|
perror("sctp read");
|
|
|
|
|
if (fromlen != nullptr) {
|
|
|
|
|
*fromlen = sizeof(*from);
|
|
|
|
|
}
|
|
|
|
|
return rd_sz;
|
|
|
|
|
return sctp_recvmsg(sockfd, buf, nbytes, (struct sockaddr*)from, fromlen, sinfo, &msg_flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sctp_socket::send(void* buf, ssize_t nbytes, uint32_t ppid, uint32_t stream_id)
|
|
|
|
|
int sctp_socket_t::send(void* buf, size_t nbytes, uint32_t ppid, uint32_t stream_id) const
|
|
|
|
|
{
|
|
|
|
|
return sctp_sendmsg(
|
|
|
|
|
sockfd, buf, nbytes, (struct sockaddr*)&dest_addr, sizeof(dest_addr), htonl(ppid), 0, stream_id, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sctp_socket::operator rx_sctp_socket_ref()
|
|
|
|
|
// Private Methods
|
|
|
|
|
|
|
|
|
|
int sctp_socket_t::create_socket()
|
|
|
|
|
{
|
|
|
|
|
return rx_sctp_socket_ref(this);
|
|
|
|
|
sockfd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
|
|
|
|
|
if (sockfd == -1) {
|
|
|
|
|
perror("Could not create SCTP socket\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Private Methods
|
|
|
|
|
/***************************************************************
|
|
|
|
|
* TCP Socket
|
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
|
|
int sctp_socket::bind_addr(const char* bind_addr_str, int port)
|
|
|
|
|
void tcp_socket_t::reset()
|
|
|
|
|
{
|
|
|
|
|
if (sockfd < 0) {
|
|
|
|
|
if (create_socket()) {
|
|
|
|
|
return -1;
|
|
|
|
|
reset_();
|
|
|
|
|
dest_addr = {};
|
|
|
|
|
if (connfd >= 0) {
|
|
|
|
|
connfd = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int tcp_socket_t::listen_addr(const char* bind_addr_str, int port)
|
|
|
|
|
{
|
|
|
|
|
if (sockfd < 0 and bind_addr(bind_addr_str, port) != 0) {
|
|
|
|
|
reset();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr_in.sin_family = AF_INET;
|
|
|
|
|
if (inet_pton(AF_INET, bind_addr_str, &(addr_in.sin_addr)) != 1) {
|
|
|
|
|
perror("inet_pton");
|
|
|
|
|
// Listen for connections
|
|
|
|
|
if (listen(sockfd, 1) != 0) {
|
|
|
|
|
perror("listen");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
addr_in.sin_port = (port != 0) ? htons(port) : 0;
|
|
|
|
|
if (bind(sockfd, (struct sockaddr*)&addr_in, sizeof(addr_in))) {
|
|
|
|
|
perror("bind()");
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int tcp_socket_t::accept_connection()
|
|
|
|
|
{
|
|
|
|
|
socklen_t clilen = sizeof(dest_addr);
|
|
|
|
|
connfd = accept(sockfd, (struct sockaddr*)&dest_addr, &clilen);
|
|
|
|
|
if (connfd < 0) {
|
|
|
|
|
perror("accept");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sctp_socket::create_socket()
|
|
|
|
|
int tcp_socket_t::connect_addr(const char* bind_addr_str, const char* dest_addr_str, int dest_port)
|
|
|
|
|
{
|
|
|
|
|
sockfd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
|
|
|
|
|
if (sockfd == -1) {
|
|
|
|
|
perror("Could not create SCTP socket\n");
|
|
|
|
|
if (sockfd < 0 and bind_addr(bind_addr_str, 0) != 0) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return connect_to(&dest_addr, dest_addr_str, dest_port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int tcp_socket_t::create_socket()
|
|
|
|
|
{
|
|
|
|
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
|
if (sockfd == -1) {
|
|
|
|
|
perror("Could not create TCP socket\n");
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int tcp_socket_t::read(void* buf, size_t nbytes) const
|
|
|
|
|
{
|
|
|
|
|
int n = ::read(connfd, buf, nbytes);
|
|
|
|
|
if (n == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (n == -1) {
|
|
|
|
|
perror("read");
|
|
|
|
|
}
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int tcp_socket_t::send(void* buf, size_t nbytes) const
|
|
|
|
|
{
|
|
|
|
|
// Loop until all bytes are sent
|
|
|
|
|
char* ptr = (char*)buf;
|
|
|
|
|
while (nbytes > 0) {
|
|
|
|
|
ssize_t i = ::send(connfd, ptr, nbytes, 0);
|
|
|
|
|
if (i < 1) {
|
|
|
|
|
perror("Error calling send()\n");
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
ptr += i;
|
|
|
|
|
nbytes -= i;
|
|
|
|
|
}
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
@ -222,39 +309,33 @@ rx_multisocket_handler::~rx_multisocket_handler()
|
|
|
|
|
close(pipefd[0]);
|
|
|
|
|
close(pipefd[1]);
|
|
|
|
|
|
|
|
|
|
// close all sockets
|
|
|
|
|
for (auto& handler_pair : active_sctp_sockets) {
|
|
|
|
|
if (close(handler_pair.first) == -1) {
|
|
|
|
|
rxSockError("Failed to close socket fd=%d\n", handler_pair.first);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rxSockDebug("closed.\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rx_multisocket_handler::register_sctp_socket(rx_sctp_socket_ref sock, callback_t recv_handler_)
|
|
|
|
|
bool rx_multisocket_handler::register_socket_(std::pair<const int, std::function<void()> >&& elem)
|
|
|
|
|
{
|
|
|
|
|
int fd = elem.first;
|
|
|
|
|
std::lock_guard<std::mutex> lock(socket_mutex);
|
|
|
|
|
if (sock.fd() < 0) {
|
|
|
|
|
if (fd < 0) {
|
|
|
|
|
rxSockError("Provided SCTP socket must be already open\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (active_sctp_sockets.count(sock.fd()) > 0) {
|
|
|
|
|
rxSockError("Tried to register fd=%d, but this fd already exists\n", sock.fd());
|
|
|
|
|
if (active_sockets.count(fd) > 0) {
|
|
|
|
|
rxSockError("Tried to register fd=%d, but this fd already exists\n", fd);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
active_sctp_sockets.insert(std::make_pair(sock.fd(), sctp_handler_t{std::move(recv_handler_), sock}));
|
|
|
|
|
active_sockets.insert(std::move(elem));
|
|
|
|
|
|
|
|
|
|
// this unlocks the reading thread to add new connections
|
|
|
|
|
ctrl_cmd_t msg;
|
|
|
|
|
msg.cmd = ctrl_cmd_t::cmd_id_t::NEW_FD;
|
|
|
|
|
msg.new_fd = sock.fd();
|
|
|
|
|
msg.new_fd = fd;
|
|
|
|
|
if (write(pipefd[1], &msg, sizeof(msg)) != sizeof(msg)) {
|
|
|
|
|
rxSockError("while writing to control pipe\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rxSockDebug("socket fd=%d has been registered.\n", sock.fd());
|
|
|
|
|
rxSockDebug("socket fd=%d has been registered.\n", fd);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -284,16 +365,14 @@ void rx_multisocket_handler::run_thread()
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(socket_mutex);
|
|
|
|
|
|
|
|
|
|
// call read callback for all SCTP connections
|
|
|
|
|
for (auto& handler_pair : active_sctp_sockets) {
|
|
|
|
|
// call read callback for all SCTP/TCP/UDP connections
|
|
|
|
|
for (auto& handler_pair : active_sockets) {
|
|
|
|
|
if (not FD_ISSET(handler_pair.first, &read_fd_set)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
handler_pair.second.callback(handler_pair.second.sctp_ptr);
|
|
|
|
|
handler_pair.second();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: For TCP and UDP
|
|
|
|
|
|
|
|
|
|
// handle ctrl messages
|
|
|
|
|
if (FD_ISSET(pipefd[0], &read_fd_set)) {
|
|
|
|
|
ctrl_cmd_t msg;
|
|
|
|
|