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