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/protocol/server.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));
}