a49c3b12e87a520040b2e17afb036c11119c6786
[asterisk/asterisk.git] / res / ari / resource_recordings.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012 - 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief /api-docs/recordings.{format} implementation- Recording resources
22  *
23  * \author David M. Lee, II <dlee@digium.com>
24  */
25
26 /*** MODULEINFO
27         <depend type="module">res_stasis_recording</depend>
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_REGISTER_FILE()
34
35 #include "asterisk/stasis_app_recording.h"
36 #include "resource_recordings.h"
37
38 void ast_ari_recordings_list_stored(struct ast_variable *headers,
39         struct ast_ari_recordings_list_stored_args *args,
40         struct ast_ari_response *response)
41 {
42         RAII_VAR(struct ao2_container *, recordings, NULL, ao2_cleanup);
43         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
44         struct ao2_iterator i;
45         void *obj;
46
47         recordings = stasis_app_stored_recording_find_all();
48
49         if (!recordings) {
50                 ast_ari_response_alloc_failed(response);
51                 return;
52         }
53
54         json = ast_json_array_create();
55         if (!json) {
56                 ast_ari_response_alloc_failed(response);
57                 return;
58         }
59
60         i = ao2_iterator_init(recordings, 0);
61         while ((obj = ao2_iterator_next(&i))) {
62                 RAII_VAR(struct stasis_app_stored_recording *, recording, obj,
63                         ao2_cleanup);
64
65                 int r = ast_json_array_append(
66                         json, stasis_app_stored_recording_to_json(recording));
67                 if (r != 0) {
68                         ast_ari_response_alloc_failed(response);
69                         ao2_iterator_destroy(&i);
70                         return;
71                 }
72         }
73         ao2_iterator_destroy(&i);
74
75         ast_ari_response_ok(response, ast_json_ref(json));
76 }
77
78 void ast_ari_recordings_get_stored(struct ast_variable *headers,
79         struct ast_ari_recordings_get_stored_args *args,
80         struct ast_ari_response *response)
81 {
82         RAII_VAR(struct stasis_app_stored_recording *, recording, NULL,
83                 ao2_cleanup);
84         struct ast_json *json;
85
86         recording = stasis_app_stored_recording_find_by_name(
87                 args->recording_name);
88         if (recording == NULL) {
89                 ast_ari_response_error(response, 404, "Not Found",
90                         "Recording not found");
91                 return;
92         }
93
94         json = stasis_app_stored_recording_to_json(recording);
95         if (json == NULL) {
96                 ast_ari_response_error(response, 500,
97                         "Internal Server Error", "Error building response");
98                 return;
99         }
100
101         ast_ari_response_ok(response, json);
102 }
103
104 void ast_ari_recordings_copy_stored(struct ast_variable *headers,
105         struct ast_ari_recordings_copy_stored_args *args,
106         struct ast_ari_response *response)
107 {
108         RAII_VAR(struct stasis_app_stored_recording *, src_recording, NULL,
109                 ao2_cleanup);
110         RAII_VAR(struct stasis_app_stored_recording *, dst_recording, NULL,
111                 ao2_cleanup);
112         struct ast_json *json;
113         int res;
114
115         src_recording = stasis_app_stored_recording_find_by_name(
116                 args->recording_name);
117         if (src_recording == NULL) {
118                 ast_ari_response_error(response, 404, "Not Found",
119                         "Recording not found");
120                 return;
121         }
122
123         dst_recording = stasis_app_stored_recording_find_by_name(
124                 args->destination_recording_name);
125         if (dst_recording) {
126                 ast_ari_response_error(response, 409, "Conflict",
127                         "A recording with the same name already exists on the system");
128                 return;
129         }
130
131         /* See if we got our name rejected */
132         switch (errno) {
133         case EINVAL:
134                 ast_ari_response_error(response, 400, "Bad request",
135                         "Invalid destination recording name");
136                 return;
137         case EACCES:
138                 ast_ari_response_error(response, 403, "Forbidden",
139                         "Destination file path is forbidden");
140                 return;
141         default:
142                 break;
143         }
144
145         res = stasis_app_stored_recording_copy(src_recording,
146                 args->destination_recording_name, &dst_recording);
147         if (res) {
148                 switch (errno) {
149                 case EACCES:
150                 case EPERM:
151                         ast_ari_response_error(response, 500,
152                                 "Internal Server Error",
153                                 "Copy failed");
154                         break;
155                 default:
156                         ast_log(LOG_WARNING,
157                                 "Unexpected error copying recording %s to %s: %s\n",
158                                 args->recording_name, args->destination_recording_name, strerror(errno));
159                         ast_ari_response_error(response, 500,
160                                 "Internal Server Error",
161                                 "Copy failed");
162                         break;
163                 }
164                 return;
165         }
166
167         json = stasis_app_stored_recording_to_json(dst_recording);
168         if (json == NULL) {
169                 ast_ari_response_error(response, 500,
170                         "Internal Server Error", "Error building response");
171                 return;
172         }
173
174         ast_ari_response_ok(response, json);
175 }
176
177 void ast_ari_recordings_delete_stored(struct ast_variable *headers,
178         struct ast_ari_recordings_delete_stored_args *args,
179         struct ast_ari_response *response)
180 {
181         RAII_VAR(struct stasis_app_stored_recording *, recording, NULL,
182                 ao2_cleanup);
183         int res;
184
185         recording = stasis_app_stored_recording_find_by_name(
186                 args->recording_name);
187         if (recording == NULL) {
188                 ast_ari_response_error(response, 404, "Not Found",
189                         "Recording not found");
190                 return;
191         }
192
193         res = stasis_app_stored_recording_delete(recording);
194
195         if (res != 0) {
196                 switch (errno) {
197                 case EACCES:
198                 case EPERM:
199                         ast_ari_response_error(response, 500,
200                                 "Internal Server Error",
201                                 "Delete failed");
202                         break;
203                 default:
204                         ast_log(LOG_WARNING,
205                                 "Unexpected error deleting recording %s: %s\n",
206                                 args->recording_name, strerror(errno));
207                         ast_ari_response_error(response, 500,
208                                 "Internal Server Error",
209                                 "Delete failed");
210                         break;
211                 }
212                 return;
213         }
214
215         ast_ari_response_no_content(response);
216 }
217
218 void ast_ari_recordings_get_live(struct ast_variable *headers,
219         struct ast_ari_recordings_get_live_args *args,
220         struct ast_ari_response *response)
221 {
222         RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
223         struct ast_json *json;
224
225         recording = stasis_app_recording_find_by_name(args->recording_name);
226         if (recording == NULL) {
227                 ast_ari_response_error(response, 404, "Not Found",
228                         "Recording not found");
229                 return;
230         }
231
232         json = stasis_app_recording_to_json(recording);
233         if (json == NULL) {
234                 ast_ari_response_error(response, 500,
235                         "Internal Server Error", "Error building response");
236                 return;
237         }
238
239         ast_ari_response_ok(response, json);
240 }
241
242 static void control_recording(const char *name,
243         enum stasis_app_recording_media_operation operation,
244         struct ast_ari_response *response)
245 {
246         RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
247         enum stasis_app_recording_oper_results res;
248
249         recording = stasis_app_recording_find_by_name(name);
250         if (recording == NULL) {
251                 ast_ari_response_error(response, 404, "Not Found",
252                         "Recording not found");
253                 return;
254         }
255
256         res = stasis_app_recording_operation(recording, operation);
257
258         switch (res) {
259         case STASIS_APP_RECORDING_OPER_OK:
260                 ast_ari_response_no_content(response);
261                 return;
262         case STASIS_APP_RECORDING_OPER_FAILED:
263                 ast_ari_response_error(response, 500,
264                         "Internal Server Error", "Recording operation failed");
265                 return;
266         case STASIS_APP_RECORDING_OPER_NOT_RECORDING:
267                 ast_ari_response_error(response, 409,
268                         "Conflict", "Recording not in session");
269         }
270 }
271
272 void ast_ari_recordings_cancel(struct ast_variable *headers,
273         struct ast_ari_recordings_cancel_args *args,
274         struct ast_ari_response *response)
275 {
276         control_recording(args->recording_name, STASIS_APP_RECORDING_CANCEL,
277                 response);
278 }
279
280 void ast_ari_recordings_stop(struct ast_variable *headers,
281         struct ast_ari_recordings_stop_args *args,
282         struct ast_ari_response *response)
283 {
284         control_recording(args->recording_name, STASIS_APP_RECORDING_STOP,
285                 response);
286 }
287
288 void ast_ari_recordings_pause(struct ast_variable *headers,
289         struct ast_ari_recordings_pause_args *args,
290         struct ast_ari_response *response)
291 {
292         control_recording(args->recording_name, STASIS_APP_RECORDING_PAUSE,
293                 response);
294 }
295
296 void ast_ari_recordings_unpause(struct ast_variable *headers,
297         struct ast_ari_recordings_unpause_args *args,
298         struct ast_ari_response *response)
299 {
300         control_recording(args->recording_name, STASIS_APP_RECORDING_UNPAUSE,
301                 response);
302 }
303
304 void ast_ari_recordings_mute(struct ast_variable *headers,
305         struct ast_ari_recordings_mute_args *args,
306         struct ast_ari_response *response)
307 {
308         control_recording(args->recording_name, STASIS_APP_RECORDING_MUTE,
309                 response);
310 }
311
312 void ast_ari_recordings_unmute(struct ast_variable *headers,
313         struct ast_ari_recordings_unmute_args *args,
314         struct ast_ari_response *response)
315 {
316         control_recording(args->recording_name, STASIS_APP_RECORDING_UNMUTE,
317                 response);
318 }