Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1493,10 +1493,14 @@ AC_CHECK_HEADER(netinet/sctp.h, [ AC_DEFINE(OF_HAVE_SCTP, 1, [Whether we have SCTP]) AC_DEFINE(OF_HAVE_NETINET_SCTP_H, 1, [Whether we have netinet/sctp.h]) AC_SUBST(USE_SRCS_SCTP, '${SRCS_SCTP}') + ], [], [ + #ifdef OF_HAVE_SYS_SOCKET_H + # include + #endif ]) AC_CHECK_HEADERS([arpa/inet.h netdb.h sys/sockio.h]) AC_CHECK_HEADERS([net/if.h], [], [], [ #ifdef OF_HAVE_SYS_SOCKET_H # include Index: src/OFSCTPSocket.m ================================================================== --- src/OFSCTPSocket.m +++ src/OFSCTPSocket.m @@ -16,10 +16,12 @@ * version 3.0 along with this program. If not, see * . */ #include "config.h" + +#define _XPG4_2 #include #include #include #include @@ -49,10 +51,14 @@ #import "OFNotOpenException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFSetOptionFailedException.h" #import "OFWriteFailedException.h" + +#ifdef OF_SOLARIS +# define SCTP_UNORDERED MSG_UNORDERED +#endif const OFSCTPMessageInfoKey OFSCTPStreamID = @"OFSCTPStreamID"; const OFSCTPMessageInfoKey OFSCTPPPID = @"OFSCTPPPID"; const OFSCTPMessageInfoKey OFSCTPUnordered = @"OFSCTPUnordered"; @@ -92,16 +98,16 @@ @dynamic delegate; - (bool)of_createSocketForAddress: (const OFSocketAddress *)address errNo: (int *)errNo { + const struct sctp_event_subscribe events = { + .sctp_data_io_event = 1 + }; #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; #endif -#ifdef SCTP_RECVRCVINFO - int one = 1; -#endif if (_socket != OFInvalidSocketHandle) @throw [OFAlreadyOpenException exceptionWithObject: self]; if ((_socket = socket( @@ -115,21 +121,19 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); #endif -#ifdef SCTP_RECVRCVINFO - if (setsockopt(_socket, IPPROTO_SCTP, SCTP_RECVRCVINFO, &one, - sizeof(one)) != 0) { + if (setsockopt(_socket, IPPROTO_SCTP, SCTP_EVENTS, &events, + sizeof(events)) != 0) { *errNo = _OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; return false; } -#endif return true; } - (bool)of_connectSocketToAddress: (const OFSocketAddress *)address @@ -331,25 +335,25 @@ objc_autoreleasePoolPop(pool); return address; } -#ifdef SCTP_RECVRCVINFO - (instancetype)accept { + const struct sctp_event_subscribe events = { + .sctp_data_io_event = 1 + }; OFSCTPSocket *accepted = [super accept]; - int one = 1; - if (setsockopt(accepted->_socket, IPPROTO_SCTP, SCTP_RECVRCVINFO, &one, - sizeof(one)) != 0) + if (setsockopt(accepted->_socket, IPPROTO_SCTP, SCTP_EVENTS, &events, + sizeof(events)) != 0) @throw [OFAcceptSocketFailedException exceptionWithSocket: self errNo: _OFSocketErrNo()]; return accepted; } -#endif - (size_t)receiveIntoBuffer: (void *)buffer length: (size_t)length { return [self receiveIntoBuffer: buffer length: length info: NULL]; } @@ -361,11 +365,11 @@ ssize_t ret; struct iovec iov = { .iov_base = buffer, .iov_len = length }; - char cmsgBuffer[CMSG_SPACE(sizeof(struct sctp_rcvinfo))]; + char cmsgBuffer[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cmsgBuffer, .msg_controllen = sizeof(cmsgBuffer) @@ -389,19 +393,19 @@ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level != IPPROTO_SCTP) continue; - if (cmsg->cmsg_type == SCTP_RCVINFO) { - struct sctp_rcvinfo rcvinfo; - memcpy(&rcvinfo, CMSG_DATA(cmsg), sizeof(rcvinfo)); + if (cmsg->cmsg_type == SCTP_SNDRCV) { + struct sctp_sndrcvinfo sndrcv; + memcpy(&sndrcv, CMSG_DATA(cmsg), sizeof(sndrcv)); OFNumber *streamID = [OFNumber numberWithUnsignedShort: - rcvinfo.rcv_sid]; + sndrcv.sinfo_stream]; OFNumber *PPID = [OFNumber numberWithUnsignedLong: - rcvinfo.rcv_ppid]; + OFFromBigEndian32(sndrcv.sinfo_ppid)]; OFNumber *unordered = [OFNumber numberWithBool: - (rcvinfo.rcv_flags & SCTP_UNORDERED)]; + (sndrcv.sinfo_flags & SCTP_UNORDERED)]; *info = [OFDictionary dictionaryWithKeysAndObjects: OFSCTPStreamID, streamID, OFSCTPPPID, PPID, OFSCTPUnordered, unordered, nil]; @@ -473,19 +477,19 @@ ssize_t bytesWritten; struct iovec iov = { .iov_base = (void *)buffer, .iov_len = length }; - struct sctp_sndinfo sndinfo = { - .snd_sid = (uint16_t) + struct sctp_sndrcvinfo sndrcv = { + .sinfo_stream = (uint16_t) [[info objectForKey: OFSCTPStreamID] unsignedShortValue], - .snd_ppid = (uint32_t) - [[info objectForKey: OFSCTPPPID] unsignedLongValue], - .snd_flags = ([[info objectForKey: OFSCTPUnordered] boolValue] + .sinfo_ppid = OFToBigEndian32((uint32_t) + [[info objectForKey: OFSCTPPPID] unsignedLongValue]), + .sinfo_flags = ([[info objectForKey: OFSCTPUnordered] boolValue] ? SCTP_UNORDERED : 0) }; - char cmsgBuffer[CMSG_SPACE(sizeof(sndinfo))]; + char cmsgBuffer[CMSG_SPACE(sizeof(sndrcv))]; struct cmsghdr *cmsg = (struct cmsghdr *)(void *)&cmsgBuffer; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = &cmsgBuffer, @@ -497,13 +501,13 @@ if (length > SSIZE_MAX) @throw [OFOutOfRangeException exception]; cmsg->cmsg_level = IPPROTO_SCTP; - cmsg->cmsg_type = SCTP_SNDINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(sndinfo)); - memcpy(CMSG_DATA(cmsg), &sndinfo, sizeof(sndinfo)); + cmsg->cmsg_type = SCTP_SNDRCV; + cmsg->cmsg_len = CMSG_LEN(sizeof(sndrcv)); + memcpy(CMSG_DATA(cmsg), &sndrcv, sizeof(sndrcv)); if ((bytesWritten = sendmsg(_socket, &msg, 0)) < 0) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length