2 * Copyright (c) 2009-2010 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/types.h>
34 #include <sys/socket.h>
45 #include "proto_impl.h"
47 #define SP_CTX_MAGIC 0x50c3741
52 #define SP_SIDE_UNDEF 0
53 #define SP_SIDE_CLIENT 1
54 #define SP_SIDE_SERVER 2
57 static void sp_close(void *ctx);
60 sp_client(const char *addr, void **ctxp)
65 if (strcmp(addr, "socketpair://") != 0)
68 spctx = malloc(sizeof(*spctx));
72 if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) < 0) {
78 spctx->sp_side = SP_SIDE_UNDEF;
79 spctx->sp_magic = SP_CTX_MAGIC;
86 sp_connect(void *ctx __unused)
89 assert(!"proto_connect() not supported on socketpairs");
94 sp_server(const char *addr, void **ctxp __unused)
97 if (strcmp(addr, "socketpair://") != 0)
100 assert(!"proto_server() not supported on socketpairs");
105 sp_accept(void *ctx __unused, void **newctxp __unused)
108 assert(!"proto_server() not supported on socketpairs");
113 sp_send(void *ctx, const unsigned char *data, size_t size)
115 struct sp_ctx *spctx = ctx;
118 assert(spctx != NULL);
119 assert(spctx->sp_magic == SP_CTX_MAGIC);
121 switch (spctx->sp_side) {
124 * If the first operation done by the caller is proto_send(),
125 * we assume this the client.
128 spctx->sp_side = SP_SIDE_CLIENT;
129 /* Close other end. */
130 close(spctx->sp_fd[1]);
132 assert(spctx->sp_fd[0] >= 0);
133 fd = spctx->sp_fd[0];
136 assert(spctx->sp_fd[1] >= 0);
137 fd = spctx->sp_fd[1];
143 return (proto_common_send(fd, data, size));
147 sp_recv(void *ctx, unsigned char *data, size_t size)
149 struct sp_ctx *spctx = ctx;
152 assert(spctx != NULL);
153 assert(spctx->sp_magic == SP_CTX_MAGIC);
155 switch (spctx->sp_side) {
158 * If the first operation done by the caller is proto_recv(),
159 * we assume this the server.
162 spctx->sp_side = SP_SIDE_SERVER;
163 /* Close other end. */
164 close(spctx->sp_fd[0]);
166 assert(spctx->sp_fd[1] >= 0);
167 fd = spctx->sp_fd[1];
170 assert(spctx->sp_fd[0] >= 0);
171 fd = spctx->sp_fd[0];
177 return (proto_common_recv(fd, data, size));
181 sp_descriptor(const void *ctx)
183 const struct sp_ctx *spctx = ctx;
185 assert(spctx != NULL);
186 assert(spctx->sp_magic == SP_CTX_MAGIC);
187 assert(spctx->sp_side == SP_SIDE_CLIENT ||
188 spctx->sp_side == SP_SIDE_SERVER);
190 switch (spctx->sp_side) {
192 assert(spctx->sp_fd[0] >= 0);
193 return (spctx->sp_fd[0]);
195 assert(spctx->sp_fd[1] >= 0);
196 return (spctx->sp_fd[1]);
203 sp_address_match(const void *ctx __unused, const char *addr __unused)
206 assert(!"proto_address_match() not supported on socketpairs");
211 sp_local_address(const void *ctx __unused, char *addr __unused,
212 size_t size __unused)
215 assert(!"proto_local_address() not supported on socketpairs");
220 sp_remote_address(const void *ctx __unused, char *addr __unused,
221 size_t size __unused)
224 assert(!"proto_remote_address() not supported on socketpairs");
231 struct sp_ctx *spctx = ctx;
233 assert(spctx != NULL);
234 assert(spctx->sp_magic == SP_CTX_MAGIC);
236 switch (spctx->sp_side) {
238 close(spctx->sp_fd[0]);
239 close(spctx->sp_fd[1]);
242 close(spctx->sp_fd[0]);
245 close(spctx->sp_fd[1]);
255 static struct hast_proto sp_proto = {
256 .hp_name = "socketpair",
257 .hp_client = sp_client,
258 .hp_connect = sp_connect,
259 .hp_server = sp_server,
260 .hp_accept = sp_accept,
263 .hp_descriptor = sp_descriptor,
264 .hp_address_match = sp_address_match,
265 .hp_local_address = sp_local_address,
266 .hp_remote_address = sp_remote_address,
270 static __constructor void
274 proto_register(&sp_proto);