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/tcp.h> /* TCP stuff */
13 #include <netdb.h> /* gethostbyname() */
16 #include "net-const.h"
21 /* Used internally to really add the server once we have an IP address. */
22 static int add_tcp_server_addr(nmdb_t
*db
, in_addr_t
*inetaddr
, int port
)
25 struct nmdb_srv
*newsrv
, *newarray
;
27 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
31 newarray
= realloc(db
->servers
,
32 sizeof(struct nmdb_srv
) * (db
->nservers
+ 1));
33 if (newarray
== NULL
) {
38 db
->servers
= newarray
;
42 port
= TCP_SERVER_PORT
;
44 newsrv
= &(db
->servers
[db
->nservers
- 1]);
47 newsrv
->info
.in
.srvsa
.sin_family
= AF_INET
;
48 newsrv
->info
.in
.srvsa
.sin_port
= htons(port
);
49 newsrv
->info
.in
.srvsa
.sin_addr
.s_addr
= *inetaddr
;
51 rv
= connect(fd
, (struct sockaddr
*) &(newsrv
->info
.in
.srvsa
),
52 sizeof(newsrv
->info
.in
.srvsa
));
56 /* Disable Nagle algorithm because we often send small packets. Huge
57 * gain in performance. */
59 if (setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &rv
, sizeof(rv
)) < 0 )
62 newsrv
->type
= TCP_CONN
;
64 /* keep the list sorted by port, so we can do a reliable selection */
65 qsort(db
->servers
, db
->nservers
, sizeof(struct nmdb_srv
),
72 newarray
= realloc(db
->servers
,
73 sizeof(struct nmdb_srv
) * (db
->nservers
- 1));
74 if (newarray
== NULL
) {
80 db
->servers
= newarray
;
86 /* Same as nmdb_add_tipc_server() but for TCP connections. */
87 int nmdb_add_tcp_server(nmdb_t
*db
, const char *addr
, int port
)
93 /* We try to resolve and then pass it to add_tcp_server_addr(). */
94 rv
= inet_pton(AF_INET
, addr
, &ia
);
96 he
= gethostbyname(addr
);
100 ia
.s_addr
= *( (in_addr_t
*) (he
->h_addr_list
[0]) );
103 return add_tcp_server_addr(db
, &(ia
.s_addr
), port
);
106 int tcp_srv_send(struct nmdb_srv
*srv
, unsigned char *buf
, size_t bsize
)
112 memcpy(buf
, (const void *) &len
, 4);
114 rv
= ssend(srv
->fd
, buf
, bsize
, 0);
120 static ssize_t
recv_msg(int fd
, unsigned char *buf
, size_t bsize
)
125 rv
= recv(fd
, buf
, bsize
, 0);
130 t
= srecv(fd
, buf
+ rv
, 4 - rv
, 0);
138 msgsize
= * ((uint32_t *) buf
);
139 msgsize
= ntohl(msgsize
);
145 t
= srecv(fd
, buf
+ rv
, msgsize
- rv
, 0);
157 /* Used internally to get and parse replies from the server. */
158 uint32_t tcp_get_rep(struct nmdb_srv
*srv
,
159 unsigned char *buf
, size_t bsize
,
160 unsigned char **payload
, size_t *psize
)
165 rv
= recv_msg(srv
->fd
, buf
, bsize
);
169 id
= * ((uint32_t *) buf
+ 1);
171 reply
= * ((uint32_t *) buf
+ 2);
172 reply
= ntohl(reply
);
178 if (payload
!= NULL
) {
179 *payload
= buf
+ 4 + 4 + 4;
180 *psize
= rv
- 4 - 4 - 4;
186 /* Stubs to use when TCP is not enabled. */
192 int nmdb_add_tcp_server(nmdb_t
*db
, const char *addr
, int port
)
197 int tcp_srv_send(struct nmdb_srv
*srv
, unsigned char *buf
, size_t bsize
)
202 uint32_t tcp_get_rep(struct nmdb_srv
*srv
,
203 unsigned char *buf
, size_t bsize
,
204 unsigned char **payload
, size_t *psize
)
209 #endif /* ENABLE_TCP */