]> rtime.felk.cvut.cz Git - frescor/forb.git/commitdiff
Finished UNIX protocol and a test for it
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 28 Aug 2008 13:38:29 +0000 (15:38 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 28 Aug 2008 13:38:29 +0000 (15:38 +0200)
Makefile.omk
forb-internal.h
forb.c
proto.c
proto.h
proto_unix.c
proto_unix.h [new file with mode: 0644]
tests/Makefile.omk
tests/proto_unix.c [new file with mode: 0644]

index dabf74c12e810636766650527898966627feaf96..2af20d9cb2e298aa9f95dc2a63caba44c510ca4a 100644 (file)
@@ -5,7 +5,13 @@ forb_SOURCES = forb.c cdr.c sha1.c uuid.c iop.c
 forb_CLIENT_IDL = forb-idl.idl\r
 \r
 to_forb_subdir=$(1)->forb/$(strip $(1))\r
-renamed_include_HEADERS = \\r
+\r
+ifeq ($(CONFIG_FORB_PROTO_UNIX),y)\r
+forb_SOURCES += proto_unix.c\r
+renamed_include_HEADERS += $(call to_forb_subdir, proto_unix.h) \r
+endif\r
+\r
+renamed_include_HEADERS += \\r
        $(call to_forb_subdir, forb.h) \\r
        $(call to_forb_subdir, forb-internal.h) \\r
        $(call to_forb_subdir, basic_types.h) \\r
@@ -17,3 +23,8 @@ renamed_include_HEADERS = \
 \r
 renamed_include_GEN_HEADERS = \\r
        $(call to_forb_subdir,forb-idl.h)\r
+\r
+default_CONFIG = CONFIG_FORB_PROTO_UNIX=y\r
+\r
+config_include_HEADERS = forb_config.h\r
+forb_config_DEFINES = CONFIG_FORB_PROTO_UNIX\r
index 11dea4461d8898a86bde239ed99b090bbda369ff..827b75b3a4070f5ec11685f2dd7ff1f55284cf30 100644 (file)
@@ -44,7 +44,7 @@ typedef struct forb_rt {
 } forb_rt;
 
 typedef struct forb {
-       forb_uuid_t uuid;
+       forb_server_t server;
        fosa_mutex_t mutex;     /**< Mutex for request_id and GAVL trees */
        CORBA_long request_id;  /**< Value of next sent request_id */
        forb_rt rt;             /**< Routing table */
@@ -91,4 +91,7 @@ forb_new_request(forb_request_t *req, forb_object obj);
 forb_object_key forb_object_to_key(forb_object obj);
 forb_object forb_key_to_object(forb_object_key key);
 
+void
+forb_server_init(forb_server_t *serer);
+
 #endif
diff --git a/forb.c b/forb.c
index aa35cba2f0454c856dbc1675b141c2a1f6800280..ce48d6c9cbe2f5295e440f08c9b4841fb7cae8cd 100644 (file)
--- a/forb.c
+++ b/forb.c
@@ -38,7 +38,7 @@ forb_orb forb_init(void)
        memset(forb, 0, sizeof(*forb));
        
        object->instance_data = forb;
-       forb_uuid_generate(&forb->uuid);
+       forb_server_init(&forb->server);
        if (fosa_mutex_init(&forb->mutex, 0) != 0) goto err2;
        if (fosa_mutex_init(&forb->port_mutex, 0) != 0) goto err2;
 
@@ -179,3 +179,9 @@ forb_put_connection(forb_conn_t *conn)
 {
        /* TODO */
 }
+
+void
+forb_server_init(forb_server_t *server)
+{
+       forb_uuid_generate(&server->uuid);
+}
diff --git a/proto.c b/proto.c
index f87e66ba1f76fb6f2b0f411fa3cb5eb87d9c5b36..c6e7b850a0623e6bab0b06be77d05be09e607289 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -51,3 +51,4 @@ void *forb_port_receiver_thread(void *arg)
        }
        return NULL;
 }
+
diff --git a/proto.h b/proto.h
index f5f25e75a03d00d2f4050ca6e01b940779f8bf9c..a99ff1d99f6453bb44f37d0ea59dd110fdcc4de1 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -1,3 +1,13 @@
+/**
+ * @file   proto.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Thu Aug 28 10:36:23 2008
+ * 
+ * @brief  FORB transport protocol module
+ * 
+ * 
+ */
+
 #ifndef FORB_PROTO_H
 #define FORB_PROTO_H
 
@@ -8,10 +18,60 @@ typedef struct forb_proto forb_proto_t;
 typedef struct forb_port forb_port_t;
 typedef struct forb_conn forb_conn_t;
 
+
+/**
+ * Description of a FORB transport protocol.
+ */
 struct forb_proto {
-       void *proto_data;
-       forb_conn_t *(*connect)(forb_server_t *server);
-       size_t (*send)(forb_conn_t *conn, void *buf, size_t len);
+       int (*port_destroy)(forb_port_t *port);
+       /** 
+        * Establishes connection with another communication partner.
+        *
+        * This function may use forb_conn::proto_data to store any
+        * information related to the connection. No other field in
+        * forb_conn should be modified. The port used for this
+        * connection has to be set by called in @c conn->port.
+        * 
+        * @param[in] conn Connection to use
+        * @param[in] proto_addr Pointer to destination address in a protocol specific format.
+        * 
+        * @return Zero on success, negative error code on error.
+        */
+       int (*connect)(forb_conn_t *conn, void *proto_addr);
+
+       /** 
+        * Closes the connection.
+        *
+        * All data allocated for this connection must be deallocated
+        * by this function.
+        * 
+        * @param conn Connection to disconnect 
+        * 
+        * @return Zero on success, negative error code on error.
+        */
+       int (*disconnect)(forb_conn_t *conn);
+       /** 
+        * Sends data through a connection
+        * 
+        * @param conn Connection to use 
+        * @param buf Data to send
+        * @param len Length of data to send
+        * 
+        * @return Length of the sent data (should be equal to @a len on
+        * success) or negative error code on error.
+        */
+       size_t (*send)(forb_conn_t *conn, const void *buf, size_t len);
+
+       /** 
+        * Receives data through a port
+        * 
+        * @param port Port to use 
+        * @param buf Where to store the received data
+        * @param len Length the buffer @a buf
+        * 
+        * @return Length of the received data or negative error code
+        * on error.
+        */
        size_t (*recv)(forb_port_t *port, void *buf, size_t len);
 };
 
@@ -20,23 +80,25 @@ struct forb_proto {
  * FORB transport protocol (see ::forb_proto).
  */
 struct forb_port {
-       forb_proto_t *proto;
-       void *proto_data;
+       const forb_proto_t *proto; /**< Protocol used on this port */
+       void *proto_data;       /**< Protocol specific data */
        fosa_thread_id_t receiver_thread; /**< The thread running forb_port_receiver_thread() */
        CDR_Codec codec;        /**< Receiving buffer */
        ul_list_node_t node;
        //gavl_cust_root_field_t peers; /**< Peers discoveder on this port by discovery protocol */
 };
 
+/**
+ * Connection to another
+ */
 struct forb_conn {
-       forb_port_t *port;
-       void *proto_data;
+       forb_port_t *port;      /**< Port of this connection */
+       void *proto_data;       /**< Protocol specific data */
 };
 
-enum forb_protos {
-       FORB_PROTO_UNIX,
-       FORB_PROTO_FNA,
-       __FORB_PROTO_COUNT
+struct forb_peer {
+       forb_uuid_t uuid;
+       void *proto_data;
 };
 
 UL_LIST_CUST_DEC(forb_port,    /* cust_prefix */
index e12a3798a42b6b2ce89ae5bae2b9de851b5969c5..67a700a2f6692ce26f57c4b43683e75a351066a2 100644 (file)
 #include <forb/proto.h>
+#include <forb/proto_unix.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
 
+/** UNIX protocol data for ports. */
+struct unix_port {
+       int socket;     
+};
 
-/**
- * UNIX protocol data for ports.
- */
-static struct unix_port {
-       int socket;
-} unix_port_data;
+typedef struct sockaddr_un unix_addr_t;
 
-/**
- * UNIX protcol data for connections.
- */
+/** UNIX protocol data for connections. */
 struct unix_conn {
-       int socket;
+       unix_addr_t addr;
 };
 
-static size_t unix_send(forb_conn_t *conn, void *buf, size_t len)
+static inline struct unix_conn*
+conn_to_uconn(forb_conn_t *conn) { return conn->proto_data; }
+
+static struct unix_port*
+conn_to_uport(forb_conn_t *conn) { return conn->port->proto_data; }
+
+static size_t
+unix_send(forb_conn_t *conn, const void *buf, size_t len)
 {
-       struct unix_conn *c = conn->proto_data;
-       return send(c->socket, buf, len, 0);
+       struct unix_conn *c = conn_to_uconn(conn);
+       struct unix_port *p = conn_to_uport(conn);
+       //printf("send to %s\n", c->addr.sun_path);
+       return sendto(p->socket, buf, len, 0,
+                     (struct sockaddr*)&c->addr, sizeof(c->addr));
 }
 
-static size_t unix_recv(forb_port_t *port, void *buf, size_t len)
+static size_t
+unix_recv(forb_port_t *port, void *buf, size_t len)
 {
        struct unix_port *p = port->proto_data;
        return recv(p->socket, buf, len, 0);
 }
 
+static int
+unix_connect(forb_conn_t *conn, void *addr)
+{
+       struct unix_conn *pd;
+       pd = forb_malloc(sizeof(*pd));
+       if (!pd) return -1;
+
+       pd->addr = *(unix_addr_t*)addr;
+       conn->proto_data = pd;
+       return 0;
+}
+
+static int
+unix_disconnect(forb_conn_t *conn)
+{
+       struct unix_conn *pd = conn->proto_data;
+       forb_free(pd);
+       return 0;
+}
+
+static int
+unix_port_destroy(forb_port_t * port)
+{
+       struct unix_port *pd = port->proto_data;
+       struct sockaddr_un addr;
+       socklen_t len = sizeof(addr);
+       getsockname(pd->socket, (struct sockaddr*)&addr, &len);
+       if (addr.sun_family == AF_UNIX)
+               unlink(addr.sun_path);
+       close(pd->socket);
+       forb_free(pd);
+       return 0;
+}
 
 static const forb_proto_t proto_unix = {
-       .proto_data = NULL,
-       .connect = NULL,
+       .port_destroy = unix_port_destroy,
+       .connect = unix_connect,
+       .disconnect = unix_disconnect,
        .send = unix_send,
        .recv = unix_recv
 };
 
-/* We have one fixed port for unix protocol */
-static forb_port_t port = {
-       .proto_data = unix_port_data,
-       .proto = &proto_unix,
-};
+static void
+unix_server_to_addr(struct sockaddr_un *addr, const forb_server_t *server)
+{
+       char str[65];
+       addr->sun_family = AF_UNIX;
+       sprintf(addr->sun_path, "/tmp/forb-%s",
+               forb_uuid_to_string(str, &server->uuid, sizeof(str)));
+}
 
-static bool port_init(forb_t *forb, struct unix_port *up)
+/** 
+ * Initializes UNIX protocol port.
+ * 
+ * @param port Port to initialize.
+ * @param server Server this port belongs to.
+ * 
+ * @return Zero on success, -1 on error and errno is set
+ * appropriately.
+ */
+int
+forb_unix_port_init(forb_port_t *port, const forb_server_t *server)
 {
-       int s, ret;       
+       
+       int ret;       
        struct sockaddr_un addr;
-       char uuid[65];
-       s = socket(PF_UNIX, SOCK_DGRAM, 0);
-       if (s == -1)
-               return false;
-
-       /* Prepare socket address */
-       addr.sun_family = AF_UNIX;
-       sprintf(addr.sun_path, "/tmp/forb-%s",
-               forb_uuid_to_string(uuid, forb->uuid, sizeof(uuid)));
-       ret = bind(s, &addr, sizeof(addr));
-       if (ret == -1) {
-               goto err;
-       }
+       struct unix_port *pd;
+
+       pd = forb_malloc(sizeof(*pd));
+       if (!pd)
+               return -1;
        
-       up.socket = s;
-       return true;
+       pd->socket = socket(PF_UNIX, SOCK_DGRAM, 0);
+       if (pd->socket == -1) goto err1;
+
+       unix_server_to_addr(&addr, server);
+       ret = bind(pd->socket, (struct sockaddr*)&addr, sizeof(addr));
+       if (ret == -1) goto err;
+
+       port->proto = &proto_unix;
+       port->proto_data = pd;
+       return 0;
 err:
-       close(s);
-       return false;
+       ret = errno;
+       close(pd->socket);
+       errno = ret;
+err1:
+       ret = errno;
+       forb_free(pd);
+       errno = ret;
+       return -1;
 }
 
-bool forb_proto_unix_init(forb_orb orb)
-{
-       forb_t *forb = forb_data(orb);
-       port_init(forb, &unix_port_data);
-       forb_register_and_run_port(&port);
-       return true;
-}
+/* bool forb_proto_unix_init(forb_orb orb) */
+/* { */
+/*     forb_t *forb = forb_data(orb); */
+/*     port_init(&forb->uuid, &unix_port_data); */
+/*     forb_register_and_run_port(&port); */
+/*     return true; */
+/* } */
diff --git a/proto_unix.h b/proto_unix.h
new file mode 100644 (file)
index 0000000..c1a4fdf
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef FORB_PROTO_UNIX_H
+#define FORB_PROTO_UNIX_H
+
+int forb_unix_port_init(forb_port_t *port, const forb_server_t *server);
+
+#endif
index af5c12c882bafb8c8059ca1b4a6dbe07b9381fc1..27691738543102e53609e1e95422b9c7ed838e0a 100644 (file)
@@ -1,4 +1,5 @@
-test_PROGRAMS = hello_inproc
+test_PROGRAMS = hello_inproc proto_unix
+CFLAGS += -DTEST
 
 lib_LOADLIBES = forb ulut fosa rt
 
@@ -15,3 +16,5 @@ include_GEN_HEADERS = hello.h
 # test_PROGRAMS += hello_server
 # hello_server_SOURCES = hello_server.c
 # hello_inproc_SERVER_IDL = hello.idl
+
+proto_unix_SOURCES = proto_unix.c
diff --git a/tests/proto_unix.c b/tests/proto_unix.c
new file mode 100644 (file)
index 0000000..6189ae8
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * @file   proto_unix.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Thu Aug 28 15:20:37 2008
+ * 
+ * @brief Unit test for UNIX socket based FORB transport protocol
+ */
+
+#include <error.h>
+#include "../proto_unix.c"
+
+const char *msg = "Hello world!";
+#define NUM_PORTS 10
+
+int main()
+{
+       forb_server_t server[NUM_PORTS];
+       forb_port_t port[NUM_PORTS];
+       int i, ret;
+
+       for (i=0; i<NUM_PORTS; i++) {
+               forb_server_init(&server[i]);
+               if (forb_unix_port_init(&port[i], &server[i]) != 0)
+                       error(1, errno, "forb_unix_port_init(%d)", i);
+       }
+
+/*     forb_peer_t peers[NUM_PORTS]; */
+/*     unix_discover_peers(&port[0], peers, NUM_PORTS); */
+
+       for (i=1; i<NUM_PORTS; i++) {
+               forb_conn_t conn;
+               char buf[100];
+               int len;
+               struct sockaddr_un addr;
+
+               unix_server_to_addr(&addr, &server[i]);
+               conn.port = &port[0];
+               ret = unix_connect(&conn, &addr);
+               if (ret != 0) {
+                       error(1, errno, "connect(%d)", i);
+               }
+
+               len = strlen(msg)+1;
+               ret = unix_send(&conn, msg, len);
+               if (ret != len) 
+                       error(1, errno, "send(to %d) = %d", i, ret);
+
+               ret = unix_recv(&port[i], buf, sizeof(buf));
+               if (ret != len) 
+                       error(1, errno, "recv(port[%d]) = %d", i, ret);
+
+               if (strcmp(msg, buf) != 0)
+                       error(1, errno, "port %d: received wrong data", i);
+
+               unix_disconnect(&conn);
+       }
+
+       for (i=0; i<NUM_PORTS; i++) {
+               unix_port_destroy(&port[i]);
+       }
+
+       return 0;
+}