Mercurial > libavformat.hg
annotate tcp.c @ 3754:8d267b43eaba libavformat
Move malloc() down until after all initializations, so that the resource is
only allocated if initialization worked. This means that on failure, we
don't have to deallocate it.
author | rbultje |
---|---|
date | Sat, 23 Aug 2008 18:46:30 +0000 |
parents | 42ed3629601d |
children | b9c1bcc6c1ca |
rev | line source |
---|---|
0 | 1 /* |
2 * TCP protocol | |
3 * Copyright (c) 2002 Fabrice Bellard. | |
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> | |
1754 | 23 #include "network.h" |
2773 | 24 #include "os_support.h" |
180 | 25 #include <sys/time.h> |
0 | 26 |
27 typedef struct TCPContext { | |
28 int fd; | |
29 } TCPContext; | |
30 | |
31 /* return non zero if error */ | |
32 static 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; | |
683
095009fc2f35
kill warnings patch by (Mns Rullgrd <mru inprovide com>)
michael
parents:
511
diff
changeset
|
37 TCPContext *s = NULL; |
180 | 38 fd_set wfds; |
39 int fd_max, ret; | |
40 struct timeval tv; | |
41 socklen_t optlen; | |
3752
4ef51601582d
Remove useless comments. See "[PATCH] tcp.c/udp.c memleak?" for discussion.
rbultje
parents:
3114
diff
changeset
|
42 char proto[1024],path[1024],tmp[1024]; |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
43 |
3753
42ed3629601d
Fix memleak on some OSes in case network initialization fails. See
rbultje
parents:
3752
diff
changeset
|
44 if(!ff_network_init()) |
42ed3629601d
Fix memleak on some OSes in case network initialization fails. See
rbultje
parents:
3752
diff
changeset
|
45 return AVERROR(EIO); |
42ed3629601d
Fix memleak on some OSes in case network initialization fails. See
rbultje
parents:
3752
diff
changeset
|
46 |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
47 url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), |
3752
4ef51601582d
Remove useless comments. See "[PATCH] tcp.c/udp.c memleak?" for discussion.
rbultje
parents:
3114
diff
changeset
|
48 &port, path, sizeof(path), uri); |
4ef51601582d
Remove useless comments. See "[PATCH] tcp.c/udp.c memleak?" for discussion.
rbultje
parents:
3114
diff
changeset
|
49 if (strcmp(proto,"tcp")) goto fail; |
4ef51601582d
Remove useless comments. See "[PATCH] tcp.c/udp.c memleak?" for discussion.
rbultje
parents:
3114
diff
changeset
|
50 if ((q = strchr(hostname,'@'))) { strcpy(tmp,q+1); strcpy(hostname,tmp); } |
885 | 51 |
0 | 52 if (port <= 0 || port >= 65536) |
53 goto fail; | |
885 | 54 |
0 | 55 dest_addr.sin_family = AF_INET; |
56 dest_addr.sin_port = htons(port); | |
57 if (resolve_host(&dest_addr.sin_addr, hostname) < 0) | |
58 goto fail; | |
59 | |
1810
d85795da84ab
change PF_INET to AF_INET to be consistent in the whole project. PF_INET is deprecated, while AF_INET is referred by the POSIX standards
alex
parents:
1787
diff
changeset
|
60 fd = socket(AF_INET, SOCK_STREAM, 0); |
0 | 61 if (fd < 0) |
62 goto fail; | |
2057
857fbfeb2fa0
implement ff_socket_nonblock and use it in networking code
alex
parents:
2056
diff
changeset
|
63 ff_socket_nonblock(fd, 1); |
885 | 64 |
180 | 65 redo: |
885 | 66 ret = connect(fd, (struct sockaddr *)&dest_addr, |
180 | 67 sizeof(dest_addr)); |
68 if (ret < 0) { | |
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
69 if (ff_neterrno() == FF_NETERROR(EINTR)) |
180 | 70 goto redo; |
2321 | 71 if (ff_neterrno() != FF_NETERROR(EINPROGRESS) && |
72 ff_neterrno() != FF_NETERROR(EAGAIN)) | |
180 | 73 goto fail; |
0 | 74 |
180 | 75 /* wait until we are connected or until abort */ |
76 for(;;) { | |
77 if (url_interrupt_cb()) { | |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
78 ret = AVERROR(EINTR); |
180 | 79 goto fail1; |
80 } | |
81 fd_max = fd; | |
82 FD_ZERO(&wfds); | |
83 FD_SET(fd, &wfds); | |
84 tv.tv_sec = 0; | |
85 tv.tv_usec = 100 * 1000; | |
86 ret = select(fd_max + 1, NULL, &wfds, NULL, &tv); | |
87 if (ret > 0 && FD_ISSET(fd, &wfds)) | |
88 break; | |
89 } | |
885 | 90 |
180 | 91 /* test error */ |
92 optlen = sizeof(ret); | |
93 getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); | |
94 if (ret != 0) | |
95 goto fail; | |
96 } | |
3754
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
97 s = av_malloc(sizeof(TCPContext)); |
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
98 if (!s) |
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
99 return AVERROR(ENOMEM); |
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
100 h->priv_data = s; |
8d267b43eaba
Move malloc() down until after all initializations, so that the resource is
rbultje
parents:
3753
diff
changeset
|
101 h->is_streamed = 1; |
0 | 102 s->fd = fd; |
103 return 0; | |
104 | |
105 fail: | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2057
diff
changeset
|
106 ret = AVERROR(EIO); |
180 | 107 fail1: |
0 | 108 if (fd >= 0) |
1670 | 109 closesocket(fd); |
180 | 110 return ret; |
0 | 111 } |
112 | |
65 | 113 static int tcp_read(URLContext *h, uint8_t *buf, int size) |
0 | 114 { |
115 TCPContext *s = h->priv_data; | |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
116 int len, fd_max, ret; |
180 | 117 fd_set rfds; |
118 struct timeval tv; | |
0 | 119 |
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
|
120 for (;;) { |
180 | 121 if (url_interrupt_cb()) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
122 return AVERROR(EINTR); |
180 | 123 fd_max = s->fd; |
124 FD_ZERO(&rfds); | |
125 FD_SET(s->fd, &rfds); | |
126 tv.tv_sec = 0; | |
127 tv.tv_usec = 100 * 1000; | |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
128 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
|
129 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
|
130 len = recv(s->fd, buf, size, 0); |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
131 if (len < 0) { |
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
132 if (ff_neterrno() != FF_NETERROR(EINTR) && |
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
133 ff_neterrno() != FF_NETERROR(EAGAIN)) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
134 return AVERROR(errno); |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
135 } else return len; |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
136 } else if (ret < 0) { |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
137 return -1; |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
138 } |
0 | 139 } |
140 } | |
141 | |
65 | 142 static int tcp_write(URLContext *h, uint8_t *buf, int size) |
0 | 143 { |
144 TCPContext *s = h->priv_data; | |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
145 int ret, size1, fd_max, len; |
180 | 146 fd_set wfds; |
147 struct timeval tv; | |
0 | 148 |
149 size1 = size; | |
150 while (size > 0) { | |
180 | 151 if (url_interrupt_cb()) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
152 return AVERROR(EINTR); |
180 | 153 fd_max = s->fd; |
154 FD_ZERO(&wfds); | |
155 FD_SET(s->fd, &wfds); | |
156 tv.tv_sec = 0; | |
157 tv.tv_usec = 100 * 1000; | |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
158 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
|
159 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
|
160 len = send(s->fd, buf, size, 0); |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
161 if (len < 0) { |
2056
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
162 if (ff_neterrno() != FF_NETERROR(EINTR) && |
eeea52739ff3
use ff_neterrno() and FF_NETERROR() for networking error handling
alex
parents:
2050
diff
changeset
|
163 ff_neterrno() != FF_NETERROR(EAGAIN)) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1754
diff
changeset
|
164 return AVERROR(errno); |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
165 continue; |
261
5f27f90ed496
Fix a very nasty problem with extra bytes appearing in TCP data streams.
philipjsg
parents:
229
diff
changeset
|
166 } |
388
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
167 size -= len; |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
168 buf += len; |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
169 } else if (ret < 0) { |
9af30d452a0a
tcp select() check and enables pressing 'q' when reading/(writing) from
michael
parents:
385
diff
changeset
|
170 return -1; |
261
5f27f90ed496
Fix a very nasty problem with extra bytes appearing in TCP data streams.
philipjsg
parents:
229
diff
changeset
|
171 } |
0 | 172 } |
173 return size1 - size; | |
174 } | |
175 | |
176 static int tcp_close(URLContext *h) | |
177 { | |
178 TCPContext *s = h->priv_data; | |
179 closesocket(s->fd); | |
2351
b9a881c0967e
Add initialization and cleanup functions for Winsock
ramiro
parents:
2321
diff
changeset
|
180 ff_network_close(); |
0 | 181 av_free(s); |
182 return 0; | |
183 } | |
184 | |
185 URLProtocol tcp_protocol = { | |
186 "tcp", | |
187 tcp_open, | |
188 tcp_read, | |
189 tcp_write, | |
190 NULL, /* seek */ | |
191 tcp_close, | |
192 }; |