1 /*
2  * Copyright © 2019 Manuel Stoeckl
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 #ifndef WAYPIPE_PARSING_H
26 #define WAYPIPE_PARSING_H
27 
28 #include <stdbool.h>
29 #include <stdint.h>
30 
31 struct char_window;
32 struct int_window;
33 struct fd_translation_map;
34 struct main_config;
35 
36 struct wp_interface;
37 /** An object used by the wayland protocol. Specific types may extend
38  * this struct, using the following data as a header */
39 struct wp_object {
40 	struct wp_object *t_left, *t_right; // inline tree implementation
41 	const struct wp_interface *type;    // Use to lookup the message handler
42 	uint32_t obj_id;
43 	bool is_zombie; // object deleted but not yet acknowledged remotely
44 };
45 struct message_tracker {
46 	/* Tree containing all objects that are currently alive or zombie */
47 	struct wp_object *objtree_root;
48 	/* sequence number to discriminate between wl_buffer objects; object ids
49 	 * and pointers are not guaranteed to be unique */
50 	uint64_t buffer_seqno;
51 };
52 /** Context object, to be passed to the protocol handler functions */
53 struct context {
54 	struct globals *const g;
55 	struct message_tracker *const tracker;
56 	struct wp_object *obj;
57 	bool drop_this_msg;
58 	/* If true, running as waypipe client, and interfacing with compositor's
59 	 * buffers */
60 	const bool on_display_side;
61 	/* The transferred message can be rewritten in place, and resized, as
62 	 * long as there is space available. Setting 'fds_changed' will
63 	 * prevent the fd zone start from autoincrementing after running
64 	 * the function, which may be useful when injecting messages with fds */
65 	const int message_available_space;
66 	uint32_t *const message;
67 	int message_length;
68 	bool fds_changed;
69 	struct int_window *const fds;
70 };
71 
72 /** Add a protocol object to the list, replacing any preceding object with
73  * the same id. */
74 void tracker_insert(struct message_tracker *mt, struct wp_object *obj);
75 void tracker_remove(struct message_tracker *mt, struct wp_object *obj);
76 /** Replace an object that is already in the protocol list with a new object
77  * that has the same id; will silently fail if id not present */
78 void tracker_replace_existing(
79 		struct message_tracker *mt, struct wp_object *obj);
80 struct wp_object *tracker_get(struct message_tracker *mt, uint32_t id);
81 
82 int init_message_tracker(struct message_tracker *mt);
83 void cleanup_message_tracker(struct message_tracker *mt);
84 
85 /** Read message size from header; the 8 bytes beyond data must exist */
86 int peek_message_size(const void *data);
87 const char *get_nth_packed_string(const char *pack, int n);
88 enum parse_state { PARSE_KNOWN, PARSE_UNKNOWN, PARSE_ERROR };
89 /**
90  * The return value is false iff the given message should be dropped.
91  * The flag `unidentified_changes` is set to true if the message does
92  * not correspond to a known protocol.
93  *
94  * The message data payload may be modified and increased in size.
95  *
96  * The window `chars` should start at the message start, end
97  * at its end, and indicate remaining space.
98  * The window `fds` should start at the next fd in the queue, ends
99  * with the last.
100  *
101  * The start and end of `chars` will be moved to the new end of the message.
102  * The end of `fds` may be moved if any fds are inserted or discarded.
103  * The start of fds will be moved, depending on how many fds were consumed.
104  */
105 enum parse_state handle_message(struct globals *g, bool on_display_side,
106 		bool from_client, struct char_window *chars,
107 		struct int_window *fds);
108 /**
109  * Given a set of messages and fds, parse the messages, and if indicated
110  * by parsing logic, compact the message buffer by removing selected
111  * messages, or edit message contents.
112  *
113  * The `source_bytes` window indicates the range of unread data; it's
114  * zone start point will be advanced. The 'dest_bytes' window indicates
115  * the range of written data; it's zone end point will be advanced.
116  *
117  * The file descriptor queue `fds` will have its start advanced, leaving only
118  * file descriptors that have not yet been read. Further edits may be made
119  * to inject new file descriptors.
120  */
121 void parse_and_prune_messages(struct globals *g, bool on_display_side,
122 		bool from_client, struct char_window *source_bytes,
123 		struct char_window *dest_bytes, struct int_window *fds);
124 
125 // handlers.c
126 /** Create a new Wayland protocol object of the given type; some types
127  * produce structs extending from wp_object */
128 struct wp_object *create_wp_object(
129 		uint32_t it, const struct wp_interface *type);
130 /** Type-specific destruction routines, also dereferencing linked shadow_fds */
131 void destroy_wp_object(struct wp_object *object);
132 
133 extern const struct wp_interface *the_display_interface;
134 
135 #endif // WAYPIPE_PARSING_H
136