|
- /*
- * Unix socket protocol
- * Copyright (c) 2013 Luca Barbato
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
- /**
- * @file
- *
- * Unix socket url_protocol
- */
-
- #include "libavutil/avstring.h"
- #include "libavutil/opt.h"
- #include "os_support.h"
- #include "network.h"
- #include <sys/un.h>
- #include "url.h"
-
- typedef struct UnixContext {
- const AVClass *class;
- struct sockaddr_un addr;
- int timeout;
- int listen;
- int type;
- int fd;
- } UnixContext;
-
- #define OFFSET(x) offsetof(UnixContext, x)
- #define ED AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_ENCODING_PARAM
- static const AVOption unix_options[] = {
- { "listen", "Open socket for listening", OFFSET(listen), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ED },
- { "timeout", "Timeout in ms", OFFSET(timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ED },
- { "type", "Socket type", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = SOCK_STREAM }, INT_MIN, INT_MAX, ED, "type" },
- { "stream", "Stream (reliable stream-oriented)", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_STREAM }, INT_MIN, INT_MAX, ED, "type" },
- { "datagram", "Datagram (unreliable packet-oriented)", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_DGRAM }, INT_MIN, INT_MAX, ED, "type" },
- { "seqpacket", "Seqpacket (reliable packet-oriented", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_SEQPACKET }, INT_MIN, INT_MAX, ED, "type" },
- { NULL }
- };
-
- static const AVClass unix_class = {
- .class_name = "unix",
- .item_name = av_default_item_name,
- .option = unix_options,
- .version = LIBAVUTIL_VERSION_INT,
- };
-
- static int unix_open(URLContext *h, const char *filename, int flags)
- {
- UnixContext *s = h->priv_data;
- int fd, ret;
-
- av_strstart(filename, "unix:", &filename);
- s->addr.sun_family = AF_UNIX;
- av_strlcpy(s->addr.sun_path, filename, sizeof(s->addr.sun_path));
-
- if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0)
- return ff_neterrno();
-
- if (s->listen) {
- ret = ff_listen_bind(fd, (struct sockaddr *)&s->addr,
- sizeof(s->addr), s->timeout, h);
- if (ret < 0)
- goto fail;
- fd = ret;
- } else {
- ret = ff_listen_connect(fd, (struct sockaddr *)&s->addr,
- sizeof(s->addr), s->timeout, h, 0);
- if (ret < 0)
- goto fail;
- }
-
- s->fd = fd;
-
- return 0;
-
- fail:
- if (s->listen && AVUNERROR(ret) != EADDRINUSE)
- unlink(s->addr.sun_path);
- if (fd >= 0)
- closesocket(fd);
- return ret;
- }
-
- static int unix_read(URLContext *h, uint8_t *buf, int size)
- {
- UnixContext *s = h->priv_data;
- int ret;
-
- if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
- ret = ff_network_wait_fd(s->fd, 0);
- if (ret < 0)
- return ret;
- }
- ret = recv(s->fd, buf, size, 0);
- return ret < 0 ? ff_neterrno() : ret;
- }
-
- static int unix_write(URLContext *h, const uint8_t *buf, int size)
- {
- UnixContext *s = h->priv_data;
- int ret;
-
- if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
- ret = ff_network_wait_fd(s->fd, 1);
- if (ret < 0)
- return ret;
- }
- ret = send(s->fd, buf, size, MSG_NOSIGNAL);
- return ret < 0 ? ff_neterrno() : ret;
- }
-
- static int unix_close(URLContext *h)
- {
- UnixContext *s = h->priv_data;
- if (s->listen)
- unlink(s->addr.sun_path);
- closesocket(s->fd);
- return 0;
- }
-
- static int unix_get_file_handle(URLContext *h)
- {
- UnixContext *s = h->priv_data;
- return s->fd;
- }
-
- URLProtocol ff_unix_protocol = {
- .name = "unix",
- .url_open = unix_open,
- .url_read = unix_read,
- .url_write = unix_write,
- .url_close = unix_close,
- .url_get_file_handle = unix_get_file_handle,
- .priv_data_size = sizeof(UnixContext),
- .priv_data_class = &unix_class,
- .flags = URL_PROTOCOL_FLAG_NETWORK,
- };
|