dtn_api.c

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 
00018 #include <errno.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <sys/types.h>
00023 #include <sys/socket.h>
00024 #include <netinet/in.h>
00025 #include <stdlib.h>
00026 
00027 #include "dtn_api.h"
00028 #include "dtn_ipc.h"
00029 
00030 //----------------------------------------------------------------------
00031 int 
00032 dtn_open(dtn_handle_t* h)
00033 {
00034     dtnipc_handle_t* handle;
00035 
00036     handle = (dtnipc_handle_t *) malloc(sizeof(struct dtnipc_handle));
00037     if (!handle) {
00038         *h = NULL;
00039         return DTN_EINTERNAL;
00040     }
00041     
00042     if (dtnipc_open(handle) != 0) {
00043         int ret = handle->err;
00044         free(handle);
00045         *h = NULL;
00046         return ret;
00047     }
00048 
00049     xdr_setpos(&handle->xdr_encode, 0);
00050     xdr_setpos(&handle->xdr_decode, 0);
00051 
00052     *h = (dtn_handle_t)handle;
00053     return DTN_SUCCESS;
00054 }
00055 
00056 //----------------------------------------------------------------------
00057 int
00058 dtn_close(dtn_handle_t handle)
00059 {
00060     dtnipc_close((dtnipc_handle_t *)handle);
00061     free(handle);
00062     return DTN_SUCCESS;
00063 }
00064 
00065 //----------------------------------------------------------------------
00066 int
00067 dtn_errno(dtn_handle_t handle)
00068 {
00069     return ((dtnipc_handle_t*)handle)->err;
00070 }
00071 
00072 //----------------------------------------------------------------------
00073 char*
00074 dtn_strerror(int err)
00075 {
00076     switch(err) {
00077     case DTN_SUCCESS:   return "success";
00078     case DTN_EINVAL:    return "invalid argument";
00079     case DTN_EXDR:      return "error in xdr routines";
00080     case DTN_ECOMM:     return "error in ipc communication";
00081     case DTN_ECONNECT:  return "error connecting to server";
00082     case DTN_ETIMEOUT:  return "operation timed out";
00083     case DTN_ESIZE:     return "payload too large";
00084     case DTN_ENOTFOUND: return "not found";
00085     case DTN_EINTERNAL: return "internal error";
00086     case DTN_EINPOLL:   return "illegal operation called after dtn_poll";
00087     case DTN_EBUSY:     return "registration already in use";
00088     case DTN_EMSGTYPE:  return "unknown ipc message type";
00089     case DTN_ENOSPACE:  return "no storage space";
00090     case -1:            return "(invalid error code -1)";
00091     }
00092 
00093     // there's a small race condition here in case there are two
00094     // simultaneous calls that will clobber the same buffer, but this
00095     // should be rare and the worst that happens is that the output
00096     // string is garbled
00097     static char buf[128];
00098     snprintf(buf, sizeof(buf), "(unknown error %d)", err);
00099     return buf;
00100 }
00101 
00102 //----------------------------------------------------------------------
00103 int
00104 dtn_build_local_eid(dtn_handle_t h,
00105                     dtn_endpoint_id_t* local_eid,
00106                     const char* tag)
00107 {
00108     int status;
00109     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00110     XDR* xdr_encode = &handle->xdr_encode;
00111     XDR* xdr_decode = &handle->xdr_decode;
00112     struct dtn_service_tag_t service_tag;
00113 
00114     // check if the handle is in the middle of poll
00115     if (handle->in_poll) {
00116         handle->err = DTN_EINPOLL;
00117         return -1;
00118     }
00119     
00120     // validate the tag length
00121     size_t len = strlen(tag) + 1;
00122     if (len > DTN_MAX_ENDPOINT_ID) {
00123         handle->err = DTN_EINVAL;
00124         return -1;
00125     }
00126 
00127     // pack the request
00128     memset(&service_tag, 0, sizeof(service_tag));
00129     memcpy(&service_tag.tag[0], tag, len);
00130     if (!xdr_dtn_service_tag_t(xdr_encode, &service_tag)) {
00131         handle->err = DTN_EXDR;
00132         return -1;
00133     }
00134 
00135     // send the message
00136     if (dtnipc_send(handle, DTN_LOCAL_EID) != 0) {
00137         return -1;
00138     }
00139 
00140     // get the reply
00141     if (dtnipc_recv(handle, &status) < 0) {
00142         return -1;
00143     }
00144 
00145     // handle server-side errors
00146     if (status != DTN_SUCCESS) {
00147         handle->err = status;
00148         return -1;
00149     }
00150 
00151     // unpack the response
00152     memset(local_eid, 0, sizeof(*local_eid));
00153     if (!xdr_dtn_endpoint_id_t(xdr_decode, local_eid)) {
00154         handle->err = DTN_EXDR;
00155         return -1;
00156     }
00157     
00158     return 0;
00159 }
00160 
00161 //----------------------------------------------------------------------
00162 int
00163 dtn_register(dtn_handle_t h,
00164              dtn_reg_info_t *reginfo,
00165              dtn_reg_id_t* newregid)
00166 {
00167     int status;
00168     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00169     XDR* xdr_encode = &handle->xdr_encode;
00170     XDR* xdr_decode = &handle->xdr_decode;
00171     
00172     // check if the handle is in the middle of poll
00173     if (handle->in_poll) {
00174         handle->err = DTN_EINPOLL;
00175         return -1;
00176     }
00177     
00178     // pack the request
00179     if (!xdr_dtn_reg_info_t(xdr_encode, reginfo)) {
00180         handle->err = DTN_EXDR;
00181         return -1;
00182     }
00183 
00184     // send the message
00185     if (dtnipc_send(handle, DTN_REGISTER) != 0) {
00186         return -1;
00187     }
00188 
00189     // get the reply
00190     if (dtnipc_recv(handle, &status) < 0) {
00191         return -1;
00192     }
00193 
00194     // handle server-side errors
00195     if (status != DTN_SUCCESS) {
00196         handle->err = status;
00197         return -1;
00198     }
00199 
00200     // unpack the response
00201     if (!xdr_dtn_reg_id_t(xdr_decode, newregid)) {
00202         handle->err = DTN_EXDR;
00203         return -1;
00204     }
00205 
00206     return 0;
00207 }
00208 
00209 //----------------------------------------------------------------------
00210 int
00211 dtn_unregister(dtn_handle_t h, dtn_reg_id_t regid)
00212 {
00213     int status;
00214     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00215 
00216     XDR* xdr_encode = &handle->xdr_encode;
00217 
00218     // check if the handle is in the middle of poll
00219     if (handle->in_poll) {
00220         handle->err = DTN_EINPOLL;
00221         return -1;
00222     }
00223     
00224     // pack the request
00225     if (!xdr_dtn_reg_id_t(xdr_encode, &regid)) {
00226         handle->err = DTN_EXDR;
00227         return -1;
00228     }
00229 
00230     // send the message
00231     if (dtnipc_send(handle, DTN_UNREGISTER) != 0) {
00232         return -1;
00233     }
00234 
00235     // get the reply
00236     if (dtnipc_recv(handle, &status) < 0) {
00237         return -1;
00238     }
00239 
00240     // handle server-side errors
00241     if (status != DTN_SUCCESS) {
00242         handle->err = status;
00243         return -1;
00244     }
00245     
00246     return 0;
00247 }
00248 
00249 //----------------------------------------------------------------------
00250 int
00251 dtn_find_registration(dtn_handle_t h,
00252                       dtn_endpoint_id_t *eid,
00253                       dtn_reg_id_t* regid)
00254 {
00255     int status;
00256     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00257     XDR* xdr_encode = &handle->xdr_encode;
00258     XDR* xdr_decode = &handle->xdr_decode;
00259 
00260     // check if the handle is in the middle of poll
00261     if (handle->in_poll) {
00262         handle->err = DTN_EINPOLL;
00263         return -1;
00264     }
00265     
00266     // pack the request
00267     if (!xdr_dtn_endpoint_id_t(xdr_encode, eid)) {
00268         handle->err = DTN_EXDR;
00269         return -1;
00270     }
00271 
00272     // send the message
00273     if (dtnipc_send(handle, DTN_FIND_REGISTRATION) != 0) {
00274         return -1;
00275     }
00276 
00277     // get the reply
00278     if (dtnipc_recv(handle, &status) < 0) {
00279         return -1;
00280     }
00281 
00282     // handle server-side errors
00283     if (status != DTN_SUCCESS) {
00284         handle->err = status;
00285         return -1;
00286     }
00287 
00288     // unpack the response
00289     if (!xdr_dtn_reg_id_t(xdr_decode, regid)) {
00290         handle->err = DTN_EXDR;
00291         return -1;
00292     }
00293 
00294     return 0;
00295 }
00296 
00297 //----------------------------------------------------------------------
00298 int
00299 dtn_change_registration(dtn_handle_t h,
00300                         dtn_reg_id_t regid,
00301                         dtn_reg_info_t *reginfo)
00302 {
00303     (void)regid;
00304     (void)reginfo;
00305     
00306     // XXX/demmer implement me
00307     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00308 
00309     // check if the handle is in the middle of poll
00310     if (handle->in_poll) {
00311         handle->err = DTN_EINPOLL;
00312         return -1;
00313     }
00314     
00315     handle->err = DTN_EINTERNAL;
00316     return -1;
00317 }
00318 
00319 //---------------------------------------------------------------------- 
00320 int
00321 dtn_bind(dtn_handle_t h, dtn_reg_id_t regid)
00322 {
00323     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00324     XDR* xdr_encode = &handle->xdr_encode;
00325 
00326     // check if the handle is in the middle of poll
00327     if (handle->in_poll) {
00328         handle->err = DTN_EINPOLL;
00329         return -1;
00330     }
00331     
00332     // pack the request
00333     if (!xdr_dtn_reg_id_t(xdr_encode, &regid)) {
00334         handle->err = DTN_EXDR;
00335         return -1;
00336     }
00337 
00338     // send the message
00339     if (dtnipc_send_recv(handle, DTN_BIND) < 0) {
00340         return -1;
00341     }
00342 
00343     return 0;
00344 }
00345 
00346 //---------------------------------------------------------------------- 
00347 int
00348 dtn_unbind(dtn_handle_t h, dtn_reg_id_t regid)
00349 {
00350     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00351     XDR* xdr_encode = &handle->xdr_encode;
00352 
00353     // check if the handle is in the middle of poll
00354     if (handle->in_poll) {
00355         handle->err = DTN_EINPOLL;
00356         return -1;
00357     }
00358     
00359     // pack the request
00360     if (!xdr_dtn_reg_id_t(xdr_encode, &regid)) {
00361         handle->err = DTN_EXDR;
00362         return -1;
00363     }
00364 
00365     // send the message
00366     if (dtnipc_send_recv(handle, DTN_UNBIND) < 0) {
00367         return -1;
00368     }
00369 
00370     return 0;
00371 }
00372 
00373 //----------------------------------------------------------------------
00374 int
00375 dtn_send(dtn_handle_t h,
00376          dtn_bundle_spec_t* spec,
00377          dtn_bundle_payload_t* payload,
00378          dtn_bundle_id_t* id)
00379 {
00380     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00381     XDR* xdr_encode = &handle->xdr_encode;
00382     XDR* xdr_decode = &handle->xdr_decode;
00383 
00384     // check if the handle is in the middle of poll
00385     if (handle->in_poll) {
00386         handle->err = DTN_EINPOLL;
00387         return -1;
00388     }
00389 
00390     // pack the arguments
00391     if ((!xdr_dtn_bundle_spec_t(xdr_encode, spec)) ||
00392         (!xdr_dtn_bundle_payload_t(xdr_encode, payload))) {
00393         handle->err = DTN_EXDR;
00394         return -1;
00395     }
00396 
00397     // send the message
00398     if (dtnipc_send_recv(handle, DTN_SEND) < 0) {
00399         return -1;
00400     }
00401     
00402     // unpack the bundle id return value
00403     memset(id, 0, sizeof(id));
00404     
00405     if (!xdr_dtn_bundle_id_t(xdr_decode, id))
00406     {
00407         handle->err = DTN_EXDR;
00408         return DTN_EXDR;
00409     }
00410 
00411     return 0;
00412 }
00413 
00414 //----------------------------------------------------------------------
00415 int
00416 dtn_recv(dtn_handle_t h,
00417          dtn_bundle_spec_t* spec,
00418          dtn_bundle_payload_location_t location,
00419          dtn_bundle_payload_t* payload,
00420          dtn_timeval_t timeout)
00421 {
00422     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00423     XDR* xdr_encode = &handle->xdr_encode;
00424     XDR* xdr_decode = &handle->xdr_decode;
00425 
00426     if (handle->in_poll) {
00427         int poll_status = 0;
00428         if (dtnipc_recv(handle, &poll_status) != 0) {
00429             return -1;
00430         }
00431         
00432         if (poll_status != DTN_SUCCESS) {
00433             handle->err = poll_status;
00434             return -1;
00435         }
00436     }
00437 
00438     
00439     // zero out the spec and payload structures
00440     memset(spec, 0, sizeof(*spec));
00441     memset(payload, 0, sizeof(*payload));
00442 
00443     // pack the arguments
00444     if ((!xdr_dtn_bundle_payload_location_t(xdr_encode, &location)) ||
00445         (!xdr_dtn_timeval_t(xdr_encode, &timeout)))
00446     {
00447         handle->err = DTN_EXDR;
00448         return -1;
00449     }
00450 
00451     // send the message
00452     if (dtnipc_send_recv(handle, DTN_RECV) < 0) {
00453         return -1;
00454     }
00455 
00456     // unpack the bundle
00457     if (!xdr_dtn_bundle_spec_t(xdr_decode, spec) ||
00458         !xdr_dtn_bundle_payload_t(xdr_decode, payload))
00459     {
00460         handle->err = DTN_EXDR;
00461         return -1;
00462     }
00463     
00464     return 0;
00465 }
00466 
00467 //----------------------------------------------------------------------
00468 int
00469 dtn_begin_poll(dtn_handle_t h, dtn_timeval_t timeout)
00470 {
00471     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00472     XDR* xdr_encode = &handle->xdr_encode;
00473     
00474     // check if the handle is already in the middle of poll
00475     if (handle->in_poll) {
00476         handle->err = DTN_EINPOLL;
00477         return -1;
00478     }
00479 
00480     handle->in_poll = 1;
00481     
00482     if ((!xdr_dtn_timeval_t(xdr_encode, &timeout)))
00483     {
00484         handle->err = DTN_EXDR;
00485         return -1;
00486     }
00487 
00488     // send the message but don't block for the response code -- we'll
00489     // grab it in dtn_recv or dtn_cancel_poll
00490     if (dtnipc_send(handle, DTN_BEGIN_POLL) < 0) {
00491         return -1;
00492     }
00493     
00494     return 0;
00495 }
00496 
00497 //----------------------------------------------------------------------
00498 int
00499 dtn_cancel_poll(dtn_handle_t h)
00500 {
00501     dtnipc_handle_t* handle = (dtnipc_handle_t*)h;
00502     
00503     // make sure the handle is already in the middle of poll
00504     if (! (handle->in_poll)) {
00505         handle->err = DTN_EINVAL;
00506         return -1;
00507     }
00508 
00509     // clear the poll flag
00510     handle->in_poll = 0;
00511     
00512     // send the message and get the response code. however there is a
00513     // race condition meaning that we can't tell whether what we get
00514     // back is the original response from poll or from the subsequent
00515     // call to cancel poll
00516     if (dtnipc_send_recv(handle, DTN_CANCEL_POLL) < 0) {
00517         return -1;
00518     }
00519     
00520     return 0;
00521 }
00522 
00523 /*************************************************************
00524  *
00525  *                     Utility Functions
00526  *
00527  *************************************************************/
00528 void
00529 dtn_copy_eid(dtn_endpoint_id_t* dst, dtn_endpoint_id_t* src)
00530 {
00531     memcpy(dst->uri, src->uri, DTN_MAX_ENDPOINT_ID);
00532 }
00533 
00534 //----------------------------------------------------------------------
00535 int
00536 dtn_parse_eid_string(dtn_endpoint_id_t* eid, const char* str)
00537 {
00538     char *s;
00539     size_t len;
00540 
00541     len = strlen(str) + 1;
00542 
00543     // check string length
00544     if (len > DTN_MAX_ENDPOINT_ID) {
00545         return DTN_ESIZE;
00546     }
00547     
00548     // make sure there's a colon
00549     s = strchr(str, ':');
00550     if (!s) {
00551         return DTN_EINVAL;
00552     }
00553 
00554     // XXX/demmer make sure the scheme / ssp are comprised only of
00555     // legal URI characters
00556     memcpy(&eid->uri[0], str, len);
00557 
00558     return 0;
00559 }
00560 
00561 //----------------------------------------------------------------------
00562 int
00563 dtn_set_payload(dtn_bundle_payload_t* payload,
00564                 dtn_bundle_payload_location_t location,
00565                 char* val, int len)
00566 {
00567     memset(payload, 0, sizeof(dtn_bundle_payload_t));
00568     payload->location = location;
00569 
00570     if (location == DTN_PAYLOAD_MEM && len > DTN_MAX_BUNDLE_MEM) {
00571         return DTN_ESIZE;
00572     }
00573     
00574     switch (location) {
00575     case DTN_PAYLOAD_MEM:
00576         payload->buf.buf_val = val;
00577         payload->buf.buf_len = len;
00578         break;
00579     case DTN_PAYLOAD_FILE:
00580     case DTN_PAYLOAD_TEMP_FILE:
00581         payload->filename.filename_val = val;
00582         payload->filename.filename_len = len;
00583         break;
00584     }
00585 
00586     return 0;
00587 }
00588 
00589 //----------------------------------------------------------------------
00590 void
00591 dtn_free_payload(dtn_bundle_payload_t* payload)
00592 {
00593     xdr_free((xdrproc_t)xdr_dtn_bundle_payload_t, (char*)payload);
00594 }
00595 
00596 //----------------------------------------------------------------------
00597 const char*
00598 dtn_status_report_reason_to_str(dtn_status_report_reason_t reason)
00599 {
00600     switch (reason) {
00601     case REASON_NO_ADDTL_INFO:
00602         return "no additional information";
00603 
00604     case REASON_LIFETIME_EXPIRED:
00605         return "lifetime expired";
00606 
00607     case REASON_FORWARDED_UNIDIR_LINK:
00608         return "forwarded over unidirectional link";
00609 
00610     case REASON_TRANSMISSION_CANCELLED:
00611         return "transmission cancelled";
00612 
00613     case REASON_DEPLETED_STORAGE:
00614         return "depleted storage";
00615 
00616     case REASON_ENDPOINT_ID_UNINTELLIGIBLE:
00617         return "endpoint id unintelligible";
00618 
00619     case REASON_NO_ROUTE_TO_DEST:
00620         return "no known route to destination";
00621 
00622     case REASON_NO_TIMELY_CONTACT:
00623         return "no timely contact";
00624 
00625     case REASON_BLOCK_UNINTELLIGIBLE:
00626         return "block unintelligible";
00627 
00628     default:
00629         return "(unknown reason)";
00630     }
00631 }

Generated on Thu Jun 7 12:54:26 2007 for DTN Reference Implementation by  doxygen 1.5.1