Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Conn-stream management functions |
| 3 | * |
| 4 | * Copyright 2021 Christopher Faulet <cfaulet@haproxy.com> |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU General Public License |
| 8 | * as published by the Free Software Foundation; either version |
| 9 | * 2 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | */ |
| 12 | |
| 13 | #include <haproxy/api.h> |
| 14 | #include <haproxy/connection.h> |
| 15 | #include <haproxy/conn_stream.h> |
| 16 | #include <haproxy/pool.h> |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 17 | #include <haproxy/stream_interface.h> |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 18 | |
| 19 | DECLARE_POOL(pool_head_connstream, "conn_stream", sizeof(struct conn_stream)); |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 20 | DECLARE_POOL(pool_head_cs_endpoint, "cs_endpoint", sizeof(struct cs_endpoint)); |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 21 | |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 22 | void cs_endpoint_init(struct cs_endpoint *endp) |
| 23 | { |
| 24 | endp->target = NULL; |
| 25 | endp->ctx = NULL; |
| 26 | endp->flags = CS_EP_NONE; |
| 27 | } |
| 28 | |
| 29 | struct cs_endpoint *cs_endpoint_new() |
| 30 | { |
| 31 | struct cs_endpoint *endp; |
| 32 | |
| 33 | endp = pool_alloc(pool_head_cs_endpoint); |
| 34 | if (unlikely(!endp)) |
| 35 | return NULL; |
| 36 | |
| 37 | cs_endpoint_init(endp); |
| 38 | return endp; |
| 39 | } |
| 40 | |
| 41 | void cs_endpoint_free(struct cs_endpoint *endp) |
| 42 | { |
| 43 | pool_free(pool_head_cs_endpoint, endp); |
| 44 | } |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 45 | |
Christopher Faulet | dd2d0d8 | 2021-12-20 09:34:32 +0100 | [diff] [blame] | 46 | /* Tries to allocate a new conn_stream and initialize its main fields. On |
| 47 | * failure, nothing is allocated and NULL is returned. |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 48 | */ |
Christopher Faulet | b669d68 | 2022-03-22 18:37:19 +0100 | [diff] [blame] | 49 | struct conn_stream *cs_new(struct cs_endpoint *endp) |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 50 | { |
| 51 | struct conn_stream *cs; |
| 52 | |
| 53 | cs = pool_alloc(pool_head_connstream); |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 54 | |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 55 | if (unlikely(!cs)) |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 56 | goto alloc_error; |
Christopher Faulet | bb772d0 | 2022-03-22 15:28:36 +0100 | [diff] [blame] | 57 | |
| 58 | cs->obj_type = OBJ_TYPE_CS; |
| 59 | cs->flags = CS_FL_NONE; |
Christopher Faulet | 62e7574 | 2022-03-31 09:16:34 +0200 | [diff] [blame] | 60 | cs->state = CS_ST_INI; |
Christopher Faulet | 1d98777 | 2022-03-29 18:03:35 +0200 | [diff] [blame] | 61 | cs->hcto = TICK_ETERNITY; |
Christopher Faulet | bb772d0 | 2022-03-22 15:28:36 +0100 | [diff] [blame] | 62 | cs->app = NULL; |
Christopher Faulet | bb772d0 | 2022-03-22 15:28:36 +0100 | [diff] [blame] | 63 | cs->si = NULL; |
| 64 | cs->data_cb = NULL; |
Christopher Faulet | 8da67aa | 2022-03-29 17:53:09 +0200 | [diff] [blame] | 65 | cs->src = NULL; |
| 66 | cs->dst = NULL; |
Christopher Faulet | b669d68 | 2022-03-22 18:37:19 +0100 | [diff] [blame] | 67 | if (!endp) { |
| 68 | endp = cs_endpoint_new(); |
| 69 | if (unlikely(!endp)) |
| 70 | goto alloc_error; |
| 71 | } |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 72 | cs->endp = endp; |
| 73 | |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 74 | return cs; |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 75 | |
| 76 | alloc_error: |
| 77 | pool_free(pool_head_connstream, cs); |
| 78 | return NULL; |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 79 | } |
| 80 | |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 81 | struct conn_stream *cs_new_from_mux(struct cs_endpoint *endp, struct session *sess, struct buffer *input) |
| 82 | { |
| 83 | struct conn_stream *cs; |
| 84 | |
| 85 | cs = cs_new(endp); |
| 86 | if (unlikely(!cs)) |
| 87 | return NULL; |
| 88 | if (unlikely(!stream_new(sess, cs, input))) { |
| 89 | pool_free(pool_head_connstream, cs); |
| 90 | cs = NULL; |
| 91 | } |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 92 | endp->flags &= ~CS_EP_ORPHAN; |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 93 | return cs; |
| 94 | } |
| 95 | |
| 96 | struct conn_stream *cs_new_from_applet(struct cs_endpoint *endp, struct session *sess, struct buffer *input) |
| 97 | { |
| 98 | struct conn_stream *cs; |
| 99 | struct appctx *appctx = endp->ctx; |
| 100 | |
| 101 | cs = cs_new(endp); |
| 102 | if (unlikely(!cs)) |
| 103 | return NULL; |
| 104 | appctx->owner = cs; |
| 105 | if (unlikely(!stream_new(sess, cs, input))) { |
| 106 | pool_free(pool_head_connstream, cs); |
| 107 | cs = NULL; |
| 108 | } |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 109 | endp->flags &= ~CS_EP_ORPHAN; |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 110 | return cs; |
| 111 | } |
| 112 | |
| 113 | struct conn_stream *cs_new_from_strm(struct stream *strm, unsigned int flags) |
| 114 | { |
| 115 | struct conn_stream *cs; |
| 116 | |
| 117 | cs = cs_new(NULL); |
| 118 | if (unlikely(!cs)) |
| 119 | return NULL; |
| 120 | cs->flags |= flags; |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 121 | cs->endp->flags |= CS_EP_DETACHED; |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 122 | cs->si = si_new(cs); |
| 123 | if (unlikely(!cs->si)) { |
| 124 | cs_free(cs); |
| 125 | return NULL; |
| 126 | } |
| 127 | cs->app = &strm->obj_type; |
| 128 | cs->si->ops = &si_embedded_ops; |
| 129 | cs->data_cb = NULL; |
| 130 | return cs; |
| 131 | } |
| 132 | |
| 133 | struct conn_stream *cs_new_from_check(struct check *check, unsigned int flags) |
| 134 | { |
| 135 | struct conn_stream *cs; |
| 136 | |
| 137 | cs = cs_new(NULL); |
| 138 | if (unlikely(!cs)) |
| 139 | return NULL; |
| 140 | cs->flags |= flags; |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 141 | cs->endp->flags |= CS_EP_DETACHED; |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 142 | cs->app = &check->obj_type; |
| 143 | cs->data_cb = &check_conn_cb; |
| 144 | return cs; |
| 145 | } |
| 146 | |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 147 | /* Releases a conn_stream previously allocated by cs_new(), as well as any |
| 148 | * buffer it would still hold. |
| 149 | */ |
| 150 | void cs_free(struct conn_stream *cs) |
| 151 | { |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 152 | si_free(cs->si); |
Christopher Faulet | 8da67aa | 2022-03-29 17:53:09 +0200 | [diff] [blame] | 153 | sockaddr_free(&cs->src); |
| 154 | sockaddr_free(&cs->dst); |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 155 | if (cs->endp) { |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 156 | BUG_ON(!(cs->endp->flags & CS_EP_DETACHED)); |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 157 | cs_endpoint_free(cs->endp); |
| 158 | } |
Christopher Faulet | 1329f2a | 2021-12-16 17:32:56 +0100 | [diff] [blame] | 159 | pool_free(pool_head_connstream, cs); |
| 160 | } |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 161 | |
| 162 | |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 163 | /* Attaches a conn_stream to an mux endpoint and sets the endpoint ctx */ |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 164 | void cs_attach_mux(struct conn_stream *cs, void *target, void *ctx) |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 165 | { |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 166 | struct connection *conn = ctx; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 167 | |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 168 | cs->endp->target = target; |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 169 | cs->endp->ctx = ctx; |
| 170 | cs->endp->flags |= CS_EP_T_MUX; |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 171 | cs->endp->flags &= ~CS_EP_DETACHED; |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 172 | if (!conn->ctx) |
| 173 | conn->ctx = cs; |
| 174 | if (cs_strm(cs)) { |
| 175 | cs->si->ops = &si_conn_ops; |
| 176 | cs->data_cb = &si_conn_cb; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 177 | } |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 178 | else if (cs_check(cs)) |
| 179 | cs->data_cb = &check_conn_cb; |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | /* Attaches a conn_stream to an applet endpoint and sets the endpoint ctx */ |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 183 | void cs_attach_applet(struct conn_stream *cs, void *target, void *ctx) |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 184 | { |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 185 | struct appctx *appctx = target; |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 186 | |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 187 | cs->endp->target = target; |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 188 | cs->endp->ctx = ctx; |
| 189 | cs->endp->flags |= CS_EP_T_APPLET; |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 190 | cs->endp->flags &= ~CS_EP_DETACHED; |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 191 | appctx->owner = cs; |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 192 | if (cs_strm(cs)) { |
Christopher Faulet | 9388204 | 2022-01-19 14:56:50 +0100 | [diff] [blame] | 193 | cs->si->ops = &si_applet_ops; |
| 194 | cs->data_cb = NULL; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 195 | } |
| 196 | } |
| 197 | |
| 198 | /* Attaches a conn_stream to a app layer and sets the relevant callbacks */ |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 199 | int cs_attach_strm(struct conn_stream *cs, struct stream *strm) |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 200 | { |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 201 | cs->app = &strm->obj_type; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 202 | |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 203 | cs->si = si_new(cs); |
| 204 | if (unlikely(!cs->si)) |
| 205 | return -1; |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 206 | cs->endp->flags &= ~CS_EP_ORPHAN; |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 207 | if (cs->endp->flags & CS_EP_T_MUX) { |
| 208 | cs->si->ops = &si_conn_ops; |
| 209 | cs->data_cb = &si_conn_cb; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 210 | } |
Christopher Faulet | a9e8b39 | 2022-03-23 11:01:09 +0100 | [diff] [blame] | 211 | else if (cs->endp->flags & CS_EP_T_APPLET) { |
| 212 | cs->si->ops = &si_applet_ops; |
| 213 | cs->data_cb = NULL; |
| 214 | } |
| 215 | else { |
| 216 | cs->si->ops = &si_embedded_ops; |
| 217 | cs->data_cb = NULL; |
| 218 | } |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 219 | return 0; |
| 220 | } |
| 221 | |
| 222 | /* Detach the conn_stream from the endpoint, if any. For a connecrion, if a mux |
| 223 | * owns the connection ->detach() callback is called. Otherwise, it means the |
| 224 | * conn-stream owns the connection. In this case the connection is closed and |
| 225 | * released. For an applet, the appctx is released. At the end, the conn-stream |
| 226 | * is not released but some fields a reset. |
| 227 | */ |
| 228 | void cs_detach_endp(struct conn_stream *cs) |
| 229 | { |
Christopher Faulet | b041b23 | 2022-03-24 10:27:02 +0100 | [diff] [blame] | 230 | if (!cs->endp) |
| 231 | goto reset_cs; |
| 232 | |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 233 | if (cs->endp->flags & CS_EP_T_MUX) { |
| 234 | struct connection *conn = cs_conn(cs); |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 235 | |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 236 | if (conn->mux) { |
Christopher Faulet | 54e85cb | 2022-01-06 08:46:56 +0100 | [diff] [blame] | 237 | /* TODO: handle unsubscribe for healthchecks too */ |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 238 | cs->endp->flags |= CS_EP_ORPHAN; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 239 | if (cs->si && cs->si->wait_event.events != 0) |
| 240 | conn->mux->unsubscribe(cs, cs->si->wait_event.events, &cs->si->wait_event); |
| 241 | conn->mux->detach(cs); |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 242 | cs->endp = NULL; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 243 | } |
| 244 | else { |
| 245 | /* It's too early to have a mux, let's just destroy |
| 246 | * the connection |
| 247 | */ |
| 248 | conn_stop_tracking(conn); |
| 249 | conn_full_close(conn); |
| 250 | if (conn->destroy_cb) |
| 251 | conn->destroy_cb(conn); |
| 252 | conn_free(conn); |
| 253 | } |
| 254 | } |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 255 | else if (cs->endp->flags & CS_EP_T_APPLET) { |
| 256 | struct appctx *appctx = cs_appctx(cs); |
| 257 | |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 258 | cs->endp->flags |= CS_EP_ORPHAN; |
Christopher Faulet | 9affa93 | 2022-03-15 11:29:59 +0100 | [diff] [blame] | 259 | if (cs->si) |
| 260 | si_applet_release(cs->si); |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 261 | appctx_free(appctx); |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 262 | cs->endp = NULL; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 263 | } |
| 264 | |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 265 | if (cs->endp) { |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 266 | /* the cs is the only one one the endpoint */ |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 267 | cs_endpoint_init(cs->endp); |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 268 | cs->endp->flags |= CS_EP_DETACHED; |
Christopher Faulet | db90f2a | 2022-03-22 16:06:25 +0100 | [diff] [blame] | 269 | } |
| 270 | |
Christopher Faulet | b041b23 | 2022-03-24 10:27:02 +0100 | [diff] [blame] | 271 | reset_cs: |
Christopher Faulet | c36de9d | 2022-01-06 08:44:58 +0100 | [diff] [blame] | 272 | /* FIXME: Rest CS for now but must be reviewed. CS flags are only |
| 273 | * connection related for now but this will evolved |
| 274 | */ |
Christopher Faulet | 3099511 | 2022-03-25 15:32:38 +0100 | [diff] [blame] | 275 | cs->flags &= CS_FL_ISBACK; |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 276 | if (cs->si) |
| 277 | cs->si->ops = &si_embedded_ops; |
| 278 | cs->data_cb = NULL; |
Christopher Faulet | c36de9d | 2022-01-06 08:44:58 +0100 | [diff] [blame] | 279 | |
| 280 | if (cs->app == NULL) |
| 281 | cs_free(cs); |
| 282 | } |
| 283 | |
| 284 | void cs_detach_app(struct conn_stream *cs) |
| 285 | { |
| 286 | si_free(cs->si); |
| 287 | cs->app = NULL; |
| 288 | cs->si = NULL; |
| 289 | cs->data_cb = NULL; |
Christopher Faulet | 8da67aa | 2022-03-29 17:53:09 +0200 | [diff] [blame] | 290 | sockaddr_free(&cs->src); |
| 291 | sockaddr_free(&cs->dst); |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 292 | if (!cs->endp || (cs->endp->flags & CS_EP_DETACHED)) |
Christopher Faulet | c36de9d | 2022-01-06 08:44:58 +0100 | [diff] [blame] | 293 | cs_free(cs); |
Christopher Faulet | cda94ac | 2021-12-23 17:28:17 +0100 | [diff] [blame] | 294 | } |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 295 | |
| 296 | int cs_reset_endp(struct conn_stream *cs) |
| 297 | { |
Christopher Faulet | b041b23 | 2022-03-24 10:27:02 +0100 | [diff] [blame] | 298 | struct cs_endpoint *new_endp; |
| 299 | |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 300 | BUG_ON(!cs->app); |
Christopher Faulet | b041b23 | 2022-03-24 10:27:02 +0100 | [diff] [blame] | 301 | if (!__cs_endp_target(cs)) { |
| 302 | /* endpoint not attached or attached to a mux with no |
| 303 | * target. Thus the endpoint will not be release but just |
| 304 | * reset |
| 305 | */ |
| 306 | cs_detach_endp(cs); |
| 307 | return 0; |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 308 | } |
Christopher Faulet | b041b23 | 2022-03-24 10:27:02 +0100 | [diff] [blame] | 309 | |
| 310 | /* allocate the new endpoint first to be able to set error if it |
| 311 | * fails */ |
| 312 | new_endp = cs_endpoint_new(); |
| 313 | if (!unlikely(new_endp)) { |
| 314 | cs->endp->flags |= CS_EP_ERROR; |
| 315 | return -1; |
| 316 | } |
| 317 | |
| 318 | cs_detach_endp(cs); |
| 319 | BUG_ON(cs->endp); |
| 320 | cs->endp = new_endp; |
| 321 | cs->endp->flags |= CS_EP_DETACHED; |
Christopher Faulet | 9ec2f4d | 2022-03-23 15:15:29 +0100 | [diff] [blame] | 322 | return 0; |
| 323 | } |