Statistics
| Branch: | Revision:

ffmpeg / libav / tcp.c @ 9eb82647

History | View | Annotate | Download (3.93 KB)

1 171bbb03 Fabrice Bellard
/*
2
 * TCP protocol
3
 * Copyright (c) 2002 Fabrice Bellard.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19 9eb82647 François Revol
#include <sys/socket.h>
20 171bbb03 Fabrice Bellard
#include "avformat.h"
21
#include <unistd.h>
22
#include <ctype.h>
23
#include <sys/types.h>
24
#include <netinet/in.h>
25 9ddd71fc François Revol
#ifndef __BEOS__
26
# include <arpa/inet.h>
27
#else
28
# include "barpainet.h"
29
#endif
30 171bbb03 Fabrice Bellard
#include <netdb.h>
31
32
typedef struct TCPContext {
33
    int fd;
34
} TCPContext;
35
36
/* resolve host with also IP address parsing */
37
int resolve_host(struct in_addr *sin_addr, const char *hostname)
38
{
39
    struct hostent *hp;
40
41
    if ((inet_aton(hostname, sin_addr)) == 0) {
42
        hp = gethostbyname(hostname);
43
        if (!hp)
44
            return -1;
45
        memcpy (sin_addr, hp->h_addr, sizeof(struct in_addr));
46
    }
47
    return 0;
48
}
49
50
/* return non zero if error */
51
static int tcp_open(URLContext *h, const char *uri, int flags)
52
{
53
    struct sockaddr_in dest_addr;
54
    char hostname[1024], *q;
55
    int port, fd = -1;
56
    TCPContext *s;
57
    const char *p;
58
59
    s = av_malloc(sizeof(TCPContext));
60
    if (!s)
61
        return -ENOMEM;
62
    h->priv_data = s;
63
    p = uri;
64
    if (!strstart(p, "tcp://", &p))
65
        goto fail;
66
    q = hostname;
67
    while (*p != ':' && *p != '/' && *p != '\0') {
68
        if ((q - hostname) < sizeof(hostname) - 1)
69
            *q++ = *p;
70
        p++;
71
    }
72
    *q = '\0';
73
    if (*p != ':')
74
        goto fail;
75
    p++;
76
    port = strtoul(p, (char **)&p, 10);
77
    if (port <= 0 || port >= 65536)
78
        goto fail;
79
    
80
    dest_addr.sin_family = AF_INET;
81
    dest_addr.sin_port = htons(port);
82
    if (resolve_host(&dest_addr.sin_addr, hostname) < 0)
83
        goto fail;
84
85
    fd = socket(PF_INET, SOCK_STREAM, 0);
86
    if (fd < 0)
87
        goto fail;
88
89
    if (connect(fd, (struct sockaddr *)&dest_addr, 
90
                sizeof(dest_addr)) < 0)
91
        goto fail;
92
93
    s->fd = fd;
94
    return 0;
95
96
 fail:
97
    if (fd >= 0)
98
        close(fd);
99
    av_free(s);
100
    return -EIO;
101
}
102
103
static int tcp_read(URLContext *h, UINT8 *buf, int size)
104
{
105
    TCPContext *s = h->priv_data;
106
    int size1, len;
107
108
    size1 = size;
109
    while (size > 0) {
110 9ddd71fc François Revol
#ifdef CONFIG_BEOS_NETSERVER
111
        len = recv (s->fd, buf, size, 0);
112
#else
113 171bbb03 Fabrice Bellard
        len = read (s->fd, buf, size);
114 9ddd71fc François Revol
#endif
115 171bbb03 Fabrice Bellard
        if (len < 0) {
116
            if (errno != EINTR && errno != EAGAIN)
117 9ddd71fc François Revol
#ifdef __BEOS__
118
                return errno;
119
#else
120 171bbb03 Fabrice Bellard
                return -errno;
121 9ddd71fc François Revol
#endif
122 171bbb03 Fabrice Bellard
            else
123
                continue;
124
        } else if (len == 0) {
125
            break;
126
        }
127
        size -= len;
128
        buf += len;
129
    }
130
    return size1 - size;
131
}
132
133
static int tcp_write(URLContext *h, UINT8 *buf, int size)
134
{
135
    TCPContext *s = h->priv_data;
136
    int ret, size1;
137
138
    size1 = size;
139
    while (size > 0) {
140 9ddd71fc François Revol
#ifdef CONFIG_BEOS_NETSERVER
141
        ret = send (s->fd, buf, size, 0);
142
#else
143 171bbb03 Fabrice Bellard
        ret = write (s->fd, buf, size);
144 9ddd71fc François Revol
#endif
145 171bbb03 Fabrice Bellard
        if (ret < 0 && errno != EINTR && errno != EAGAIN)
146 9ddd71fc François Revol
#ifdef __BEOS__
147
            return errno;
148
#else
149 171bbb03 Fabrice Bellard
            return -errno;
150 9ddd71fc François Revol
#endif
151 171bbb03 Fabrice Bellard
        size -= ret;
152
        buf += ret;
153
    }
154
    return size1 - size;
155
}
156
157
static int tcp_close(URLContext *h)
158
{
159
    TCPContext *s = h->priv_data;
160 9ddd71fc François Revol
#ifdef CONFIG_BEOS_NETSERVER
161
    closesocket(s->fd);
162
#else
163 171bbb03 Fabrice Bellard
    close(s->fd);
164 9ddd71fc François Revol
#endif
165 171bbb03 Fabrice Bellard
    av_free(s);
166
    return 0;
167
}
168
169
URLProtocol tcp_protocol = {
170
    "tcp",
171
    tcp_open,
172
    tcp_read,
173
    tcp_write,
174
    NULL, /* seek */
175
    tcp_close,
176
};