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
\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
} 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 */
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
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;
{
/* TODO */
}
+
+void
+forb_server_init(forb_server_t *server)
+{
+ forb_uuid_generate(&server->uuid);
+}
+/**
+ * @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
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);
};
* 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 */
#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; */
+/* } */
--- /dev/null
+#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
-test_PROGRAMS = hello_inproc
+test_PROGRAMS = hello_inproc proto_unix
+CFLAGS += -DTEST
lib_LOADLIBES = forb ulut fosa rt
# test_PROGRAMS += hello_server
# hello_server_SOURCES = hello_server.c
# hello_inproc_SERVER_IDL = hello.idl
+
+proto_unix_SOURCES = proto_unix.c
--- /dev/null
+/**
+ * @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;
+}