⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tport_type_sctp.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@CFILE tport_type_sctp.c Transport using SCTP. * * See tport.docs for more detailed description of tport interface. * * @RFC4168. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Martti Mela <Martti.Mela@nokia.com> * * @date Created: Fri Mar 24 08:45:49 EET 2006 ppessi * @date Original Created: Thu Jul 20 12:54:32 2000 ppessi */#include "config.h"#if HAVE_SCTP#include "tport_internal.h"#if HAVE_NETINET_SCTP_H#include <netinet/sctp.h>#endif#include <stdlib.h>#include <time.h>#include <assert.h>#include <errno.h>#include <limits.h>#include <string.h>/* ---------------------------------------------------------------------- *//* SCTP */#undef MAX_STREAMS#define MAX_STREAMS MAX_STREAMS/* Missing socket symbols */#ifndef SOL_SCTP#define SOL_SCTP IPPROTO_SCTP#endifenum { MAX_STREAMS = 1 };typedef struct tport_sctp_t{  tport_t sctp_base[1];    msg_t *sctp_recv[MAX_STREAMS];  struct sctp_send {    msg_t *ss_msg;    msg_iovec_t *ss_unsent;	/**< Pointer to first unsent iovec */    unsigned     ss_unsentlen;  /**< Number of unsent iovecs */    msg_iovec_t *ss_iov;	/**< Iovecs allocated for sending */    unsigned     ss_iovlen;	/**< Number of allocated iovecs */  } sctp_send[MAX_STREAMS];} tport_sctp_t;#define TP_SCTP_MSG_MAX (65536)static int tport_sctp_init_primary(tport_primary_t *, 				   tp_name_t tpn[1], 				   su_addrinfo_t *, tagi_t const *,				   char const **return_culprit);static int tport_sctp_init_client(tport_primary_t *, 				  tp_name_t tpn[1], 				  su_addrinfo_t *, tagi_t const *,				  char const **return_culprit);static int tport_sctp_init_secondary(tport_t *self, int socket, int accepted,				     char const **return_reason);static int tport_sctp_init_socket(tport_primary_t *pri, 				  int socket,				  char const **return_reason);static int tport_recv_sctp(tport_t *self);static ssize_t tport_send_sctp(tport_t const *self, msg_t *msg,			       msg_iovec_t iov[], size_t iovused);static int tport_sctp_next_timer(tport_t *self, su_time_t *, char const **);static void tport_sctp_timer(tport_t *self, su_time_t);tport_vtable_t const tport_sctp_client_vtable ={  "sctp", tport_type_client,  sizeof (tport_primary_t),  tport_sctp_init_client,  NULL,  tport_accept,  NULL,  sizeof (tport_t),  tport_sctp_init_secondary,  NULL,  NULL,  NULL,  NULL,  tport_recv_sctp,  tport_send_sctp,  NULL,  NULL,  NULL,  NULL,  tport_sctp_next_timer,  tport_sctp_timer,};tport_vtable_t const tport_sctp_vtable ={  "sctp", tport_type_local,  sizeof (tport_primary_t),  tport_sctp_init_primary,  NULL,  tport_accept,  NULL,  sizeof (tport_t),  tport_sctp_init_secondary,  NULL,  NULL,  NULL,  NULL,  tport_recv_sctp,  tport_send_sctp,  NULL,  NULL,  NULL,  NULL,  tport_sctp_next_timer,  tport_sctp_timer,};static int tport_sctp_init_primary(tport_primary_t *pri, 				   tp_name_t tpn[1],				   su_addrinfo_t *ai,				   tagi_t const *tags,				   char const **return_culprit){  int socket;  if (pri->pri_params->tpp_mtu > TP_SCTP_MSG_MAX)    pri->pri_params->tpp_mtu = TP_SCTP_MSG_MAX;  socket = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);  if (socket == INVALID_SOCKET)    return *return_culprit = "socket", -1;  if (tport_sctp_init_socket(pri, socket, return_culprit) < 0)    return -1;    return tport_stream_init_primary(pri, socket, tpn, ai, tags, return_culprit);}static int tport_sctp_init_client(tport_primary_t *pri, 				  tp_name_t tpn[1],				  su_addrinfo_t *ai,				  tagi_t const *tags,				  char const **return_culprit){  if (pri->pri_params->tpp_mtu > TP_SCTP_MSG_MAX)    pri->pri_params->tpp_mtu = TP_SCTP_MSG_MAX;  return tport_tcp_init_client(pri, tpn, ai, tags, return_culprit);}static int tport_sctp_init_secondary(tport_t *self, int socket, int accepted,				     char const **return_reason){  self->tp_has_connection = 1;  if (accepted) {    /* Accepted socket inherit the init information from listen socket */    return 0;  }  else {    return tport_sctp_init_socket(self->tp_pri, socket, return_reason);  }}/** Initialize a SCTP socket */static int tport_sctp_init_socket(tport_primary_t *pri, 				  int socket,				  char const **return_reason){  struct sctp_initmsg initmsg = { 0 };  initmsg.sinit_num_ostreams = MAX_STREAMS;  initmsg.sinit_max_instreams = MAX_STREAMS;  if (setsockopt(socket, SOL_SCTP, SCTP_INITMSG, &initmsg, sizeof initmsg) < 0)    return *return_reason = "SCTP_INITMSG", -1;  return 0;}/** Receive data available on the socket. * * @retval -1 error * @retval 0  end-of-stream   * @retval 1  normal receive * @retval 2  incomplete recv, recv again */static int tport_recv_sctp(tport_t *self){  msg_t *msg;  ssize_t N, veclen;  msg_iovec_t iovec[2] = {{ 0 }};  char sctp_buf[TP_SCTP_MSG_MAX];  iovec[0].mv_base = sctp_buf;  iovec[0].mv_len = sizeof(sctp_buf);  N = su_vrecv(self->tp_socket, iovec, 1, 0, NULL, NULL);  if (N == SOCKET_ERROR) {    return su_is_blocking(su_errno()) ? 1 : -1;  }  if (N == 0) {    if (self->tp_msg)      msg_recv_commit(self->tp_msg, 0, 1);    return 0;    /* End of stream */  }  tport_recv_bytes(self, N, N);  veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0);  if (veclen < 0)    return -1;  assert(veclen == 1); assert(iovec[0].mv_len == N);  msg = self->tp_msg;  msg_set_address(msg, self->tp_addr, self->tp_addrlen);  memcpy(iovec[0].mv_base, sctp_buf, iovec[0].mv_len);  if (self->tp_master->mr_dump_file)    tport_dump_iovec(self, msg, N, iovec, veclen, "recv", "from");  msg_recv_commit(msg, N, 0);  /* Mark buffer as used */  return 2;}static ssize_t tport_send_sctp(tport_t const *self, msg_t *msg,			       msg_iovec_t iov[], size_t iovused){    return su_vsend(self->tp_socket, iov, iovused, MSG_NOSIGNAL, NULL, 0);}/** Calculate tick timer if send is pending. */int tport_next_sctp_send_tick(tport_t *self,			    su_time_t *return_target, 			    char const **return_why){  unsigned timeout = 100;  /* Retry 10 times a second... */  if (tport_has_queued(self)) {    su_time_t ntime = su_time_add(self->tp_ktime, timeout);    if (su_time_cmp(ntime, *return_target) < 0)      *return_target = ntime, *return_why = "send tick";  }  return 0;}/** Tick timer if send is pending */void tport_sctp_send_tick_timer(tport_t *self, su_time_t now){  unsigned timeout = 100;  /* Send timeout */  if (tport_has_queued(self) &&       su_time_cmp(su_time_add(self->tp_ktime, timeout), now) < 0) {    uint64_t bytes = self->tp_stats.sent_bytes;    su_time_t stime = self->tp_stime;    tport_send_queue(self);    if (self->tp_stats.sent_bytes == bytes)      self->tp_stime = stime;	/* Restore send timestamp */  }}/** Calculate next timer for SCTP. */int tport_sctp_next_timer(tport_t *self,			 su_time_t *return_target, 			 char const **return_why){  return     tport_next_recv_timeout(self, return_target, return_why) |    tport_next_sctp_send_tick(self, return_target, return_why);}/** SCTP timer. */void tport_sctp_timer(tport_t *self, su_time_t now){  tport_sctp_send_tick_timer(self, now);  tport_recv_timeout_timer(self, now);  tport_base_timer(self, now);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -