2
#include <sys/socket.h>
3
#include <netinet/in.h>
14
* The magic offset is needed here because RPC over TCP includes a
15
* field that RPC over UDP doesn't. Luvverly.
17
static int rpc_do_reply(struct client *clnt, struct rpc *rpc, size_t off)
21
if ((ret = read(clnt->sock,
22
((char *) rpc->reply) + off,
23
rpc->reply_len - off)) == -1) {
27
else if (ret < sizeof(struct rpc_reply) - off) {
28
fprintf(stderr, "short read: %d < %zu\n", ret,
29
sizeof(struct rpc_reply) - off);
32
rpc->reply_len = ret + off;
34
if ((!off && !(ntohl(rpc->reply->hdr.frag_hdr) & LAST_FRAG)) ||
35
rpc->reply->hdr.udp.xid != rpc->call->hdr.udp.xid ||
36
rpc->reply->hdr.udp.msg_type != htonl(RPC_REPLY)) {
37
fprintf(stderr, "bad reply\n");
41
if (ntohl(rpc->reply->state) != REPLY_OK) {
42
fprintf(stderr, "rpc failed: %d\n", ntohl(rpc->reply->state));
55
static void rpc_header(struct client *clnt, struct rpc *rpc)
59
rpc->call->hdr.frag_hdr = htonl(LAST_FRAG | rpc->call_len);
60
rpc->call->hdr.udp.xid = lrand48();
61
rpc->call->hdr.udp.msg_type = htonl(RPC_CALL);
62
rpc->call->rpc_vers = htonl(2);
65
static int rpc_call_tcp(struct client *clnt, struct rpc *rpc)
69
rpc_header(clnt, rpc);
71
if ((ret = write(clnt->sock, rpc->call, rpc->call_len)) == -1) {
75
else if (ret < rpc->call_len) {
76
fprintf(stderr, "short write: %d < %zu\n",
81
ret = rpc_do_reply(clnt, rpc, 0);
91
static int rpc_call_udp(struct client *clnt, struct rpc *rpc)
94
#define TIMEOUT_MS 3000
96
#define UDP_HDR_OFF (sizeof(struct rpc_header) - sizeof(struct rpc_udp_header))
97
struct pollfd fds[NR_FDS];
101
rpc_header(clnt, rpc);
103
fds[0].fd = clnt->sock;
104
fds[0].events = POLLRDNORM;
106
rpc->call_len -= UDP_HDR_OFF;
108
for (i = 0; i < MAX_TRIES; i++) {
109
int timeout_ms = TIMEOUT_MS + (lrand48() % (TIMEOUT_MS / 2));
110
if ((ret = write(clnt->sock,
111
((char *) rpc->call) + UDP_HDR_OFF,
112
rpc->call_len)) == -1) {
116
else if (ret < rpc->call_len) {
117
fprintf(stderr, "short write: %d < %zu\n", ret,
121
for (; i < MAX_TRIES; i++) {
122
if ((ret = poll(fds, NR_FDS, timeout_ms)) == -1) {
127
DEBUG(("Timeout #%d\n", i + 1));
130
if ((ret = rpc_do_reply(clnt, rpc, UDP_HDR_OFF)) == 0) {
133
DEBUG(("Failed on try #%d - retrying\n",
146
struct client *tcp_client(__u32 server, __u16 port, __u32 flags)
148
struct client *clnt = malloc(sizeof(*clnt));
149
struct sockaddr_in addr;
157
memset(clnt, 0, sizeof(clnt));
159
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
164
if ((flags & CLI_RESVPORT) && bindresvport(sock, 0) == -1) {
165
perror("bindresvport");
170
clnt->call_stub = rpc_call_tcp;
172
addr.sin_family = AF_INET;
173
addr.sin_port = htons(port);
174
addr.sin_addr.s_addr = server;
176
if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
191
struct client *udp_client(__u32 server, __u16 port, __u32 flags)
193
struct client *clnt = malloc(sizeof(*clnt));
194
struct sockaddr_in addr;
202
memset(clnt, 0, sizeof(clnt));
204
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
209
if ((flags & CLI_RESVPORT) && bindresvport(sock, 0) == -1) {
210
perror("bindresvport");
213
struct sockaddr_in me;
215
me.sin_family = AF_INET;
217
me.sin_addr.s_addr = INADDR_ANY;
219
if (0 && bind(sock, (struct sockaddr *) &me, sizeof(me)) == -1) {
226
clnt->call_stub = rpc_call_udp;
228
addr.sin_family = AF_INET;
229
addr.sin_port = htons(port);
230
addr.sin_addr.s_addr = server;
232
if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
247
void client_free(struct client *c)
254
int rpc_call(struct client *client, struct rpc *rpc)
256
return client->call_stub(client, rpc);