author | Alberto Bertogli
<albertito@gmail.com> 2007-06-07 05:15:45 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2007-06-07 05:15:45 UTC |
parent | 4b89315ea2b0dd996c137fe9676c845d99565322 |
libnmdb/Makefile | +5 | -2 |
libnmdb/internal.h | +2 | -0 |
libnmdb/libnmdb.c | +9 | -2 |
libnmdb/net-const.h | +4 | -0 |
libnmdb/nmdb.h | +4 | -0 |
libnmdb/udp.c | +145 | -0 |
libnmdb/udp.h | +12 | -0 |
diff --git a/libnmdb/Makefile b/libnmdb/Makefile index cdd95b0..9206f10 100644 --- a/libnmdb/Makefile +++ b/libnmdb/Makefile @@ -1,10 +1,13 @@ ENABLE_TIPC = 1 ENABLE_TCP = 1 +ENABLE_UDP = 1 CFLAGS += -std=c99 -Wall -O3 ALL_CFLAGS = -D_XOPEN_SOURCE=500 -fPIC $(CFLAGS) -ALL_CFLAGS += -DENABLE_TIPC=$(ENABLE_TIPC) -DENABLE_TCP=$(ENABLE_TCP) +ALL_CFLAGS += -DENABLE_TIPC=$(ENABLE_TIPC) \ + -DENABLE_TCP=$(ENABLE_TCP) \ + -DENABLE_UDP=$(ENABLE_UDP) ifdef DEBUG ALL_CFLAGS += -g @@ -22,7 +25,7 @@ endif PREFIX=/usr/local -OBJS = libnmdb.o tcp.o tipc.o +OBJS = libnmdb.o tcp.o tipc.o udp.o default: all diff --git a/libnmdb/internal.h b/libnmdb/internal.h index fac8d8e..4c2f93c 100644 --- a/libnmdb/internal.h +++ b/libnmdb/internal.h @@ -6,6 +6,7 @@ * and TCP connections in struct nmdb_srv. */ #define TIPC_CONN 1 #define TCP_CONN 2 +#define UDP_CONN 3 /* The ID code for requests is hardcoded for now, until asynchronous requests * * are implemented. */ @@ -15,6 +16,7 @@ * the message contents. */ #define TIPC_MSG_OFFSET 0 #define TCP_MSG_OFFSET 4 +#define UDP_MSG_OFFSET 0 /* Functions used internally but shared among the different files. */ int compare_servers(const void *s1, const void *s2); diff --git a/libnmdb/libnmdb.c b/libnmdb/libnmdb.c index e3fd173..ed6c7bb 100644 --- a/libnmdb/libnmdb.c +++ b/libnmdb/libnmdb.c @@ -11,6 +11,7 @@ #include "net-const.h" #include "tipc.h" #include "tcp.h" +#include "udp.h" #include "internal.h" @@ -38,8 +39,8 @@ int compare_servers(const void *s1, const void *s2) return 1; } #endif -#if ENABLE_TCP - if (srv1->type == TCP_CONN) { +#if ENABLE_TCP || ENABLE_UDP + if (srv1->type == TCP_CONN || srv1->type == UDP_CONN) { in_addr_t a1, a2; a1 = srv1->info.tcp.srvsa.sin_addr.s_addr; a2 = srv2->info.tcp.srvsa.sin_addr.s_addr; @@ -155,6 +156,8 @@ static int srv_send(struct nmdb_srv *srv, return tipc_srv_send(srv, buf, bsize); else if (srv->type == TCP_CONN) return tcp_srv_send(srv, buf, bsize); + else if (srv->type == UDP_CONN) + return udp_srv_send(srv, buf, bsize); else return 0; } @@ -170,6 +173,8 @@ static uint32_t get_rep(struct nmdb_srv *srv, return tipc_get_rep(srv, buf, bsize, payload, psize); else if (srv->type == TCP_CONN) return tcp_get_rep(srv, buf, bsize, payload, psize); + else if (srv->type == UDP_CONN) + return udp_get_rep(srv, buf, bsize, payload, psize); else return 0; } @@ -183,6 +188,8 @@ static int srv_get_msg_offset(struct nmdb_srv *srv) return TIPC_MSG_OFFSET; else if (srv->type == TCP_CONN) return TCP_MSG_OFFSET; + else if (srv->type == UDP_CONN) + return UDP_MSG_OFFSET; else return 0; } diff --git a/libnmdb/net-const.h b/libnmdb/net-const.h index 16871e7..bdaa29d 100644 --- a/libnmdb/net-const.h +++ b/libnmdb/net-const.h @@ -15,6 +15,10 @@ #define TCP_SERVER_ADDR "0.0.0.0" #define TCP_SERVER_PORT 26010 +/* UDP default listen address and port. */ +#define UDP_SERVER_ADDR "0.0.0.0" +#define UDP_SERVER_PORT 26010 + /* Protocol version, for checking in the network header. */ #define PROTO_VER 1 diff --git a/libnmdb/nmdb.h b/libnmdb/nmdb.h index 2d44b5d..ded1cd0 100644 --- a/libnmdb/nmdb.h +++ b/libnmdb/nmdb.h @@ -21,6 +21,10 @@ struct nmdb_srv { struct sockaddr_in srvsa; socklen_t srvlen; } tcp; + struct { + struct sockaddr_in srvsa; + socklen_t srvlen; + } udp; } info; }; diff --git a/libnmdb/udp.c b/libnmdb/udp.c new file mode 100644 index 0000000..5ece6e8 --- /dev/null +++ b/libnmdb/udp.c @@ -0,0 +1,145 @@ + +#if ENABLE_UDP + +#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/udp.h> /* UDP 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_udp_server_addr(nmdb_t *db, in_addr_t *inetaddr, int port) +{ + int fd; + struct nmdb_srv *newsrv, *newarray; + + fd = socket(AF_INET, SOCK_DGRAM, 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 = UDP_SERVER_PORT; + + newsrv = &(db->servers[db->nservers - 1]); + + newsrv->fd = fd; + newsrv->info.udp.srvsa.sin_family = AF_INET; + newsrv->info.udp.srvsa.sin_port = htons(port); + newsrv->info.udp.srvsa.sin_addr.s_addr = *inetaddr; + newsrv->info.udp.srvlen = sizeof(struct sockaddr_in); + + newsrv->type = UDP_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; +} + +/* Same as nmdb_add_tcp_server() but for UDP. */ +int nmdb_add_udp_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_udp_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_udp_server_addr(db, &(ia.s_addr), port); +} + +int udp_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.udp.srvsa), + srv->info.udp.srvlen); + if (rv <= 0) + return 0; + return 1; +} + +/* Used internally to get and parse replies from the server. */ +uint32_t udp_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 UDP is not enabled. */ + +#include "nmdb.h" + +int nmdb_add_udp_server(nmdb_t *db, int port) +{ + return 0; +} + +int udp_srv_send(struct nmdb_srv *srv, + const unsigned char *buf, size_t bsize) +{ + return 0; +} + +uint32_t udp_get_rep(struct nmdb_srv *srv, + unsigned char *buf, size_t bsize, + unsigned char **payload, size_t *psize) +{ + return -1; +} + +#endif /* ENABLE_UDP */ + diff --git a/libnmdb/udp.h b/libnmdb/udp.h new file mode 100644 index 0000000..7515941 --- /dev/null +++ b/libnmdb/udp.h @@ -0,0 +1,12 @@ + +#ifndef _UDP_H +#define _UDP_H + +int udp_srv_send(struct nmdb_srv *srv, + const unsigned char *buf, size_t bsize); +uint32_t udp_get_rep(struct nmdb_srv *srv, + unsigned char *buf, size_t bsize, + unsigned char **payload, size_t *psize); + +#endif +