add sock conn ref
[cor_2_6_31.git] / net / cor / sock.c
blob12f5765331f82fc0cd4e946ac1795660bc8123a7
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 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 (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 (sock->sk != 0)
94 return -EISCONN;
96 rconn = alloc_conn(GFP_KERNEL);
98 kref_get(&(rconn->ref));
100 if (rconn == 0)
101 return -ENOMEM;
103 conn_init_sock_source(rconn);
104 conn_init_sock_target(rconn->reversedir);
106 sock->sk = (struct sock *) rconn;
107 sock->state = SS_CONNECTED;
109 return 0;
112 static int cor_rdytoaccept(struct connlistener *cl)
114 int rc;
115 mutex_lock(&(cl->lock));
116 rc = (list_empty(&(cl->conn_queue)) == 0);
117 mutex_unlock(&(cl->lock));
118 return rc;
121 const struct proto_ops cor_proto_ops;
123 int cor_socket_accept(struct socket *sock, struct socket *newsock, int flags)
125 struct connlistener *cl = (struct connlistener *) sock->sk;
127 int rc = check_connlistener_state(cl);
129 struct conn *newconn;
131 if (unlikely(rc))
132 return -EINVAL;
134 mutex_lock(&(cl->lock));
136 if (unlikely(cl->queue_maxlen <= 0)) {
137 mutex_unlock(&(cl->lock));
138 return -EINVAL;
141 while (list_empty(&(cl->conn_queue))) {
142 mutex_unlock(&(cl->lock));
143 if (wait_event_interruptible(cl->wait, cor_rdytoaccept(cl))) {
144 return -ERESTARTSYS;
146 mutex_lock(&(cl->lock));
149 newconn = container_of(cl->conn_queue.next, struct conn,
150 source.sock.cl_list);
152 BUG_ON(newconn->sourcetype != SOURCE_SOCK);
154 list_del(cl->conn_queue.next);
156 cl->queue_len--;
158 mutex_unlock(&(cl->lock));
160 newsock->ops = &cor_proto_ops;
161 newsock->sk = (struct sock *) newconn;
162 newsock->state = SS_CONNECTED;
164 return 0;
167 int cor_socket_listen(struct socket *sock, int len)
169 struct connlistener *cl = (struct connlistener *) sock->sk;
171 int rc = check_connlistener_state(cl);
173 if (unlikely(rc))
174 return -EOPNOTSUPP;
176 mutex_lock(&(cl->lock));
177 cl->queue_maxlen = len;
178 mutex_unlock(&(cl->lock));
180 return 0;
183 int cor_socket_shutdown(struct socket *sock, int flags)
185 return -ENOTSUPP;
188 int cor_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
190 return -ENOIOCTLCMD;
193 static int sendmsg_maypush(struct conn *rconn)
195 int ret;
196 mutex_lock(&(rconn->rcv_lock));
197 ret = (databuf_maypush(&(rconn->buf)) != 0) ||
198 unlikely(atomic_read(&(rconn->isreset)) != 0);
199 mutex_unlock(&(rconn->rcv_lock));
200 return ret;
203 int cor_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
204 size_t total_len)
206 int copied = 0;
208 struct conn *rconn = (struct conn *) sock->sk;
210 int rc = check_conn_state(rconn);
212 int blocking = (msg->msg_flags & MSG_DONTWAIT) == 0;
214 if (unlikely(rc))
215 return -EBADF;
217 recv:
218 mutex_lock(&(rconn->rcv_lock));
220 if (unlikely(atomic_read(&(rconn->isreset)) != 0)) {
221 copied = -EPIPE;
222 goto out;
225 copied = receive_userbuf(rconn, msg);
227 out:
228 mutex_unlock(&(rconn->rcv_lock));
230 if (copied == -EAGAIN && blocking) {
231 if (wait_event_interruptible(rconn->source.sock.wait,
232 sendmsg_maypush(rconn) == 0))
233 goto recv;
234 copied = -ERESTARTSYS;
237 return copied;
240 static int cor_readytoread(struct conn *sconn)
242 int rc = 0;
243 mutex_lock(&(sconn->rcv_lock));
244 rc = (sconn->buf.read_remaining != 0) ||
245 unlikely(atomic_read(&(sconn->isreset)) != 0);
246 mutex_unlock(&(sconn->rcv_lock));
247 return rc;
250 int cor_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
251 size_t total_len, int flags)
253 struct conn *rconn = (struct conn *) sock->sk;
254 struct conn *sconn = rconn->reversedir;
255 size_t copied = 0;
257 int rc = check_conn_state(rconn);
259 int blocking = (flags & MSG_DONTWAIT) == 0;
261 if (unlikely(rc))
262 return -EBADF;
264 BUG_ON(sconn == 0);
266 recv:
267 mutex_lock(&(sconn->rcv_lock));
269 if (unlikely(atomic_read(&(rconn->isreset)) != 0)) {
270 copied = -EPIPE;
271 goto out;
274 copied = databuf_pulluser(sconn, msg);
275 databuf_ackread(&(sconn->buf));
276 wake_sender(sconn);
278 out:
279 mutex_unlock(&(sconn->rcv_lock));
281 if (copied == -EAGAIN && blocking) {
282 if (wait_event_interruptible(sconn->target.sock.wait,
283 cor_readytoread(sconn)) == 0)
284 goto recv;
285 copied = -ERESTARTSYS;
288 return copied;
291 const struct proto_ops cor_proto_ops = {
292 .family = PF_COR,
293 .owner = THIS_MODULE,
294 .release = cor_socket_release,
295 .bind = cor_socket_bind,
296 .connect = cor_socket_connect,
297 .accept = cor_socket_accept,
298 .listen = cor_socket_listen,
299 .shutdown = cor_socket_shutdown,
300 .ioctl = cor_ioctl,
301 .sendmsg = cor_sendmsg,
302 .recvmsg = cor_recvmsg
304 /*socketpair
305 getname
306 poll
307 compat_ioctl
308 setsockopt
309 getsockopt
310 compat_setsockopt
311 compat_getsockopt
312 mmap
313 sendpage
314 splice_read*/
317 int cor_createsock(struct net *net, struct socket *sock, int protocol)
319 if (0 != protocol)
320 return -EPROTONOSUPPORT;
322 sock->state = SS_UNCONNECTED;
323 sock->ops = &cor_proto_ops;
325 return 0;
328 static struct net_proto_family cor_net_proto_family = {
329 .family = PF_COR,
330 .create = cor_createsock,
331 .owner = THIS_MODULE
334 static int __init cor_sock_init(void)
336 sock_register(&cor_net_proto_family);
337 return 0;
340 module_init(cor_sock_init);
342 MODULE_LICENSE("GPL");