Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / core / net / unix.c
blob63e91af6ed3d54fb52f729ca5f666c9362c89f1f
1 /*
2 * ZeX/OS
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/>.
20 #include <system.h>
21 #include <string.h>
22 #include <fd.h>
23 #include <net/eth.h>
24 #include <net/net.h>
25 #include <net/if.h>
26 #include <net/packet.h>
27 #include <net/socket.h>
28 #include <net/unix.h>
29 #include <errno.h>
31 proto_unix_conn_t proto_unix_conn_list;
32 proto_unix_backlog_t proto_unix_backlog_list;
34 /* prototypes */
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);
44 /** Unix protocol
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)
55 int ret = -1;
57 proto_unix_conn_t *session = net_proto_unix_conn_findbypath (addr->sun_path);
59 if (!session)
60 return -1;
62 proto_unix_conn_t *conn = net_proto_unix_conn_find (fd);
64 if (!conn)
65 return -1;
67 ret = net_proto_unix_conn_set (conn, addr->sun_path, 0);
69 if (!net_proto_unix_backlog_add (session, conn))
70 return -1;
72 //conn->session = session;
74 unsigned long stime = timer_ticks;
76 /* blocking mode */
77 if (!(conn->flags & O_NONBLOCK)) {
78 if (!ret)
79 return -1;
81 for (;;) {
82 schedule ();
84 /* timeout for 3s */
85 if ((stime+3000) < timer_ticks)
86 return -1;
88 if (conn->state == PROTO_UNIX_CONN_STATE_ESTABILISHED) {
89 ret = 0;
90 break;
93 } else
94 /* non-blocking mode */
95 return -1;
97 return ret;
100 int net_proto_unix_send (int fd, char *msg, unsigned size)
102 proto_unix_conn_t *conn = net_proto_unix_conn_find (fd);
104 if (!conn)
105 return -1;
107 int ret = net_proto_unix_write (conn, msg, size);
109 if (ret) {
110 /* blocking mode */
111 if (!(conn->flags & O_NONBLOCK)) {
113 } else {
114 /* non-blocking mode */
115 /* TODO: ? */
120 return size;
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);
128 if (!conn)
129 return -3;
131 if (!msg)
132 return -4;
134 int ret = 0;
136 /* blocking mode */
137 if (!(conn->flags & O_NONBLOCK)) {
138 unsigned long stime = timer_ticks;
140 while (!conn->len) {
141 if ((stime+10000) < timer_ticks)
142 return 0;
144 schedule ();
146 } else {
147 if (!conn->len)
148 return 0;
151 if (!conn->data)
152 return -5;
154 if (conn->len >= size)
155 return -2;
157 ret = conn->len;
159 if (conn->len > 0)
160 memcpy (msg, conn->data, conn->len);
162 conn->len = 0;
164 kfree (conn->data);
166 return ret;
170 int net_proto_unix_close (int fd)
172 proto_unix_conn_t *conn = net_proto_unix_conn_find (fd);
174 if (!conn)
175 return -1;
177 int ret = net_proto_unix_conn_del (conn);
179 return ret;
182 int net_proto_unix_fcntl (int fd, int cmd, long arg)
184 proto_unix_conn_t *conn = net_proto_unix_conn_find (fd);
186 if (!conn)
187 return -1;
189 switch (cmd) {
190 case F_GETFL:
191 return conn->flags;
192 case F_SETFL:
193 conn->flags = arg;
194 return 0;
197 return -1;
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);
204 if (!conn)
205 return -1;
207 int ret = net_proto_unix_conn_set (conn, addr->sun_path, 1);
209 if (ret)
210 return 0;
212 return -1;
215 int net_proto_unix_listen (int fd, int backlog)
217 /* TODO */
219 return 0;
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);
226 if (!conn)
227 return -1;
229 unsigned i = 0;
231 proto_unix_backlog_t *backlog = 0;
233 /* blocking mode */
234 if (!(conn->flags & O_NONBLOCK)) {
235 while (!i) {
236 for (backlog = proto_unix_backlog_list.next; backlog != &proto_unix_backlog_list; backlog = backlog->next) {
237 if (backlog->conn == conn) {
238 i = 1;
239 break;
243 schedule ();
245 } else {
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) {
249 i = 1;
250 break;
255 if (!i)
256 return -1;
258 fd_t *fd_new = fd_create (FD_SOCK);
260 if (!fd_new)
261 return -1;
263 net_proto_unix_conn_add (fd_new);
265 proto_unix_conn_t *conn_new = net_proto_unix_conn_find (fd_new->id);
267 if (!conn_new)
268 return -1;
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;
281 kfree (backlog);
283 return fd_new->id;
286 /** UNIX protocol
287 * hardcore code :P
290 int net_proto_unix_write (proto_unix_conn_t *conn, char *data, unsigned len)
292 if (!data || !conn || !len)
293 return 0;
295 conn = (proto_unix_conn_t *) conn->session;
297 if (!conn)
298 return 0;
300 if (!conn->len)
301 conn->data = (char *) kmalloc (sizeof (char) * (len + 1));
302 else
303 conn->data = (char *) krealloc (conn->data, (sizeof (char) * (conn->len+len)));
305 if (!conn->data)
306 return -1;
308 memcpy (conn->data+conn->len, data, len);
310 conn->len += len;
312 return conn->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));
324 if (!conn) {
325 errno_set (ENOMEM);
326 return -1;
329 memset (conn, 0, sizeof (proto_unix_conn_t));
331 conn->flags = 0;
332 conn->path = 0;
333 conn->session = 0;
335 conn->fd = fd->id;
337 /* add into list */
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;
343 return 0;
346 /* Setup new connection */
347 int net_proto_unix_conn_set (proto_unix_conn_t *conn, char *path, unsigned char bind)
349 if (!conn)
350 return 0;
352 unsigned l = strlen (path);
354 if (!l)
355 return 0;
357 conn->path = (char *) kmalloc (sizeof (char) * (l + 1));
359 if (!conn->path)
360 return 0;
362 memcpy (conn->path, path, l);
363 conn->path[l] = '\0';
365 conn->len = 0;
366 conn->data = 0;
367 conn->bind = bind;
369 return 1;
372 /* Delete existing connection from list */
373 unsigned net_proto_unix_conn_del (proto_unix_conn_t *conn)
375 if (!conn)
376 return 0;
378 if (conn->len)
379 kfree (conn->data);
381 if (conn->path)
382 kfree (conn->path);
384 conn->len = 0;
386 conn->next->prev = conn->prev;
387 conn->prev->next = conn->next;
389 kfree (conn);
391 return 1;
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) {
398 if (conn->fd == fd)
399 return conn;
402 return 0;
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) {
409 if (!conn->path)
410 continue;
412 if (!strcmp (conn->path, path) && conn->bind)
413 return conn;
416 return 0;
419 /* Create new UNIX backlog stamp */
420 int net_proto_unix_backlog_add (proto_unix_conn_t *conn, proto_unix_conn_t *session)
422 if (!conn)
423 return 0;
425 proto_unix_backlog_t *backlog;
427 /* alloc and init context */
428 backlog = (proto_unix_backlog_t *) kmalloc (sizeof (proto_unix_backlog_t));
430 if (!backlog)
431 return 0;
433 backlog->conn = conn;
434 backlog->session = session;
436 /* add into list */
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;
442 return 1;
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;
454 return 1;