buffering bugfixes
[cor_2_6_31.git] / net / cor / sock.c
blobcb8d30c8996c68ff280c205c91922d8e6e08e8bf
1 /*
2 * Connection oriented routing
3 * Copyright (C) 2007-2010 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 kref_put(&(rconn->ref), free_conn);
56 } else {
57 BUG();
60 return 0;
63 int cor_socket_bind(struct socket *sock, struct sockaddr *myaddr,
64 int sockaddr_len)
66 struct connlistener *listener;
67 struct cor_sockaddr *addr = (struct cor_sockaddr *) myaddr;
69 if (unlikely(sock->sk != 0))
70 return -EINVAL;
72 if (sockaddr_len < sizeof(struct cor_sockaddr))
73 return -EINVAL;
75 if (addr->type != SOCKADDRTYPE_PORT)
76 return -EINVAL;
78 listener = open_port(addr->addr.port);
80 if (listener == 0)
81 return -EADDRINUSE;
83 sock->sk = (struct sock *) listener;
85 return 0;
88 int cor_socket_connect(struct socket *sock, struct sockaddr *vaddr,
89 int sockaddr_len, int flags)
91 struct conn *rconn;
93 if (unlikely(sock->sk != 0))
94 return -EISCONN;
96 rconn = alloc_conn(GFP_KERNEL);
98 kref_get(&(rconn->ref));
100 if (unlikely(rconn == 0))
101 return -ENOMEM;
103 mutex_lock(&(rconn->rcv_lock));
104 mutex_lock(&(rconn->reversedir->rcv_lock));
105 conn_init_sock_source(rconn);
106 conn_init_sock_target(rconn->reversedir);
107 mutex_unlock(&(rconn->reversedir->rcv_lock));
108 mutex_unlock(&(rconn->rcv_lock));
110 sock->sk = (struct sock *) rconn;
111 sock->state = SS_CONNECTED;
113 return 0;
116 static int cor_rdytoaccept(struct connlistener *cl)
118 int rc;
119 mutex_lock(&(cl->lock));
120 rc = (list_empty(&(cl->conn_queue)) == 0);
121 mutex_unlock(&(cl->lock));
122 return rc;
125 const struct proto_ops cor_proto_ops;
127 int cor_socket_accept(struct socket *sock, struct socket *newsock, int flags)
129 struct connlistener *cl = (struct connlistener *) sock->sk;
131 int rc = check_connlistener_state(cl);
133 struct conn *newconn;
135 if (unlikely(rc))
136 return -EINVAL;
138 mutex_lock(&(cl->lock));
140 if (unlikely(cl->queue_maxlen <= 0)) {
141 mutex_unlock(&(cl->lock));
142 return -EINVAL;
145 while (list_empty(&(cl->conn_queue))) {
146 mutex_unlock(&(cl->lock));
147 if (wait_event_interruptible(cl->wait, cor_rdytoaccept(cl))) {
148 return -ERESTARTSYS;
150 mutex_lock(&(cl->lock));
153 newconn = container_of(cl->conn_queue.next, struct conn,
154 source.sock.cl_list);
156 BUG_ON(newconn->sourcetype != SOURCE_SOCK);
158 list_del(cl->conn_queue.next);
160 cl->queue_len--;
162 mutex_unlock(&(cl->lock));
164 newsock->ops = &cor_proto_ops;
165 newsock->sk = (struct sock *) newconn;
166 newsock->state = SS_CONNECTED;
168 return 0;
171 int cor_socket_listen(struct socket *sock, int len)
173 struct connlistener *cl = (struct connlistener *) sock->sk;
175 int rc = check_connlistener_state(cl);
177 if (unlikely(rc))
178 return -EOPNOTSUPP;
180 mutex_lock(&(cl->lock));
181 cl->queue_maxlen = len;
182 mutex_unlock(&(cl->lock));
184 return 0;
187 int cor_socket_shutdown(struct socket *sock, int flags)
189 return -ENOTSUPP;
192 int cor_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
194 return -ENOIOCTLCMD;
197 static int sendmsg_maypush(struct conn *rconn)
199 int ret;
200 mutex_lock(&(rconn->rcv_lock));
201 ret = (databuf_maypush(&(rconn->buf)) != 0) ||
202 unlikely(atomic_read(&(rconn->isreset)) != 0);
203 mutex_unlock(&(rconn->rcv_lock));
204 return ret;
207 int cor_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
208 size_t total_len)
210 int copied = 0;
212 struct conn *rconn = (struct conn *) sock->sk;
214 int rc = check_conn_state(rconn);
216 int blocking = (msg->msg_flags & MSG_DONTWAIT) == 0;
218 if (unlikely(rc))
219 return -EBADF;
221 recv:
222 mutex_lock(&(rconn->rcv_lock));
224 if (unlikely(atomic_read(&(rconn->isreset)) != 0)) {
225 copied = -EPIPE;
226 goto out;
229 copied = receive_userbuf(rconn, msg);
231 out:
232 mutex_unlock(&(rconn->rcv_lock));
234 if (copied == -EAGAIN && blocking) {
235 if (wait_event_interruptible(rconn->source.sock.wait,
236 sendmsg_maypush(rconn) == 0))
237 goto recv;
238 copied = -ERESTARTSYS;
241 return copied;
244 static int cor_readytoread(struct conn *sconn)
246 int rc = 0;
247 mutex_lock(&(sconn->rcv_lock));
248 rc = (sconn->buf.read_remaining != 0) ||
249 unlikely(atomic_read(&(sconn->isreset)) != 0);
250 mutex_unlock(&(sconn->rcv_lock));
251 return rc;
254 int cor_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
255 size_t total_len, int flags)
257 struct conn *rconn = (struct conn *) sock->sk;
258 struct conn *sconn = rconn->reversedir;
259 size_t copied = 0;
261 int rc = check_conn_state(rconn);
263 int blocking = (flags & MSG_DONTWAIT) == 0;
265 if (unlikely(rc))
266 return -EBADF;
268 BUG_ON(sconn == 0);
270 recv:
271 mutex_lock(&(sconn->rcv_lock));
273 if (unlikely(atomic_read(&(rconn->isreset)) != 0)) {
274 copied = -EPIPE;
275 goto out;
278 copied = databuf_pulluser(sconn, msg);
279 databuf_ackread(sconn);
280 wake_sender(sconn);
282 out:
283 mutex_unlock(&(sconn->rcv_lock));
285 if (copied == -EAGAIN && blocking) {
286 if (wait_event_interruptible(sconn->target.sock.wait,
287 cor_readytoread(sconn)) == 0)
288 goto recv;
289 copied = -ERESTARTSYS;
292 return copied;
295 const struct proto_ops cor_proto_ops = {
296 .family = PF_COR,
297 .owner = THIS_MODULE,
298 .release = cor_socket_release,
299 .bind = cor_socket_bind,
300 .connect = cor_socket_connect,
301 .accept = cor_socket_accept,
302 .listen = cor_socket_listen,
303 .shutdown = cor_socket_shutdown,
304 .ioctl = cor_ioctl,
305 .sendmsg = cor_sendmsg,
306 .recvmsg = cor_recvmsg
308 /*socketpair
309 getname
310 poll
311 compat_ioctl
312 setsockopt
313 getsockopt
314 compat_setsockopt
315 compat_getsockopt
316 mmap
317 sendpage
318 splice_read*/
321 int cor_createsock(struct net *net, struct socket *sock, int protocol)
323 if (unlikely(protocol != 0))
324 return -EPROTONOSUPPORT;
326 sock->state = SS_UNCONNECTED;
327 sock->ops = &cor_proto_ops;
329 return 0;
332 static struct net_proto_family cor_net_proto_family = {
333 .family = PF_COR,
334 .create = cor_createsock,
335 .owner = THIS_MODULE
338 static int __init cor_sock_init(void)
340 sock_register(&cor_net_proto_family);
341 return 0;
344 module_init(cor_sock_init);
346 MODULE_LICENSE("GPL");