author | Alberto Bertogli
<albertito@gmail.com> 2007-06-04 00:33:12 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2007-06-04 00:33:12 UTC |
parent | f919b36091128976dedae4b9f6f999e3cbacf1c2 |
libnmdb/Makefile | +5 | -5 |
libnmdb/internal.h | +20 | -0 |
libnmdb/libnmdb.c | +4 | -314 |
libnmdb/nmdb.h | +1 | -0 |
libnmdb/tcp.c | +183 | -0 |
libnmdb/tcp.h | +12 | -0 |
libnmdb/tipc.c | +129 | -0 |
libnmdb/tipc.h | +12 | -0 |
diff --git a/libnmdb/Makefile b/libnmdb/Makefile index e467d0e..22cd048 100644 --- a/libnmdb/Makefile +++ b/libnmdb/Makefile @@ -18,7 +18,7 @@ endif PREFIX=/usr/local -OBJS = libnmdb.o +OBJS = libnmdb.o tcp.o tipc.o default: all @@ -28,11 +28,11 @@ all: libs libs: libnmdb.so libnmdb.a -libnmdb.so: libnmdb.o - $(CC) $(ALL_CFLAGS) -shared -fPIC libnmdb.o -o libnmdb.so +libnmdb.so: $(OBJS) + $(CC) $(ALL_CFLAGS) -shared -fPIC $(OBJS) -o libnmdb.so -libnmdb.a: libnmdb.o - $(AR) cr libnmdb.a libnmdb.o +libnmdb.a: $(OBJS) + $(AR) cr libnmdb.a $(OBJS) install: libs diff --git a/libnmdb/internal.h b/libnmdb/internal.h new file mode 100644 index 0000000..8df2b47 --- /dev/null +++ b/libnmdb/internal.h @@ -0,0 +1,20 @@ + +#ifndef _INTERNAL_H +#define _INTERNAL_H + +/* Different connection types. Used internally to differentiate between TIPC + * and TCP connections in struct nmdb_srv. */ +#define TIPC_CONN 1 +#define TCP_CONN 2 + +/* The ID code for requests is hardcoded for now, until asynchronous requests + * * are implemented. */ +#define ID_CODE 1 + +/* Functions used internally but shared among the different files. */ +int compare_servers(const void *s1, const void *s2); +ssize_t srecv(int fd, unsigned char *buf, size_t count, int flags); +ssize_t ssend(int fd, const unsigned char *buf, size_t count, int flags); + +#endif + diff --git a/libnmdb/libnmdb.c b/libnmdb/libnmdb.c index 53d341c..11fa73f 100644 --- a/libnmdb/libnmdb.c +++ b/libnmdb/libnmdb.c @@ -7,321 +7,16 @@ #include <string.h> /* memcpy() */ #include <unistd.h> /* close() */ -#if ENABLE_TIPC -#include <linux/tipc.h> /* TIPC stuff */ -#endif - -#if ENABLE_TCP -#include <netinet/tcp.h> /* TCP stuff */ -#include <netdb.h> /* gethostbyname() */ -#endif - #include "nmdb.h" #include "net-const.h" - -/* The ID code for requests is hardcoded for now, until asynchronous requests - * are implemented. */ -#define ID_CODE 1 - -/* Different connection types. Used internally to differentiate between TIPC - * and TCP connections in struct nmdb_srv. */ -#define TIPC_CONN 1 -#define TCP_CONN 2 - - -static int compare_servers(const void *s1, const void *s2); -ssize_t srecv(int fd, unsigned char *buf, size_t count, int flags); -ssize_t ssend(int fd, const unsigned char *buf, size_t count, int flags); - - -/* - * TIPC specific code - */ - -#if ENABLE_TIPC - -/* Add a TIPC server to the db connection. Requests will select which server - * to use by hashing the key. */ -int nmdb_add_tipc_server(nmdb_t *db, int port) -{ - int fd; - struct nmdb_srv *newsrv, *newarray; - - fd = socket(AF_TIPC, SOCK_RDM, 0); - if (fd < 0) - return 0; - - newarray = realloc(db->servers, - sizeof(struct nmdb_srv) * (db->nservers + 1)); - if (newarray == NULL) { - close(fd); - return 0; - } - - db->servers = newarray; - db->nservers++; - - if (port < 0) - port = TIPC_SERVER_INST; - - newsrv = &(db->servers[db->nservers - 1]); - - newsrv->fd = fd; - newsrv->info.tipc.port = port; - newsrv->info.tipc.srvsa.family = AF_TIPC; - newsrv->info.tipc.srvsa.addrtype = TIPC_ADDR_NAMESEQ; - newsrv->info.tipc.srvsa.addr.nameseq.type = TIPC_SERVER_TYPE; - newsrv->info.tipc.srvsa.addr.nameseq.lower = port; - newsrv->info.tipc.srvsa.addr.nameseq.upper = port; - newsrv->info.tipc.srvsa.scope = TIPC_CLUSTER_SCOPE; - newsrv->info.tipc.srvlen = (socklen_t) sizeof(newsrv->info.tipc.srvsa); - - newsrv->type = TIPC_CONN; - - /* keep the list sorted by port, so we can do a reliable selection */ - qsort(db->servers, db->nservers, sizeof(struct nmdb_srv), - compare_servers); - - return 1; -} - -static int tipc_srv_send(struct nmdb_srv *srv, - const unsigned char *buf, size_t bsize) -{ - ssize_t rv; - rv = sendto(srv->fd, buf, bsize, 0, - (struct sockaddr *) &(srv->info.tipc.srvsa), - srv->info.tipc.srvlen); - if (rv <= 0) - return 0; - return 1; -} - -/* Used internally to get and parse replies from the server. */ -static uint32_t tipc_get_rep(struct nmdb_srv *srv, - unsigned char *buf, size_t bsize, - unsigned char **payload, size_t *psize) -{ - ssize_t rv; - uint32_t id, reply; - - rv = recv(srv->fd, buf, bsize, 0); - if (rv < 4 + 4) { - return -1; - } - - id = * (uint32_t *) buf; - id = ntohl(id); - reply = * ((uint32_t *) buf + 1); - reply = ntohl(reply); - - if (id != ID_CODE) { - return -1; - } - - if (payload != NULL) { - *payload = buf + 4 + 4; - *psize = rv - 4 - 4; - } - return reply; -} - -#else -/* Stubs to use when TIPC is not enabled. */ - -int nmdb_add_tipc_server(nmdb_t *db, int port) -{ - return 0; -} - -static int tipc_srv_send(struct nmdb_srv *srv, - const unsigned char *buf, size_t bsize) -{ - return 0; -} - -static uint32_t tipc_get_rep(struct nmdb_srv *srv, - unsigned char *buf, size_t bsize, - unsigned char **payload, size_t *psize) -{ - return -1; -} - -#endif /* ENABLE_TIPC */ - - -/* - * TCP specific code - */ - -#if ENABLE_TCP - -/* Used internally to really add the server once we have an IP address. */ -static int add_tcp_server_addr(nmdb_t *db, in_addr_t *inetaddr, int port) -{ - int rv, fd; - struct nmdb_srv *newsrv, *newarray; - - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) - return 0; - - newarray = realloc(db->servers, - sizeof(struct nmdb_srv) * (db->nservers + 1)); - if (newarray == NULL) { - close(fd); - return 0; - } - - db->servers = newarray; - db->nservers++; - - if (port < 0) - port = TCP_SERVER_PORT; - - newsrv = &(db->servers[db->nservers - 1]); - - newsrv->fd = fd; - newsrv->info.tcp.srvsa.sin_family = AF_INET; - newsrv->info.tcp.srvsa.sin_port = htons(port); - newsrv->info.tcp.srvsa.sin_addr.s_addr = *inetaddr; - - rv = connect(fd, (struct sockaddr *) &(newsrv->info.tcp.srvsa), - sizeof(newsrv->info.tcp.srvsa)); - if (rv < 0) - goto error_exit; - - /* Disable Nagle algorithm because we often send small packets. Huge - * gain in performance. */ - rv = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &rv, sizeof(rv)) < 0 ) - goto error_exit; - - newsrv->type = TCP_CONN; - - /* keep the list sorted by port, so we can do a reliable selection */ - qsort(db->servers, db->nservers, sizeof(struct nmdb_srv), - compare_servers); - - return 1; - -error_exit: - close(fd); - newarray = realloc(db->servers, - sizeof(struct nmdb_srv) * (db->nservers - 1)); - if (newarray == NULL) { - db->servers = NULL; - db->nservers = 0; - return 0; - } - - db->servers = newarray; - db->nservers -= 1; - - return 0; -} - -/* Same as nmdb_add_tipc_server() but for TCP connections. */ -int nmdb_add_tcp_server(nmdb_t *db, const char *addr, int port) -{ - int rv; - struct hostent *he; - struct in_addr ia; - - /* We try to resolve and then pass it to add_tcp_server_addr(). */ - rv = inet_pton(AF_INET, addr, &ia); - if (rv <= 0) { - he = gethostbyname(addr); - if (he == NULL) - return 0; - - ia.s_addr = *( (in_addr_t *) (he->h_addr_list[0]) ); - } - - return add_tcp_server_addr(db, &(ia.s_addr), port); -} - -static int tcp_srv_send(struct nmdb_srv *srv, - const unsigned char *buf, size_t bsize) -{ - ssize_t rv; - uint32_t len; - - len = htonl(bsize + 4); - rv = ssend(srv->fd, (unsigned char *) &len, 4, 0); - if (rv != 4) - return 0; - - rv = ssend(srv->fd, buf, bsize, 0); - if (rv != bsize) - return 0; - return 1; -} - -/* Used internally to get and parse replies from the server. */ -static uint32_t tcp_get_rep(struct nmdb_srv *srv, - unsigned char *buf, size_t bsize, - unsigned char **payload, size_t *psize) -{ - ssize_t rv; - uint32_t id, reply, msgsize; - - rv = srecv(srv->fd, (unsigned char *) &msgsize, 4, 0); - if (rv != 4) - return -1; - - msgsize = ntohl(msgsize); - if (bsize < msgsize) - return -1; - - rv = srecv(srv->fd, buf, msgsize - 4, 0); - if (rv != msgsize - 4) { - return -1; - } - - id = * (uint32_t *) buf; - id = ntohl(id); - reply = * ((uint32_t *) buf + 1); - reply = ntohl(reply); - - if (id != ID_CODE) { - return -1; - } - - if (payload != NULL) { - *payload = buf + 4 + 4; - *psize = rv - 4 - 4; - } - return reply; -} - -#else -/* Stubs to use when TCP is not enabled. */ - -int nmdb_add_tcp_server(nmdb_t *db, const char *addr, int port) -{ - return 0; -} - -static int tcp_srv_send(struct nmdb_srv *srv, - const unsigned char *buf, size_t bsize) -{ - return 0; -} - -static uint32_t tcp_get_rep(struct nmdb_srv *srv, - unsigned char *buf, size_t bsize, - unsigned char **payload, size_t *psize) -{ - return -1; -} - -#endif /* ENABLE_TCP */ +#include "tipc.h" +#include "tcp.h" +#include "internal.h" /* Compare two servers by their connection identifiers. It is used internally * to keep the server array sorted with qsort(). */ -static int compare_servers(const void *s1, const void *s2) +int compare_servers(const void *s1, const void *s2) { struct nmdb_srv *srv1 = (struct nmdb_srv *) s1; struct nmdb_srv *srv2 = (struct nmdb_srv *) s2; @@ -373,11 +68,6 @@ static int compare_servers(const void *s1, const void *s2) } - -/* - * Generic code - */ - /* Like recv() but either fails, or returns a complete read; if we return less * than count is because EOF was reached */ ssize_t srecv(int fd, unsigned char *buf, size_t count, int flags) diff --git a/libnmdb/nmdb.h b/libnmdb/nmdb.h index e1e3b27..2d44b5d 100644 --- a/libnmdb/nmdb.h +++ b/libnmdb/nmdb.h @@ -7,6 +7,7 @@ #include <linux/tipc.h> /* struct sockaddr_tipc */ #include <netinet/in.h> /* struct sockaddr_in */ + struct nmdb_srv { int fd; int type; diff --git a/libnmdb/tcp.c b/libnmdb/tcp.c new file mode 100644 index 0000000..1f03f1f --- /dev/null +++ b/libnmdb/tcp.c @@ -0,0 +1,183 @@ + +#if ENABLE_TCP + +#include <sys/types.h> /* socket defines */ +#include <sys/socket.h> /* socket functions */ +#include <stdlib.h> /* malloc() */ +#include <stdint.h> /* uint32_t and friends */ +#include <arpa/inet.h> /* htonls() and friends */ +#include <string.h> /* memcpy() */ +#include <unistd.h> /* close() */ + +#include <netinet/tcp.h> /* TCP stuff */ +#include <netdb.h> /* gethostbyname() */ + +#include "nmdb.h" +#include "net-const.h" +#include "internal.h" + + +/* Used internally to really add the server once we have an IP address. */ +static int add_tcp_server_addr(nmdb_t *db, in_addr_t *inetaddr, int port) +{ + int rv, fd; + struct nmdb_srv *newsrv, *newarray; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + return 0; + + newarray = realloc(db->servers, + sizeof(struct nmdb_srv) * (db->nservers + 1)); + if (newarray == NULL) { + close(fd); + return 0; + } + + db->servers = newarray; + db->nservers++; + + if (port < 0) + port = TCP_SERVER_PORT; + + newsrv = &(db->servers[db->nservers - 1]); + + newsrv->fd = fd; + newsrv->info.tcp.srvsa.sin_family = AF_INET; + newsrv->info.tcp.srvsa.sin_port = htons(port); + newsrv->info.tcp.srvsa.sin_addr.s_addr = *inetaddr; + + rv = connect(fd, (struct sockaddr *) &(newsrv->info.tcp.srvsa), + sizeof(newsrv->info.tcp.srvsa)); + if (rv < 0) + goto error_exit; + + /* Disable Nagle algorithm because we often send small packets. Huge + * gain in performance. */ + rv = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &rv, sizeof(rv)) < 0 ) + goto error_exit; + + newsrv->type = TCP_CONN; + + /* keep the list sorted by port, so we can do a reliable selection */ + qsort(db->servers, db->nservers, sizeof(struct nmdb_srv), + compare_servers); + + return 1; + +error_exit: + close(fd); + newarray = realloc(db->servers, + sizeof(struct nmdb_srv) * (db->nservers - 1)); + if (newarray == NULL) { + db->servers = NULL; + db->nservers = 0; + return 0; + } + + db->servers = newarray; + db->nservers -= 1; + + return 0; +} + +/* Same as nmdb_add_tipc_server() but for TCP connections. */ +int nmdb_add_tcp_server(nmdb_t *db, const char *addr, int port) +{ + int rv; + struct hostent *he; + struct in_addr ia; + + /* We try to resolve and then pass it to add_tcp_server_addr(). */ + rv = inet_pton(AF_INET, addr, &ia); + if (rv <= 0) { + he = gethostbyname(addr); + if (he == NULL) + return 0; + + ia.s_addr = *( (in_addr_t *) (he->h_addr_list[0]) ); + } + + return add_tcp_server_addr(db, &(ia.s_addr), port); +} + +int tcp_srv_send(struct nmdb_srv *srv, + const unsigned char *buf, size_t bsize) +{ + ssize_t rv; + uint32_t len; + + len = htonl(bsize + 4); + rv = ssend(srv->fd, (unsigned char *) &len, 4, 0); + if (rv != 4) + return 0; + + rv = ssend(srv->fd, buf, bsize, 0); + if (rv != bsize) + return 0; + return 1; +} + +/* Used internally to get and parse replies from the server. */ +uint32_t tcp_get_rep(struct nmdb_srv *srv, + unsigned char *buf, size_t bsize, + unsigned char **payload, size_t *psize) +{ + ssize_t rv; + uint32_t id, reply, msgsize; + + rv = srecv(srv->fd, (unsigned char *) &msgsize, 4, 0); + if (rv != 4) + return -1; + + msgsize = ntohl(msgsize); + if (bsize < msgsize) + return -1; + + rv = srecv(srv->fd, buf, msgsize - 4, 0); + if (rv != msgsize - 4) { + return -1; + } + + id = * (uint32_t *) buf; + id = ntohl(id); + reply = * ((uint32_t *) buf + 1); + reply = ntohl(reply); + + if (id != ID_CODE) { + return -1; + } + + if (payload != NULL) { + *payload = buf + 4 + 4; + *psize = rv - 4 - 4; + } + return reply; +} + +#else +/* Stubs to use when TCP is not enabled. */ + +#include "nmdb.h" + +int nmdb_add_tcp_server(nmdb_t *db, const char *addr, int port) +{ + return 0; +} + +int tcp_srv_send(struct nmdb_srv *srv, + const unsigned char *buf, size_t bsize) +{ + return 0; +} + +uint32_t tcp_get_rep(struct nmdb_srv *srv, + unsigned char *buf, size_t bsize, + unsigned char **payload, size_t *psize) +{ + return -1; +} + +#endif /* ENABLE_TCP */ + diff --git a/libnmdb/tcp.h b/libnmdb/tcp.h new file mode 100644 index 0000000..4252353 --- /dev/null +++ b/libnmdb/tcp.h @@ -0,0 +1,12 @@ + +#ifndef _TCP_H +#define _TCP_H + +int tcp_srv_send(struct nmdb_srv *srv, + const unsigned char *buf, size_t bsize); +uint32_t tcp_get_rep(struct nmdb_srv *srv, + unsigned char *buf, size_t bsize, + unsigned char **payload, size_t *psize); + +#endif + diff --git a/libnmdb/tipc.c b/libnmdb/tipc.c new file mode 100644 index 0000000..cea13ff --- /dev/null +++ b/libnmdb/tipc.c @@ -0,0 +1,129 @@ + +#if ENABLE_TIPC + +#include <sys/types.h> /* socket defines */ +#include <sys/socket.h> /* socket functions */ +#include <stdlib.h> /* malloc() */ +#include <stdint.h> /* uint32_t and friends */ +#include <arpa/inet.h> /* htonls() and friends */ +#include <string.h> /* memcpy() */ +#include <unistd.h> /* close() */ + +#include <linux/tipc.h> /* TIPC stuff */ + +#include "nmdb.h" +#include "net-const.h" +#include "internal.h" + + +/* Add a TIPC server to the db connection. Requests will select which server + * to use by hashing the key. */ +int nmdb_add_tipc_server(nmdb_t *db, int port) +{ + int fd; + struct nmdb_srv *newsrv, *newarray; + + fd = socket(AF_TIPC, SOCK_RDM, 0); + if (fd < 0) + return 0; + + newarray = realloc(db->servers, + sizeof(struct nmdb_srv) * (db->nservers + 1)); + if (newarray == NULL) { + close(fd); + return 0; + } + + db->servers = newarray; + db->nservers++; + + if (port < 0) + port = TIPC_SERVER_INST; + + newsrv = &(db->servers[db->nservers - 1]); + + newsrv->fd = fd; + newsrv->info.tipc.port = port; + newsrv->info.tipc.srvsa.family = AF_TIPC; + newsrv->info.tipc.srvsa.addrtype = TIPC_ADDR_NAMESEQ; + newsrv->info.tipc.srvsa.addr.nameseq.type = TIPC_SERVER_TYPE; + newsrv->info.tipc.srvsa.addr.nameseq.lower = port; + newsrv->info.tipc.srvsa.addr.nameseq.upper = port; + newsrv->info.tipc.srvsa.scope = TIPC_CLUSTER_SCOPE; + newsrv->info.tipc.srvlen = (socklen_t) sizeof(newsrv->info.tipc.srvsa); + + newsrv->type = TIPC_CONN; + + /* keep the list sorted by port, so we can do a reliable selection */ + qsort(db->servers, db->nservers, sizeof(struct nmdb_srv), + compare_servers); + + return 1; +} + +int tipc_srv_send(struct nmdb_srv *srv, + const unsigned char *buf, size_t bsize) +{ + ssize_t rv; + rv = sendto(srv->fd, buf, bsize, 0, + (struct sockaddr *) &(srv->info.tipc.srvsa), + srv->info.tipc.srvlen); + if (rv <= 0) + return 0; + return 1; +} + +/* Used internally to get and parse replies from the server. */ +uint32_t tipc_get_rep(struct nmdb_srv *srv, + unsigned char *buf, size_t bsize, + unsigned char **payload, size_t *psize) +{ + ssize_t rv; + uint32_t id, reply; + + rv = recv(srv->fd, buf, bsize, 0); + if (rv < 4 + 4) { + return -1; + } + + id = * (uint32_t *) buf; + id = ntohl(id); + reply = * ((uint32_t *) buf + 1); + reply = ntohl(reply); + + if (id != ID_CODE) { + return -1; + } + + if (payload != NULL) { + *payload = buf + 4 + 4; + *psize = rv - 4 - 4; + } + return reply; +} + +#else +/* Stubs to use when TIPC is not enabled. */ + +#include "nmdb.h" + +int nmdb_add_tipc_server(nmdb_t *db, int port) +{ + return 0; +} + +int tipc_srv_send(struct nmdb_srv *srv, + const unsigned char *buf, size_t bsize) +{ + return 0; +} + +uint32_t tipc_get_rep(struct nmdb_srv *srv, + unsigned char *buf, size_t bsize, + unsigned char **payload, size_t *psize) +{ + return -1; +} + +#endif /* ENABLE_TIPC */ + diff --git a/libnmdb/tipc.h b/libnmdb/tipc.h new file mode 100644 index 0000000..82b8cb2 --- /dev/null +++ b/libnmdb/tipc.h @@ -0,0 +1,12 @@ + +#ifndef _TIPC_H +#define _TIPC_H + +int tipc_srv_send(struct nmdb_srv *srv, + const unsigned char *buf, size_t bsize); +uint32_t tipc_get_rep(struct nmdb_srv *srv, + unsigned char *buf, size_t bsize, + unsigned char **payload, size_t *psize); + +#endif +