From patchwork Fri Nov 3 08:27:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jeyapal, Karthick" X-Patchwork-Id: 5843 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.161.90 with SMTP id m26csp3080806jah; Fri, 3 Nov 2017 01:27:41 -0700 (PDT) X-Google-Smtp-Source: ABhQp+T4RxLOSKK1R1z5/VdaYVhb9EPJ+zIk6jVKNG1pQaCmbK/WUGElPLepJGXiyPsRTnmY4MGh X-Received: by 10.223.201.8 with SMTP id m8mr4162540wrh.260.1509697661661; Fri, 03 Nov 2017 01:27:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1509697661; cv=none; d=google.com; s=arc-20160816; b=U3kkcDHP2umZj1dIzn7Nijem1NjZ6hRemphCD+zsv9XSGPwKShhhWjwa4QB5ExW0aQ gXI/2u7mcLxPCWlmJQi/7mguUHYYThIc9LEBms0E74GB4gp0b17DKX10/AL7nf+ahNmQ Jr7zD6wkCaPx2WXW9axIvIfJF2r1PlXeG8yatBNgrZhuSrmvPgQetdfzDTkdo6IuplP2 moMXJjGpny/MCMJQi4iCHvEt6cF+vC5wMDEbuRRhSALyUEmFjCr/qYqBpk/M0zgTnMHU coft6rHZ+GK8cxKRwFN08nldHgFRJ8k9C+zQTrEEHEd1/44xZObzkQATXcFiTFf67j9j mpNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:feedback-id:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to :arc-authentication-results; bh=5BjuT/AmuzZtgaFtZtuG/Cc4Shng012P0AeVoXslKSM=; b=zbMfWa+UZpNJIbj0i0DblAc0wgWxvKd+cjtPnk57puwaXZLn/kEyqcZ6p1VHHZZFOP mCY8TsQmnKcpY8Yugo+4yzimqbyizFCMm4UsvFtkWnXplQVrbSWHfpqB0WwtlqYX/jex tVf/b5ft+/xkeov12YgpTVnOw1UY/h3h6lpBSfurPhrPaA9q8ASlZWtJff1c2JByN5W0 uw6XrUGZn75t/tSevp8+hUSzcVwWASqpdLyO4O7dyVv4EcbtPp0XUvsTiR3HISrJfFLk 8ID5ikZS1TMw7XltN0BDgjU8gCiU+2ePHZUkYTJXQDVANam98/sY8FhjlYK2JxaQJJQp VFiA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@smtpservice.net header.s=m78bu0.a1-4.dyn header.b=i0sGb14P; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=NONE dis=NONE) header.from=akamai.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 203si1293641wmn.160.2017.11.03.01.27.37; Fri, 03 Nov 2017 01:27:41 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@smtpservice.net header.s=m78bu0.a1-4.dyn header.b=i0sGb14P; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=NONE dis=NONE) header.from=akamai.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A562568A181; Fri, 3 Nov 2017 10:27:15 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from a2i831.smtp2go.com (a2i831.smtp2go.com [103.47.207.63]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4759E68A12A for ; Fri, 3 Nov 2017 10:27:08 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=smtpservice.net; s=m78bu0.a1-4.dyn; x=1509698544; h=Feedback-ID: X-Smtpcorp-Track:Message-Id:Date:Subject:To:From:Reply-To:Sender: List-Unsubscribe; bh=78ADR3niXVGW3lGD0vg4wJDq+ccgXfzOz9lK5fBduf8=; b=i0sGb14P /0FWXUVDhCwJpzNbGYGRoc+RW5OOutfBp3o0SxhAkpXBAbRkBcL5jFwZO9HCuzPcDQ53BekIi6TBi 0ZwTIM+BHnTuibPYS2qGrC0a3zw9WSUlXvAITaHZE0gRnvr5/5jZo8XZVBMLu9cw9PAP4CslaMpiL WwzFPTd5b2PHOVQC/c1yFuvKT+ZMKNGXbvSiteMsaH8R2CNhiACZQ25A4Ak3mSfEsIA7LFPcen7ho cKEUBHwrUU0IUOn+ljPF3sEuCWXhKhQIYkpcC+LaNMx5qn3tpm2kFjJxmmqP4+xMDmVgOzUCQxk3r JrWudjKkS7FKaZ8A4fRRjmrrKQ==; From: Karthick J To: ffmpeg-devel@ffmpeg.org Date: Fri, 3 Nov 2017 13:57:01 +0530 Message-Id: <1509697623-2745-2-git-send-email-kjeyapal@akamai.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1509697623-2745-1-git-send-email-kjeyapal@akamai.com> References: <1509697623-2745-1-git-send-email-kjeyapal@akamai.com> X-Smtpcorp-Track: 1-jbJsDIIZrjKX.BGh_FH1I2 Feedback-ID: 337386m:337386asVRLGB:337386syc1Ozuo4O:SMTPCORP X-Report-Abuse: Please forward a copy of this message, including all headers, to Subject: [FFmpeg-devel] [PATCH 2/4] libavformat/tcp: Added an option to reuse sockets X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Karthick J MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" --- doc/protocols.texi | 4 ++ libavformat/tcp.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/tcp.h | 27 ++++++++++ libavformat/utils.c | 2 + 4 files changed, 183 insertions(+) create mode 100644 libavformat/tcp.h diff --git a/doc/protocols.texi b/doc/protocols.texi index a7968ff..62d317d 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1242,6 +1242,10 @@ Set receive buffer size, expressed bytes. @item send_buffer_size=@var{bytes} Set send buffer size, expressed bytes. + +@item reuse_sockets=@var{1|0} +Reuse sockets instead of opening a new socket each time. +Default value is 0. @end table The following example shows how to setup a listening TCP connection diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 06368ff..8bca628 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -1,6 +1,7 @@ /* * TCP protocol * Copyright (c) 2002 Fabrice Bellard + * Copyright (c) 2017 Akamai Technologies, Inc * * This file is part of FFmpeg. * @@ -19,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" +#include "tcp.h" +#include "libavcodec/internal.h" #include "libavutil/avassert.h" #include "libavutil/parseutils.h" #include "libavutil/opt.h" @@ -38,6 +41,7 @@ typedef struct TCPOptions { int listen_timeout; int recv_buffer_size; int send_buffer_size; + int reuse_sockets; } TCPOptions; typedef struct TCPContext { @@ -47,6 +51,16 @@ typedef struct TCPContext { TCPOptions options; } TCPContext; +typedef struct TCPSocket { + char *hostname; + int port; + int in_use; + int64_t last_close_time; + int fd; + TCPOptions options; + struct TCPSocket *next; +} TCPSocket; + #define OFFSET(x) (offsetof(TCPContext, options) + offsetof(TCPOptions, x)) #define D AV_OPT_FLAG_DECODING_PARAM #define E AV_OPT_FLAG_ENCODING_PARAM @@ -56,6 +70,7 @@ static const AVOption options[] = { { "listen_timeout", "Connection awaiting timeout (in milliseconds)", OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "send_buffer_size", "Socket send buffer size (in bytes)", OFFSET(send_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "recv_buffer_size", "Socket receive buffer size (in bytes)", OFFSET(recv_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "reuse_sockets", "Reuse sockets instead of opening a new socket each time", OFFSET(reuse_sockets), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { NULL } }; @@ -66,6 +81,116 @@ static const AVClass tcp_class = { .version = LIBAVUTIL_VERSION_INT, }; +static TCPSocket *first_socket = NULL; + +static TCPSocket* tcp_socket_create (TCPContext *s, char *name, int port) +{ + TCPSocket *p = NULL; + + p = (TCPSocket *) calloc (1, sizeof(TCPSocket)); + if (p == NULL) { + return NULL; + } + + p->hostname = strdup(name); + p->port = port; + p->in_use = 1; + p->fd = s->fd; + p->options = s->options; + p->next = NULL; + + return p; +} + +static int tcp_socket_free (TCPSocket *socket) +{ + if (socket) { + closesocket(socket->fd); + free(socket->hostname); + free(socket); + } + return 0; +} + +static void tcp_list_add(TCPContext *s, char *name, int port) +{ + TCPSocket *socket = tcp_socket_create(s, name, port); + + if (!socket) + return; + avpriv_lock_avformat(); + socket->next = first_socket; + first_socket = socket; + avpriv_unlock_avformat(); + +} + +static void tcp_list_remove_next(TCPSocket *socket) +{ + TCPSocket *temp; + if (socket) { + temp = socket->next; + socket->next = socket->next->next; + } else { + temp = first_socket; + first_socket = first_socket->next; + } + tcp_socket_free(temp); + +} + +static int tcp_socket_find (TCPContext *s, char *name, int port) +{ + int lfd = -1; + TCPSocket *p = first_socket; + TCPSocket *prev = NULL; + int64_t current_time = av_gettime(); + avpriv_lock_avformat(); + while(p) { + const int idle_timeout = 60 * 1000000; + // Remove idle connections + if (!p->in_use && (current_time - p->last_close_time) > idle_timeout) { + tcp_list_remove_next(prev); + } else { + // Reuse the connection if a correct match if found + if (!p->in_use && lfd == -1 && + !strcmp(p->hostname, name) && (p->port == port) && + !memcmp(&p->options, &s->options, sizeof(s->options))) { + p->in_use = 1; + lfd = p->fd; + } + prev = p; + } + p = p->next; + + } + avpriv_unlock_avformat(); + return lfd; +} + +static void tcp_socket_release (int search_fd) +{ + TCPSocket *p = first_socket; + + while(p) { + if (p->fd == search_fd) { + p->last_close_time = av_gettime(); + p->in_use = 0; + break; + } + p = p->next; + } +} + +void ff_tcp_deinit(void) +{ + avpriv_lock_avformat(); + while(first_socket) { + tcp_list_remove_next(NULL); + } + avpriv_unlock_avformat(); +} + /* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { @@ -107,6 +232,16 @@ static int tcp_open(URLContext *h, const char *uri, int flags) s->open_timeout = h->rw_timeout = s->options.rw_timeout; } + /* Check for an existing connection */ + if (s->options.reuse_sockets) { + int reuse_fd = tcp_socket_find(s, hostname, port); + if (-1 != reuse_fd) { + h->is_streamed = 1; + s->fd = reuse_fd; + av_log (h, AV_LOG_INFO, "reusing socket fd = %d\n", reuse_fd); + return 0; + } + } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); @@ -178,6 +313,10 @@ static int tcp_open(URLContext *h, const char *uri, int flags) h->is_streamed = 1; s->fd = fd; + if (s->options.reuse_sockets) { + tcp_list_add (s, hostname, port); + av_log (h, AV_LOG_DEBUG, "add socket fd = %d\n", fd); + } freeaddrinfo(ai); return 0; @@ -246,6 +385,11 @@ static int tcp_shutdown(URLContext *h, int flags) TCPContext *s = h->priv_data; int how; + if (s->options.reuse_sockets) { + av_log (h, AV_LOG_DEBUG, "Not shutting down.. assuming Re-use later\n"); + return 0; + } + if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) { how = SHUT_RDWR; } else if (flags & AVIO_FLAG_WRITE) { @@ -260,6 +404,12 @@ static int tcp_shutdown(URLContext *h, int flags) static int tcp_close(URLContext *h) { TCPContext *s = h->priv_data; + + if (s->options.reuse_sockets) { + av_log (h, AV_LOG_DEBUG, "Not closing.. assuming Re-use later\n"); + tcp_socket_release(s->fd); + return 0; + } closesocket(s->fd); return 0; } diff --git a/libavformat/tcp.h b/libavformat/tcp.h new file mode 100644 index 0000000..c36a4de --- /dev/null +++ b/libavformat/tcp.h @@ -0,0 +1,27 @@ +/* + * TCP Protocol + * Copyright (c) 2017 Akamai Technologies, Inc. + * + * 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 + */ + +#ifndef AVFORMAT_TCP_H_ +#define AVFORMAT_TCP_H_ + +void ff_tcp_deinit(void); + +#endif /* AVFORMAT_TCP_H_ */ diff --git a/libavformat/utils.c b/libavformat/utils.c index cbfb78b..9b22c47 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -48,6 +48,7 @@ #include "metadata.h" #if CONFIG_NETWORK #include "network.h" +#include "tcp.h" #endif #include "riff.h" #include "url.h" @@ -4859,6 +4860,7 @@ int avformat_network_deinit(void) #if CONFIG_NETWORK ff_network_close(); ff_tls_deinit(); + ff_tcp_deinit(); ff_network_inited_globally = 0; #endif return 0;