/* ************************************************************************** */ /* _____ _ */ /* protocol/server.c |_ _|__ _ _| |__ ___ _ _ */ /* | Project: libp7 | |/ _ \| | | | '_ \ / _ \ | | | */ /* | | (_) | |_| | | | | __/ |_| | */ /* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ /* Last updated: 2017/01/04 15:02:36 |___/ */ /* */ /* ************************************************************************** */ #include #include #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)); }