cake
/
libp7
Archived
1
0
Fork 1
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libp7/src/usage/server/classical.c

330 lines
9.1 KiB
C

/* *****************************************************************************
* usage/server/classical.c -- set up a classical protocol 7 server.
* Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libp7.
* libp7 is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libp7 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libp7; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libp7/internals.h>
#include <string.h>
/* ************************************************************************** */
/* Utilities */
/* ************************************************************************** */
/* cookie structure */
typedef struct {
p7_server_t *info;
p7_filesystem_t *filesystems;
} p7_server_cookie_t;
/* macros */
#define gather_fs() \
p7_filesystem_t *fs = find_filesystem(response.args[4], \
cookie->filesystems); \
if (!fs) return (p7_error_unknown);
#define gather_sdir() \
const char *sdir = response.args[0]; \
if (!sdir) sdir = fs->working_directory;
/**
* find_filesystem:
* Find a filesystem in a list.
*
* @arg name the name of the filesystem to look for.
* @arg filesystems the filesystems list (with terminating entry)
* @return the filesystem.
*/
static p7_filesystem_t *find_filesystem(const char *name,
p7_filesystem_t *filesystems)
{
while (filesystems->name) {
if (!strcmp(name, filesystems->name))
return (filesystems);
filesystems++;
}
return (NULL);
}
/* ************************************************************************** */
/* General callbacks */
/* ************************************************************************** */
/**
* send_server_info:
* Send the server information.
*
* @arg cookie the cookie.
* @arg handle the libp7 handle.
* @return the libp7 error.
*/
static int send_server_info(p7_server_cookie_t *cookie, p7_handle_t *handle)
{
return (p7_seven_send_eack(handle, cookie->info));
}
/* ************************************************************************** */
/* Backup-related callbacks */
/* ************************************************************************** */
/**
* backup_ram:
* Request a RAM image transfer.
*
* @arg cookie the cookie.
* @arg handle the libp7 handle.
* @return the libp7 error.
*/
static int backup_ram(p7_server_cookie_t *cookie, p7_handle_t *handle)
{
p7_server_t *info = cookie->info;
/* check that we have the RAM */
if (!info->ram) return (p7_error_unknown);
/* accept and roleswap */
int err = p7_seven_send_ack(handle, 1);
if (err) return (err);
if (response.type != p7_seven_type_swp)
return (p7_error_unknown);
/* send the command */
err = p7_seven_send_cmdbak_putram(handle);
if (err) return (err);
if (response.type == p7_seven_type_ack) {
/* send the thing */
err = p7_seven_send_data(handle, info->ram, info->ram_capacity,
0, NULL);
if (err) return (err);
}
/* re-swap roles */
return (p7_seven_send_swp(handle));
}
/**
* backup_rom:
* Request a ROM image transfer.
*
* @arg cookie the cookie.
* @arg handle the libp7 handle.
* @return the libp7 error.
*/
static int backup_rom(p7_server_cookie_t *cookie, p7_handle_t *handle)
{
p7_server_t *info = cookie->info;
/* check that we have the ROM */
if (!info->flash_rom) return (p7_error_unknown);
/* accept and roleswap */
int err = p7_seven_send_ack(handle, 1);
if (err) return (err);
if (response.type != p7_seven_type_swp)
return (p7_error_unknown);
/* send the command */
err = p7_seven_send_cmdbak_putrom(handle);
if (err) return (err);
if (response.type == p7_seven_type_ack) {
/* send the thing */
err = p7_seven_send_data(handle, info->flash_rom,
info->flash_rom_capacity, 0, NULL);
if (err) return (err);
}
/* re-swap roles */
return (p7_seven_send_swp(handle));
}
/**
* backup_boot:
* Request a bootcode transfer.
*
* @arg cookie the cookie.
* @arg handle the libp7 handle.
* @return the libp7 error.
*/
static int backup_boot(p7_server_cookie_t *cookie, p7_handle_t *handle)
{
p7_server_t *info = cookie->info;
/* check that we have the bootcode */
if (!info->bootcode) return (p7_error_unknown);
/* accept and roleswap */
int err = p7_seven_send_ack(handle, 1);
if (err) return (err);
if (response.type != p7_seven_type_swp)
return (p7_error_unknown);
/* send the command */
err = p7_seven_send_cmdbak_putboot(handle);
if (err) return (err);
if (response.type == p7_seven_type_ack) {
/* send the thing */
err = p7_seven_send_data(handle, info->bootcode, info->bootcode_size,
0, NULL);
if (err) return (err);
}
/* re-swap roles */
return (p7_seven_send_swp(handle));
}
/* ************************************************************************** */
/* Storage-related callbacks */
/* ************************************************************************** */
/**
* create_directory:
* Create a directory.
*
* @arg cookie the cookie.
* @arg handle the libp7 handle.
* @return the libp7 error.
*/
static int create_directory(p7_server_cookie_t *cookie, p7_handle_t *handle)
{
gather_fs()
gather_sdir()
/* create the directory */
if (!fs->create_directory || !sdir)
return (p7_error_unknown);
int err = (*fs->create_directory)(fs->cookie, sdir);
if (err) return (err);
/* send ack */
return (p7_seven_send_ack(handle, 1));
}
/**
* delete_directory:
* Delete a directory.
*
* @arg cookie the cookie.
* @arg handle the libp7 handle.
* @return the libp7 error.
*/
static int delete_directory(p7_server_cookie_t *cookie, p7_handle_t *handle)
{
gather_fs()
gather_sdir()
/* delete the directory */
if (!fs->delete_directory || !sdir)
return (p7_error_unknown);
int err = (*fs->delete_directory)(fs->cookie, sdir);
if (err) return (err);
/* send ack */
return (p7_seven_send_ack(handle, 1));
}
/**
* rename_directory:
* Rename a directory.
*
* @arg cookie the cookie.
* @arg handle the libp7 handle.
* @return the libp7 error.
*/
static int rename_directory(p7_server_cookie_t *cookie, p7_handle_t *handle)
{
gather_fs()
gather_sdir()
/* rename the directory */
if (!fs->rename_directory || !sdir || !response.args[1])
return (p7_error_unknown);
int err = (*fs->rename_directory)(fs->cookie, sdir, response.args[1]);
if (err) return (err);
/* send ack */
return (p7_seven_send_ack(handle, 1));
}
/**
* change_working_directory:
* Change the current working directory.
*
* @arg cookie the cookie.
* @arg handle the libp7 handle.
* @return the libp7 error.
*/
static int change_working_directory(p7_server_cookie_t *cookie,
p7_handle_t *handle)
{
gather_fs()
/* check and change working directory */
log_info("Changing directory to \"%s\"", response.args[0]);
if (!response.args[0])
fs->working_directory = NULL;
else if (fs->directory_exists
&& (*fs->directory_exists)(fs->cookie, response.args[0])) {
log_info("Directory does not exist, not changing!");
return (p7_error_unknown);
} else {
fs->working_directory = fs->_wd;
strncpy(fs->_wd, response.args[0], 256);
fs->_wd[256] = 0;
}
/* success! */
return (p7_seven_send_ack(handle, 1));
}
/* ************************************************************************** */
/* Main function */
/* ************************************************************************** */
/**
* p7_serve:
* Initialize a server.
*
* @arg handle the libp7 handle.
* @arg info the server information.
* @arg callbacks the server callbacks.
* @return the error code.
*/
int p7_serve(p7_handle_t *handle, p7_server_t *info,
p7_filesystem_t *filesystems)
{
/* make cookie and commands */
p7_server_cookie_t cookie = {
.info = info,
.filesystems = filesystems};
p7_server_callback_t callbacks[256] = {
/* main commands */
[p7_seven_cmdsys_getinfo] = (p7_server_callback_t)send_server_info,
/* backup commands */
[p7_seven_cmdbak_reqram] = (p7_server_callback_t)backup_ram,
[p7_seven_cmdbak_reqrom] = (p7_server_callback_t)backup_rom,
[p7_seven_cmdbak_reqboot] = (p7_server_callback_t)backup_boot,
/* storage-related commands */
[p7_seven_cmdfls_mkdir] = (p7_server_callback_t)create_directory,
[p7_seven_cmdfls_rmdir] = (p7_server_callback_t)delete_directory,
[p7_seven_cmdfls_mvdir] = (p7_server_callback_t)rename_directory,
[p7_seven_cmdfls_cwd] = (p7_server_callback_t)change_working_directory,
};
/* serve! */
return (p7_serve_directly(handle, callbacks, (void*)&cookie));
}