00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #include <errno.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <fcntl.h>
00025 #include <string.h>
00026 #include <limits.h>
00027 #include <sys/types.h>
00028 #include <sys/socket.h>
00029 #include <sys/stat.h>
00030 #include <netinet/in.h>
00031 #include <stdlib.h>
00032 #include <unistd.h>
00033
00034 #include "dtn_api.h"
00035 #include "dtn_ipc.h"
00036
00037
00038 int
00039 dtn_open(dtn_handle_t* h)
00040 {
00041 dtnipc_handle_t* handle;
00042
00043 handle = (dtnipc_handle_t *) malloc(sizeof(struct dtnipc_handle));
00044 if (!handle) {
00045 *h = NULL;
00046 return DTN_EINTERNAL;
00047 }
00048
00049 if (dtnipc_open(handle) != 0) {
00050 int ret = handle->err;
00051 free(handle);
00052 *h = NULL;
00053 return ret;
00054 }
00055
00056 xdr_setpos(&handle->xdr_encode, 0);
00057 xdr_setpos(&handle->xdr_decode, 0);
00058
00059 *h = (dtn_handle_t)handle;
00060 return DTN_SUCCESS;
00061 }
00062
00063
00064 int
00065 dtn_close(dtn_handle_t handle)
00066 {
00067 dtnipc_close((dtnipc_handle_t *)handle);
00068 free(handle);
00069 return DTN_SUCCESS;
00070 }
00071
00072
00073 int
00074 dtn_errno(dtn_handle_t handle)
00075 {
00076 return ((dtnipc_handle_t*)handle)->err;
00077 }
00078
00079
00080 void
00081 dtn_set_errno(dtn_handle_t handle, int err)
00082 {
00083 ((dtnipc_handle_t*)handle)->err = err;
00084 }
00085
00086
00087 int
00088 dtn_build_local_eid(dtn_handle_t h,
00089 dtn_endpoint_id_t* local_eid,
00090 const char* tag)
00091 {
00092 int status;
00093 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00094 XDR* xdr_encode = &handle->xdr_encode;
00095 XDR* xdr_decode = &handle->xdr_decode;
00096 struct dtn_service_tag_t service_tag;
00097
00098
00099 if (handle->in_poll) {
00100 handle->err = DTN_EINPOLL;
00101 return -1;
00102 }
00103
00104
00105 size_t len = strlen(tag) + 1;
00106 if (len > DTN_MAX_ENDPOINT_ID) {
00107 handle->err = DTN_EINVAL;
00108 return -1;
00109 }
00110
00111
00112 memset(&service_tag, 0, sizeof(service_tag));
00113 memcpy(&service_tag.tag[0], tag, len);
00114 if (!xdr_dtn_service_tag_t(xdr_encode, &service_tag)) {
00115 handle->err = DTN_EXDR;
00116 return -1;
00117 }
00118
00119
00120 if (dtnipc_send(handle, DTN_LOCAL_EID) != 0) {
00121 return -1;
00122 }
00123
00124
00125 if (dtnipc_recv(handle, &status) < 0) {
00126 return -1;
00127 }
00128
00129
00130 if (status != DTN_SUCCESS) {
00131 handle->err = status;
00132 return -1;
00133 }
00134
00135
00136 memset(local_eid, 0, sizeof(*local_eid));
00137 if (!xdr_dtn_endpoint_id_t(xdr_decode, local_eid)) {
00138 handle->err = DTN_EXDR;
00139 return -1;
00140 }
00141
00142 return 0;
00143 }
00144
00145
00146 int
00147 dtn_register(dtn_handle_t h,
00148 dtn_reg_info_t *reginfo,
00149 dtn_reg_id_t* newregid)
00150 {
00151 int status;
00152 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00153 XDR* xdr_encode = &handle->xdr_encode;
00154 XDR* xdr_decode = &handle->xdr_decode;
00155
00156
00157 if (handle->in_poll) {
00158 handle->err = DTN_EINPOLL;
00159 return -1;
00160 }
00161
00162
00163 if (!xdr_dtn_reg_info_t(xdr_encode, reginfo)) {
00164 handle->err = DTN_EXDR;
00165 return -1;
00166 }
00167
00168
00169 if (dtnipc_send(handle, DTN_REGISTER) != 0) {
00170 return -1;
00171 }
00172
00173
00174 if (dtnipc_recv(handle, &status) < 0) {
00175 return -1;
00176 }
00177
00178
00179 if (status != DTN_SUCCESS) {
00180 handle->err = status;
00181 return -1;
00182 }
00183
00184
00185 if (!xdr_dtn_reg_id_t(xdr_decode, newregid)) {
00186 handle->err = DTN_EXDR;
00187 return -1;
00188 }
00189
00190 return 0;
00191 }
00192
00193
00194 int
00195 dtn_unregister(dtn_handle_t h, dtn_reg_id_t regid)
00196 {
00197 int status;
00198 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00199
00200 XDR* xdr_encode = &handle->xdr_encode;
00201
00202
00203 if (handle->in_poll) {
00204 handle->err = DTN_EINPOLL;
00205 return -1;
00206 }
00207
00208
00209 if (!xdr_dtn_reg_id_t(xdr_encode, ®id)) {
00210 handle->err = DTN_EXDR;
00211 return -1;
00212 }
00213
00214
00215 if (dtnipc_send(handle, DTN_UNREGISTER) != 0) {
00216 return -1;
00217 }
00218
00219
00220 if (dtnipc_recv(handle, &status) < 0) {
00221 return -1;
00222 }
00223
00224
00225 if (status != DTN_SUCCESS) {
00226 handle->err = status;
00227 return -1;
00228 }
00229
00230 return 0;
00231 }
00232
00233
00234 int
00235 dtn_find_registration(dtn_handle_t h,
00236 dtn_endpoint_id_t *eid,
00237 dtn_reg_id_t* regid)
00238 {
00239 int status;
00240 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00241 XDR* xdr_encode = &handle->xdr_encode;
00242 XDR* xdr_decode = &handle->xdr_decode;
00243
00244
00245 if (handle->in_poll) {
00246 handle->err = DTN_EINPOLL;
00247 return -1;
00248 }
00249
00250
00251 if (!xdr_dtn_endpoint_id_t(xdr_encode, eid)) {
00252 handle->err = DTN_EXDR;
00253 return -1;
00254 }
00255
00256
00257 if (dtnipc_send(handle, DTN_FIND_REGISTRATION) != 0) {
00258 return -1;
00259 }
00260
00261
00262 if (dtnipc_recv(handle, &status) < 0) {
00263 return -1;
00264 }
00265
00266
00267 if (status != DTN_SUCCESS) {
00268 handle->err = status;
00269 return -1;
00270 }
00271
00272
00273 if (!xdr_dtn_reg_id_t(xdr_decode, regid)) {
00274 handle->err = DTN_EXDR;
00275 return -1;
00276 }
00277
00278 return 0;
00279 }
00280
00281
00282 int
00283 dtn_change_registration(dtn_handle_t h,
00284 dtn_reg_id_t regid,
00285 dtn_reg_info_t *reginfo)
00286 {
00287 (void)regid;
00288 (void)reginfo;
00289
00290
00291 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00292
00293
00294 if (handle->in_poll) {
00295 handle->err = DTN_EINPOLL;
00296 return -1;
00297 }
00298
00299 handle->err = DTN_EINTERNAL;
00300 return -1;
00301 }
00302
00303
00304 int
00305 dtn_bind(dtn_handle_t h, dtn_reg_id_t regid)
00306 {
00307 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00308 XDR* xdr_encode = &handle->xdr_encode;
00309
00310
00311 if (handle->in_poll) {
00312 handle->err = DTN_EINPOLL;
00313 return -1;
00314 }
00315
00316
00317 if (!xdr_dtn_reg_id_t(xdr_encode, ®id)) {
00318 handle->err = DTN_EXDR;
00319 return -1;
00320 }
00321
00322
00323 if (dtnipc_send_recv(handle, DTN_BIND) < 0) {
00324 return -1;
00325 }
00326
00327 return 0;
00328 }
00329
00330
00331 int
00332 dtn_unbind(dtn_handle_t h, dtn_reg_id_t regid)
00333 {
00334 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00335 XDR* xdr_encode = &handle->xdr_encode;
00336
00337
00338 if (handle->in_poll) {
00339 handle->err = DTN_EINPOLL;
00340 return -1;
00341 }
00342
00343
00344 if (!xdr_dtn_reg_id_t(xdr_encode, ®id)) {
00345 handle->err = DTN_EXDR;
00346 return -1;
00347 }
00348
00349
00350 if (dtnipc_send_recv(handle, DTN_UNBIND) < 0) {
00351 return -1;
00352 }
00353
00354 return 0;
00355 }
00356
00357
00358 int
00359 dtn_send(dtn_handle_t h,
00360 dtn_reg_id_t regid,
00361 dtn_bundle_spec_t* spec,
00362 dtn_bundle_payload_t* payload,
00363 dtn_bundle_id_t* id)
00364 {
00365 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00366 XDR* xdr_encode = &handle->xdr_encode;
00367 XDR* xdr_decode = &handle->xdr_decode;
00368
00369
00370 if (handle->in_poll) {
00371 handle->err = DTN_EINPOLL;
00372 return -1;
00373 }
00374
00375
00376 if ((!xdr_dtn_reg_id_t(xdr_encode, ®id)) ||
00377 (!xdr_dtn_bundle_spec_t(xdr_encode, spec)) ||
00378 (!xdr_dtn_bundle_payload_t(xdr_encode, payload))) {
00379 handle->err = DTN_EXDR;
00380 return -1;
00381 }
00382
00383
00384 if (dtnipc_send_recv(handle, DTN_SEND) < 0) {
00385 return -1;
00386 }
00387
00388
00389 memset(id, 0, sizeof(id));
00390
00391 if (!xdr_dtn_bundle_id_t(xdr_decode, id))
00392 {
00393 handle->err = DTN_EXDR;
00394 return DTN_EXDR;
00395 }
00396
00397 return 0;
00398 }
00399
00400
00401 int
00402 dtn_cancel(dtn_handle_t h,
00403 dtn_bundle_id_t* id)
00404 {
00405 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00406 XDR* xdr_encode = &handle->xdr_encode;
00407
00408
00409 if (handle->in_poll) {
00410 handle->err = DTN_EINPOLL;
00411 return -1;
00412 }
00413
00414
00415 if (!xdr_dtn_bundle_id_t(xdr_encode, id)) {
00416 handle->err = DTN_EXDR;
00417 return -1;
00418 }
00419
00420
00421 if (dtnipc_send_recv(handle, DTN_CANCEL) < 0) {
00422 return -1;
00423 }
00424
00425 return 0;
00426 }
00427
00428
00429 int
00430 dtn_recv(dtn_handle_t h,
00431 dtn_bundle_spec_t* spec,
00432 dtn_bundle_payload_location_t location,
00433 dtn_bundle_payload_t* payload,
00434 dtn_timeval_t timeout)
00435 {
00436 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00437 XDR* xdr_encode = &handle->xdr_encode;
00438 XDR* xdr_decode = &handle->xdr_decode;
00439
00440 if (handle->in_poll) {
00441 handle->in_poll = 0;
00442
00443 int poll_status = 0;
00444 if (dtnipc_recv(handle, &poll_status) != 0) {
00445 return -1;
00446 }
00447
00448 if (poll_status != DTN_SUCCESS) {
00449 handle->err = poll_status;
00450 return -1;
00451 }
00452 }
00453
00454
00455 memset(spec, 0, sizeof(*spec));
00456 memset(payload, 0, sizeof(*payload));
00457
00458
00459 if ((!xdr_dtn_bundle_payload_location_t(xdr_encode, &location)) ||
00460 (!xdr_dtn_timeval_t(xdr_encode, &timeout)))
00461 {
00462 handle->err = DTN_EXDR;
00463 return -1;
00464 }
00465
00466
00467 if (dtnipc_send_recv(handle, DTN_RECV) < 0) {
00468 return -1;
00469 }
00470
00471
00472 if (!xdr_dtn_bundle_spec_t(xdr_decode, spec) ||
00473 !xdr_dtn_bundle_payload_t(xdr_decode, payload))
00474 {
00475 handle->err = DTN_EXDR;
00476 return -1;
00477 }
00478
00479
00480
00481
00482 if (location == DTN_PAYLOAD_MEM && payload->location == DTN_PAYLOAD_FILE)
00483 {
00484 char filename[PATH_MAX];
00485 strncpy(filename, payload->filename.filename_val, PATH_MAX);
00486
00487 int fd = open(filename, O_RDONLY, 0);
00488 if (fd <= 0) {
00489 fprintf(stderr, "DTN API internal error opening payload file %s: %s\n",
00490 filename, strerror(errno));
00491 return DTN_EXDR;
00492 }
00493
00494 struct stat st;
00495 if (fstat(fd, &st) != 0) {
00496 fprintf(stderr, "DTN API internal error getting stat of payload file: %s\n",
00497 strerror(errno));
00498 return DTN_EXDR;
00499 }
00500
00501 dtn_free_payload(payload);
00502
00503 payload->location = DTN_PAYLOAD_MEM;
00504 unsigned int len = st.st_size;
00505 payload->buf.buf_len = len;
00506 payload->buf.buf_val = (char*)malloc(len);
00507
00508 char* bp = payload->buf.buf_val;
00509 do {
00510 int n = read(fd, bp, len);
00511
00512 if (n <= 0) {
00513 fprintf(stderr,
00514 "DTN API internal error reading payload file (%d/%u): %s\n",
00515 n, len, strerror(errno));
00516 return DTN_EXDR;
00517 }
00518
00519 len -= n;
00520 bp += n;
00521 } while (len > 0);
00522
00523 close(fd);
00524
00525 if (unlink(filename) != 0) {
00526 fprintf(stderr, "DTN API internal error removing payload file %s: %s\n",
00527 filename, strerror(errno));
00528 return DTN_EXDR;
00529 }
00530 }
00531 else if (location != payload->location)
00532 {
00533 fprintf(stderr,
00534 "DTN API internal error: location != payload location\n");
00535
00536 handle->err = DTN_EXDR;
00537 return -1;
00538 }
00539
00540 return 0;
00541 }
00542
00543
00544 int
00545 dtn_session_update(dtn_handle_t h,
00546 unsigned int* status,
00547 dtn_endpoint_id_t* session,
00548 dtn_timeval_t timeout)
00549 {
00550 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00551 XDR* xdr_encode = &handle->xdr_encode;
00552 XDR* xdr_decode = &handle->xdr_decode;
00553
00554 if (handle->in_poll) {
00555 handle->in_poll = 0;
00556
00557 int poll_status = 0;
00558 if (dtnipc_recv(handle, &poll_status) != 0) {
00559 return -1;
00560 }
00561
00562 if (poll_status != DTN_SUCCESS) {
00563 handle->err = poll_status;
00564 return -1;
00565 }
00566 }
00567
00568
00569 if ((!xdr_dtn_timeval_t(xdr_encode, &timeout)))
00570 {
00571 handle->err = DTN_EXDR;
00572 return -1;
00573 }
00574
00575
00576 if (dtnipc_send_recv(handle, DTN_SESSION_UPDATE) < 0) {
00577 return -1;
00578 }
00579
00580 memset(status, 0, sizeof(*status));
00581 memset(session, 0, sizeof(*session));
00582
00583
00584 if (!xdr_u_int(xdr_decode, status) ||
00585 !xdr_dtn_endpoint_id_t(xdr_decode, session))
00586 {
00587 handle->err = DTN_EXDR;
00588 return -1;
00589 }
00590
00591 return 0;
00592 }
00593
00594
00595 int
00596 dtn_poll_fd(dtn_handle_t h)
00597 {
00598 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00599 return handle->sock;
00600 }
00601
00602
00603 int
00604 dtn_begin_poll(dtn_handle_t h, dtn_timeval_t timeout)
00605 {
00606 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00607 XDR* xdr_encode = &handle->xdr_encode;
00608
00609
00610 if (handle->in_poll) {
00611 handle->err = DTN_EINPOLL;
00612 return -1;
00613 }
00614
00615 handle->in_poll = 1;
00616
00617 if ((!xdr_dtn_timeval_t(xdr_encode, &timeout)))
00618 {
00619 handle->err = DTN_EXDR;
00620 return -1;
00621 }
00622
00623
00624
00625 if (dtnipc_send(handle, DTN_BEGIN_POLL) < 0) {
00626 return -1;
00627 }
00628
00629 return handle->sock;
00630 }
00631
00632
00633 int
00634 dtn_cancel_poll(dtn_handle_t h)
00635 {
00636 dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00637
00638
00639 if (! (handle->in_poll)) {
00640 handle->err = DTN_EINVAL;
00641 return -1;
00642 }
00643
00644
00645 handle->in_poll = 0;
00646
00647
00648
00649 int poll_status = dtnipc_send_recv(handle, DTN_CANCEL_POLL);
00650 if (poll_status != DTN_SUCCESS && poll_status != DTN_ETIMEOUT) {
00651 handle->err = poll_status;
00652 return -1;
00653 }
00654
00655 int cancel_status;
00656 if (dtnipc_recv(handle, &cancel_status) != 0) {
00657 return -1;
00658 }
00659 handle->err = cancel_status;
00660
00661 if (cancel_status != DTN_SUCCESS) {
00662 return -1;
00663 }
00664
00665 return 0;
00666 }
00667
00668
00669
00670
00671
00672
00673 void
00674 dtn_copy_eid(dtn_endpoint_id_t* dst, dtn_endpoint_id_t* src)
00675 {
00676 memcpy(dst->uri, src->uri, DTN_MAX_ENDPOINT_ID);
00677 }
00678
00679
00680 int
00681 dtn_parse_eid_string(dtn_endpoint_id_t* eid, const char* str)
00682 {
00683 char *s;
00684 size_t len;
00685
00686 len = strlen(str) + 1;
00687
00688
00689 if (len > DTN_MAX_ENDPOINT_ID) {
00690 return DTN_ESIZE;
00691 }
00692
00693
00694 s = strchr(str, ':');
00695 if (!s) {
00696 return DTN_EINVAL;
00697 }
00698
00699
00700
00701 memcpy(&eid->uri[0], str, len);
00702
00703 return 0;
00704 }
00705
00706
00707 int
00708 dtn_set_payload(dtn_bundle_payload_t* payload,
00709 dtn_bundle_payload_location_t location,
00710 char* val, int len)
00711 {
00712 memset(payload, 0, sizeof(dtn_bundle_payload_t));
00713 payload->location = location;
00714
00715 if (location == DTN_PAYLOAD_MEM && len > DTN_MAX_BUNDLE_MEM) {
00716 return DTN_ESIZE;
00717 }
00718
00719 switch (location) {
00720 case DTN_PAYLOAD_MEM:
00721 payload->buf.buf_val = val;
00722 payload->buf.buf_len = len;
00723 break;
00724 case DTN_PAYLOAD_FILE:
00725 case DTN_PAYLOAD_TEMP_FILE:
00726 payload->filename.filename_val = val;
00727 payload->filename.filename_len = len;
00728 break;
00729 }
00730
00731 return 0;
00732 }
00733
00734
00735 void
00736 dtn_free_payload(dtn_bundle_payload_t* payload)
00737 {
00738 xdr_free((xdrproc_t)xdr_dtn_bundle_payload_t, (char*)payload);
00739 }
00740
00741
00742 const char*
00743 dtn_status_report_reason_to_str(dtn_status_report_reason_t reason)
00744 {
00745 switch (reason) {
00746 case REASON_NO_ADDTL_INFO:
00747 return "no additional information";
00748
00749 case REASON_LIFETIME_EXPIRED:
00750 return "lifetime expired";
00751
00752 case REASON_FORWARDED_UNIDIR_LINK:
00753 return "forwarded over unidirectional link";
00754
00755 case REASON_TRANSMISSION_CANCELLED:
00756 return "transmission cancelled";
00757
00758 case REASON_DEPLETED_STORAGE:
00759 return "depleted storage";
00760
00761 case REASON_ENDPOINT_ID_UNINTELLIGIBLE:
00762 return "endpoint id unintelligible";
00763
00764 case REASON_NO_ROUTE_TO_DEST:
00765 return "no known route to destination";
00766
00767 case REASON_NO_TIMELY_CONTACT:
00768 return "no timely contact";
00769
00770 case REASON_BLOCK_UNINTELLIGIBLE:
00771 return "block unintelligible";
00772
00773 default:
00774 return "(unknown reason)";
00775 }
00776 }