diff options
-rw-r--r-- | pflocal/sock.c | 106 |
1 files changed, 89 insertions, 17 deletions
diff --git a/pflocal/sock.c b/pflocal/sock.c index 968ec460..14936513 100644 --- a/pflocal/sock.c +++ b/pflocal/sock.c @@ -54,31 +54,103 @@ sock_aquire_write_pipe (struct sock *sock) return pipe; } +/* ---------------------------------------------------------------- */ + +/* Return a new socket with the given pipe ops in SOCK. */ error_t -sock_create (int type, struct sock *result) +sock_create (struct pipe_ops *pipe_ops, struct sock **sock) { static unsigned next_sock_id = 0; - struct sock *sock = malloc (sizeof (struct sock)); + struct sock *new = malloc (sizeof (struct sock)); - if (sock == NULL) + if (new == NULL) return ENOMEM; - sock->refs = 0; - sock->read_pipe = sock->write_pipe = NULL; - sock->id = next_sock_id++; - bzero (&sock->change_time, sizeof (sock->change_time)); - mutex_init (&sock->lock); + new->refs = 0; + new->read_pipe = new->write_pipe = NULL; + new->id = next_sock_id++; + new->pipe_ops = pipe_ops; + new->listenq = NULL; + new->addr = NULL; + bzero (&new->change_time, sizeof (new->change_time)); + mutex_init (&new->lock); + + *sock = new; + return 0; +} + +void +sock_free (struct sock *sock) +{ + +} + +/* Return a new user port on SOCK, in PORT and PORT_TYPE. */ +error_t +sock_create_port (struct sock *sock, + mach_port_t *port, mach_msg_type_name_t *port_type) +{ + struct sock_user *user = + port_allocate_port (sock_user_bucket, + sizeof (struct sock_user), sock_user_class); + + if (!user) + return ENOMEM; + + mutex_lock (&sock->lock); + sock->refs++; + mutex_unlock (&sock->lock); + + user->sock = sock; + + *port = ports_get_right (user); + *port_type = MACH_MSG_TYPE_MAKE_SEND; + + return 0; +} + +/* ---------------------------------------------------------------- */ - switch (type) +/* We hold this lock when we want to lock both sockets for a attach + operation, to avoid another attach with the sockets reversed happening. + Attach should be the only place trying to lock two sockets at once, so + this should be safe... */ +static struct mutex connect_lock; + +/* Connect together the previously unconnected sockets SOCK1 and SOCK2. */ +error_t +sock_connect (struct sock *sock1, struct sock *sock2) +{ + if (sock1->pipe_ops != sock2->pipe_ops) + return EOPNOTSUPP; /* XXX?? */ + + mutex_lock (&connect_lock); + mutex_lock (&sock1->lock); + mutex_lock (&sock2->lock); + + if (sock1->read_pipe || sock1->write_pipe + || sock2->read_pipe || sock2->write_pipe) + err = EISCONN; + else { - case SOCK_STREAM: - sock->pipe_ops = stream_pipe_ops; break; - case SOCK_DGRAM: - sock->pipe_ops = dgram_pipe_ops; break; - default: - free (sock); - return ESOCKTNOSUPPORT; + struct pipe *pipe1, *pipe2; + err = pipe_create (sock1, sock2, sock1->pipe_ops, &pipe1); + if (!err) + { + err = pipe_create (sock2, sock1, sock1->pipe_ops, &pipe2); + if (err) + pipe_free (pipe1); + } + if (!err) + { + sock1->write_pipe = sock2->read_pipe = pipe1; + sock2->write_pipe = sock1->read_pipe = pipe2; + } } - return 0; + mutex_unlock (&sock2->lock); + mutex_unlock (&sock1->lock); + mutex_unlock (&connect_lock); + + return err; } |