source: trunk/packages/xen-3.1/xen-3.1/tools/vnet/libxutil/socket_stream.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 5.7 KB
Line 
1/*
2 * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 *
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or
7 * (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19/** @file
20 * An IOStream implementation using sockets.
21 */
22#ifndef __KERNEL__
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28#include <errno.h>
29#include "allocate.h"
30#include "socket_stream.h"
31
32#define MODULE_NAME "sock"
33#define DEBUG 0
34//#undef DEBUG
35#include "debug.h"
36
37static int socket_read(IOStream *s, void *buf, size_t n);
38static int socket_write(IOStream *s, const void *buf, size_t n);
39static int socket_error(IOStream *s);
40static int socket_close(IOStream *s);
41static void socket_free(IOStream *s);
42static int socket_flush(IOStream *s);
43
44/** Methods used by a socket IOStream. */
45static const IOMethods socket_methods = {
46    read:  socket_read,
47    write: socket_write,
48    error: socket_error,
49    close: socket_close,
50    free:  socket_free,
51    flush: socket_flush,
52};
53
54/** Get the socket data.
55 *
56 * @param io socket stream
57 * @return data
58 */
59static inline SocketData * socket_data(IOStream *io){
60    return (SocketData *)io->data;
61}
62
63/** Test if a stream is a socket stream.
64 *
65 * @param io stream
66 * @return 0 if a socket stream, -EINVAL if not
67 */
68int socket_stream_check(IOStream *io){
69    return (io && io->methods == &socket_methods ? 0 : -EINVAL);
70}
71
72/** Get the data for a socket stream.
73 *
74 * @param io stream
75 * @param data return value for the data
76 * @return 0 if a socket stream, -EINVAL if not
77 */
78int socket_stream_data(IOStream *io, SocketData **data){
79    int err = socket_stream_check(io);
80    if(err){
81        *data = NULL;
82    } else {
83        *data = socket_data(io);
84    }
85    return err;
86}
87
88/** Set the destination address for a socket stream.
89 *
90 * @param io stream
91 * @param addr address
92 * @return 0 if a socket stream, -EINVAL if not
93 */
94int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){
95    int err = 0;
96    SocketData *data = NULL;
97    err = socket_stream_data(io, &data);
98    if(!err){
99        data->daddr = *addr;
100    }
101    return err;
102}
103
104/** Set the send flags for a socket stream.
105 *
106 * @param io stream
107 * @param flags flags
108 * @return 0 if a socket stream, -EINVAL if not
109 */
110int socket_stream_set_flags(IOStream *io, int flags){
111    int err = 0;
112    SocketData *data = NULL;
113    err = socket_stream_data(io, &data);
114    if(!err){
115        data->flags = flags;
116    }
117    return err;
118}
119
120/** Write to the underlying socket using sendto.
121 *
122 * @param stream input
123 * @param buf where to put input
124 * @param n number of bytes to write
125 * @return number of bytes written
126 */
127static int socket_write(IOStream *s, const void *buf, size_t n){
128    SocketData *data = socket_data(s);
129    struct sockaddr *daddr = (struct sockaddr *)&data->daddr;
130    socklen_t daddr_n = sizeof(data->daddr);
131    int k;
132    dprintf("> sock=%d addr=%s:%d n=%d\n",
133            data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n);
134    if(0){
135        struct sockaddr_in self = {};
136        socklen_t self_n;
137        getsockname(data->fd, (struct sockaddr *)&self, &self_n);
138        dprintf("> sockname sock=%d %s:%d\n",
139                data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port));
140    }
141    k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n);
142    dprintf("> sendto=%d\n", k);
143    return k;
144}
145
146/** Read from the underlying stream using recv();
147 *
148 * @param stream input
149 * @param buf where to put input
150 * @param n number of bytes to read
151 * @return number of bytes read
152 */
153static int socket_read(IOStream *s, void *buf, size_t n){
154    SocketData *data = socket_data(s);
155    int k;
156    struct sockaddr *saddr = (struct sockaddr *)&data->saddr;
157    socklen_t saddr_n = sizeof(data->saddr);
158    k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n);
159    return k;
160}
161
162/** Flush the socket (no-op).
163 *
164 * @param s socket stream
165 * @return 0 on success, error code otherwise
166 */
167static int socket_flush(IOStream *s){
168    return 0;
169}
170
171/** Check if a socket stream has an error (no-op).
172 *
173 * @param s socket stream
174 * @return 1 if has an error, 0 otherwise
175 */
176static int socket_error(IOStream *s){
177    // Read SOL_SOCKET/SO_ERROR ?
178    return 0;
179}
180
181/** Close a socket stream.
182 *
183 * @param s socket stream to close
184 * @return result of the close
185 */
186static int socket_close(IOStream *s){
187    SocketData *data = socket_data(s);
188    return close(data->fd);
189}
190
191/** Free a socket stream.
192 *
193 * @param s socket stream
194 */
195static void socket_free(IOStream *s){
196    SocketData *data = socket_data(s);
197    deallocate(data);
198}
199
200/** Create an IOStream for a socket.
201 *
202 * @param fd socket to wtap
203 * @return new IOStream using fd for i/o
204 */
205IOStream *socket_stream_new(int fd){
206    int err = -ENOMEM;
207    IOStream *io = NULL;
208    SocketData *data = NULL;
209
210    io = ALLOCATE(IOStream);
211    if(!io) goto exit;
212    io->methods = &socket_methods;
213    data = ALLOCATE(SocketData);
214    if(!data) goto exit;
215    io->data = data;
216    data->fd = fd;
217    data->buf_n = sizeof(data->buf);
218    err = 0;
219  exit:
220    if(err){
221        if(io){
222            if(data) deallocate(data);
223            deallocate(io);
224            io = NULL;
225        }
226    }
227    return io;
228}
229
230#endif
Note: See TracBrowser for help on using the repository browser.