dtn_api.c

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

Generated on Fri Dec 22 14:47:58 2006 for DTN Reference Implementation by  doxygen 1.5.1