00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <errno.h>
00020 #include <string.h>
00021 #include <unistd.h>
00022 #include <sys/types.h>
00023 #include <sys/socket.h>
00024 #include <netinet/in.h>
00025 #include <arpa/inet.h>
00026 #include <oasys/compat/inet_aton.h>
00027 #include <oasys/compat/inttypes.h>
00028
00029 #include "dtn_ipc.h"
00030 #include "dtn_errno.h"
00031 #include "dtn_types.h"
00032
00033
00034 int dtnipc_version = DTN_IPC_VERSION;
00035
00036 const char*
00037 dtnipc_msgtoa(u_int8_t type)
00038 {
00039 #define CASE(_type) case _type : return #_type; break;
00040
00041 switch(type) {
00042 CASE(DTN_OPEN);
00043 CASE(DTN_CLOSE);
00044 CASE(DTN_LOCAL_EID);
00045 CASE(DTN_REGISTER);
00046 CASE(DTN_UNREGISTER);
00047 CASE(DTN_FIND_REGISTRATION);
00048 CASE(DTN_CHANGE_REGISTRATION);
00049 CASE(DTN_BIND);
00050 CASE(DTN_SEND);
00051 CASE(DTN_RECV);
00052 CASE(DTN_BEGIN_POLL);
00053 CASE(DTN_CANCEL_POLL);
00054
00055 default:
00056 return "(unknown type)";
00057 }
00058
00059 #undef CASE
00060 }
00061
00062
00063
00064
00065 int
00066 dtnipc_open(dtnipc_handle_t* handle)
00067 {
00068 int ret;
00069 char *env, *end;
00070 struct sockaddr_in sa;
00071 in_addr_t ipc_addr;
00072 u_int16_t ipc_port;
00073 u_int32_t handshake;
00074 u_int port;
00075
00076
00077 memset(handle, 0, sizeof(dtnipc_handle_t));
00078
00079
00080
00081
00082
00083 xdrmem_create(&handle->xdr_encode, handle->buf + 8,
00084 DTN_MAX_API_MSG, XDR_ENCODE);
00085
00086 xdrmem_create(&handle->xdr_decode, handle->buf + 8,
00087 DTN_MAX_API_MSG, XDR_DECODE);
00088
00089
00090 handle->sock = socket(PF_INET, SOCK_STREAM, 0);
00091 if (handle->sock < 0)
00092 {
00093 handle->err = DTN_ECOMM;
00094 dtnipc_close(handle);
00095 return -1;
00096 }
00097
00098
00099
00100 ipc_addr = htonl(INADDR_LOOPBACK);
00101 ipc_port = DTN_IPC_PORT;
00102
00103 if ((env = getenv("DTNAPI_ADDR")) != NULL) {
00104 if (inet_aton(env, (struct in_addr*)&ipc_addr) == 0)
00105 {
00106 fprintf(stderr, "DTNAPI_ADDR environment variable (%s) "
00107 "not a valid ip address\n", env);
00108 exit(1);
00109 }
00110 }
00111
00112 if ((env = getenv("DTNAPI_PORT")) != NULL) {
00113 port = strtoul(env, &end, 10);
00114 if (*end != '\0' || port > 0xffff)
00115 {
00116 fprintf(stderr, "DTNAPI_PORT environment variable (%s) "
00117 "not a valid ip port\n", env);
00118 exit(1);
00119 }
00120 ipc_port = (u_int16_t)port;
00121 }
00122
00123
00124 memset(&sa, 0, sizeof(sa));
00125 sa.sin_family = AF_INET;
00126 sa.sin_addr.s_addr = ipc_addr;
00127 sa.sin_port = htons(ipc_port);
00128
00129 ret = connect(handle->sock, (const struct sockaddr*)&sa, sizeof(sa));
00130 if (ret != 0) {
00131 handle->err = DTN_ECOMM;
00132 dtnipc_close(handle);
00133 return -1;
00134 }
00135
00136
00137
00138
00139 handshake = htonl(DTN_OPEN << 16 | dtnipc_version);
00140 ret = write(handle->sock, &handshake, sizeof(handshake));
00141 if (ret != sizeof(handshake)) {
00142 handle->err = DTN_ECOMM;
00143 dtnipc_close(handle);
00144 return -1;
00145 }
00146
00147
00148 handshake = 0;
00149 ret = read(handle->sock, &handshake, sizeof(handshake));
00150 if (ret != sizeof(handshake) || (ntohl(handshake) >> 16) != DTN_OPEN) {
00151 handle->err = DTN_ECOMM;
00152 dtnipc_close(handle);
00153 return -1;
00154 }
00155
00156 if ((ntohl(handshake) & 0x0ffff) != DTN_IPC_VERSION) {
00157 handle->err = DTN_EMSGTYPE;
00158 dtnipc_close(handle);
00159 return -1;
00160 }
00161
00162 return 0;
00163 }
00164
00165
00166
00167
00168
00169 int
00170 dtnipc_close(dtnipc_handle_t* handle)
00171 {
00172 int ret;
00173
00174
00175 if (handle->err != DTN_ECOMM) {
00176 ret = dtnipc_send_recv(handle, DTN_CLOSE);
00177 } else {
00178 ret = -1;
00179 }
00180
00181 xdr_destroy(&handle->xdr_encode);
00182 xdr_destroy(&handle->xdr_decode);
00183
00184 if (handle->sock > 0) {
00185 close(handle->sock);
00186 }
00187
00188 handle->sock = 0;
00189
00190 return ret;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 int
00200 dtnipc_send(dtnipc_handle_t* handle, dtnapi_message_type_t type)
00201 {
00202 int ret;
00203 u_int32_t len, msglen;
00204
00205
00206
00207
00208
00209
00210 handle->buf[3] = type;
00211
00212 len = xdr_getpos(&handle->xdr_encode);
00213 msglen = len + 5;
00214 len = htonl(len);
00215 memcpy(&handle->buf[4], &len, sizeof(len));
00216
00217
00218 xdr_setpos(&handle->xdr_encode, 0);
00219
00220
00221 char* bp = &handle->buf[3];
00222 do {
00223 ret = write(handle->sock, bp, msglen);
00224
00225 if (ret <= 0) {
00226 if (errno == EINTR)
00227 continue;
00228
00229 handle->err = DTN_ECOMM;
00230 dtnipc_close(handle);
00231 return -1;
00232 }
00233
00234 bp += ret;
00235 msglen -= ret;
00236
00237 } while (msglen > 0);
00238
00239 return 0;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 int
00251 dtnipc_recv(dtnipc_handle_t* handle, int* status)
00252 {
00253 int ret;
00254 u_int32_t len, nread;
00255 u_int32_t statuscode;
00256
00257
00258 xdr_setpos(&handle->xdr_decode, 0);
00259
00260
00261 ret = read(handle->sock, handle->buf, sizeof(handle->buf));
00262
00263
00264 if (ret < 8) {
00265 handle->err = DTN_ECOMM;
00266 dtnipc_close(handle);
00267 return -1;
00268 }
00269
00270 memcpy(&statuscode, handle->buf, sizeof(statuscode));
00271 statuscode = ntohl(statuscode);
00272 *status = statuscode;
00273
00274 memcpy(&len, &handle->buf[4], sizeof(len));
00275 len = ntohl(len);
00276
00277
00278 nread = ret;
00279 while (nread < len + 8) {
00280 ret = read(handle->sock,
00281 &handle->buf[nread], sizeof(handle->buf) - nread);
00282 if (ret <= 0) {
00283 if (errno == EINTR)
00284 continue;
00285
00286 handle->err = DTN_ECOMM;
00287 dtnipc_close(handle);
00288 return -1;
00289 }
00290
00291 nread += ret;
00292 }
00293
00294 return len;
00295 }
00296
00297
00303 int dtnipc_send_recv(dtnipc_handle_t* handle, dtnapi_message_type_t type)
00304 {
00305 int status;
00306
00307
00308 if (dtnipc_send(handle, type) < 0) {
00309 return -1;
00310 }
00311
00312
00313 if (dtnipc_recv(handle, &status) < 0) {
00314 return -1;
00315 }
00316
00317
00318 if (status != DTN_SUCCESS) {
00319 handle->err = status;
00320 return -1;
00321 }
00322
00323 return 0;
00324 }