databuf bugfixes
[cor_2_6_31.git] / net / cor / sock.c
blob51620d08aa8308ebef0ca69b507b4844973a959f
1 /*
2 * Connection oriented routing
3 * Copyright (C) 2007-2008 Michael Blizek
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 #include <net/sock.h>
22 #include <linux/net.h>
23 #include <asm/uaccess.h>
25 #include "cor.h"
27 static int check_connlistener_state(struct connlistener *cl)
29 if (likely(cl != 0 && cl->sockstate == SOCKSTATE_LISTENER))
30 return 0;
32 return 1;
35 static int check_conn_state(struct conn *conn)
37 if (likely(conn != 0 && conn->sockstate == SOCKSTATE_CONN))
38 return 0;
40 return 1;
43 int cor_socket_release(struct socket *sock)
45 struct connlistener *cl = (struct connlistener *) sock->sk;
46 struct conn *rconn = (struct conn *) sock->sk;
48 if (sock->sk == 0)
49 return 0;
51 if (cl->sockstate == SOCKSTATE_LISTENER) {
52 close_port(cl);
53 } else if (rconn->sockstate == SOCKSTATE_CONN) {
54 reset_conn(rconn);
55 } else {
56 BUG();
59 return 0;
62 int cor_socket_bind(struct socket *sock, struct sockaddr *myaddr,
63 int sockaddr_len)
65 struct connlistener *listener;
66 struct cor_sockaddr *addr = (struct cor_sockaddr *) myaddr;
68 if (sock->sk != 0)
69 return -EINVAL;
71 if (sockaddr_len < sizeof(struct cor_sockaddr))
72 return -EINVAL;
74 if (addr->type != SOCKADDRTYPE_PORT)
75 return -EINVAL;
77 listener = open_port(addr->addr.port);
79 if (listener == 0)
80 return -EADDRINUSE;
82 sock->sk = (struct sock *) listener;
84 return 0;
87 int cor_socket_connect(struct socket *sock, struct sockaddr *vaddr,
88 int sockaddr_len, int flags)
90 struct conn *conn_rcv;
92 if (sock->sk != 0)
93 return -EISCONN;
95 conn_rcv = alloc_conn(GFP_KERNEL);
97 if (0 == conn_rcv)
98 return -ENOMEM;
100 conn_init_sock_source(conn_rcv);
101 conn_init_sock_target(conn_rcv->reversedir);
103 sock->sk = (struct sock *) conn_rcv;
104 sock->state = SS_CONNECTED;
106 return 0;
109 static int cor_rdytoaccept(struct connlistener *cl)
111 int rc;
112 mutex_lock(&(cl->lock));
113 rc = (list_empty(&(cl->conn_queue)) == 0);
114 mutex_unlock(&(cl->lock));
115 return rc;
118 const struct proto_ops cor_proto_ops;
120 int cor_socket_accept(struct socket *sock, struct socket *newsock, int flags)
122 struct connlistener *cl = (struct connlistener *) sock->sk;
124 int rc = check_connlistener_state(cl);
126 struct conn *newconn;
128 if (unlikely(rc))
129 return -EINVAL;
131 mutex_lock(&(cl->lock));
133 if (unlikely(cl->queue_maxlen <= 0)) {
134 mutex_unlock(&(cl->lock));
135 return -EINVAL;
138 while (list_empty(&(cl->conn_queue))) {
139 mutex_unlock(&(cl->lock));
140 if (wait_event_interruptible(cl->wait, cor_rdytoaccept(cl))) {
141 return -ERESTARTSYS;
143 mutex_lock(&(cl->lock));
146 newconn = container_of(cl->conn_queue.next, struct conn,
147 source.sock.cl_list);
149 BUG_ON(newconn->sourcetype != SOURCE_SOCK);
151 list_del(cl->conn_queue.next);
153 cl->queue_len--;
155 mutex_unlock(&(cl->lock));
157 newsock->ops = &cor_proto_ops;
158 newsock->sk = (struct sock *) newconn;
159 newsock->state = SS_CONNECTED;
161 return 0;
164 int cor_socket_listen(struct socket *sock, int len)
166 struct connlistener *cl = (struct connlistener *) sock->sk;
168 int rc = check_connlistener_state(cl);
170 if (unlikely(rc))
171 return -EOPNOTSUPP;
173 mutex_lock(&(cl->lock));
174 cl->queue_maxlen = len;
175 mutex_unlock(&(cl->lock));
177 return 0;
180 int cor_socket_shutdown(struct socket *sock, int flags)
182 return -ENOTSUPP;
185 int cor_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
187 return -ENOIOCTLCMD;
190 int cor_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
191 size_t total_len)
193 int copied = 0;
195 struct conn *rconn = (struct conn *) sock->sk;
197 int rc = check_conn_state(rconn);
199 int blocking = (msg->msg_flags & MSG_DONTWAIT) == 0;
201 if (unlikely(rc))
202 return -EBADF;
204 mutex_lock(&(rconn->rcv_lock));
206 if (unlikely(rconn->isreset)) {
207 copied = -EAGAIN;
208 goto out;
211 recv:
212 copied = receive_userbuf(rconn, msg);
214 if (copied == -EAGAIN && blocking) {
215 if (wait_event_interruptible(rconn->source.sock.wait,
216 databuf_maypush(&(rconn->buf)) == 0))
217 goto recv;
218 copied = -ERESTARTSYS;
221 out:
222 mutex_unlock(&(rconn->rcv_lock));
224 return copied;
227 static int cor_readytoread(struct conn *sconn)
229 int rc = 0;
230 mutex_lock(&(sconn->rcv_lock));
231 rc = (sconn->buf.read_remaining != 0);
232 mutex_unlock(&(sconn->rcv_lock));
233 return rc;
236 int cor_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
237 size_t total_len, int flags)
239 struct conn *rconn = (struct conn *) sock->sk;
240 struct conn *sconn = rconn->reversedir;
241 size_t copied = 0;
243 int rc = check_conn_state(rconn);
245 int blocking = (flags & MSG_DONTWAIT) == 0;
247 if (unlikely(rc))
248 return -EBADF;
250 BUG_ON(sconn == 0);
252 recv:
253 mutex_lock(&(sconn->rcv_lock));
255 if (unlikely(rconn->isreset)) {
256 copied = -EAGAIN;
257 goto out;
260 copied = databuf_pulluser(sconn, msg);
261 databuf_ackread(&(sconn->buf));
262 wake_sender(sconn);
264 out:
265 mutex_unlock(&(sconn->rcv_lock));
267 if (copied == -EAGAIN && blocking) {
268 if (wait_event_interruptible(sconn->target.sock.wait,
269 cor_readytoread(sconn)) == 0)
270 goto recv;
271 copied = -ERESTARTSYS;
274 return copied;
277 const struct proto_ops cor_proto_ops = {
278 .family = PF_COR,
279 .owner = THIS_MODULE,
280 .release = cor_socket_release,
281 .bind = cor_socket_bind,
282 .connect = cor_socket_connect,
283 .accept = cor_socket_accept,
284 .listen = cor_socket_listen,
285 .shutdown = cor_socket_shutdown,
286 .ioctl = cor_ioctl,
287 .sendmsg = cor_sendmsg,
288 .recvmsg = cor_recvmsg
290 /*socketpair
291 getname
292 poll
293 compat_ioctl
294 setsockopt
295 getsockopt
296 compat_setsockopt
297 compat_getsockopt
298 mmap
299 sendpage
300 splice_read*/
303 int cor_createsock(struct net *net, struct socket *sock, int protocol)
305 if (0 != protocol)
306 return -EPROTONOSUPPORT;
308 sock->state = SS_UNCONNECTED;
309 sock->ops = &cor_proto_ops;
311 return 0;
314 static struct net_proto_family cor_net_proto_family = {
315 .family = PF_COR,
316 .create = cor_createsock,
317 .owner = THIS_MODULE
320 static int __init cor_sock_init(void)
322 sock_register(&cor_net_proto_family);
323 return 0;
326 module_init(cor_sock_init);
328 MODULE_LICENSE("GPL");