Mercurial > libavformat.hg
annotate tcp.c @ 6048:e507a21a9566 libavformat
matroskaenc: Write codec time base as default duration for video tracks.
This isn't exactly semantically equivalent, but the field has already been
long abused to mean this, and writing it helps in determining a decent cfr
time base when transcoding from a mkv where the video codec stores none (VP8).
author | conrad |
---|---|
date | Mon, 24 May 2010 08:58:19 +0000 |
parents | 395592984ef0 |
children | 7fdda2416684 |
rev | line source |
---|---|
0 | 1 /* |
2 * TCP protocol | |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4206
diff
changeset
|
3 * Copyright (c) 2002 Fabrice Bellard |
0 | 4 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
923
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
923
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
923
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
0 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
923
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
923
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 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 | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
923
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
885
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
21 #include "avformat.h" | |
22 #include <unistd.h> | |
5837
d605f589f0be
move ff_url_split() and ff_url_join() declarations to internal.h
aurel
parents:
5775
diff
changeset
|
23 #include "internal.h" |
1754 | 24 #include "network.h" |
2773 | 25 #include "os_support.h" |
4206 | 26 #if HAVE_SYS_SELECT_H |
3937
c0667b2aa3ab
include sys/select.h to get select, according to posix 2001,
bcoudurier
parents:
3765
diff
changeset
|
27 #include <sys/select.h> |
3941
53c5b89b8dff
only include sys/select.h if present, fix mingw compilation
bcoudurier
parents:
3937
diff
changeset
|
28 #endif |
180 | 29 #include <sys/time.h> |
0 | 30 |
31 typedef struct TCPContext { | |
32 int fd; | |
33 } TCPContext; | |
34 | |
35 /* return non zero if error */ | |
36 static int tcp_open(URLContext *h, const char *uri, int flags) | |
37 { | |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
38 struct addrinfo hints, *ai, *cur_ai; |
0 | 39 int port, fd = -1; |
683
095009fc2f35
kill warnings patch by (Mns Rullgrd <mru inprovide com>)
michael
parents:
511
diff
changeset
|
40 TCPContext *s = NULL; |
180 | 41 fd_set wfds; |
42 int fd_max, ret; | |
43 struct timeval tv; | |
44 socklen_t optlen; | |
3765
d55fb12134d1
Remove check for @ in tcp.c which removes the authorization data from the
rbultje
parents:
3756
diff
changeset
|
45 char hostname[1024],proto[1024],path[1024]; |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
46 char portstr[10]; |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
47 |
5775 | 48 ff_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), |
3756 | 49 &port, path, sizeof(path), uri); |
50 if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) | |
3755
b9c1bcc6c1ca
On failure, return directly because the fail: case does nothing. This also
rbultje
parents:
3754
diff
changeset
|
51 return AVERROR(EINVAL); |
885 | 52 |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
53 memset(&hints, 0, sizeof(hints)); |
5595
0980c09b05c1
Fix BSD compile (PF_UNSPEC is not a standard define, AF_UNSPEC is).
rbultje
parents:
5518
diff
changeset
|
54 hints.ai_family = AF_UNSPEC; |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
55 hints.ai_socktype = SOCK_STREAM; |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
56 snprintf(portstr, sizeof(portstr), "%d", port); |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
57 if (getaddrinfo(hostname, portstr, &hints, &ai)) |
3755
b9c1bcc6c1ca
On failure, return directly because the fail: case does nothing. This also
rbultje
parents:
3754
diff
changeset
|
58 return AVERROR(EIO); |
0 | 59 |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
60 cur_ai = ai; |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
61 |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
62 restart: |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
63 fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); |
0 | 64 if (fd < 0) |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
65 goto fail; |
2057
857fbfeb2fa0
implement ff_socket_nonblock and use it in networking code
alex
parents:
2056
diff
changeset
|
66 ff_socket_nonblock(fd, 1); |
885 | 67 |
180 | 68 redo: |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
69 ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); |
180 | 70 if (ret < 0) { |
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
71 if (ff_neterrno() == FF_NETERROR(EINTR)) |
180 | 72 goto redo; |
2321 | 73 if (ff_neterrno() != FF_NETERROR(EINPROGRESS) && |
74 ff_neterrno() != FF_NETERROR(EAGAIN)) | |
180 | 75 goto fail; |
0 | 76 |
180 | 77 /* wait until we are connected or until abort */ |
78 for(;;) { | |
79 if (url_interrupt_cb()) { | |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
80 ret = AVERROR(EINTR); |
180 | 81 goto fail1; |
82 } | |
83 fd_max = fd; | |
84 FD_ZERO(&wfds); | |
85 FD_SET(fd, &wfds); | |
86 tv.tv_sec = 0; | |
87 tv.tv_usec = 100 * 1000; | |
88 ret = select(fd_max + 1, NULL, &wfds, NULL, &tv); | |
89 if (ret > 0 && FD_ISSET(fd, &wfds)) | |
90 break; | |
91 } | |
885 | 92 |
180 | 93 /* test error */ |
94 optlen = sizeof(ret); | |
95 getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); | |
96 if (ret != 0) | |
97 goto fail; | |
98 } | |
3754
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
99 s = av_malloc(sizeof(TCPContext)); |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
100 if (!s) { |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
101 freeaddrinfo(ai); |
3754
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
102 return AVERROR(ENOMEM); |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
103 } |
3754
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
104 h->priv_data = s; |
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
105 h->is_streamed = 1; |
0 | 106 s->fd = fd; |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
107 freeaddrinfo(ai); |
0 | 108 return 0; |
109 | |
110 fail: | |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
111 if (cur_ai->ai_next) { |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
112 /* Retry with the next sockaddr */ |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
113 cur_ai = cur_ai->ai_next; |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
114 if (fd >= 0) |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
115 closesocket(fd); |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
116 goto restart; |
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
117 } |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2057
diff
changeset
|
118 ret = AVERROR(EIO); |
180 | 119 fail1: |
0 | 120 if (fd >= 0) |
1670 | 121 closesocket(fd); |
5518
0dc71c7f6653
Use getaddrinfo() instead of resolve_host(). Patch by Martin Storsj
rbultje
parents:
5102
diff
changeset
|
122 freeaddrinfo(ai); |
180 | 123 return ret; |
0 | 124 } |
125 | |
65 | 126 static int tcp_read(URLContext *h, uint8_t *buf, int size) |
0 | 127 { |
128 TCPContext *s = h->priv_data; | |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
129 int len, fd_max, ret; |
180 | 130 fd_set rfds; |
131 struct timeval tv; | |
0 | 132 |
385
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
261
diff
changeset
|
133 for (;;) { |
180 | 134 if (url_interrupt_cb()) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
135 return AVERROR(EINTR); |
180 | 136 fd_max = s->fd; |
137 FD_ZERO(&rfds); | |
138 FD_SET(s->fd, &rfds); | |
139 tv.tv_sec = 0; | |
140 tv.tv_usec = 100 * 1000; | |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
141 ret = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
142 if (ret > 0 && FD_ISSET(s->fd, &rfds)) { |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
143 len = recv(s->fd, buf, size, 0); |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
144 if (len < 0) { |
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
145 if (ff_neterrno() != FF_NETERROR(EINTR) && |
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
146 ff_neterrno() != FF_NETERROR(EAGAIN)) |
5102 | 147 return AVERROR(ff_neterrno()); |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
148 } else return len; |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
149 } else if (ret < 0) { |
5896
395592984ef0
Don't report EINTR from select as an error, retry select instead
mstorsjo
parents:
5837
diff
changeset
|
150 if (ff_neterrno() == FF_NETERROR(EINTR)) |
395592984ef0
Don't report EINTR from select as an error, retry select instead
mstorsjo
parents:
5837
diff
changeset
|
151 continue; |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
152 return -1; |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
153 } |
0 | 154 } |
155 } | |
156 | |
65 | 157 static int tcp_write(URLContext *h, uint8_t *buf, int size) |
0 | 158 { |
159 TCPContext *s = h->priv_data; | |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
160 int ret, size1, fd_max, len; |
180 | 161 fd_set wfds; |
162 struct timeval tv; | |
0 | 163 |
164 size1 = size; | |
165 while (size > 0) { | |
180 | 166 if (url_interrupt_cb()) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
167 return AVERROR(EINTR); |
180 | 168 fd_max = s->fd; |
169 FD_ZERO(&wfds); | |
170 FD_SET(s->fd, &wfds); | |
171 tv.tv_sec = 0; | |
172 tv.tv_usec = 100 * 1000; | |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
173 ret = select(fd_max + 1, NULL, &wfds, NULL, &tv); |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
174 if (ret > 0 && FD_ISSET(s->fd, &wfds)) { |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
175 len = send(s->fd, buf, size, 0); |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
176 if (len < 0) { |
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
177 if (ff_neterrno() != FF_NETERROR(EINTR) && |
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
178 ff_neterrno() != FF_NETERROR(EAGAIN)) |
5102 | 179 return AVERROR(ff_neterrno()); |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
180 continue; |
261
5f27f90ed496
Fix a very nasty problem with extra bytes appearing in TCP data streams.
philipjsg
parents:
229
diff
changeset
|
181 } |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
182 size -= len; |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
183 buf += len; |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
184 } else if (ret < 0) { |
5896
395592984ef0
Don't report EINTR from select as an error, retry select instead
mstorsjo
parents:
5837
diff
changeset
|
185 if (ff_neterrno() == FF_NETERROR(EINTR)) |
395592984ef0
Don't report EINTR from select as an error, retry select instead
mstorsjo
parents:
5837
diff
changeset
|
186 continue; |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
187 return -1; |
261
5f27f90ed496
Fix a very nasty problem with extra bytes appearing in TCP data streams.
philipjsg
parents:
229
diff
changeset
|
188 } |
0 | 189 } |
190 return size1 - size; | |
191 } | |
192 | |
193 static int tcp_close(URLContext *h) | |
194 { | |
195 TCPContext *s = h->priv_data; | |
196 closesocket(s->fd); | |
197 av_free(s); | |
198 return 0; | |
199 } | |
200 | |
4640
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4251
diff
changeset
|
201 static int tcp_get_file_handle(URLContext *h) |
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4251
diff
changeset
|
202 { |
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4251
diff
changeset
|
203 TCPContext *s = h->priv_data; |
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4251
diff
changeset
|
204 return s->fd; |
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4251
diff
changeset
|
205 } |
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4251
diff
changeset
|
206 |
0 | 207 URLProtocol tcp_protocol = { |
208 "tcp", | |
209 tcp_open, | |
210 tcp_read, | |
211 tcp_write, | |
212 NULL, /* seek */ | |
213 tcp_close, | |
4640
b34d9614b887
Add url_get_file_handle(), which is used to get the file descriptor
rbultje
parents:
4251
diff
changeset
|
214 .url_get_file_handle = tcp_get_file_handle, |
0 | 215 }; |