summaryrefslogtreecommitdiff
path: root/ecp
diff options
context:
space:
mode:
Diffstat (limited to 'ecp')
-rw-r--r--ecp/src/ecp/dir/Makefile2
-rw-r--r--ecp/src/ecp/dir/dir_client.c156
-rw-r--r--ecp/src/ecp/dir/dir_client.h15
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, &region, &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