dnxTransport.c

Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002 
00003    Copyright (c) 2006-2007, Intellectual Reserve, Inc. All rights reserved.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License version 2 as
00007    published by the Free Software Foundation.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; if not, write to the Free Software
00016    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018   --------------------------------------------------------------------------*/
00019 
00028 #include "dnxTransport.h"
00029 #include "dnxTSPI.h"
00030 
00031 #include "dnxDebug.h"
00032 #include "dnxError.h"
00033 #include "dnxLogging.h"
00034 #include "dnxProtocol.h"
00035 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <unistd.h>
00039 #include <string.h>
00040 #include <pthread.h>
00041 #include <syslog.h>
00042 #include <errno.h>
00043 #include <assert.h>
00044 #include <sys/socket.h>
00045 #include <netinet/in.h>
00046 #include <arpa/inet.h>
00047 
00048 #define elemcount(x) (sizeof(x)/sizeof(*(x)))
00049 
00051 #define DNX_MAX_CHAN_MAP   1000
00052 
00054 typedef struct DnxChanMap_
00055 {
00056    char * name;         
00057    char * url;          
00058    int (*txAlloc)(char * url, iDnxChannel ** icpp);  
00059 } DnxChanMap;
00060 
00062 typedef struct DnxTransport
00063 {
00064    char * scheme;
00065    char * libpath;
00066    int (*txAlloc)(char * url, iDnxChannel ** icpp);
00067    int (*txInit)(int (**ptxAlloc)(char * url, iDnxChannel ** icpp));
00068    void (*txExit)(void);
00069 } DnxTransport;
00070 
00071 // ---------------------------------------------------------------------------
00072 // This structure is temporary till we start loading from disk, at which point
00073 // URL schemes may then be added at runtime via the configuration file, eg.,
00074 // transport = dnx+transport : /path/to/transport/service/provider/library
00075 
00076 #include "dnxTcp.h"
00077 #include "dnxUdp.h"
00078 #include "dnxMsgQ.h"
00079 
00080 static DnxTransport gTMList[] =
00081 {
00082    { "tcp",  0, 0, dnxTcpInit,  dnxTcpDeInit  },
00083    { "udp",  0, 0, dnxUdpInit,  dnxUdpDeInit  },
00084    { "msgq", 0, 0, dnxMsgQInit, dnxMsgQDeInit },
00085 };
00086 
00087 // ---------------------------------------------------------------------------
00088 
00089 static int dnxInit = 0;             
00090 static pthread_mutex_t chanMutex;   
00091 static DnxChanMap gChannelMap[DNX_MAX_CHAN_MAP]; 
00092 
00093 /*--------------------------------------------------------------------------
00094                               IMPLEMENTATION
00095   --------------------------------------------------------------------------*/
00096 
00106 char * dnxNtop(const void * sastr, char * buf, size_t bufsz)
00107 {
00108    const struct sockaddr * sa = (const struct sockaddr *)sastr;
00109 
00110    if (!sa)
00111    {
00112       strncpy(buf, "<Unknown Address>", bufsz);
00113       buf[bufsz - 1] = 0;
00114       return buf;
00115    }
00116    switch(sa->sa_family)
00117    {
00118       case AF_INET:
00119          inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, buf, bufsz);
00120          break;
00121 
00122       case AF_INET6:
00123          inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),buf, INET6_ADDRSTRLEN);
00124          break;
00125 
00126       default:
00127          strncpy(buf, "<Unknown AF>", bufsz);
00128          buf[bufsz - 1] = 0;
00129          break;
00130    }
00131    return buf;
00132 }
00133 
00141 static int dnxChanMapUrlParse(DnxChanMap * chanMap, char * url)
00142 {
00143    char * ep;
00144    int i;
00145 
00146    assert(chanMap && url && strlen(url) <= DNX_MAX_URL);
00147 
00148    // locate end of scheme
00149    if ((ep = strstr(url, "://")) == 0)
00150       return DNX_ERR_BADURL;
00151 
00152    // set allocator for this transport based on the scheme string
00153    for (i = 0; i < elemcount(gTMList); i++)
00154       if (!strncmp(url, gTMList[i].scheme, ep - url))
00155       {
00156          chanMap->txAlloc = gTMList[i].txAlloc;
00157          break;
00158       }
00159 
00160    return i < elemcount(gTMList) ? DNX_OK : DNX_ERR_BADURL;
00161 }
00162 
00163 //----------------------------------------------------------------------------
00164 
00172 static int dnxChanMapFindSlot(DnxChanMap ** chanMap)
00173 {
00174    int i;
00175 
00176    assert(chanMap);
00177 
00178    // see if we can find an empty slot in the global channel map
00179    for (i = 0; i < DNX_MAX_CHAN_MAP && gChannelMap[i].name; i++)
00180       ;
00181 
00182    *chanMap = (DnxChanMap *)((i < DNX_MAX_CHAN_MAP) ? &gChannelMap[i] : 0);
00183 
00184    return *chanMap ? DNX_OK : DNX_ERR_CAPACITY;
00185 }
00186 
00187 //----------------------------------------------------------------------------
00188 
00197 static int dnxChanMapFindName(char * name, DnxChanMap ** chanMap)
00198 {
00199    int i;
00200 
00201    assert(name && *name && chanMap);
00202 
00203    // see if this name exists in the global channel map
00204    for (i = 0; i < DNX_MAX_CHAN_MAP; i++)
00205       if (gChannelMap[i].name && !strcmp(name, gChannelMap[i].name))
00206          break;
00207 
00208    *chanMap = (DnxChanMap *)((i < DNX_MAX_CHAN_MAP) ? &gChannelMap[i] : 0);
00209 
00210    return *chanMap ? DNX_OK : DNX_ERR_NOTFOUND;
00211 }
00212 
00213 //----------------------------------------------------------------------------
00214 
00223 static int dnxChanMapAllocChannel(char * name, iDnxChannel ** icpp)
00224 {
00225    DnxChanMap * chanMap;
00226    int ret;
00227 
00228    assert(name && *name && icpp);
00229 
00230    DNX_PT_MUTEX_LOCK(&chanMutex);
00231 
00232    if ((ret = dnxChanMapFindName(name, &chanMap)) == DNX_OK)
00233       ret = chanMap->txAlloc(chanMap->url, icpp);
00234 
00235    DNX_PT_MUTEX_UNLOCK(&chanMutex);
00236 
00237    return ret;
00238 }
00239 
00240 /*--------------------------------------------------------------------------
00241                                  INTERFACE
00242   --------------------------------------------------------------------------*/
00243 
00251 int dnxChanMapAdd(char * name, char * url)
00252 {
00253    DnxChanMap tmp, * chanMap;
00254    int ret;
00255 
00256    assert(name && *name && url && strlen(url) < DNX_MAX_URL);
00257 
00258    // parse and validate the URL
00259    if ((ret = dnxChanMapUrlParse(&tmp, url)) != DNX_OK)
00260       return ret;
00261 
00262    // set the name, unless we are overriding an existing channel
00263    if ((tmp.name = xstrdup(name)) == 0 || (tmp.url = xstrdup(url)) == 0)
00264    {
00265       xfree(tmp.name);
00266       return DNX_ERR_MEMORY;
00267    }
00268 
00269    DNX_PT_MUTEX_LOCK(&chanMutex);
00270 
00271    // see if this name already exists, otherwise grab an empty channel slot
00272    if ((ret = dnxChanMapFindName(name, &chanMap)) == DNX_OK
00273          || (ret = dnxChanMapFindSlot(&chanMap)) == DNX_OK)
00274    {
00275       xfree(chanMap->name);
00276       xfree(chanMap->url);
00277       memcpy(chanMap, &tmp, sizeof *chanMap);
00278    }
00279 
00280    DNX_PT_MUTEX_UNLOCK(&chanMutex);
00281 
00282    // on error, release previously allocated memory
00283    if (ret != DNX_OK)
00284    {
00285       xfree(tmp.name);
00286       xfree(tmp.url);
00287    }
00288    return ret;
00289 }
00290 
00291 //----------------------------------------------------------------------------
00292 
00297 void dnxChanMapDelete(char * name)
00298 {
00299    DnxChanMap * chanMap;
00300 
00301    assert(name && *name);
00302 
00303    DNX_PT_MUTEX_LOCK(&chanMutex);
00304 
00305    // locate resource by name
00306    if (dnxChanMapFindName(name, &chanMap) == DNX_OK)
00307    {
00308       // release allocated variables, clear object
00309       xfree(chanMap->name);
00310       xfree(chanMap->url);
00311       memset(chanMap, 0, sizeof *chanMap);
00312    }
00313 
00314    DNX_PT_MUTEX_UNLOCK(&chanMutex);
00315 }
00316 
00317 //----------------------------------------------------------------------------
00318 
00336 int dnxConnect(char * name, int mode, DnxChannel ** channel)
00337 {
00338    DnxChanMap * chanMap;
00339    iDnxChannel * icp;
00340    int ret;
00341 
00342    assert(name && *name && channel);
00343 
00344    // locate channel resource by name, return a new unopened channel
00345    if ((ret = dnxChanMapAllocChannel(name, &icp)) == DNX_OK)
00346    {
00347       if ((ret = icp->txOpen(icp, mode)) != DNX_OK)
00348          icp->txDelete(icp);
00349    }
00350    if (ret == DNX_OK)
00351       *channel = (DnxChannel *)icp;
00352    return ret;
00353 }
00354 
00355 //----------------------------------------------------------------------------
00356 
00361 void dnxDisconnect(DnxChannel * channel)
00362 {
00363    iDnxChannel * icp = (iDnxChannel *)channel;
00364 
00365    assert(channel);
00366 
00367    if (icp->txClose(icp) == DNX_OK)
00368       icp->txDelete(icp);
00369 }
00370 
00371 //----------------------------------------------------------------------------
00372 
00389 int dnxGet(DnxChannel * channel, char * buf, int * size, int timeout, char * src)
00390 {
00391    iDnxChannel * icp = (iDnxChannel *)channel;
00392    assert(channel && buf && size && *size > 0);
00393    return icp->txRead(icp, buf, size, timeout, src);
00394 }
00395 
00396 //----------------------------------------------------------------------------
00397 
00412 int dnxPut(DnxChannel * channel, char * buf, int size, int timeout, char * dst)
00413 {
00414    iDnxChannel * icp = (iDnxChannel *)channel;
00415    assert(channel && buf && size > 0 && size < DNX_MAX_MSG);
00416    return icp->txWrite(icp, buf, size, timeout, dst);
00417 }
00418 
00419 //----------------------------------------------------------------------------
00420 
00426 void dnxGetStats(DnxChannel * channel, DnxTransStats * tsp)
00427 {
00428    iDnxChannel * icp = (iDnxChannel *)channel;
00429    assert(channel && tsp);
00430    if (icp->txGetStats)
00431       icp->txGetStats(icp, tsp);
00432 }
00433 
00434 //----------------------------------------------------------------------------
00435 
00440 void dnxResetStats(DnxChannel * channel)
00441 {
00442    iDnxChannel * icp = (iDnxChannel *)channel;
00443    assert(channel);
00444    if (icp->txResetStats)
00445       icp->txResetStats(icp);
00446 }
00447 
00448 //----------------------------------------------------------------------------
00449 
00457 int dnxChanMapInit(char * fileName)
00458 {
00459    int i;
00460 
00461    assert(!dnxInit);
00462 
00463    memset(gChannelMap, 0, sizeof gChannelMap);
00464 
00465    DNX_PT_MUTEX_INIT(&chanMutex);
00466 
00467    // initialize transport module table
00468    for (i = 0; i < elemcount(gTMList); i++)
00469    {
00470       int ret;
00471       if ((ret = gTMList[i].txInit(&gTMList[i].txAlloc)) != DNX_OK)
00472       {
00473          while (i--) gTMList[i].txExit();
00474          DNX_PT_MUTEX_DESTROY(&chanMutex);
00475          return ret;
00476       }
00477    }
00478 
00481    dnxInit = 1;
00482 
00483    return DNX_OK;
00484 }
00485 
00486 //----------------------------------------------------------------------------
00487 
00490 void dnxChanMapRelease(void)
00491 {
00492    if (dnxInit)
00493    {
00494       int i;
00495 
00496       DNX_PT_MUTEX_LOCK(&chanMutex);
00497 
00498       for (i = 0; i < DNX_MAX_CHAN_MAP; i++)
00499       {
00500          xfree(gChannelMap[i].name);
00501          xfree(gChannelMap[i].url);
00502       }
00503 
00504       memset(gChannelMap, 0, sizeof gChannelMap);
00505 
00506       DNX_PT_MUTEX_UNLOCK(&chanMutex);
00507       DNX_PT_MUTEX_DESTROY(&chanMutex);
00508 
00509       // de-initialize transport module table
00510       i = elemcount(gTMList);
00511       while (i--) gTMList[i].txExit();
00512 
00513       dnxInit = 0;
00514    }
00515 }
00516 
00517 /*--------------------------------------------------------------------------*/
00518 

Generated on Tue Apr 13 15:48:07 2010 for DNX by  doxygen 1.5.6