3 * Pass an mr_params off to the Moira server and get a reply
5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
12 #include "mr_private.h"
18 #include <netinet/in.h>
29 4-byte total length (including these 4 bytes)
30 4-byte version number (MR_VERSION_2 == 2)
31 4-byte opcode (from client) or status (from server)
34 4-byte len, followed by null-terminated string, padded to 4-byte boundary
35 (the len doesn't include the padding)
38 (followed by more packets if status was MR_MORE_DATA)
40 All numbers are in network byte order.
43 int mr_do_call(struct mr_params *params, struct mr_params *reply)
49 status = mr_send(_mr_conn, params);
50 if (status == MR_SUCCESS)
51 status = mr_receive(_mr_conn, reply);
59 int mr_send(int fd, struct mr_params *params)
66 length = 16; /* length + version + opcode/status + argc */
70 argl = params->mr_argl;
71 for (i = 0; i < params->mr_argc; i++)
72 length += 8 + argl[i];
76 argl = malloc(params->mr_argc * sizeof(int));
77 if (params->mr_argc && !argl)
79 for (i = 0; i < params->mr_argc; i++)
81 argl[i] = strlen(params->mr_argv[i]) + 1;
82 length += 8 + argl[i];
93 memset(buf, 0, length);
95 putlong(buf + 4, MR_VERSION_2);
96 putlong(buf + 8, params->u.mr_procno);
97 putlong(buf + 12, params->mr_argc);
99 for (i = 0, p = buf + 16; i < params->mr_argc; i++)
102 memcpy(p += 4, params->mr_argv[i], argl[i]);
103 p += argl[i] + (4 - argl[i] % 4) % 4;
106 putlong(buf, length);
108 written = send(fd, buf, length, 0);
110 if (!params->mr_argl)
113 if (written != (int)length)
119 int mr_receive(int fd, struct mr_params *reply)
123 memset(reply, 0, sizeof(struct mr_params));
125 status = mr_cont_receive(fd, reply);
126 while (status == -1);
131 /* Read some or all of a client response, without losing if it turns
132 * out to be malformed. Returns MR_SUCCESS on success, an error code
133 * on failure, or -1 if the packet hasn't been completely received
137 int mr_cont_receive(int fd, struct mr_params *reply)
144 if (!reply->mr_flattened)
148 size = recv(fd, lbuf, 4, 0);
150 return size ? MR_ABORTED : MR_NOT_CONNECTED;
151 getlong(lbuf, length);
154 reply->mr_flattened = malloc(length);
155 if (!reply->mr_flattened)
157 memcpy(reply->mr_flattened, lbuf, 4);
158 reply->mr_filled = 4;
163 getlong(reply->mr_flattened, length);
165 more = recv(fd, reply->mr_flattened + reply->mr_filled,
166 length - reply->mr_filled, 0);
169 mr_destroy_reply(*reply);
173 reply->mr_filled += more;
175 if (reply->mr_filled != length)
178 getlong(reply->mr_flattened + 4, data);
179 if (data != MR_VERSION_2)
181 mr_destroy_reply(*reply);
182 return MR_VERSION_MISMATCH;
185 getlong(reply->mr_flattened + 8, reply->u.mr_status);
186 getlong(reply->mr_flattened + 12, reply->mr_argc);
187 if (reply->mr_argc > ((int)length - 16) / 8)
189 mr_destroy_reply(*reply);
192 reply->mr_argv = malloc(reply->mr_argc * sizeof(char *));
193 reply->mr_argl = malloc(reply->mr_argc * sizeof(int));
194 if (reply->mr_argc && (!reply->mr_argv || !reply->mr_argl))
196 mr_destroy_reply(*reply);
200 p = (char *)reply->mr_flattened + 16;
201 end = (char *)reply->mr_flattened + length;
202 for (i = 0; i < reply->mr_argc && p + 4 <= end; i++)
204 getlong(p, reply->mr_argl[i]);
205 if (p + 4 + reply->mr_argl[i] > end)
207 reply->mr_argv[i] = p + 4;
208 p += 4 + reply->mr_argl[i] + (4 - reply->mr_argl[i] % 4) % 4;
211 if (i != reply->mr_argc)
213 mr_destroy_reply(*reply);
220 void mr_destroy_reply(mr_params reply)
224 free(reply.mr_flattened);