/** * Reads and handles all Guacamole instructions from the given guac_socket * until end-of-stream is reached. * * @param state * The current state of the Guacamole input log interpreter. * * @param path * The name of the file being parsed (for logging purposes). This file * must already be open and available through the given socket. * * @param socket * The guac_socket through which instructions should be read. * * @return * Zero on success, non-zero if parsing of Guacamole protocol data through * the given socket fails. */ static int guaclog_read_instructions(guaclog_state* state, const char* path, guac_socket* socket) { /* Obtain Guacamole protocol parser */ guac_parser* parser = guac_parser_alloc(); if (parser == NULL) return 1; /* Continuously read and handle all instructions */ while (!guac_parser_read(parser, socket, -1)) { guaclog_handle_instruction(state, parser->opcode, parser->argc, parser->argv); } /* Fail on read/parse error */ if (guac_error != GUAC_STATUS_CLOSED) { guaclog_log(GUAC_LOG_ERROR, "%s: %s", path, guac_status_string(guac_error)); guac_parser_free(parser); return 1; } /* Parse complete */ guac_parser_free(parser); return 0; }
void guacd_log_handshake_failure() { if (guac_error == GUAC_STATUS_CLOSED) guacd_log(GUAC_LOG_INFO, "Guacamole connection closed during handshake"); else if (guac_error == GUAC_STATUS_PROTOCOL_ERROR) guacd_log(GUAC_LOG_ERROR, "Guacamole protocol violation. Perhaps the version of " "guacamole-client is incompatible with this version of " "guacd?"); else guacd_log(GUAC_LOG_WARNING, "Guacamole handshake failed: %s", guac_status_string(guac_error)); }
/** * Prints an error message using the logging facilities of the given user, * automatically including any information present in guac_error. * * @param user * The guac_user associated with the error that occurred. * * @param level * The level at which to log this message. * * @param message * The message to log. */ static void guac_user_log_guac_error(guac_user* user, guac_client_log_level level, const char* message) { if (guac_error != GUAC_STATUS_SUCCESS) { /* If error message provided, include in log */ if (guac_error_message != NULL) guac_user_log(user, level, "%s: %s", message, guac_error_message); /* Otherwise just log with standard status string */ else guac_user_log(user, level, "%s: %s", message, guac_status_string(guac_error)); } /* Just log message if no status code */ else guac_user_log(user, level, "%s", message); }
int guaclog_interpret(const char* path, const char* out_path, bool force) { /* Open input file */ int fd = open(path, O_RDONLY); if (fd < 0) { guaclog_log(GUAC_LOG_ERROR, "%s: %s", path, strerror(errno)); return 1; } /* Lock entire input file for reading by the current process */ struct flock file_lock = { .l_type = F_RDLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, .l_pid = getpid() }; /* Abort if file cannot be locked for reading */ if (!force && fcntl(fd, F_SETLK, &file_lock) == -1) { /* Warn if lock cannot be acquired */ if (errno == EACCES || errno == EAGAIN) guaclog_log(GUAC_LOG_WARNING, "Refusing to interpret log of " "in-progress session \"%s\" (specify the -f option to " "override this behavior).", path); /* Log an error if locking fails in an unexpected way */ else guaclog_log(GUAC_LOG_ERROR, "Cannot lock \"%s\" for reading: %s", path, strerror(errno)); close(fd); return 1; } /* Allocate input state for interpreting process */ guaclog_state* state = guaclog_state_alloc(out_path); if (state == NULL) { close(fd); return 1; } /* Obtain guac_socket wrapping file descriptor */ guac_socket* socket = guac_socket_open(fd); if (socket == NULL) { guaclog_log(GUAC_LOG_ERROR, "%s: %s", path, guac_status_string(guac_error)); close(fd); guaclog_state_free(state); return 1; } guaclog_log(GUAC_LOG_INFO, "Writing input events from \"%s\" " "to \"%s\" ...", path, out_path); /* Attempt to read all instructions in the file */ if (guaclog_read_instructions(state, path, socket)) { guac_socket_free(socket); guaclog_state_free(state); return 1; } /* Close input and finish interpreting process */ guac_socket_free(socket); return guaclog_state_free(state); }