60538758 | /* * Unix socket protocol * Copyright (c) 2013 Luca Barbato * |
8d06ce79 | * This file is part of FFmpeg. |
60538758 | * |
8d06ce79 | * FFmpeg is free software; you can redistribute it and/or |
60538758 | * 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. * |
8d06ce79 | * FFmpeg is distributed in the hope that it will be useful, |
60538758 | * 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 |
8d06ce79 | * License along with FFmpeg; if not, write to the Free Software |
60538758 | * 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" |
be03912a | #include <sys/un.h> |
60538758 | #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[] = { |
43ecec0f | { "listen", "Open socket for listening", OFFSET(listen), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ED }, |
60538758 | { "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)); |
bb937825 | if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0) |
60538758 | return ff_neterrno(); |
3ee2ec5e | if (s->timeout < 0 && h->rw_timeout) s->timeout = h->rw_timeout / 1000; |
60538758 | if (s->listen) { |
27852f2f | ret = ff_listen_bind(fd, (struct sockaddr *)&s->addr, sizeof(s->addr), s->timeout, h); if (ret < 0) |
60538758 | goto fail; |
27852f2f | fd = ret; |
60538758 | } else { ret = ff_listen_connect(fd, (struct sockaddr *)&s->addr, |
abe5268c | sizeof(s->addr), s->timeout, h, 0); |
60538758 | if (ret < 0) goto fail; } s->fd = fd; return 0; fail: |
2a0ec47b | if (s->listen && AVUNERROR(ret) != EADDRINUSE) |
60538758 | 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); |
1b45e6db | if (!ret && s->type == SOCK_STREAM) return AVERROR_EOF; |
60538758 | 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; } |
6ee1cb57 | ret = send(s->fd, buf, size, MSG_NOSIGNAL); |
60538758 | 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; } |
2758cded | const URLProtocol ff_unix_protocol = { |
60538758 | .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, }; |