ia64/xen-unstable

view tools/vnet/libxutil/socket_stream.c @ 6766:219d96d545fc

merge?
author cl349@firebug.cl.cam.ac.uk
date Mon Sep 12 20:00:41 2005 +0000 (2005-09-12)
parents 9f22db685802
children
line source
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 */
19 /** @file
20 * An IOStream implementation using sockets.
21 */
22 #ifndef __KERNEL__
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"
32 #define MODULE_NAME "sock"
33 #define DEBUG 0
34 //#undef DEBUG
35 #include "debug.h"
37 static int socket_read(IOStream *s, void *buf, size_t n);
38 static int socket_write(IOStream *s, const void *buf, size_t n);
39 static int socket_error(IOStream *s);
40 static int socket_close(IOStream *s);
41 static void socket_free(IOStream *s);
42 static int socket_flush(IOStream *s);
44 /** Methods used by a socket IOStream. */
45 static 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 };
54 /** Get the socket data.
55 *
56 * @param io socket stream
57 * @return data
58 */
59 static inline SocketData * socket_data(IOStream *io){
60 return (SocketData *)io->data;
61 }
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 */
68 int socket_stream_check(IOStream *io){
69 return (io && io->methods == &socket_methods ? 0 : -EINVAL);
70 }
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 */
78 int 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 }
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 */
94 int 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 }
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 */
110 int 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 }
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 */
127 static 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 }
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 */
153 static 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 }
162 /** Flush the socket (no-op).
163 *
164 * @param s socket stream
165 * @return 0 on success, error code otherwise
166 */
167 static int socket_flush(IOStream *s){
168 return 0;
169 }
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 */
176 static int socket_error(IOStream *s){
177 // Read SOL_SOCKET/SO_ERROR ?
178 return 0;
179 }
181 /** Close a socket stream.
182 *
183 * @param s socket stream to close
184 * @return result of the close
185 */
186 static int socket_close(IOStream *s){
187 SocketData *data = socket_data(s);
188 return close(data->fd);
189 }
191 /** Free a socket stream.
192 *
193 * @param s socket stream
194 */
195 static void socket_free(IOStream *s){
196 SocketData *data = socket_data(s);
197 deallocate(data);
198 }
200 /** Create an IOStream for a socket.
201 *
202 * @param fd socket to wtap
203 * @return new IOStream using fd for i/o
204 */
205 IOStream *socket_stream_new(int fd){
206 int err = -ENOMEM;
207 IOStream *io = NULL;
208 SocketData *data = NULL;
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 }
230 #endif