3 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (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, see <http://www.gnu.org/licenses/>.
26 #include <net/packet.h>
27 #include <net/socket.h>
31 proto_unix_conn_t proto_unix_conn_list
;
32 proto_unix_backlog_t proto_unix_backlog_list
;
35 int net_proto_unix_read_cache (proto_unix_conn_t
*conn
, char *data
, unsigned len
);
36 int net_proto_unix_write (proto_unix_conn_t
*conn
, char *data
, unsigned len
);
37 proto_unix_conn_t
*net_proto_unix_conn_find (int fd
);
38 proto_unix_conn_t
*net_proto_unix_conn_findbypath (char *path
);
39 int net_proto_unix_conn_set (proto_unix_conn_t
*conn
, char *path
, unsigned char bind
);
40 unsigned net_proto_unix_conn_del (proto_unix_conn_t
*conn
);
41 int net_proto_unix_conn_add ();
42 int net_proto_unix_backlog_add (proto_unix_conn_t
*conn
, proto_unix_conn_t
*session
);
45 * User-friendly socket functions
47 int net_proto_unix_socket (fd_t
*fd
)
49 return net_proto_unix_conn_add (fd
);
52 extern unsigned long timer_ticks
;
53 int net_proto_unix_connect (int fd
, sockaddr_un
*addr
)
57 proto_unix_conn_t
*session
= net_proto_unix_conn_findbypath (addr
->sun_path
);
62 proto_unix_conn_t
*conn
= net_proto_unix_conn_find (fd
);
67 ret
= net_proto_unix_conn_set (conn
, addr
->sun_path
, 0);
69 if (!net_proto_unix_backlog_add (session
, conn
))
72 //conn->session = session;
74 unsigned long stime
= timer_ticks
;
77 if (!(conn
->flags
& O_NONBLOCK
)) {
85 if ((stime
+3000) < timer_ticks
)
88 if (conn
->state
== PROTO_UNIX_CONN_STATE_ESTABILISHED
) {
94 /* non-blocking mode */
100 int net_proto_unix_send (int fd
, char *msg
, unsigned size
)
102 proto_unix_conn_t
*conn
= net_proto_unix_conn_find (fd
);
107 int ret
= net_proto_unix_write (conn
, msg
, size
);
111 if (!(conn
->flags
& O_NONBLOCK
)) {
114 /* non-blocking mode */
123 extern unsigned long timer_ticks
;
124 int net_proto_unix_recv (int fd
, char *msg
, unsigned size
)
126 proto_unix_conn_t
*conn
= net_proto_unix_conn_find (fd
);
137 if (!(conn
->flags
& O_NONBLOCK
)) {
138 unsigned long stime
= timer_ticks
;
141 if ((stime
+10000) < timer_ticks
)
154 if (conn
->len
>= size
)
160 memcpy (msg
, conn
->data
, conn
->len
);
170 int net_proto_unix_close (int fd
)
172 proto_unix_conn_t
*conn
= net_proto_unix_conn_find (fd
);
177 int ret
= net_proto_unix_conn_del (conn
);
182 int net_proto_unix_fcntl (int fd
, int cmd
, long arg
)
184 proto_unix_conn_t
*conn
= net_proto_unix_conn_find (fd
);
200 int net_proto_unix_bind (int fd
, sockaddr_un
*addr
, socklen_t len
)
202 proto_unix_conn_t
*conn
= net_proto_unix_conn_find (fd
);
207 int ret
= net_proto_unix_conn_set (conn
, addr
->sun_path
, 1);
215 int net_proto_unix_listen (int fd
, int backlog
)
222 int net_proto_unix_accept (int fd
, sockaddr_un
*addr
, socklen_t
*addrlen
)
224 proto_unix_conn_t
*conn
= net_proto_unix_conn_find (fd
);
231 proto_unix_backlog_t
*backlog
= 0;
234 if (!(conn
->flags
& O_NONBLOCK
)) {
236 for (backlog
= proto_unix_backlog_list
.next
; backlog
!= &proto_unix_backlog_list
; backlog
= backlog
->next
) {
237 if (backlog
->conn
== conn
) {
246 /* non-blocking mode */
247 for (backlog
= proto_unix_backlog_list
.next
; backlog
!= &proto_unix_backlog_list
; backlog
= backlog
->next
) {
248 if (backlog
->conn
== conn
) {
258 fd_t
*fd_new
= fd_create (FD_SOCK
);
263 net_proto_unix_conn_add (fd_new
);
265 proto_unix_conn_t
*conn_new
= net_proto_unix_conn_find (fd_new
->id
);
270 backlog
->session
->session
= conn_new
;
271 backlog
->session
->state
= PROTO_UNIX_CONN_STATE_ESTABILISHED
;
273 net_proto_unix_conn_set (conn_new
, conn
->path
, 0);
275 conn_new
->session
= (void *) backlog
->session
;
277 /* remove from queue accepted connection */
278 backlog
->next
->prev
= backlog
->prev
;
279 backlog
->prev
->next
= backlog
->next
;
290 int net_proto_unix_write (proto_unix_conn_t
*conn
, char *data
, unsigned len
)
292 if (!data
|| !conn
|| !len
)
295 conn
= (proto_unix_conn_t
*) conn
->session
;
301 conn
->data
= (char *) kmalloc (sizeof (char) * (len
+ 1));
303 conn
->data
= (char *) krealloc (conn
->data
, (sizeof (char) * (conn
->len
+len
)));
308 memcpy (conn
->data
+conn
->len
, data
, len
);
316 /* Create new UNIX connection */
317 int net_proto_unix_conn_add (fd_t
*fd
)
319 proto_unix_conn_t
*conn
;
321 /* alloc and init context */
322 conn
= (proto_unix_conn_t
*) kmalloc (sizeof (proto_unix_conn_t
));
329 memset (conn
, 0, sizeof (proto_unix_conn_t
));
338 conn
->next
= &proto_unix_conn_list
;
339 conn
->prev
= proto_unix_conn_list
.prev
;
340 conn
->prev
->next
= conn
;
341 conn
->next
->prev
= conn
;
346 /* Setup new connection */
347 int net_proto_unix_conn_set (proto_unix_conn_t
*conn
, char *path
, unsigned char bind
)
352 unsigned l
= strlen (path
);
357 conn
->path
= (char *) kmalloc (sizeof (char) * (l
+ 1));
362 memcpy (conn
->path
, path
, l
);
363 conn
->path
[l
] = '\0';
372 /* Delete existing connection from list */
373 unsigned net_proto_unix_conn_del (proto_unix_conn_t
*conn
)
386 conn
->next
->prev
= conn
->prev
;
387 conn
->prev
->next
= conn
->next
;
394 proto_unix_conn_t
*net_proto_unix_conn_find (int fd
)
396 proto_unix_conn_t
*conn
= NULL
;
397 for (conn
= proto_unix_conn_list
.next
; conn
!= &proto_unix_conn_list
; conn
= conn
->next
) {
405 proto_unix_conn_t
*net_proto_unix_conn_findbypath (char *path
)
407 proto_unix_conn_t
*conn
= NULL
;
408 for (conn
= proto_unix_conn_list
.next
; conn
!= &proto_unix_conn_list
; conn
= conn
->next
) {
412 if (!strcmp (conn
->path
, path
) && conn
->bind
)
419 /* Create new UNIX backlog stamp */
420 int net_proto_unix_backlog_add (proto_unix_conn_t
*conn
, proto_unix_conn_t
*session
)
425 proto_unix_backlog_t
*backlog
;
427 /* alloc and init context */
428 backlog
= (proto_unix_backlog_t
*) kmalloc (sizeof (proto_unix_backlog_t
));
433 backlog
->conn
= conn
;
434 backlog
->session
= session
;
437 backlog
->next
= &proto_unix_backlog_list
;
438 backlog
->prev
= proto_unix_backlog_list
.prev
;
439 backlog
->prev
->next
= backlog
;
440 backlog
->next
->prev
= backlog
;
445 /* init of unix protocol */
446 unsigned init_net_proto_unix ()
448 proto_unix_conn_list
.next
= &proto_unix_conn_list
;
449 proto_unix_conn_list
.prev
= &proto_unix_conn_list
;
451 proto_unix_backlog_list
.next
= &proto_unix_backlog_list
;
452 proto_unix_backlog_list
.prev
= &proto_unix_backlog_list
;