1/*- 2 * Copyright (c) 2009-2010 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Pawel Jakub Dawidek under sponsorship from 6 * the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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. 16 * 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 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 2009-2010 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Pawel Jakub Dawidek under sponsorship from 6 * the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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. 16 * 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 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h>
|
34 35#include <assert.h> 36#include <errno.h> 37#include <stdint.h> 38 39#include "proto.h" 40#include "proto_impl.h" 41 42#define PROTO_CONN_MAGIC 0x907041c 43struct proto_conn { 44 int pc_magic; 45 struct hast_proto *pc_proto; 46 void *pc_ctx; 47 int pc_side; 48#define PROTO_SIDE_CLIENT 0 49#define PROTO_SIDE_SERVER_LISTEN 1 50#define PROTO_SIDE_SERVER_WORK 2 51}; 52 53static LIST_HEAD(, hast_proto) protos = LIST_HEAD_INITIALIZER(protos); 54 55void 56proto_register(struct hast_proto *proto) 57{ 58 59 LIST_INSERT_HEAD(&protos, proto, hp_next); 60} 61 62static int 63proto_common_setup(const char *addr, struct proto_conn **connp, int side) 64{ 65 struct hast_proto *proto; 66 struct proto_conn *conn; 67 void *ctx; 68 int ret; 69 70 assert(side == PROTO_SIDE_CLIENT || side == PROTO_SIDE_SERVER_LISTEN); 71 72 conn = malloc(sizeof(*conn)); 73 if (conn == NULL) 74 return (-1); 75 76 LIST_FOREACH(proto, &protos, hp_next) { 77 if (side == PROTO_SIDE_CLIENT) 78 ret = proto->hp_client(addr, &ctx); 79 else /* if (side == PROTO_SIDE_SERVER_LISTEN) */ 80 ret = proto->hp_server(addr, &ctx); 81 /* 82 * ret == 0 - success 83 * ret == -1 - addr is not for this protocol 84 * ret > 0 - right protocol, but an error occured 85 */ 86 if (ret >= 0) 87 break; 88 } 89 if (proto == NULL) { 90 /* Unrecognized address. */ 91 free(conn); 92 errno = EINVAL; 93 return (-1); 94 } 95 if (ret > 0) { 96 /* An error occured. */ 97 free(conn); 98 errno = ret; 99 return (-1); 100 } 101 conn->pc_proto = proto; 102 conn->pc_ctx = ctx; 103 conn->pc_side = side; 104 conn->pc_magic = PROTO_CONN_MAGIC; 105 *connp = conn; 106 return (0); 107} 108 109int 110proto_client(const char *addr, struct proto_conn **connp) 111{ 112 113 return (proto_common_setup(addr, connp, PROTO_SIDE_CLIENT)); 114} 115 116int 117proto_connect(struct proto_conn *conn) 118{ 119 int ret; 120 121 assert(conn != NULL); 122 assert(conn->pc_magic == PROTO_CONN_MAGIC); 123 assert(conn->pc_side == PROTO_SIDE_CLIENT); 124 assert(conn->pc_proto != NULL); 125 126 ret = conn->pc_proto->hp_connect(conn->pc_ctx); 127 if (ret != 0) { 128 errno = ret; 129 return (-1); 130 } 131 132 return (0); 133} 134 135int 136proto_server(const char *addr, struct proto_conn **connp) 137{ 138 139 return (proto_common_setup(addr, connp, PROTO_SIDE_SERVER_LISTEN)); 140} 141 142int 143proto_accept(struct proto_conn *conn, struct proto_conn **newconnp) 144{ 145 struct proto_conn *newconn; 146 int ret; 147 148 assert(conn != NULL); 149 assert(conn->pc_magic == PROTO_CONN_MAGIC); 150 assert(conn->pc_side == PROTO_SIDE_SERVER_LISTEN); 151 assert(conn->pc_proto != NULL); 152 153 newconn = malloc(sizeof(*newconn)); 154 if (newconn == NULL) 155 return (-1); 156 157 ret = conn->pc_proto->hp_accept(conn->pc_ctx, &newconn->pc_ctx); 158 if (ret != 0) { 159 free(newconn); 160 errno = ret; 161 return (-1); 162 } 163 164 newconn->pc_proto = conn->pc_proto; 165 newconn->pc_side = PROTO_SIDE_SERVER_WORK; 166 newconn->pc_magic = PROTO_CONN_MAGIC; 167 *newconnp = newconn; 168 169 return (0); 170} 171 172int 173proto_send(struct proto_conn *conn, const void *data, size_t size) 174{ 175 int ret; 176 177 assert(conn != NULL); 178 assert(conn->pc_magic == PROTO_CONN_MAGIC); 179 assert(conn->pc_proto != NULL); 180 181 ret = conn->pc_proto->hp_send(conn->pc_ctx, data, size); 182 if (ret != 0) { 183 errno = ret; 184 return (-1); 185 } 186 return (0); 187} 188 189int 190proto_recv(struct proto_conn *conn, void *data, size_t size) 191{ 192 int ret; 193 194 assert(conn != NULL); 195 assert(conn->pc_magic == PROTO_CONN_MAGIC); 196 assert(conn->pc_proto != NULL); 197 198 ret = conn->pc_proto->hp_recv(conn->pc_ctx, data, size); 199 if (ret != 0) { 200 errno = ret; 201 return (-1); 202 } 203 return (0); 204} 205 206int 207proto_descriptor(const struct proto_conn *conn) 208{ 209 210 assert(conn != NULL); 211 assert(conn->pc_magic == PROTO_CONN_MAGIC); 212 assert(conn->pc_proto != NULL); 213 214 return (conn->pc_proto->hp_descriptor(conn->pc_ctx)); 215} 216 217bool 218proto_address_match(const struct proto_conn *conn, const char *addr) 219{ 220 221 assert(conn != NULL); 222 assert(conn->pc_magic == PROTO_CONN_MAGIC); 223 assert(conn->pc_proto != NULL); 224 225 return (conn->pc_proto->hp_address_match(conn->pc_ctx, addr)); 226} 227 228void 229proto_local_address(const struct proto_conn *conn, char *addr, size_t size) 230{ 231 232 assert(conn != NULL); 233 assert(conn->pc_magic == PROTO_CONN_MAGIC); 234 assert(conn->pc_proto != NULL); 235 236 conn->pc_proto->hp_local_address(conn->pc_ctx, addr, size); 237} 238 239void 240proto_remote_address(const struct proto_conn *conn, char *addr, size_t size) 241{ 242 243 assert(conn != NULL); 244 assert(conn->pc_magic == PROTO_CONN_MAGIC); 245 assert(conn->pc_proto != NULL); 246 247 conn->pc_proto->hp_remote_address(conn->pc_ctx, addr, size); 248} 249
| 36 37#include <assert.h> 38#include <errno.h> 39#include <stdint.h> 40 41#include "proto.h" 42#include "proto_impl.h" 43 44#define PROTO_CONN_MAGIC 0x907041c 45struct proto_conn { 46 int pc_magic; 47 struct hast_proto *pc_proto; 48 void *pc_ctx; 49 int pc_side; 50#define PROTO_SIDE_CLIENT 0 51#define PROTO_SIDE_SERVER_LISTEN 1 52#define PROTO_SIDE_SERVER_WORK 2 53}; 54 55static LIST_HEAD(, hast_proto) protos = LIST_HEAD_INITIALIZER(protos); 56 57void 58proto_register(struct hast_proto *proto) 59{ 60 61 LIST_INSERT_HEAD(&protos, proto, hp_next); 62} 63 64static int 65proto_common_setup(const char *addr, struct proto_conn **connp, int side) 66{ 67 struct hast_proto *proto; 68 struct proto_conn *conn; 69 void *ctx; 70 int ret; 71 72 assert(side == PROTO_SIDE_CLIENT || side == PROTO_SIDE_SERVER_LISTEN); 73 74 conn = malloc(sizeof(*conn)); 75 if (conn == NULL) 76 return (-1); 77 78 LIST_FOREACH(proto, &protos, hp_next) { 79 if (side == PROTO_SIDE_CLIENT) 80 ret = proto->hp_client(addr, &ctx); 81 else /* if (side == PROTO_SIDE_SERVER_LISTEN) */ 82 ret = proto->hp_server(addr, &ctx); 83 /* 84 * ret == 0 - success 85 * ret == -1 - addr is not for this protocol 86 * ret > 0 - right protocol, but an error occured 87 */ 88 if (ret >= 0) 89 break; 90 } 91 if (proto == NULL) { 92 /* Unrecognized address. */ 93 free(conn); 94 errno = EINVAL; 95 return (-1); 96 } 97 if (ret > 0) { 98 /* An error occured. */ 99 free(conn); 100 errno = ret; 101 return (-1); 102 } 103 conn->pc_proto = proto; 104 conn->pc_ctx = ctx; 105 conn->pc_side = side; 106 conn->pc_magic = PROTO_CONN_MAGIC; 107 *connp = conn; 108 return (0); 109} 110 111int 112proto_client(const char *addr, struct proto_conn **connp) 113{ 114 115 return (proto_common_setup(addr, connp, PROTO_SIDE_CLIENT)); 116} 117 118int 119proto_connect(struct proto_conn *conn) 120{ 121 int ret; 122 123 assert(conn != NULL); 124 assert(conn->pc_magic == PROTO_CONN_MAGIC); 125 assert(conn->pc_side == PROTO_SIDE_CLIENT); 126 assert(conn->pc_proto != NULL); 127 128 ret = conn->pc_proto->hp_connect(conn->pc_ctx); 129 if (ret != 0) { 130 errno = ret; 131 return (-1); 132 } 133 134 return (0); 135} 136 137int 138proto_server(const char *addr, struct proto_conn **connp) 139{ 140 141 return (proto_common_setup(addr, connp, PROTO_SIDE_SERVER_LISTEN)); 142} 143 144int 145proto_accept(struct proto_conn *conn, struct proto_conn **newconnp) 146{ 147 struct proto_conn *newconn; 148 int ret; 149 150 assert(conn != NULL); 151 assert(conn->pc_magic == PROTO_CONN_MAGIC); 152 assert(conn->pc_side == PROTO_SIDE_SERVER_LISTEN); 153 assert(conn->pc_proto != NULL); 154 155 newconn = malloc(sizeof(*newconn)); 156 if (newconn == NULL) 157 return (-1); 158 159 ret = conn->pc_proto->hp_accept(conn->pc_ctx, &newconn->pc_ctx); 160 if (ret != 0) { 161 free(newconn); 162 errno = ret; 163 return (-1); 164 } 165 166 newconn->pc_proto = conn->pc_proto; 167 newconn->pc_side = PROTO_SIDE_SERVER_WORK; 168 newconn->pc_magic = PROTO_CONN_MAGIC; 169 *newconnp = newconn; 170 171 return (0); 172} 173 174int 175proto_send(struct proto_conn *conn, const void *data, size_t size) 176{ 177 int ret; 178 179 assert(conn != NULL); 180 assert(conn->pc_magic == PROTO_CONN_MAGIC); 181 assert(conn->pc_proto != NULL); 182 183 ret = conn->pc_proto->hp_send(conn->pc_ctx, data, size); 184 if (ret != 0) { 185 errno = ret; 186 return (-1); 187 } 188 return (0); 189} 190 191int 192proto_recv(struct proto_conn *conn, void *data, size_t size) 193{ 194 int ret; 195 196 assert(conn != NULL); 197 assert(conn->pc_magic == PROTO_CONN_MAGIC); 198 assert(conn->pc_proto != NULL); 199 200 ret = conn->pc_proto->hp_recv(conn->pc_ctx, data, size); 201 if (ret != 0) { 202 errno = ret; 203 return (-1); 204 } 205 return (0); 206} 207 208int 209proto_descriptor(const struct proto_conn *conn) 210{ 211 212 assert(conn != NULL); 213 assert(conn->pc_magic == PROTO_CONN_MAGIC); 214 assert(conn->pc_proto != NULL); 215 216 return (conn->pc_proto->hp_descriptor(conn->pc_ctx)); 217} 218 219bool 220proto_address_match(const struct proto_conn *conn, const char *addr) 221{ 222 223 assert(conn != NULL); 224 assert(conn->pc_magic == PROTO_CONN_MAGIC); 225 assert(conn->pc_proto != NULL); 226 227 return (conn->pc_proto->hp_address_match(conn->pc_ctx, addr)); 228} 229 230void 231proto_local_address(const struct proto_conn *conn, char *addr, size_t size) 232{ 233 234 assert(conn != NULL); 235 assert(conn->pc_magic == PROTO_CONN_MAGIC); 236 assert(conn->pc_proto != NULL); 237 238 conn->pc_proto->hp_local_address(conn->pc_ctx, addr, size); 239} 240 241void 242proto_remote_address(const struct proto_conn *conn, char *addr, size_t size) 243{ 244 245 assert(conn != NULL); 246 assert(conn->pc_magic == PROTO_CONN_MAGIC); 247 assert(conn->pc_proto != NULL); 248 249 conn->pc_proto->hp_remote_address(conn->pc_ctx, addr, size); 250} 251
|