1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef LIB_FIDL_BIND_H_
6 #define LIB_FIDL_BIND_H_
7 
8 #include <lib/async/dispatcher.h>
9 #include <zircon/fidl.h>
10 
11 __BEGIN_CDECLS
12 
13 // A generic FIDL dispatch function.
14 //
15 // For FIDL interfaces with [Layout="Simple"], the C backend generates a
16 // dispatch function that decodes the |msg| and calls through an |ops| table.
17 //
18 // This function signature matches the structure of these generated functions
19 // but with the type of the |ops| table erased.
20 //
21 // Example:
22 //
23 //  fidl_bind(dispacher, channel, (fidl_dispatch_t*)spaceship_SpaceShip_dispatch, ctx, &kOps);
24 //
25 typedef zx_status_t(fidl_dispatch_t)(void* ctx, fidl_txn_t* txn,
26                                      fidl_msg_t* msg, const void* ops);
27 
28 // Binds a |dispatch| function to channel| using |dispatcher|.
29 //
30 // This function adds an |async_wait_t| to the given |dispatcher| that waits
31 // asynchronously for new messages to arrive on |channel|. When a message
32 // arrives, the |dispatch| function is called on one of the threads associated
33 // with the |dispatcher| with the |fidl_msg_t| as well as the given |ctx| and
34 // |ops|.
35 //
36 // Typically, the |dispatch| function is generated by the C backend for FIDL
37 // interfaces with with [Layout="Simple"] (see |fidl_dispatch_t|). These
38 // dispatch functions decode the |fidl_msg_t| and call through the |ops| table
39 // implementations of the interface's methods, passing along the |ctx| and a
40 // |fidl_txn_t| (if the method has a reply message).
41 //
42 // The |fidl_txn_t| passed to |dispatch| is valid only until |dispatch| returns.
43 // If the method has a reply message, the |reply| function on the |fidl_txn_t|
44 // object must be called synchronously within the |dispatch| call.
45 //
46 // If a client wishes to reply to the message asynchronously, |fidl_async_txn_create|
47 // must be invoked on |fidl_txn_t|, and ZX_ERR_ASYNC must be returned.
48 //
49 // Returns whether |fidl_bind| was able to begin waiting on the given |channel|.
50 // Upon any error, |channel| is closed and the binding is terminated. Shutting down
51 // the |dispatcher| also results in |channel| being closed.
52 //
53 // It is safe to shutdown the dispatcher at any time.
54 //
55 // It is unsafe to destroy the dispatcher from within a dispatch function.
56 // It is unsafe to destroy the dispatcher while any |fidl_async_txn_t| objects
57 // are alive.
58 zx_status_t fidl_bind(async_dispatcher_t* dispatcher, zx_handle_t channel,
59                       fidl_dispatch_t* dispatch, void* ctx, const void* ops);
60 
61 // An asynchronous FIDL txn.
62 //
63 // This is an opaque wrapper around |fidl_txn_t| which can extend the lifetime
64 // of the object beyond the dispatched function.
65 typedef struct fidl_async_txn fidl_async_txn_t;
66 
67 // Takes ownership of |txn| and allows usage of the txn beyond the currently
68 // dispatched function.
69 //
70 // If this function is invoked within a dispatched function, that function
71 // must return ZX_ERR_ASYNC.
72 //
73 // The result must be destroyed with a call to |fidl_async_txn_complete|.
74 fidl_async_txn_t* fidl_async_txn_create(fidl_txn_t* txn);
75 
76 // Acquire a reference to the |fidl_txn_t| backing this txn object.
77 //
78 // It is unsafe to use this |fidl_txn_t| after |async_txn| is completed.
79 fidl_txn_t* fidl_async_txn_borrow(fidl_async_txn_t* async_txn);
80 
81 // Destroys an asynchronous transaction created with |fidl_async_txn_create|.
82 //
83 // If requested, rebinds the underlying txn against the binding.
84 // Returns an error if |rebind| is true and the transaction could not be
85 // re-bound.
86 //
87 // In all cases, the |async_txn| object is consumed.
88 zx_status_t fidl_async_txn_complete(fidl_async_txn_t* async_txn, bool rebind);
89 
90 __END_CDECLS
91 
92 #endif // LIB_FIDL_BIND_H_
93