Document the API change in the UPGRADING document
[nmdb.git] / libnmdb / sctp.c
blob427c03bd819e1a820a129513ce548a714e1ae0ae
2 #if ENABLE_SCTP
4 #include <sys/types.h> /* socket defines */
5 #include <sys/socket.h> /* socket functions */
6 #include <stdlib.h> /* malloc() */
7 #include <stdint.h> /* uint32_t and friends */
8 #include <arpa/inet.h> /* htonls() and friends */
9 #include <string.h> /* memcpy() */
10 #include <unistd.h> /* close() */
12 #include <netinet/sctp.h> /* SCTP stuff */
13 #include <netdb.h> /* gethostbyname() */
15 #include "nmdb.h"
16 #include "net-const.h"
17 #include "internal.h"
18 #include "sctp.h"
21 /* Used internally to really add the server once we have an IP address. */
22 static int add_sctp_server_addr(nmdb_t *db, in_addr_t *inetaddr, int port)
24 int fd, rv;
25 struct nmdb_srv *newsrv, *newarray;
27 fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
28 if (fd < 0)
29 return 0;
31 /* Disable Nagle algorithm because we often send small
32 * packets. Huge gain in performance. */
33 rv = 1;
34 if (setsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, &rv, sizeof(rv)) < 0 ) {
35 close(fd);
36 return 0;
39 newarray = realloc(db->servers,
40 sizeof(struct nmdb_srv) * (db->nservers + 1));
41 if (newarray == NULL) {
42 close(fd);
43 return 0;
46 db->servers = newarray;
47 db->nservers++;
49 if (port < 0)
50 port = SCTP_SERVER_PORT;
52 newsrv = &(db->servers[db->nservers - 1]);
54 newsrv->fd = fd;
55 newsrv->info.in.srvsa.sin_family = AF_INET;
56 newsrv->info.in.srvsa.sin_port = htons(port);
57 newsrv->info.in.srvsa.sin_addr.s_addr = *inetaddr;
58 newsrv->info.in.srvlen = sizeof(struct sockaddr_in);
60 newsrv->type = SCTP_CONN;
62 /* keep the list sorted by port, so we can do a reliable selection */
63 qsort(db->servers, db->nservers, sizeof(struct nmdb_srv),
64 compare_servers);
66 return 1;
69 /* Same as nmdb_add_tcp_server() but for SCTP. */
70 int nmdb_add_sctp_server(nmdb_t *db, const char *addr, int port)
72 int rv;
73 struct hostent *he;
74 struct in_addr ia;
76 /* We try to resolve and then pass it to add_sctp_server_addr(). */
77 rv = inet_pton(AF_INET, addr, &ia);
78 if (rv <= 0) {
79 he = gethostbyname(addr);
80 if (he == NULL)
81 return 0;
83 ia.s_addr = *( (in_addr_t *) (he->h_addr_list[0]) );
86 return add_sctp_server_addr(db, &(ia.s_addr), port);
89 int sctp_srv_send(struct nmdb_srv *srv, unsigned char *buf, size_t bsize)
91 ssize_t rv;
92 rv = sendto(srv->fd, buf, bsize, 0,
93 (struct sockaddr *) &(srv->info.in.srvsa),
94 srv->info.in.srvlen);
95 if (rv <= 0)
96 return 0;
97 return 1;
100 /* Used internally to get and parse replies from the server. */
101 uint32_t sctp_get_rep(struct nmdb_srv *srv,
102 unsigned char *buf, size_t bsize,
103 unsigned char **payload, size_t *psize)
105 ssize_t rv;
106 uint32_t id, reply;
108 rv = recv(srv->fd, buf, bsize, 0);
109 if (rv < 4 + 4) {
110 return -1;
113 id = * (uint32_t *) buf;
114 id = ntohl(id);
115 reply = * ((uint32_t *) buf + 1);
116 reply = ntohl(reply);
118 if (id != ID_CODE) {
119 return -1;
122 if (payload != NULL) {
123 *payload = buf + 4 + 4;
124 *psize = rv - 4 - 4;
126 return reply;
129 #else
130 /* Stubs to use when SCTP is not enabled. */
132 #include <stdint.h>
133 #include "nmdb.h"
134 #include "sctp.h"
136 int nmdb_add_sctp_server(nmdb_t *db, const char *addr, int port)
138 return 0;
141 int sctp_srv_send(struct nmdb_srv *srv, unsigned char *buf, size_t bsize)
143 return 0;
146 uint32_t sctp_get_rep(struct nmdb_srv *srv,
147 unsigned char *buf, size_t bsize,
148 unsigned char **payload, size_t *psize)
150 return -1;
153 #endif /* ENABLE_SCTP */