diff --git a/engine/Makefile.in b/engine/Makefile.in index d24e0221..6de27dc4 100644 --- a/engine/Makefile.in +++ b/engine/Makefile.in @@ -31,6 +31,14 @@ LIBOBJS := $(CLSOBJS) $(ENGOBJS) $(TELOBJS) $(CLIOBJS) CLEANS = $(LIBOBJS) core COMPILE = $(CXX) $(DEFS) $(DEBUG) $(INCLUDES) $(CFLAGS) LINK = $(CXX) $(LDFLAGS) +SCTPOPTS:= + +ifneq (@HAVE_SCTP@,no) +SCTPOPTS := $(SCTPOPTS) -DHAVE_SCTP +endif +ifneq (@HAVE_SCTP_NETINET@,no) +SCTPOPTS := $(SCTPOPTS) -DHAVE_SCTP_NETINET +endif prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -68,7 +76,7 @@ DataFormat.o: @srcdir@/DataFormat.cpp $(MKDEPS) $(PINC) $(COMPILE) -c $< Socket.o: @srcdir@/Socket.cpp $(MKDEPS) $(CINC) - $(COMPILE) @FDSIZE_HACK@ -c $< + $(COMPILE) @FDSIZE_HACK@ $(SCTPOPTS) -c $< Mutex.o: @srcdir@/Mutex.cpp $(MKDEPS) $(CINC) $(COMPILE) @MUTEX_HACK@ -c $< diff --git a/engine/Socket.cpp b/engine/Socket.cpp index e3c4849f..0cb121a5 100644 --- a/engine/Socket.cpp +++ b/engine/Socket.cpp @@ -33,6 +33,10 @@ #include "yateclass.h" +#ifdef HAVE_SCTP_NETINET +#include +#endif + #include #undef HAS_AF_UNIX @@ -49,6 +53,18 @@ #include #endif +#ifndef SHUT_RD +#define SHUT_RD 0 +#endif + +#ifndef SHUT_WR +#define SHUT_WR 1 +#endif + +#ifndef SHUT_RDWR +#define SHUT_RDWR 2 +#endif + #define MAX_SOCKLEN 1024 using namespace TelEngine; @@ -724,6 +740,28 @@ SOCKET Socket::acceptHandle(struct sockaddr* addr, socklen_t* addrlen) return res; } +Socket* Socket::peelOff(unsigned int assoc) +{ + SOCKET sock = peelOffHandle(assoc); + return (sock == invalidHandle()) ? 0 : new Socket(sock); +} + +SOCKET Socket::peelOffHandle(unsigned int assoc) +{ +#ifdef SCTP_SOCKOPT_PEELOFF + sctp_peeloff_arg_t buffer; + buffer.associd = assoc; + buffer.sd = invalidHandle(); + socklen_t length = sizeof(buffer); + if (!getOption(SOL_SCTP, SCTP_SOCKOPT_PEELOFF, &buffer, &length)) + return invalidHandle(); + return buffer.sd; +#else + Debug(DebugMild,"Socket::peelOffHandle() not supported on this platform"); + return invalidHandle(); +#endif +} + bool Socket::connect(struct sockaddr* addr, socklen_t addrlen) { if (addrlen && !addr) @@ -731,6 +769,25 @@ bool Socket::connect(struct sockaddr* addr, socklen_t addrlen) return checkError(::connect(m_handle,addr,addrlen)); } +bool Socket::shutdown(bool stopReads, bool stopWrites) +{ + int how; + if (stopReads) { + if (stopWrites) + how = SHUT_RDWR; + else + how = SHUT_RD; + } + else { + if (stopWrites) + how = SHUT_WR; + else + // nothing to do - no error + return true; + } + return checkError(::shutdown(m_handle,how)); +} + bool Socket::getSockName(struct sockaddr* addr, socklen_t* addrlen) { if (addrlen && !addr) diff --git a/yateclass.h b/yateclass.h index 9f3f90a0..6fe02044 100644 --- a/yateclass.h +++ b/yateclass.h @@ -3405,7 +3405,7 @@ public: void attach(HANDLE handle); /** - * Detaches the object from the socket handle + * Detaches the object from the file handle * @return The handle previously owned by this object */ HANDLE detach(); @@ -3660,6 +3660,20 @@ public: */ SOCKET acceptHandle(struct sockaddr* addr = 0, socklen_t* addrlen = 0); + /** + * Create a new socket by peeling off an association from a SCTP socket + * @param assoc Identifier of the association to peel off + * @return Open socket to the association or NULL on failure + */ + Socket* peelOff(unsigned int assoc); + + /** + * Create a new socket by peeling off an association from a SCTP socket + * @param assoc Identifier of the association to peel off + * @return Operating system handle to the association or @ref invalidHandle() on failure + */ + SOCKET peelOffHandle(unsigned int assoc); + /** * Connects the socket to a remote address * @param addr Address to connect to @@ -3676,6 +3690,14 @@ public: inline bool connect(const SocketAddr& addr) { return connect(addr.address(), addr.length()); } + /** + * Shut down one or both directions of a full-duplex socket. + * @param stopReads Request to shut down the read side of the socket + * @param stopWrites Request to shut down the write side of the socket + * @return True if operation was successfull, false if an error occured + */ + bool shutdown(bool stopReads, bool stopWrites); + /** * Retrive the address of the local socket of a connection * @param addr Address to fill in with the address of the local socket