+struct tsocket_context {
+ const char *location;
+ const struct tsocket_context_ops *ops;
+ void *private_data;
+};
+
+struct tsocket_context *_tsocket_context_create(TALLOC_CTX *mem_ctx,
+ const struct tsocket_context_ops *ops,
+ void *pstate,
+ size_t psize,
+ const char *type,
+ const char *location)
+{
+ struct tsocket_context *sock;
+ void **ppstate = (void **)pstate;
+ void *state;
+
+ sock = talloc(mem_ctx, struct tsocket_context);
+ if (sock == NULL) {
+ return NULL;
+ }
+ sock->location = location;
+ sock->ops = ops;
+
+ state = talloc_size(sock, psize);
+ if (state == NULL) {
+ talloc_free(sock);
+ return NULL;
+ }
+ talloc_set_name_const(state, type);
+
+ sock->private_data = state;
+
+ *ppstate = state;
+ return sock;
+}
+
+void *_tsocket_context_data(struct tsocket_context *sock)
+{
+ return sock->private_data;
+}
+
+struct tsocket_accept_state {
+ const struct tsocket_context_ops *ops;
+ struct tsocket_address *local;
+ struct tsocket_address *remote;
+ struct tstream_context *stream;
+};
+
+static void tsocket_accept_done(struct tevent_req *subreq);
+
+struct tevent_req *tsocket_accept_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tsocket_context *sock)
+{
+ struct tevent_req *req;
+ struct tsocket_accept_state *state;
+ struct tevent_req *subreq;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct tsocket_accept_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->ops = sock->ops;
+ state->local = NULL;
+ state->remote = NULL;
+ state->stream = NULL;
+
+ subreq = state->ops->accept_send(state, ev, sock);
+ if (tevent_req_nomem(subreq, req)) {
+ goto post;
+ }
+ tevent_req_set_callback(subreq, tsocket_accept_done, req);
+
+ return req;
+
+ post:
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void tsocket_accept_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct tsocket_accept_state *state = tevent_req_data(req,
+ struct tsocket_accept_state);
+ ssize_t ret;
+ int sys_errno;
+
+ ret = state->ops->accept_recv(subreq, &sys_errno,
+ state,
+ &state->local,
+ &state->remote,
+ &state->stream,
+ "tsocket_accept_done");
+ if (ret == -1) {
+ tevent_req_error(req, sys_errno);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int _tsocket_accept_recv(struct tevent_req *req,
+ int *perrno,
+ TALLOC_CTX *mem_ctx,
+ struct tsocket_address **local,
+ struct tsocket_address **remote,
+ struct tstream_context **stream,
+ const char *location)
+{
+ struct tsocket_accept_state *state = tevent_req_data(req,
+ struct tsocket_accept_state);
+ int ret;
+
+ ret = tsocket_simple_int_recv(req, perrno);
+ if (ret == 0) {
+ if (local) {
+ state->local->location = location;
+ *local = talloc_move(mem_ctx, &state->local);
+ }
+ if (remote) {
+ state->remote->location = location;
+ *remote = talloc_move(mem_ctx, &state->remote);
+ }
+ state->stream->location = location;
+ *stream = talloc_move(mem_ctx, &state->stream);
+ }
+
+ tevent_req_received(req);
+ return ret;
+}
+
+struct tsocket_shutdown_state {
+ const struct tsocket_context_ops *ops;
+};
+
+static void tsocket_shutdown_done(struct tevent_req *subreq);
+
+struct tevent_req *tsocket_shutdown_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tsocket_context *sock)
+{
+ struct tevent_req *req;
+ struct tsocket_shutdown_state *state;
+ struct tevent_req *subreq;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct tsocket_shutdown_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->ops = sock->ops;
+
+ subreq = state->ops->shutdown_send(state, ev, sock);
+ if (tevent_req_nomem(subreq, req)) {
+ goto post;
+ }
+ tevent_req_set_callback(subreq, tsocket_shutdown_done, req);
+
+ return req;
+
+ post:
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void tsocket_shutdown_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct tsocket_shutdown_state *state = tevent_req_data(req,
+ struct tsocket_shutdown_state);
+ int ret;
+ int sys_errno;
+
+ ret = state->ops->shutdown_recv(subreq, &sys_errno);
+ if (ret == -1) {
+ tevent_req_error(req, sys_errno);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int tsocket_shutdown_recv(struct tevent_req *req,
+ int *perrno)
+{
+ int ret;
+
+ ret = tsocket_simple_int_recv(req, perrno);
+
+ tevent_req_received(req);
+ return ret;
+}
+