use network.h instead network includes
[libav.git] / libavformat / tcp.c
CommitLineData
171bbb03
FB
1/*
2 * TCP protocol
3 * Copyright (c) 2002 Fabrice Bellard.
4 *
b78e7197
DB
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
171bbb03
FB
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
b78e7197 10 * version 2.1 of the License, or (at your option) any later version.
171bbb03 11 *
b78e7197 12 * FFmpeg is distributed in the hope that it will be useful,
171bbb03
FB
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
b78e7197 18 * License along with FFmpeg; if not, write to the Free Software
5509bffa 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
171bbb03
FB
20 */
21#include "avformat.h"
22#include <unistd.h>
42572ef5 23#include "network.h"
09787fb8
FB
24#include <sys/time.h>
25#include <fcntl.h>
171bbb03
FB
26
27typedef struct TCPContext {
28 int fd;
29} TCPContext;
30
171bbb03
FB
31/* return non zero if error */
32static int tcp_open(URLContext *h, const char *uri, int flags)
33{
34 struct sockaddr_in dest_addr;
35 char hostname[1024], *q;
36 int port, fd = -1;
88730be6 37 TCPContext *s = NULL;
09787fb8
FB
38 fd_set wfds;
39 int fd_max, ret;
40 struct timeval tv;
41 socklen_t optlen;
6ba5cbc6
PD
42 char proto[1024],path[1024],tmp[1024]; // PETR: protocol and path strings
43
44 url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname),
45 &port, path, sizeof(path), uri); // PETR: use url_split
46 if (strcmp(proto,"tcp")) goto fail; // PETR: check protocol
47 if ((q = strchr(hostname,'@'))) { strcpy(tmp,q+1); strcpy(hostname,tmp); } // PETR: take only the part after '@' for tcp protocol
115329f1 48
171bbb03
FB
49 s = av_malloc(sizeof(TCPContext));
50 if (!s)
8fa36ae0 51 return AVERROR(ENOMEM);
171bbb03 52 h->priv_data = s;
115329f1 53
171bbb03
FB
54 if (port <= 0 || port >= 65536)
55 goto fail;
115329f1 56
171bbb03
FB
57 dest_addr.sin_family = AF_INET;
58 dest_addr.sin_port = htons(port);
59 if (resolve_host(&dest_addr.sin_addr, hostname) < 0)
60 goto fail;
61
b5cccea0 62 fd = socket(AF_INET, SOCK_STREAM, 0);
171bbb03
FB
63 if (fd < 0)
64 goto fail;
09787fb8 65 fcntl(fd, F_SETFL, O_NONBLOCK);
115329f1 66
09787fb8 67 redo:
115329f1 68 ret = connect(fd, (struct sockaddr *)&dest_addr,
09787fb8
FB
69 sizeof(dest_addr));
70 if (ret < 0) {
71 if (errno == EINTR)
72 goto redo;
73 if (errno != EINPROGRESS)
74 goto fail;
171bbb03 75
09787fb8
FB
76 /* wait until we are connected or until abort */
77 for(;;) {
78 if (url_interrupt_cb()) {
8fa36ae0 79 ret = AVERROR(EINTR);
09787fb8
FB
80 goto fail1;
81 }
82 fd_max = fd;
83 FD_ZERO(&wfds);
84 FD_SET(fd, &wfds);
85 tv.tv_sec = 0;
86 tv.tv_usec = 100 * 1000;
87 ret = select(fd_max + 1, NULL, &wfds, NULL, &tv);
88 if (ret > 0 && FD_ISSET(fd, &wfds))
89 break;
90 }
115329f1 91
09787fb8
FB
92 /* test error */
93 optlen = sizeof(ret);
94 getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen);
95 if (ret != 0)
96 goto fail;
97 }
171bbb03
FB
98 s->fd = fd;
99 return 0;
100
101 fail:
0bd586c5 102 ret = AVERROR_IO;
09787fb8 103 fail1:
171bbb03 104 if (fd >= 0)
e9d511dc 105 closesocket(fd);
171bbb03 106 av_free(s);
09787fb8 107 return ret;
171bbb03
FB
108}
109
0c1a9eda 110static int tcp_read(URLContext *h, uint8_t *buf, int size)
171bbb03
FB
111{
112 TCPContext *s = h->priv_data;
b51469a0 113 int len, fd_max, ret;
09787fb8
FB
114 fd_set rfds;
115 struct timeval tv;
171bbb03 116
9eef2b77 117 for (;;) {
09787fb8 118 if (url_interrupt_cb())
8fa36ae0 119 return AVERROR(EINTR);
09787fb8
FB
120 fd_max = s->fd;
121 FD_ZERO(&rfds);
122 FD_SET(s->fd, &rfds);
123 tv.tv_sec = 0;
124 tv.tv_usec = 100 * 1000;
b51469a0
LS
125 ret = select(fd_max + 1, &rfds, NULL, NULL, &tv);
126 if (ret > 0 && FD_ISSET(s->fd, &rfds)) {
b51469a0 127 len = recv(s->fd, buf, size, 0);
b51469a0
LS
128 if (len < 0) {
129 if (errno != EINTR && errno != EAGAIN)
8fa36ae0 130 return AVERROR(errno);
b51469a0
LS
131 } else return len;
132 } else if (ret < 0) {
133 return -1;
134 }
171bbb03 135 }
171bbb03
FB
136}
137
0c1a9eda 138static int tcp_write(URLContext *h, uint8_t *buf, int size)
171bbb03
FB
139{
140 TCPContext *s = h->priv_data;
b51469a0 141 int ret, size1, fd_max, len;
09787fb8
FB
142 fd_set wfds;
143 struct timeval tv;
171bbb03
FB
144
145 size1 = size;
146 while (size > 0) {
09787fb8 147 if (url_interrupt_cb())
8fa36ae0 148 return AVERROR(EINTR);
09787fb8
FB
149 fd_max = s->fd;
150 FD_ZERO(&wfds);
151 FD_SET(s->fd, &wfds);
152 tv.tv_sec = 0;
153 tv.tv_usec = 100 * 1000;
b51469a0
LS
154 ret = select(fd_max + 1, NULL, &wfds, NULL, &tv);
155 if (ret > 0 && FD_ISSET(s->fd, &wfds)) {
b51469a0 156 len = send(s->fd, buf, size, 0);
b51469a0 157 if (len < 0) {
8fa36ae0
FR
158 if (errno != EINTR && errno != EAGAIN)
159 return AVERROR(errno);
b51469a0 160 continue;
6c8e0d4d 161 }
b51469a0
LS
162 size -= len;
163 buf += len;
164 } else if (ret < 0) {
165 return -1;
6c8e0d4d 166 }
171bbb03
FB
167 }
168 return size1 - size;
169}
170
171static int tcp_close(URLContext *h)
172{
173 TCPContext *s = h->priv_data;
9ddd71fc 174 closesocket(s->fd);
171bbb03
FB
175 av_free(s);
176 return 0;
177}
178
179URLProtocol tcp_protocol = {
180 "tcp",
181 tcp_open,
182 tcp_read,
183 tcp_write,
184 NULL, /* seek */
185 tcp_close,
186};