1 /*
2  * uhub - A tiny ADC p2p connection hub
3  * Copyright (C) 2007-2014, Jan Vidar Krey
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef HAVE_UHUB_COMMAND_H
21 #define HAVE_UHUB_COMMAND_H
22 
23 struct hub_user;
24 
25 struct adc_message
26 {
27 	fourcc_t cmd;
28 	sid_t source;
29 	sid_t target;
30 	char* cache;
31 	size_t length;
32 	size_t capacity;
33 	size_t priority;
34 	size_t references;
35 	struct linked_list*  feature_cast_include;
36 	struct linked_list*  feature_cast_exclude;
37 };
38 
39 enum msg_status_level
40 {
41 	status_level_info  = 0, /* Success/informative status message */
42 	status_level_error = 1, /* Recoverable error */
43 	status_level_fatal = 2, /* Fatal error (disconnect) */
44 };
45 
46 /**
47  * Increase the reference counter for an ADC message struct.
48  * NOTE: Always use the returned value, and not the passed value, as
49  * it ensures we can actually copy the value if needed.
50  */
51 extern struct adc_message* adc_msg_incref(struct adc_message* msg);
52 
53 /**
54  * Decrease the reference counter, and free the memory when apropriate.
55  */
56 extern void adc_msg_free(struct adc_message* msg);
57 
58 /**
59  * Perform deep copy a command.
60  * NOTE: 'references' will be zero for the copied command.
61  * @return a copy of cmd or NULL if not able to allocate memory.
62  */
63 extern struct adc_message* adc_msg_copy(const struct adc_message* cmd);
64 
65 /**
66  * This will parse 'string' and return it as a adc_message struct, or
67  * NULL if not able to allocate memory or 'string' does not contain
68  * a valid ADC command.
69  *
70  * The message is only considered valid if the user who sent it
71  * is the rightful origin of the message.
72  */
73 extern struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* string, size_t length);
74 
75 /**
76  * This will parse 'string' and return it as a adc_message struct, or
77  * NULL if not able to allocate memory or 'string' does not contain
78  * a valid ADC command.
79  */
80 extern struct adc_message* adc_msg_parse(const char* string, size_t length);
81 
82 /**
83  * This will construct a adc_message based on 'string'.
84  * Only to be used for server generated commands.
85  */
86 extern struct adc_message* adc_msg_create(const char* string);
87 
88 /**
89  * Construct a message with the given 'fourcc' and allocate
90  * 'size' bytes for later use.
91  */
92 extern struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size);
93 
94 /**
95  * Construct a message for the given 'fourcc' and add a source SID to it,
96  * in addition pre-allocate 'size' bytes at the end of the message.
97  */
98 extern struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size);
99 extern struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, size_t size);
100 
101 /**
102  * Remove a named argument from the command.
103  *
104  * @arg prefix a 2 character argument prefix
105  * @return the number of named arguments removed.
106  */
107 extern int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix[2]);
108 
109 /**
110  * Count the number of arguments matching the given 2 character prefix.
111  *
112  * @arg prefix a 2 character argument prefix
113  * @return the number of matching arguments
114  */
115 extern int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix[2]);
116 
117 /**
118  * Returns a named arguments based on the 2 character prefix.
119  * If multiple matching arguments exists, only the first one will be returned
120  * by this function.
121  *
122  * NOTE: Returned memory must be free'd with hub_free().
123  *
124  * @arg prefix a 2 character argument prefix
125  * @return the argument or NULL if OOM/not found.
126  */
127 extern char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix[2]);
128 
129 /**
130  * Returns a offset of an argument based on the 2 character prefix.
131  * If multiple matching arguments exists, only the first one will be returned
132  * by this function.
133  *
134  * @arg prefix a 2 character argument prefix
135  * @return the offset or -1 if the argument is not found.
136  */
137 extern int adc_msg_get_named_argument_index(struct adc_message* cmd, const char prefix[2]);
138 
139 /**
140  * @param cmd command to be checked
141  * @return 1 if the command does not have any arguments (parameters), 0 otherwise, -1 if cmd is invalid.
142  */
143 extern int adc_msg_is_empty(struct adc_message* cmd);
144 
145 /**
146  * Returns the argument on the offset position in the command.
147  * If offset is invalid NULL is returned.
148  *
149  * NOTE: Returned memory must be free'd with hub_free().
150  *
151  * @return the argument or NULL if OOM/not found.
152  */
153 extern char* adc_msg_get_argument(struct adc_message* cmd, int offset);
154 
155 /**
156  * Replace a named argument in the command.
157  * This will remove any matching arguments (multiple, or none),
158  * then add 'string' as an argument using the given prefix.
159  *
160  * @arg prefix a 2 character argument prefix
161  * @arg string must be escaped (see adc_msg_escape).
162  * @return  0 if successful, or -1 if an error occured.
163  */
164 extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
165 
166 /**
167  * Append an argument
168  *
169  * @arg string must be escaped (see adc_msg_escape).
170  * @return  0 if successful, or -1 if an error occured (out of memory).
171  */
172 extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
173 
174 /**
175  * Append a named argument
176  *
177  * @arg prefix a 2 character argument prefix
178  * @arg string must be escaped (see adc_msg_escape).
179  * @return  0 if successful, or -1 if an error occured (out of memory).
180  */
181 extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
182 
183 /**
184  * Append a string as a named argument.
185  * The string will automatcally be escaped, if you do not wish to escape th string use adc_msg_add_named_argument() instead.
186  *
187  * @arg prefix a 2 character argument prefix
188  * @arg string must NOT be escaped
189  * @return  0 if successful, or -1 if an error occured (out of memory).
190  */
191 extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
192 
193 /**
194  * Append an integer as a named argument.
195  */
196 extern int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int integer);
197 extern int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num);
198 
199 /**
200  * Convert a ADC command escaped string to a regular string.
201  * @return string or NULL if out of memory
202  */
203 extern char* adc_msg_unescape(const char* string);
204 
205 /**
206  * Convert a ADC command escaped string to a regular string.
207  * @return The number of bytes written to target. If the target is not large enough then
208  * the -1 is returned, but the string is guaranteed to always be \0 terminated.
209  */
210 extern int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size);
211 
212 
213 /**
214  * Convert a string to a ADC command escaped string.
215  * @return adc command escaped string or NULL if out of memory.
216  */
217 extern char* adc_msg_escape(const char* string);
218 
219 /**
220  * This will ensure a newline is at the end of the command.
221  */
222 void adc_msg_terminate(struct adc_message* cmd);
223 
224 /**
225  * This will remove any newline from the end of the command
226  */
227 void adc_msg_unterminate(struct adc_message* cmd);
228 
229 /**
230  * @return the offset for the first command argument in msg->cache.
231  * or -1 if the command is not understood.
232  * NOTE: for 'U' and 'C' commands (normally not seen by hubs),
233  * this returns 4. Should be 4 + lengthOf(cid).
234  */
235 int adc_msg_get_arg_offset(struct adc_message* msg);
236 
237 #endif /* HAVE_UHUB_COMMAND_H */
238