226 lines
5.8 KiB
C
226 lines
5.8 KiB
C
/* ************************************************************************** */
|
|
/* _____ _ */
|
|
/* protocol/server.c |_ _|__ _ _| |__ ___ _ _ */
|
|
/* | Project: libp7 | |/ _ \| | | | '_ \ / _ \ | | | */
|
|
/* | | (_) | |_| | | | | __/ |_| | */
|
|
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
|
/* Last updated: 2017/01/04 15:02:36 |___/ */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
#include <libp7/internals.h>
|
|
#include <string.h>
|
|
#define gather_fs() \
|
|
if (!(fs = find_filesystem(resp->args[4], filesystems))) { \
|
|
err = p7_send_err(handle, p7_err_other); \
|
|
break; \
|
|
}
|
|
#define gather_sdir() \
|
|
sdir = resp->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);
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
int err;
|
|
/* make checks */
|
|
chk_handle(handle);
|
|
chk_passive(handle);
|
|
|
|
/* initial check */
|
|
const p7_packet_t *resp = p7_get_response(handle);
|
|
if ((err = p7_recv(handle, 0)))
|
|
return (err);
|
|
log_info("Received packet type: 0x%x, initial: %d",
|
|
resp->type, resp->initial);
|
|
while (resp->type != p7_pt_check || !resp->initial) {
|
|
err = p7_send_err(handle, p7_err_other);
|
|
if (err) return (err);
|
|
}
|
|
|
|
/* ack and start! */
|
|
err = p7_send_ack(handle, 1);
|
|
if (err) return (err);
|
|
|
|
/* main loop */
|
|
p7_filesystem_t *fs; const char *sdir;
|
|
while (1) {
|
|
/* check command packet */
|
|
if (resp->type != p7_pt_cmd) {
|
|
if (resp->type == p7_pt_terminate) break;
|
|
p7_send_err(handle, p7_err_other);
|
|
continue ;
|
|
}
|
|
log_info("Received command was: %d", resp->code);
|
|
|
|
/* command switch! */
|
|
switch (resp->code) {
|
|
case 0x01: /* get server info */
|
|
err = p7_send_eack(handle, info);
|
|
break;
|
|
case 0x2F: /* request a RAM image transfer */
|
|
/* check that we have the RAM */
|
|
if (!info->ram) {
|
|
err = p7_send_err(handle, p7_err_other);
|
|
break;
|
|
}
|
|
|
|
/* accept and roleswap */
|
|
err = p7_send_ack(handle, 1);
|
|
if (err) break;
|
|
if (resp->type != p7_pt_roleswp) {
|
|
err = p7_send_err(handle, p7_err_other);
|
|
break;
|
|
}
|
|
|
|
/* send the thing */
|
|
err = p7_send_databuf(handle, info->ram, info->ram_capacity,
|
|
0, NULL);
|
|
if (err) break;
|
|
|
|
/* re-roleswp */
|
|
err = p7_send_roleswp(handle);
|
|
break;
|
|
case 0x40: /* create directory */
|
|
gather_fs()
|
|
gather_sdir()
|
|
|
|
if (!sdir)
|
|
err = p7_send_ack(handle, 1);
|
|
else if (!fs->create_directory
|
|
|| (*fs->create_directory)(sdir))
|
|
err = p7_send_err(handle, p7_err_other);
|
|
else
|
|
err = p7_send_ack(handle, 1);
|
|
break;
|
|
case 0x41: /* delete directory */
|
|
gather_fs()
|
|
gather_sdir()
|
|
|
|
if (!sdir)
|
|
err = p7_send_err(handle, p7_err_other);
|
|
else if (!fs->delete_directory
|
|
|| (*fs->delete_directory)(sdir))
|
|
err = p7_send_err(handle, p7_err_other);
|
|
else
|
|
err = p7_send_ack(handle, 1);
|
|
break;
|
|
case 0x42: /* rename directory */
|
|
gather_fs()
|
|
gather_sdir()
|
|
|
|
if (!sdir || !resp->args[1])
|
|
err = p7_send_err(handle, p7_err_other);
|
|
else if (!fs->rename_directory
|
|
|| !(*fs->rename_directory)(sdir, resp->args[1]))
|
|
err = p7_send_err(handle, p7_err_other);
|
|
else
|
|
err = p7_send_ack(handle, 1);
|
|
break;
|
|
case 0x43: /* change storage working directory */
|
|
gather_fs()
|
|
gather_sdir()
|
|
|
|
if (!resp->args[0]) {
|
|
fs->working_directory = NULL;
|
|
err = p7_send_ack(handle, 1);
|
|
} else if (!fs->directory_exists
|
|
|| (*fs->directory_exists)(sdir)) {
|
|
err = p7_send_err(handle, p7_err_other);
|
|
} else {
|
|
fs->working_directory = fs->_wd;
|
|
strncpy(fs->_wd, sdir, 256);
|
|
fs->_wd[256] = 0;
|
|
p7_send_ack(handle, 1);
|
|
}
|
|
break;
|
|
case 0x52: /* request a CASIOWIN entry transfer */
|
|
/* check if the CASIOWIN entry is available */
|
|
if (!info->casiowin_entry) {
|
|
err = p7_send_err(handle, p7_err_other);
|
|
break;
|
|
}
|
|
|
|
/* accept and roleswap */
|
|
err = p7_send_ack(handle, 1);
|
|
if (err) break;
|
|
if (resp->type != p7_pt_roleswp) {
|
|
err = p7_send_err(handle, p7_err_other);
|
|
break;
|
|
}
|
|
|
|
/* send the thing */
|
|
err = p7_send_databuf(handle, info->casiowin_entry, 0x80,
|
|
0, NULL);
|
|
if (err) break;
|
|
|
|
/* roleswp and wait for other command */
|
|
err = p7_send_roleswp(handle);
|
|
break;
|
|
case 0x54: /* request a bootcode transfer */
|
|
/* check if the bootcode is available */
|
|
if (!info->bootcode) {
|
|
err = p7_send_err(handle, p7_err_other);
|
|
break;
|
|
}
|
|
|
|
/* accept and roleswap */
|
|
err = p7_send_ack(handle, 1);
|
|
if (err) break;
|
|
if (resp->type != p7_pt_roleswp) {
|
|
err = p7_send_err(handle, p7_err_other);
|
|
break;
|
|
}
|
|
|
|
/* send the thing */
|
|
err = p7_send_databuf(handle, info->bootcode, info->bootcode_size,
|
|
0, NULL);
|
|
if (err) break;
|
|
|
|
/* roleswap and wait for next command */
|
|
err = p7_send_roleswp(handle);
|
|
break;
|
|
default: /* unknown command! */
|
|
err = p7_send_err(handle, p7_err_other);
|
|
}
|
|
|
|
/* now check the error */
|
|
if (err) {
|
|
/* oh crap! TODO */
|
|
return (p7_error_unknown);
|
|
}
|
|
}
|
|
|
|
/* ack and disconnect */
|
|
return (p7_send_ack(handle, 0));
|
|
}
|