diff options
Diffstat (limited to 'ecp/src')
-rw-r--r-- | ecp/src/ecp/dir/Makefile | 2 | ||||
-rw-r--r-- | ecp/src/ecp/dir/dir_client.c | 156 | ||||
-rw-r--r-- | ecp/src/ecp/dir/dir_client.h | 15 |
3 files changed, 172 insertions, 1 deletions
diff --git a/ecp/src/ecp/dir/Makefile b/ecp/src/ecp/dir/Makefile index a002b65..d371f4f 100644 --- a/ecp/src/ecp/dir/Makefile +++ b/ecp/src/ecp/dir/Makefile @@ -1,6 +1,6 @@ include ../common.mk -obj = dir.o +obj = dir.o dir_client.o %.o: %.c diff --git a/ecp/src/ecp/dir/dir_client.c b/ecp/src/ecp/dir/dir_client.c new file mode 100644 index 0000000..3b0d39d --- /dev/null +++ b/ecp/src/ecp/dir/dir_client.c @@ -0,0 +1,156 @@ +#include <stdlib.h> +#include <string.h> + +#include <ecp/core.h> +#include <ecp/dir/dir.h> + +#include "dir_client.h" + +static ecp_dir_result_t dir_result_f = NULL; + +static int dir_list_create_items(ECPDirList *dir_list, uint16_t list_size) { + dir_list->items = malloc(list_size * sizeof(ECPDirItem)); + if (dir_list->items == NULL) return ECP_ERR_ALLOC; + + dir_list->size = list_size; + return ECP_OK; +} + +static void dir_list_reset_items(ECPDirList *dir_list, uint16_t serial) { + dir_list->count = 0; + dir_list->serial = serial; + memset(dir_list->items, 0, dir_list->size * sizeof(ECPDirItem)); +} + +static int dir_handle_open(ECPConnection *conn, ECP2Buffer *b) { + int rv; + + rv = ecp_dir_handle_open(conn, b); + if (rv) return rv; + + conn->param = ecp_dir_list_create(); + if (conn->param == NULL) return ECP_ERR_ALLOC; + + return ECP_OK; +} + +static void dir_handle_close(ECPConnection *conn) { + ecp_dir_list_destroy(conn->param); +} + +static ssize_t dir_handle_msg(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, size_t msg_size, ECP2Buffer *b) { + ECPDirList *dir_list; + ECPDirList *dir_list_fin; + unsigned char count; + unsigned char region; + uint16_t serial; + ssize_t hdr_size; + unsigned char frag_cnt; + unsigned char frag_tot; + int is_first, is_last; + int i; + int rv; + + dir_list_fin = NULL; + + rv = ecp_msg_get_frag(mtype, msg, &frag_cnt, &frag_tot, NULL); + if (rv) return rv; + + hdr_size = ecp_dir_parse_msg(msg, msg_size, &count, ®ion, &serial); + if (hdr_size < 0) return hdr_size; + + dir_list = ecp_conn_get_param(conn); + + rv = ecp_frag_start(conn, seq, frag_cnt, frag_tot, &is_first, &is_last); + if (rv) goto handle_dir_msg_fin; + + if (is_first) { + if (dir_list->items == NULL) { + rv = dir_list_create_items(dir_list, frag_tot * ECP_MAX_DIR_ITEM_IN_MSG); + if (rv) goto handle_dir_msg_fin; + } + dir_list_reset_items(dir_list, serial); + } + + if ((dir_list->items == NULL) || + (serial != dir_list->serial) || + (dir_list->size < (ECP_MAX_DIR_ITEM_IN_MSG * (frag_cnt + 1)))) { + + rv = ECP_ERR; + goto handle_dir_msg_fin; + } + + msg += hdr_size; + dir_list->count += count; + for (i=0; i<count; i++) { + msg += ecp_dir_parse_item(&dir_list->items[ECP_MAX_DIR_ITEM_IN_MSG * frag_cnt + i], msg); + } + + if (is_last) { + dir_list_fin = ecp_dir_list_copy(dir_list); + if (dir_list_fin == NULL) { + rv = ECP_ERR_ALLOC; + goto handle_dir_msg_fin; + } + dir_list->items = NULL; + } + +handle_dir_msg_fin: + ecp_frag_end(conn, seq, frag_cnt, rv); + + if (rv || is_last) { + if (dir_result_f) dir_result_f(dir_list_fin, rv); + ecp_conn_close(conn); + } + + if (rv) return rv; + return msg_size; +} + +static void dir_handle_err(ECPConnection *conn, unsigned char mtype, int err) { + if (dir_result_f) dir_result_f(NULL, err); + ecp_conn_close(conn); +} + +ECPDirList *ecp_dir_list_create(void) { + ECPDirList *dir_list; + + dir_list = malloc(sizeof(ECPDirList)); + if (dir_list == NULL) return NULL; + + memset(dir_list, 0, sizeof(ECPDirList)); + + return dir_list; +} + +void ecp_dir_list_destroy(ECPDirList *dir_list) { + if (dir_list->items) free(dir_list->items); + free(dir_list); +} + +ECPDirList *ecp_dir_list_copy(ECPDirList *dir_list) { + ECPDirList *dir_list_copy; + + dir_list_copy = malloc(sizeof(ECPDirList)); + if (dir_list_copy == NULL) return NULL; + + *dir_list_copy = *dir_list; + return dir_list_copy; +} + +int ecp_dir_set_handler(ECPContext *ctx, ECPConnHandler *handler, ecp_dir_result_t dir_result) { + int rv; + + dir_result_f = dir_result; + ecp_conn_handler_init(handler, dir_handle_open, dir_handle_close, dir_handle_msg, dir_handle_err); + rv = ecp_ctx_set_handler(ctx, ECP_CTYPE_DIR, handler); + return rv; +} + +int ecp_dir_get(ECPConnection *conn, ECPSocket *sock, ECPNode *node, unsigned char region) { + int rv; + + ecp_dir_conn_init(conn, sock); + rv = ecp_dir_request(conn, node, region); + return rv; +} diff --git a/ecp/src/ecp/dir/dir_client.h b/ecp/src/ecp/dir/dir_client.h new file mode 100644 index 0000000..1977e95 --- /dev/null +++ b/ecp/src/ecp/dir/dir_client.h @@ -0,0 +1,15 @@ +typedef struct ECPDirList { + uint16_t count; + uint16_t serial; + size_t size; + ECPDirItem *items; +} ECPDirList; + +typedef void (*ecp_dir_result_t) (ECPDirList *dir_list, int err); + +ECPDirList *ecp_dir_list_create(void); +void ecp_dir_list_destroy(ECPDirList *dir_list); +ECPDirList *ecp_dir_list_copy(ECPDirList *dir_list); + +int ecp_dir_set_handler(ECPContext *ctx, ECPConnHandler *handler, ecp_dir_result_t dir_result); +int ecp_dir_get(ECPConnection *conn, ECPSocket *sock, ECPNode *node, unsigned char region);
\ No newline at end of file |