40 #include <netinet/in.h>
41 #include <netinet/sctp.h>
75 socklen_t *fromlen,
struct sctp_sndrcvinfo *sinfo,
80 char incmsg[CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))];
81 struct msghdr inmsg = { 0 };
82 struct cmsghdr *cmsg =
NULL;
87 inmsg.msg_name =
from;
88 inmsg.msg_namelen = fromlen ? *fromlen : 0;
91 inmsg.msg_control = incmsg;
92 inmsg.msg_controllen =
sizeof(incmsg);
94 if ((recvb = recvmsg(s, &inmsg, msg_flags ? *msg_flags : 0)) < 0)
98 *fromlen = inmsg.msg_namelen;
100 *msg_flags = inmsg.msg_flags;
102 for (cmsg = CMSG_FIRSTHDR(&inmsg); cmsg;
103 cmsg = CMSG_NXTHDR(&inmsg, cmsg)) {
104 if ((IPPROTO_SCTP == cmsg->cmsg_level) &&
105 (SCTP_SNDRCV == cmsg->cmsg_type))
111 memcpy(sinfo, CMSG_DATA(cmsg),
sizeof(
struct sctp_sndrcvinfo));
117 const struct sctp_sndrcvinfo *sinfo,
int flags)
119 struct msghdr outmsg = { 0 };
122 outmsg.msg_name =
NULL;
123 outmsg.msg_namelen = 0;
124 outmsg.msg_iov = &iov;
125 iov.iov_base = (
void*)msg;
127 outmsg.msg_iovlen = 1;
128 outmsg.msg_controllen = 0;
131 char outcmsg[CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))];
132 struct cmsghdr *cmsg;
134 outmsg.msg_control = outcmsg;
135 outmsg.msg_controllen =
sizeof(outcmsg);
136 outmsg.msg_flags = 0;
138 cmsg = CMSG_FIRSTHDR(&outmsg);
139 cmsg->cmsg_level = IPPROTO_SCTP;
140 cmsg->cmsg_type = SCTP_SNDRCV;
141 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct sctp_sndrcvinfo));
143 outmsg.msg_controllen = cmsg->cmsg_len;
144 memcpy(CMSG_DATA(cmsg), sinfo,
sizeof(
struct sctp_sndrcvinfo));
160 #define OFFSET(x) offsetof(SCTPContext, x)
161 #define D AV_OPT_FLAG_DECODING_PARAM
162 #define E AV_OPT_FLAG_ENCODING_PARAM
164 {
"listen",
"Listen for incoming connections",
OFFSET(listen),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags =
D|
E },
165 {
"timeout",
"Connection timeout (in milliseconds)",
OFFSET(timeout),
AV_OPT_TYPE_INT, { .i64 = 10000 }, INT_MIN, INT_MAX, .flags =
D|
E },
166 {
"listen_timeout",
"Bind timeout (in milliseconds)",
OFFSET(listen_timeout),
AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, .flags =
D|
E },
167 {
"max_streams",
"Max stream to allocate",
OFFSET(max_streams),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT16_MAX, .flags =
D|
E },
182 struct sctp_event_subscribe event = { 0 };
183 struct sctp_initmsg initparams = { 0 };
190 char hostname[1024], proto[1024], path[1024];
194 &port, path,
sizeof(path), uri);
195 if (strcmp(proto,
"sctp"))
197 if (port <= 0 || port >= 65536) {
202 p = strchr(uri,
'?');
212 snprintf(portstr,
sizeof(portstr),
"%d", port);
246 event.sctp_data_io_event = 1;
249 if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event,
250 sizeof(event)) != 0) {
252 "SCTP ERROR: Unable to subscribe to events\n");
259 if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initparams,
260 sizeof(initparams)) < 0) {
262 "SCTP ERROR: Unable to initialize socket max streams %d\n",
292 int ev = write ? POLLOUT : POLLIN;
293 struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
296 ret = poll(&p, 1, 100);
313 struct sctp_sndrcvinfo info = { 0 };
315 AV_WB16(buf, info.sinfo_stream);
316 ret = ret < 0 ? ret : ret + 2;
318 ret = recv(s->
fd, buf, size, 0);
336 struct sctp_sndrcvinfo info = { 0 };
337 info.sinfo_stream =
AV_RB16(buf);
371 .priv_data_class = &sctp_class,
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
struct sockaddr_storage dest_addr
static int ff_sctp_recvmsg(int s, void *msg, size_t len, struct sockaddr *from, socklen_t *fromlen, struct sctp_sndrcvinfo *sinfo, int *msg_flags)
#define URL_PROTOCOL_FLAG_NETWORK
#define LIBAVUTIL_VERSION_INT
int is_streamed
true if streamed (no seek possible), default = false
static const AVClass sctp_class
static int sctp_write(URLContext *h, const uint8_t *buf, int size)
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
URLProtocol ff_sctp_protocol
int ff_socket(int af, int type, int proto)
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
int ff_listen_bind(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h)
Bind to a file descriptor and poll for a connection.
miscellaneous OS support macros and functions.
int ff_listen_connect(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next)
Connect to a file descriptor and poll for result.
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static int sctp_close(URLContext *h)
static int sctp_get_file_handle(URLContext *h)
static int sctp_wait_fd(int fd, int write)
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
static int ff_sctp_send(int s, const void *msg, size_t len, const struct sctp_sndrcvinfo *sinfo, int flags)
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Describe the class of an AVClass context structure.
static const AVOption options[]
static int sctp_open(URLContext *h, const char *uri, int flags)
static int sctp_read(URLContext *h, uint8_t *buf, int size)
struct addrinfo * ai_next
unbuffered private I/O API
struct sockaddr * ai_addr