/* * symsocket.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id$"; /* * $Log$ * Revision 1.14 2012/06/22 10:22:25 james * *** empty log message *** * * Revision 1.13 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.12 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.11 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.10 2008/03/03 18:16:16 james * *** empty log message *** * * Revision 1.9 2008/03/03 18:15:19 james * *** empty log message *** * * Revision 1.8 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.7 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.6 2008/02/27 00:27:22 james * *** empty log message *** * * Revision 1.5 2008/02/20 22:54:22 staffcvs * *** empty log message *** * * Revision 1.4 2008/02/20 18:31:53 james * *** empty log message *** * * Revision 1.3 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.2 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.1 2008/02/13 18:05:06 james * *** empty log message *** * */ #include "project.h" #include #include #define BUF_SIZE 65536 #define MAX_TXN 4096 int wrap_recv (int fd, void *buf, int len) { int red; red = recv (fd, buf, len, 0); if (!red) return -1; if ((red < 0) && (errno == EAGAIN)) red = 0; return red; } int wrap_send (int fd, void *buf, int len) { int writ; errno = 0; writ = send (fd, buf, len, MSG_NOSIGNAL); if (!writ) return -1; if ((writ < 0) && (errno == EAGAIN)) writ = 0; return writ; } void socket_free (Socket * s) { if (!s) return; if (s->read_buf) slide_free (s->read_buf); if (s->write_buf) slide_free (s->write_buf); if (s->path_to_unlink) { unlink (s->path_to_unlink); free (s->path_to_unlink); } close (s->fd); free (s); } void socket_free_parent (Socket * s) { if (!s) return; if (s->read_buf) slide_free (s->read_buf); if (s->write_buf) slide_free (s->write_buf); if (s->path_to_unlink) free (s->path_to_unlink); close (s->fd); free (s); } Socket * socket_listen (char *path) { int fd; struct sockaddr_un *sun; Socket *ret; int n; unlink (path); fd = socket (PF_UNIX, SOCK_STREAM, 0); if (fd < 0) return NULL; n = strlen (path) + sizeof (struct sockaddr_un); sun = (struct sockaddr_un *) xmalloc (n); memset (sun, 0, n); sun->sun_family = AF_UNIX; strcpy (sun->sun_path, path); if (bind (fd, (struct sockaddr *) sun, SUN_LEN (sun)) < 0) { free (sun); close (fd); return NULL; } free (sun); if (listen (fd, 5) < 0) { close (fd); return NULL; } set_nonblocking (fd); ret = (Socket *) xmalloc (sizeof (Socket)); memset (ret, 0, sizeof (Socket)); ret->read_buf = NULL; ret->write_buf = NULL; ret->fd = fd; ret->path_to_unlink = strdup (path); return ret; } Socket * socket_accept (Socket * l) { Socket *ret; socklen_t len; int fd; struct sockaddr_un sun; len = sizeof (struct sockaddr_un); fd = accept (l->fd, (struct sockaddr *) &sun, &len); if (fd < 0) return NULL; ret = (Socket *) xmalloc (sizeof (Socket)); memset (ret, 0, sizeof (Socket)); set_nonblocking (fd); ret->fd = fd; ret->read_buf = slide_new (BUF_SIZE); ret->write_buf = slide_new (BUF_SIZE); ret->msg = 0; return ret; } /* Blocking for now */ Socket * socket_connect (char *path) { int n; int fd; struct sockaddr_un *sun; Socket *ret; fd = socket (PF_UNIX, SOCK_STREAM, 0); if (fd < 0) return NULL; n = strlen (path) + sizeof (struct sockaddr_un); sun = (struct sockaddr_un *) xmalloc (n); memset (sun, 0, n); sun->sun_family = AF_UNIX; strcpy (sun->sun_path, path); if (connect (fd, (struct sockaddr *) sun, SUN_LEN (sun))) { free (sun); close (fd); return NULL; } free (sun); set_nonblocking (fd); ret = (Socket *) xmalloc (sizeof (Socket)); memset (ret, 0, sizeof (Socket)); ret->fd = fd; ret->read_buf = slide_new (BUF_SIZE); ret->write_buf = slide_new (BUF_SIZE); ret->msg = 0; return ret; } void socket_consume_msg (Socket * s) { if (!s->msg) return; ipc_consume_message_in_slide (s->read_buf); s->msg = ipc_check_for_message_in_slide (s->read_buf); } void socket_pre_select (Socket * s, fd_set * rfds, fd_set * wfds) { /* Server socket */ if (SOCKET_IS_LISTENER (s)) { FD_SET (s->fd, rfds); return; } if (!SLIDE_EMPTY (s->write_buf)) FD_SET (s->fd, wfds); if (!SLIDE_FULL (s->read_buf)) FD_SET (s->fd, rfds); } int socket_post_select (Socket * s, fd_set * rfds, fd_set * wfds) { int n; int error = 0; if ((!SLIDE_EMPTY (s->write_buf)) && FD_ISSET (s->fd, wfds)) { n = (SLIDE_BYTES (s->write_buf) > MAX_TXN) ? MAX_TXN : SLIDE_BYTES (s->write_buf); n = wrap_send (s->fd, SLIDE_RPTR (s->write_buf), n); if (n > 0) slide_consume (s->write_buf, n); if (n < 0) error = -1; } if (!SLIDE_FULL (s->read_buf) && FD_ISSET (s->fd, rfds)) { n = (SLIDE_SPACE (s->read_buf) > MAX_TXN) ? MAX_TXN : SLIDE_SPACE (s->read_buf); n = wrap_recv (s->fd, SLIDE_WPTR (s->read_buf), n); if (n > 0) slide_added (s->read_buf, n); if (n < 0) error = -1; } s->msg = ipc_check_for_message_in_slide (s->read_buf); return error; } int socket_write (Socket * s, void *buf, int len) { int n; slide_expand (s->write_buf, len); memcpy (SLIDE_WPTR (s->write_buf), buf, len); slide_added (s->write_buf, len); n = (SLIDE_BYTES (s->write_buf) > MAX_TXN) ? MAX_TXN : SLIDE_BYTES (s->write_buf); n = wrap_send (s->fd, SLIDE_RPTR (s->write_buf), n); #if 0 { uint8_t *c = SLIDE_RPTR (s->write_buf); } #endif if (n > 0) slide_consume (s->write_buf, n); if (n < 0) return -1; return len; }