Hello!
I did some extra tests, and it seems that there was a bug related to
multihoming in the code I sent you yesterday. So, I send the new diff
file as an attachment!
Menyus
On Thu, Apr 9, 2009 at 2:20 PM, Menyus Hegedűs <[email protected]> wrote:
> Hello!
>
> As far as I know SIPp currently does not support SCTP
> (sipp.2009-01-21.tar.gz 21-Jan-2009 11:51).
>
> Thus, I have implement SCTP for SIPp.
> In the attachment you can find the differences generated by diff.
>
> I did some tests, and it seems to work between 2 linux PCs in multi
> and mono socket mode. New parameters related to SCTP (like multihoming
> or heartbeat) are also working.
>
> Feel free to use it, and send me comments if i did something wrong.
>
> Br, Menyus
>
diff -bruN orig/Makefile sipp.svn/Makefile
--- orig/Makefile 2008-10-29 12:20:06.000000000 +0100
+++ sipp.svn/Makefile 2009-04-07 14:04:43.444388000 +0200
@@ -105,7 +105,7 @@
CFLAGS_SunOS=${DEBUG_FLAGS} -D__SUNOS
CFLAGS_Cygwin=-D__CYGWIN -Dsocklen_t=int
CFLAGS_Darwin=-D__DARWIN
-CFLAGS=$(CFLAGS_$(SYSTEM)) $(VERINFO) $(TLS) $(PCAPPLAY) $(EXTRACFLAGS)
+CFLAGS=$(CFLAGS_$(SYSTEM)) $(VERINFO) $(TLS) $(SCTP) $(PCAPPLAY) $(EXTRACFLAGS)
#C++ Compiler Flags
CPPFLAGS_hpux=-AA -mt -D__HPUX -D_INCLUDE_LONGLONG -DNOMACROS +W829
@@ -115,7 +115,7 @@
CPPFLAGS_SunOS=${DEBUG_FLAGS} -D__SUNOS
CPPFLAGS_Cygwin=-D__CYGWIN -Dsocklen_t=int
CPPFLAGS_Darwin=-D__DARWIN
-CPPFLAGS=$(CPPFLAGS_$(SYSTEM)) $(VERINFO) $(TLS) $(PCAPPLAY) $(EXTRACPPFLAGS)
+CPPFLAGS=$(CPPFLAGS_$(SYSTEM)) $(VERINFO) $(TLS) $(SCTP) $(PCAPPLAY)
$(EXTRACPPFLAGS)
#Linker mapping
CCLINK_hpux=aCC
@@ -167,6 +167,10 @@
ossl:
$(MAKE) OSNAME=`uname|sed -e "s/CYGWIN.*/CYGWIN/"` MODELNAME=`uname
-m|sed "s/Power Macintosh/ppc/"` OBJ_TLS="auth.o sslinit.o sslthreadsafe.o
milenage.o rijndael.o" TLS_LIBS="-lssl -lcrypto" TLS="-D_USE_OPENSSL
-DOPENSSL_NO_KRB5" $(OUTPUT)
+# Building with SCTP
+sctp:
+ $(MAKE) OSNAME=`uname|sed -e "s/CYGWIN.*/CYGWIN/"` MODELNAME=`uname
-m|sed "s/Power Macintosh/ppc/"` SCTP_LIBS="-lsctp" SCTP="-D_USE_SCTP" $(OUTPUT)
+
#Building with PCAP play
pcapplay:
$(MAKE) OSNAME=`uname|sed -e "s/CYGWIN.*/CYGWIN/"` MODELNAME=`uname
-m|sed "s/Power Macintosh/ppc/"` OBJ_PCAPPLAY="send_packets.o prepare_pcap.o"
PCAPPLAY_LIBS="-lpcap" PCAPPLAY="-DPCAPPLAY" $(OUTPUT)
@@ -188,7 +192,7 @@
$(OUTPUT): $(OBJ_TLS) $(OBJ_PCAPPLAY) $(OBJ)
$(CCLINK) $(LFLAGS) $(MFLAGS) $(LIBDIR_$(SYSTEM)) \
- $(DEBUG_FLAGS) -o $@ $(OBJ_TLS) $(OBJ_PCAPPLAY) $(OBJ) $(LIBS)
$(TLS_LIBS) $(PCAPPLAY_LIBS) $(EXTRAENDLIBS)
+ $(DEBUG_FLAGS) -o $@ $(OBJ_TLS) $(OBJ_PCAPPLAY) $(OBJ) $(LIBS)
$(TLS_LIBS) $(PCAPPLAY_LIBS) $(SCTP_LIBS) $(EXTRAENDLIBS)
debug:
DEBUG_FLAGS="-g -pg" ; export DEBUG_FLAGS ; $(MAKE) all
diff -bruN orig/call.cpp sipp.svn/call.cpp
--- orig/call.cpp 2009-01-09 18:33:04.000000000 +0100
+++ sipp.svn/call.cpp 2009-04-07 16:54:18.474123900 +0200
@@ -760,7 +760,6 @@
if (existing) {
return true;
}
-
sipp_customize_socket(call_socket);
if (use_remote_sending_addr) {
@@ -3507,11 +3506,14 @@
protocol = T_TCP;
} else if (!strcmp(str_protocol, "tls") || !strcmp(str_protocol, "TLS"))
{
protocol = T_TLS;
+ } else if (!strcmp(str_protocol, "sctp") || !strcmp(str_protocol,
"SCTP")) {
+ protocol = T_SCTP;
} else {
ERROR("Unknown transport for setdest: '%s'", str_protocol);
}
- if (!call_socket && protocol == T_TCP && transport == T_TCP) {
+ if (!call_socket && ((protocol == T_TCP && transport == T_TCP) ||
+ (protocol == T_SCTP && transport == T_SCTP))) {
bool existing;
if ((associate_socket(new_sipp_call_socket(use_ipv6, transport,
&existing))) == NULL) {
ERROR_NO("Unable to get a TCP socket");
@@ -3531,7 +3533,7 @@
/* Nothing to do. */
} else if (protocol == T_TLS) {
ERROR("Changing destinations is not supported for TLS.");
- } else if (protocol == T_TCP) {
+ } else if (protocol == T_TCP || protocol == T_SCTP) {
if (!multisocket) {
ERROR("Changing destinations for TCP requires multisocket mode.");
}
@@ -3565,7 +3567,7 @@
free(str_port);
free(str_protocol);
- if (protocol == T_TCP) {
+ if (protocol == T_TCP || protocol == T_SCTP) {
close(call_socket->ss_fd);
call_socket->ss_fd = -1;
call_socket->ss_changed_dest = true;
diff -bruN orig/opentask.cpp sipp.svn/opentask.cpp
--- orig/opentask.cpp 2008-07-10 23:15:56.000000000 +0200
+++ sipp.svn/opentask.cpp 2009-04-07 11:37:13.417612600 +0200
@@ -132,6 +132,7 @@
main_socket->ss_count++;
break;
case T_TCP:
+ case T_SCTP:
case T_TLS:
call_ptr->associate_socket(tcp_multiplex);
tcp_multiplex->ss_count++;
diff -bruN orig/sipp.cpp sipp.svn/sipp.cpp
--- orig/sipp.cpp 2008-12-29 16:56:18.000000000 +0100
+++ sipp.svn/sipp.cpp 2009-04-10 10:57:27.333979900 +0200
@@ -130,6 +130,7 @@
#define SIPP_OPTION_LFNAME 36
#define SIPP_OPTION_LFOVERWRITE 37
#define SIPP_OPTION_PLUGIN 38
+#define SIPP_OPTION_NEED_SCTP 39
/* Put Each option, its help text, and type in this table. */
struct sipp_option options_table[] = {
@@ -292,6 +293,8 @@
"- tn: TCP with one socket per call,\n"
"- l1: TLS with one socket,\n"
"- ln: TLS with one socket per call,\n"
+ "- s1: SCTP with one socket (default),\n"
+ "- sn: SCTP with one socket per call,\n"
"- c1: u1 + compression (only if compression plugin loaded),\n"
"- cn: un + compression (only if compression plugin loaded).
This plugin is not provided with sipp.\n"
, SIPP_OPTION_TRANSPORT, NULL, 1},
@@ -345,6 +348,19 @@
"Format: -tdmmap {0-3}{99}{5-8}{1-31}", SIPP_OPTION_TDMMAP,
NULL, 1},
{"key", "keyword value\nSet the generic parameter named \"keyword\" to
\"value\".", SIPP_OPTION_KEY, NULL, 1},
{"set", "variable value\nSet the global variable parameter named
\"variable\" to \"value\".", SIPP_OPTION_VAR, NULL, 3},
+#ifdef _USE_SCTP
+ {"multihome", "Set multihome address for SCTP", SIPP_OPTION_IP,
multihome_ip, 1},
+ {"heartbeat", "Set heartbeat interval in ms for SCTP", SIPP_OPTION_INT,
&heartbeat, 1},
+ {"assocmaxret", "Set association max retransmit counter for SCTP",
SIPP_OPTION_INT, &assocmaxret, 1},
+ {"pathmaxret", "Set path max retransmit counter for SCTP",
SIPP_OPTION_INT, &pathmaxret, 1},
+ {"gracefulclose", "if true, SCPT assocition will be closed with
SHUTDOWN (default).\n if false, SCPT association will be closed by ABORT.\n",
SIPP_OPTION_BOOL, &gracefulclose, 1},
+#else
+ {"multihome", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+ {"heartbeat", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+ {"assocmaxret", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+ {"pathmaxret", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+ {"gracefulclose", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+#endif
{"dynamicStart", "variable value\nSet the start offset of dynamic_id
varaiable", SIPP_OPTION_INT, &startDynamicId, 1},
{"dynamicMax", "variable value\nSet the maximum of dynamic_id
variable ", SIPP_OPTION_INT, &maxDynamicId, 1},
{"dynamicStep", "variable value\nSet the increment of dynamic_id
variable", SIPP_OPTION_INT, &stepDynamicId, 1}
@@ -600,6 +616,35 @@
#endif
}
+#ifdef _USE_SCTP
+int send_sctp_nowait(int s, const void *msg, int len, int flags)
+{
+ struct sctp_sndrcvinfo sinfo;
+ memset(&sinfo,0,sizeof(sinfo));
+ sinfo.sinfo_flags=SCTP_UNORDERED; // according to RFC4168 5.1
+ sinfo.sinfo_stream=0;
+
+#if defined(MSG_DONTWAIT) && !defined(__SUNOS)
+ return sctp_send(s, msg, len, &sinfo, flags | MSG_DONTWAIT);
+#else
+ int fd_flags = fcntl(s, F_GETFL , NULL);
+ int initial_fd_flags;
+ int rc;
+
+ initial_fd_flags = fd_flags;
+ // fd_flags &= ~O_ACCMODE; // Remove the access mode from the value
+ fd_flags |= O_NONBLOCK;
+ fcntl(s, F_SETFL , fd_flags);
+
+ rc = sctp_send(s, msg, len, &sinfo, flags);
+
+ fcntl(s, F_SETFL , initial_fd_flags);
+
+ return rc;
+#endif
+}
+#endif
+
char * get_inet_address(struct sockaddr_storage * addr)
{
static char * ip_addr = NULL;
@@ -2333,12 +2378,44 @@
return len;
}
+#ifdef _USE_SCTP
+void sipp_sctp_peer_params(struct sipp_socket *socket)
+{
+ if (heartbeat>0 || pathmaxret>0)
+ {
+ struct sctp_paddrparams peerparam;
+ memset(&peerparam,0,sizeof(peerparam));
+
+ sockaddr* addresses;
+ int addresscount=sctp_getpaddrs(socket->ss_fd,0,&addresses);
+ if (addresscount<1) WARNING("sctp_getpaddrs, errno=%d",errno);
+
+ for (int i=0;i<addresscount;i++)
+ {
+ memset(&peerparam.spp_address,0,sizeof(peerparam.spp_address));
+ struct sockaddr_storage* peeraddress=(struct
sockaddr_storage*)&addresses[i];
+ memcpy(&peerparam.spp_address,peeraddress,SOCK_ADDR_SIZE(peeraddress));
+
+ peerparam.spp_hbinterval=heartbeat;
+ peerparam.spp_pathmaxrxt=pathmaxret;
+ if (heartbeat>0) peerparam.spp_flags=SPP_HB_ENABLE;
+
+ if
(setsockopt(socket->ss_fd,IPPROTO_SCTP,SCTP_PEER_ADDR_PARAMS,&peerparam,sizeof(peerparam))
== -1) {
+ sctp_freepaddrs(addresses);
+ WARNING("setsockopt(SCTP_PEER_ADDR_PARAMS) failed, errno=%d",errno);
+ }
+ }
+ sctp_freepaddrs(addresses);
+ }
+}
+#endif
+
void sipp_customize_socket(struct sipp_socket *socket)
{
unsigned int buffsize = buff_size;
/* Allows fast TCP reuse of the socket */
- if (socket->ss_transport == T_TCP || socket->ss_transport == T_TLS ) {
+ if (socket->ss_transport == T_TCP || socket->ss_transport == T_TLS ||
socket->ss_transport == T_SCTP) {
int sock_opt = 1;
if (setsockopt(socket->ss_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_opt,
@@ -2346,15 +2423,46 @@
ERROR_NO("setsockopt(SO_REUSEADDR) failed");
}
+#ifdef _USE_SCTP
+ if (socket->ss_transport == T_SCTP)
+ {
+ struct sctp_event_subscribe event;
+ memset(&event, 0, sizeof(event));
+ event.sctp_data_io_event = 1;
+ event.sctp_association_event = 1;
+ event.sctp_shutdown_event = 1;
+ if
(setsockopt(socket->ss_fd,IPPROTO_SCTP,SCTP_EVENTS,&event,sizeof(event)) == -1)
{
+ ERROR_NO("setsockopt(SCTP_EVENTS) failed, errno=%d",errno);
+ }
+
+ if (assocmaxret>0)
+ {
+ struct sctp_assocparams associnfo;
+ memset(&associnfo,0,sizeof(associnfo));
+ associnfo.sasoc_asocmaxrxt=assocmaxret;
+ if
(setsockopt(socket->ss_fd,IPPROTO_SCTP,SCTP_ASSOCINFO,&associnfo,sizeof(associnfo))
== -1) {
+ WARNING("setsockopt(SCTP_ASSOCINFO) failed, errno=%d",errno);
+ }
+ }
+
+ if (setsockopt(socket->ss_fd, IPPROTO_SCTP, SCTP_NODELAY, (void
*)&sock_opt,sizeof (sock_opt)) == -1) {
+ WARNING("setsockopt(SCTP_NODELAY) failed, errno=%d",errno);
+ }
+ }
+#endif
+
#ifndef SOL_TCP
#define SOL_TCP 6
#endif
+ if (socket->ss_transport != T_SCTP)
+ {
if (setsockopt(socket->ss_fd, SOL_TCP, TCP_NODELAY, (void *)&sock_opt,
sizeof (sock_opt)) == -1) {
{
ERROR_NO("setsockopt(TCP_NODELAY) failed");
}
}
+ }
{
struct linger linger;
@@ -2412,6 +2520,26 @@
rc = -1;
#endif
break;
+ case T_SCTP:
+#ifdef _USE_SCTP
+ {
+ if (socket->sctpstate==SCTP_DOWN)
+ {
+ errno = EPIPE;
+ return -1;
+ }
+ else if (socket->sctpstate==SCTP_CONNECTING)
+ {
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+ rc=send_sctp_nowait(socket->ss_fd, buffer, len, 0);
+ }
+#else
+ errno = EOPNOTSUPP;
+ rc = -1;
+#endif
+ break;
case T_TCP:
rc = send_nowait(socket->ss_fd, buffer, len, 0);
break;
@@ -2449,6 +2577,10 @@
pollfiles[socket->ss_pollidx].events |= POLLOUT;
+#ifdef _USE_SCTP
+ if (socket->ss_transport==T_SCTP && socket->sctpstate==SCTP_CONNECTING) ;
+ else
+#endif
nb_net_cong++;
return -1;
}
@@ -2472,7 +2604,7 @@
return enter_congestion(socket, again);
}
- if (socket->ss_transport == T_TCP && errno == EPIPE) {
+ if ((socket->ss_transport == T_TCP || socket->ss_transport == T_SCTP) &&
errno == EPIPE) {
nb_net_send_errors++;
close(socket->ss_fd);
socket->ss_fd = -1;
@@ -2520,6 +2652,8 @@
assert(errno != EAGAIN);
}
+ if (socket->ss_transport==T_SCTP && ret==-2) return 0;
+
if (socket->ss_transport == T_TCP || socket->ss_transport == T_TLS) {
if (ret == 0) {
/* The remote side closed the connection. */
@@ -2756,7 +2890,7 @@
if (!socketbuf)
return 0;
- if (socket->ss_transport == T_UDP) {
+ if (socket->ss_transport == T_UDP || socket->ss_transport == T_SCTP) {
return socketbuf->len;
}
@@ -2860,9 +2994,75 @@
while (1);
}
+#ifdef _USE_SCTP
+static void handleSCTPNotify(struct sipp_socket* socket,char* buffer)
+{
+ union sctp_notification *notifMsg;
+
+ notifMsg = (union sctp_notification *)buffer;
+ if (notifMsg->sn_header.sn_type==SCTP_ASSOC_CHANGE)
+ {
+ if (notifMsg->sn_assoc_change.sac_state == SCTP_COMM_UP)
+ {
+ socket->sctpstate=SCTP_UP;
+ sipp_sctp_peer_params(socket);
+ }
+ else
+ {
+ sipp_socket_invalidate(socket);
+ if (reset_close) close_calls(socket);
+ }
+ }
+ else if (notifMsg->sn_header.sn_type==SCTP_SHUTDOWN_EVENT)
+ {
+ sipp_socket_invalidate(socket);
+ if (reset_close) close_calls(socket);
+ }
+}
+
+void set_multihome_addr(struct sipp_socket* socket,int port)
+{
+ if (strlen(multihome_ip)>0)
+ {
+ struct addrinfo * multi_addr;
+ struct addrinfo hints;
+ memset((char*)&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = PF_UNSPEC;
+
+ if (getaddrinfo(multihome_ip, NULL, &hints, &multi_addr) != 0)
+ {
+ ERROR("Can't get multihome IP address in getaddrinfo,
multihome_ip='%s'",multihome_ip);
+ }
+
+ struct sockaddr_storage secondaryaddress;
+ memset(&secondaryaddress, 0, sizeof(secondaryaddress));
+
+ memcpy(&secondaryaddress, multi_addr->ai_addr,
SOCK_ADDR_SIZE(_RCAST(struct sockaddr_storage *,multi_addr->ai_addr)));
+ freeaddrinfo(multi_addr);
+
+ if (port>0)
+ {
+ if (secondaryaddress.ss_family==AF_INET) ((struct
sockaddr_in*)&secondaryaddress)->sin_port=htons(port);
+ else if (secondaryaddress.ss_family==AF_INET6) ((struct
sockaddr_in6*)&secondaryaddress)->sin6_port=htons(port);
+ }
+
+ int ret=sctp_bindx(socket->ss_fd,(struct sockaddr
*)&secondaryaddress,1,SCTP_BINDX_ADD_ADDR);
+ if (ret<0)
+ {
+ WARNING("Can't bind to multihome address, errno='%d'",errno);
+ }
+ }
+}
+#endif
+
/* Pull up to tcp_readsize data bytes out of the socket into our local buffer.
*/
static int empty_socket(struct sipp_socket *socket) {
- int readsize = socket->ss_transport == T_UDP ? SIPP_MAX_MSG_SIZE :
tcp_readsize;
+
+ int readsize=0;
+ if (socket->ss_transport == T_UDP || socket->ss_transport == T_SCTP)
readsize=SIPP_MAX_MSG_SIZE;
+ else readsize=tcp_readsize;
+
struct socketbuf *socketbuf;
char *buffer;
int ret;
@@ -2891,6 +3091,24 @@
ERROR("TLS support is not enabled!");
#endif
break;
+ case T_SCTP:
+#ifdef _USE_SCTP
+ struct sctp_sndrcvinfo recvinfo;
+ memset(&recvinfo,0,sizeof(recvinfo));
+ int msg_flags=0;
+
+ ret=sctp_recvmsg(socket->ss_fd, (void*)buffer,readsize,(struct sockaddr
*)&socketbuf->addr,&addrlen,&recvinfo,&msg_flags);
+
+ if (MSG_NOTIFICATION & msg_flags)
+ {
+ errno=0;
+ handleSCTPNotify(socket,buffer);
+ return -2;
+ }
+#else
+ ERROR("SCTP support is not enabled!");
+#endif
+ break;
}
if (ret <= 0) {
free_socketbuf(socketbuf);
@@ -2927,6 +3145,17 @@
#endif
shutdown(socket->ss_fd, SHUT_RDWR);
+
+#ifdef _USE_SCTP
+ if (socket->ss_transport==T_SCTP && !gracefulclose)
+ {
+ struct linger ling={1,0};
+ if (setsockopt (socket->ss_fd, SOL_SOCKET, SO_LINGER,&ling, sizeof (ling))
< 0) {
+ WARNING("Unable to set SO_LINGER option for SCTP close");
+ }
+ }
+#endif
+
close(socket->ss_fd);
socket->ss_fd = -1;
@@ -2950,6 +3179,10 @@
{
pending_messages--;
}
+
+#ifdef _USE_SCTP
+ if (socket->ss_transport==T_SCTP) socket->sctpstate=SCTP_DOWN;
+#endif
}
void sipp_close_socket (struct sipp_socket *socket) {
@@ -3070,6 +3303,7 @@
main_socket->ss_count++;
break;
case T_TCP:
+ case T_SCTP:
case T_TLS:
new_ptr->associate_socket(tcp_multiplex);
tcp_multiplex->ss_count++;
@@ -3176,7 +3410,6 @@
if (pending_messages) {
return;
}
-
/* Get socket events. */
rs = poll(pollfiles, pollnfds, wait ? 1 : 0);
if((rs < 0) && (errno == EINTR)) {
@@ -3192,6 +3425,12 @@
assert(sock);
if(pollfiles[poll_idx].revents & POLLOUT) {
+
+#ifdef _USE_SCTP
+ if (transport==T_SCTP && sock->sctpstate!=SCTP_UP) ;
+ else
+#endif
+ {
/* We can flush this socket. */
TRACE_MSG("Exit problem event on socket %d \n", sock->ss_fd);
pollfiles[poll_idx].events &= ~POLLOUT;
@@ -3200,10 +3439,11 @@
flush_socket(sock);
events++;
}
+ }
if(pollfiles[poll_idx].revents & POLLIN) {
/* We can empty this socket. */
- if ((transport == T_TCP || transport == T_TLS) && sock == main_socket) {
+ if ((transport == T_TCP || transport == T_TLS || transport == T_SCTP) &&
sock == main_socket) {
struct sipp_socket *new_sock = sipp_accept_socket(sock);
if (!new_sock) {
ERROR_NO("Accepting new TCP connection.\n");
@@ -3850,11 +4090,21 @@
int socket_fd(bool use_ipv6, int transport) {
int socket_type;
+ int protocol=0;
int fd;
switch(transport) {
case T_UDP:
socket_type = SOCK_DGRAM;
+ protocol=IPPROTO_UDP;
+ break;
+ case T_SCTP:
+#ifndef _USE_SCTP
+ ERROR("You do not have SCTP support enabled!\n");
+#else
+ socket_type = SOCK_STREAM;
+ protocol=IPPROTO_SCTP;
+#endif
break;
case T_TLS:
#ifndef _USE_OPENSSL
@@ -3865,7 +4115,7 @@
break;
}
- if((fd = socket(use_ipv6 ? AF_INET6 : AF_INET, socket_type, 0))== -1) {
+ if((fd = socket(use_ipv6 ? AF_INET6 : AF_INET, socket_type, protocol))== -1)
{
ERROR("Unable to get a %s socket (3)", TRANSPORT_TO_STRING(transport));
}
@@ -4031,13 +4281,33 @@
*port = ntohs((short)((_RCAST(struct sockaddr_in *, saddr))->sin_port));
}
+#ifdef _USE_SCTP
+ bool isany=false;
+
+ if (socket->ss_ipv6) {
+ if (memcmp(&(_RCAST(struct sockaddr_in6 *,
saddr)->sin6_addr),&in6addr_any,sizeof(in6_addr))==0) isany=true;
+ } else {
+ isany= (_RCAST(struct sockaddr_in *, saddr)->sin_addr.s_addr==INADDR_ANY);
+ }
+
+ if (transport==T_SCTP && !isany) set_multihome_addr(socket,*port);
+#endif
+
return 0;
}
int sipp_do_connect_socket(struct sipp_socket *socket) {
int ret;
- assert(socket->ss_transport == T_TCP || socket->ss_transport == T_TLS);
+ assert(socket->ss_transport == T_TCP || socket->ss_transport == T_TLS ||
socket->ss_transport == T_SCTP);
+
+#ifdef _USE_SCTP
+ if (socket->ss_transport==T_SCTP)
+ {
+ int port=0;
+ sipp_bind_socket(socket, &local_sockaddr, &port);
+ }
+#endif
errno = 0;
ret = connect(socket->ss_fd, (struct sockaddr *)&socket->ss_dest,
SOCK_ADDR_SIZE(&socket->ss_dest));
@@ -4056,6 +4326,10 @@
#endif
}
+#ifdef _USE_SCTP
+ if (socket->ss_transport==T_SCTP) socket->sctpstate=SCTP_CONNECTING;
+#endif
+
return 0;
}
@@ -4149,6 +4423,9 @@
pid = getpid();
memset(local_ip, 0, 40);
+#ifdef _USE_SCTP
+ memset(multihome_ip, 0, 40);
+#endif
memset(media_ip,0, 40);
memset(control_ip,0, 40);
memset(media_ip_escaped,0, 42);
@@ -4336,6 +4613,13 @@
case 't':
transport = T_TCP;
break;
+ case 's':
+#ifdef _USE_SCTP
+ transport = T_SCTP;
+#else
+ ERROR("To use SCTP transport you must compile SIPp with lksctp");
+#endif
+ break;
case 'l':
#ifdef _USE_OPENSSL
transport = T_TLS;
@@ -4374,6 +4658,10 @@
ERROR("You can only use a perip socket with UDP!\n");
}
break;
+ case SIPP_OPTION_NEED_SCTP:
+ CHECK_PASS();
+ ERROR("SCTP support is required for the %s option.", argv[argi]);
+ break;
case SIPP_OPTION_NEED_SSL:
CHECK_PASS();
ERROR("OpenSSL is required for the %s option.", argv[argi]);
@@ -5388,7 +5676,7 @@
}
}
- if((!multisocket) && (transport == T_TCP || transport == T_TLS) &&
+ if((!multisocket) && (transport == T_TCP || transport == T_TLS || transport
== T_SCTP) &&
(sendMode != MODE_SERVER)) {
if((tcp_multiplex = new_sipp_socket(local_ip_is_ipv6, transport)) == NULL)
{
ERROR_NO("Unable to get a TCP socket");
@@ -5398,6 +5686,7 @@
if (use_remote_sending_addr) {
remote_sockaddr = remote_sending_sockaddr ;
}
+ sipp_customize_socket(tcp_multiplex);
if(sipp_connect_socket(tcp_multiplex, &remote_sockaddr)) {
if(reset_number >0){
@@ -5417,11 +5706,10 @@
}
}
- sipp_customize_socket(tcp_multiplex);
}
- if(transport == T_TCP || transport == T_TLS) {
+ if(transport == T_TCP || transport == T_TLS || transport == T_SCTP) {
if(listen(main_socket->ss_fd, 100)) {
ERROR_NO("Unable to listen main socket");
}
diff -bruN orig/sipp.hpp sipp.svn/sipp.hpp
--- orig/sipp.hpp 2008-12-30 17:09:30.000000000 +0100
+++ sipp.svn/sipp.hpp 2009-04-08 10:05:27.741000400 +0200
@@ -31,6 +31,9 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
+#ifdef _USE_SCTP
+#include <netinet/sctp.h>
+#endif
#include <sys/time.h>
#include <sys/poll.h>
#include <sys/resource.h>
@@ -119,6 +122,7 @@
#define T_UDP 0
#define T_TCP 1
#define T_TLS 2
+#define T_SCTP 3
#ifdef _USE_OPENSSL
#define DEFAULT_TLS_CERT ((char *)"cacert.pem")
@@ -126,7 +130,7 @@
#define DEFAULT_TLS_CRL ((char *)"")
#endif
-#define TRANSPORT_TO_STRING(p) ((p==T_TCP) ? "TCP" : ((p==T_TLS)? "TLS"
:"UDP"))
+#define TRANSPORT_TO_STRING(p) ((p==T_TCP) ? "TCP" : ((p==T_TLS)? "TLS" :
((p==T_UDP)? "UDP" : "SCTP")))
#define SIPP_MAXFDS 65536
#define SIPP_MAX_MSG_SIZE 65536
@@ -234,6 +238,13 @@
extern char local_ip_escaped[42];
extern bool local_ip_is_ipv6;
extern int local_port _DEFVAL(0);
+#ifdef _USE_SCTP
+extern char multihome_ip[40];
+extern int heartbeat _DEFVAL(0);
+extern int assocmaxret _DEFVAL(0);
+extern int pathmaxret _DEFVAL(0);
+extern bool gracefulclose _DEFVAL(true);
+#endif
extern char control_ip[40];
extern int control_port _DEFVAL(0);
extern int buff_size _DEFVAL(65535);
@@ -539,6 +550,11 @@
struct socketbuf *next;
};
+#ifdef _USE_SCTP
+#define SCTP_DOWN 0
+#define SCTP_CONNECTING 1
+#define SCTP_UP 2
+#endif
/* This is an abstraction of a socket, which provides buffers for input and
* output. */
struct sipp_socket {
@@ -567,6 +583,9 @@
struct socketbuf *ss_in; /* Buffered input. */
size_t ss_msglen; /* Is there a complete SIP message waiting, and
if so how big? */
struct socketbuf *ss_out; /* Buffered output. */
+#ifdef _USE_SCTP
+ int sctpstate;
+#endif
};
/* Write data to a socket. */
------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
Sipp-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sipp-users