00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00040 #include <netinet/in.h>
00041 #include <netinet/sctp.h>
00042 #include <sys/time.h>
00043 #include <unistd.h>
00044
00045 #include "config.h"
00046
00047 #if HAVE_POLL_H
00048 #include <poll.h>
00049 #endif
00050
00051 #include "libavutil/intreadwrite.h"
00052 #include "libavutil/parseutils.h"
00053 #include "avformat.h"
00054 #include "internal.h"
00055 #include "network.h"
00056 #include "os_support.h"
00057 #include "url.h"
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 static int ff_sctp_recvmsg(int s, void *msg, size_t len, struct sockaddr *from,
00076 socklen_t *fromlen, struct sctp_sndrcvinfo *sinfo,
00077 int *msg_flags)
00078 {
00079 int recvb;
00080 struct iovec iov;
00081 char incmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
00082 struct msghdr inmsg = { 0 };
00083 struct cmsghdr *cmsg = NULL;
00084
00085 iov.iov_base = msg;
00086 iov.iov_len = len;
00087
00088 inmsg.msg_name = from;
00089 inmsg.msg_namelen = fromlen ? *fromlen : 0;
00090 inmsg.msg_iov = &iov;
00091 inmsg.msg_iovlen = 1;
00092 inmsg.msg_control = incmsg;
00093 inmsg.msg_controllen = sizeof(incmsg);
00094
00095 if ((recvb = recvmsg(s, &inmsg, msg_flags ? *msg_flags : 0)) < 0)
00096 return recvb;
00097
00098 if (fromlen)
00099 *fromlen = inmsg.msg_namelen;
00100 if (msg_flags)
00101 *msg_flags = inmsg.msg_flags;
00102
00103 for (cmsg = CMSG_FIRSTHDR(&inmsg); cmsg != NULL;
00104 cmsg = CMSG_NXTHDR(&inmsg, cmsg)) {
00105 if ((IPPROTO_SCTP == cmsg->cmsg_level) &&
00106 (SCTP_SNDRCV == cmsg->cmsg_type))
00107 break;
00108 }
00109
00110
00111 if (cmsg)
00112 memcpy(sinfo, CMSG_DATA(cmsg), sizeof(struct sctp_sndrcvinfo));
00113
00114 return recvb;
00115 }
00116
00117 static int ff_sctp_send(int s, const void *msg, size_t len,
00118 const struct sctp_sndrcvinfo *sinfo, int flags)
00119 {
00120 struct msghdr outmsg;
00121 struct iovec iov;
00122
00123 outmsg.msg_name = NULL;
00124 outmsg.msg_namelen = 0;
00125 outmsg.msg_iov = &iov;
00126 iov.iov_base = msg;
00127 iov.iov_len = len;
00128 outmsg.msg_iovlen = 1;
00129 outmsg.msg_controllen = 0;
00130
00131 if (sinfo) {
00132 char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
00133 struct cmsghdr *cmsg;
00134
00135 outmsg.msg_control = outcmsg;
00136 outmsg.msg_controllen = sizeof(outcmsg);
00137 outmsg.msg_flags = 0;
00138
00139 cmsg = CMSG_FIRSTHDR(&outmsg);
00140 cmsg->cmsg_level = IPPROTO_SCTP;
00141 cmsg->cmsg_type = SCTP_SNDRCV;
00142 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
00143
00144 outmsg.msg_controllen = cmsg->cmsg_len;
00145 memcpy(CMSG_DATA(cmsg), sinfo, sizeof(struct sctp_sndrcvinfo));
00146 }
00147
00148 return sendmsg(s, &outmsg, flags);
00149 }
00150
00151 typedef struct SCTPContext {
00152 int fd;
00153 int max_streams;
00154 struct sockaddr_storage dest_addr;
00155 socklen_t dest_addr_len;
00156 } SCTPContext;
00157
00158 static int sctp_open(URLContext *h, const char *uri, int flags)
00159 {
00160 struct addrinfo *ai, *cur_ai;
00161 struct addrinfo hints = { 0 };
00162 struct sctp_event_subscribe event = { 0 };
00163 struct sctp_initmsg initparams = { 0 };
00164 int port;
00165 int fd = -1;
00166 SCTPContext *s = h->priv_data;
00167 const char *p;
00168 char buf[256];
00169 int ret, listen_socket = 0;
00170 char hostname[1024], proto[1024], path[1024];
00171 char portstr[10];
00172
00173 av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname),
00174 &port, path, sizeof(path), uri);
00175 if (strcmp(proto,"sctp") || port <= 0 || port >= 65536)
00176 return AVERROR(EINVAL);
00177
00178 s->max_streams = 0;
00179 p = strchr(uri, '?');
00180 if (p) {
00181 if (av_find_info_tag(buf, sizeof(buf), "listen", p))
00182 listen_socket = 1;
00183 if (av_find_info_tag(buf, sizeof(buf), "max_streams", p))
00184 s->max_streams = strtol(buf, NULL, 10);
00185 }
00186
00187 hints.ai_family = AF_UNSPEC;
00188 hints.ai_socktype = SOCK_STREAM;
00189 snprintf(portstr, sizeof(portstr), "%d", port);
00190 ret = getaddrinfo(hostname, portstr, &hints, &ai);
00191 if (ret) {
00192 av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n",
00193 hostname, gai_strerror(ret));
00194 return AVERROR(EIO);
00195 }
00196
00197 cur_ai = ai;
00198
00199 fd = socket(cur_ai->ai_family, SOCK_STREAM, IPPROTO_SCTP);
00200 if (fd < 0)
00201 goto fail;
00202
00203 s->dest_addr_len = sizeof(s->dest_addr);
00204
00205 if (listen_socket) {
00206 int fd1;
00207 ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
00208 listen(fd, 100);
00209 fd1 = accept(fd, NULL, NULL);
00210 closesocket(fd);
00211 fd = fd1;
00212 } else
00213 ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
00214
00215 ff_socket_nonblock(fd, 1);
00216
00217 event.sctp_data_io_event = 1;
00218
00219
00220 if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event,
00221 sizeof(event)) != 0) {
00222 av_log(h, AV_LOG_ERROR,
00223 "SCTP ERROR: Unable to subscribe to events\n");
00224 goto fail;
00225 }
00226
00227 if (s->max_streams) {
00228 initparams.sinit_max_instreams = s->max_streams;
00229 initparams.sinit_num_ostreams = s->max_streams;
00230 if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initparams,
00231 sizeof(initparams)) < 0)
00232 av_log(h, AV_LOG_ERROR,
00233 "SCTP ERROR: Unable to initialize socket max streams %d\n",
00234 s->max_streams);
00235 }
00236
00237 h->priv_data = s;
00238 h->is_streamed = 1;
00239 s->fd = fd;
00240 freeaddrinfo(ai);
00241 return 0;
00242
00243 fail:
00244 ret = AVERROR(EIO);
00245 freeaddrinfo(ai);
00246 return ret;
00247 }
00248
00249 static int sctp_wait_fd(int fd, int write)
00250 {
00251 int ev = write ? POLLOUT : POLLIN;
00252 struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
00253 int ret;
00254
00255 ret = poll(&p, 1, 100);
00256 return ret < 0 ? ff_neterrno() : p.revents & ev ? 0 : AVERROR(EAGAIN);
00257 }
00258
00259 static int sctp_read(URLContext *h, uint8_t *buf, int size)
00260 {
00261 SCTPContext *s = h->priv_data;
00262 int ret;
00263
00264 if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
00265 ret = sctp_wait_fd(s->fd, 0);
00266 if (ret < 0)
00267 return ret;
00268 }
00269
00270 if (s->max_streams) {
00271
00272 struct sctp_sndrcvinfo info = { 0 };
00273 ret = ff_sctp_recvmsg(s->fd, buf + 2, size - 2, NULL, 0, &info, 0);
00274 AV_WB16(buf, info.sinfo_stream);
00275 ret = ret < 0 ? ret : ret + 2;
00276 } else
00277 ret = recv(s->fd, buf, size, 0);
00278
00279 return ret < 0 ? ff_neterrno() : ret;
00280 }
00281
00282 static int sctp_write(URLContext *h, const uint8_t *buf, int size)
00283 {
00284 SCTPContext *s = h->priv_data;
00285 int ret;
00286
00287 if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
00288 ret = sctp_wait_fd(s->fd, 1);
00289 if (ret < 0)
00290 return ret;
00291 }
00292
00293 if (s->max_streams) {
00294
00295 struct sctp_sndrcvinfo info = { 0 };
00296 info.sinfo_stream = AV_RB16(buf);
00297 if (info.sinfo_stream > s->max_streams)
00298 abort();
00299 ret = ff_sctp_send(s->fd, buf + 2, size - 2, &info, MSG_EOR);
00300 } else
00301 ret = send(s->fd, buf, size, 0);
00302
00303 return ret < 0 ? ff_neterrno() : ret;
00304 }
00305
00306 static int sctp_close(URLContext *h)
00307 {
00308 SCTPContext *s = h->priv_data;
00309 closesocket(s->fd);
00310 return 0;
00311 }
00312
00313 static int sctp_get_file_handle(URLContext *h)
00314 {
00315 SCTPContext *s = h->priv_data;
00316 return s->fd;
00317 }
00318
00319 URLProtocol ff_sctp_protocol = {
00320 .name = "sctp",
00321 .url_open = sctp_open,
00322 .url_read = sctp_read,
00323 .url_write = sctp_write,
00324 .url_close = sctp_close,
00325 .url_get_file_handle = sctp_get_file_handle,
00326 .priv_data_size = sizeof(SCTPContext),
00327 .flags = URL_PROTOCOL_FLAG_NETWORK,
00328 };