blob: 2cfcdf39ddf17dba4d1c7c5034ca2eff43ae8352 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "guacamole/mem.h"
#include "guacamole/client.h"
#include "guacamole/error.h"
#include "guacamole/file.h"
#include "guacamole/protocol.h"
#include "guacamole/recording.h"
#include "guacamole/socket.h"
#include "guacamole/timestamp.h"
#ifdef __MINGW32__
#include <direct.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
guac_recording* guac_recording_create(guac_client* client,
const char* path, const char* name, int create_path,
int include_output, int include_mouse, int include_touch,
int include_keys, int allow_write_existing) {
char filename[GUAC_COMMON_RECORDING_MAX_NAME_LENGTH];
guac_open_how how = {
.oflags = O_CREAT | O_WRONLY,
.mode = S_IRUSR | S_IWUSR | S_IRGRP,
.filename = filename,
.filename_size = sizeof(filename),
.flags = GUAC_O_LOCKED
};
if (create_path)
how.flags |= GUAC_O_CREATE_PATH;
if (!allow_write_existing)
how.flags |= GUAC_O_UNIQUE_SUFFIX;
/* Attempt to open recording file */
int fd = guac_openat(path, name, &how);
if (fd == -1) {
guac_client_log(client, GUAC_LOG_ERROR, "Creation of recording "
"failed: %s: %s", guac_error_message,
guac_status_string(guac_error));
return NULL;
}
/* Create recording structure with reference to underlying socket */
guac_recording* recording = guac_mem_alloc(sizeof(guac_recording));
recording->socket = guac_socket_open(fd);
recording->include_output = include_output;
recording->include_mouse = include_mouse;
recording->include_touch = include_touch;
recording->include_keys = include_keys;
/* Replace client socket with wrapped recording socket only if including
* output within the recording */
if (include_output)
client->socket = guac_socket_tee(client->socket, recording->socket);
/* Recording creation succeeded */
guac_client_log(client, GUAC_LOG_INFO, "Recording of session will be "
"saved within \"%s\" as \"%s\".", path, filename);
return recording;
}
void guac_recording_free(guac_recording* recording) {
/* If not including broadcast output, the output socket is not associated
* with the client, and must be freed manually */
if (!recording->include_output)
guac_socket_free(recording->socket);
/* Free recording itself */
guac_mem_free(recording);
}
void guac_recording_report_mouse(guac_recording* recording,
int x, int y, int button_mask) {
/* Report mouse location only if recording should contain mouse events */
if (recording->include_mouse)
guac_protocol_send_mouse(recording->socket, x, y, button_mask,
guac_timestamp_current());
}
void guac_recording_report_touch(guac_recording* recording,
int id, int x, int y, int x_radius, int y_radius,
double angle, double force) {
/* Report touches only if recording should contain touch events */
if (recording->include_touch)
guac_protocol_send_touch(recording->socket, id, x, y,
x_radius, y_radius, angle, force, guac_timestamp_current());
}
void guac_recording_report_key(guac_recording* recording,
int keysym, int pressed) {
/* Report key state only if recording should contain key events */
if (recording->include_keys)
guac_protocol_send_key(recording->socket, keysym, pressed,
guac_timestamp_current());
}