libxdas_net.c

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------
00002  * Copyright (c) 2006, Novell, Inc.
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions are 
00007  * met:
00008  * 
00009  *     * Redistributions of source code must retain the above copyright 
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright 
00012  *       notice, this list of conditions and the following disclaimer in the 
00013  *       documentation and/or other materials provided with the distribution.
00014  *     * Neither the name of the Novell nor the names of its contributors 
00015  *       may be used to endorse or promote products derived from this 
00016  *       software without specific prior written permission.
00017  * 
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00019  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00020  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
00021  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
00022  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00023  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00024  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
00025  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
00026  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *--------------------------------------------------------------------------*/
00030 
00039 #include <xdas.h>
00040 #include <xdasd.h>
00041 #include <xdas_buf.h>
00042 #include <xdas_wire.h>
00043 #include <xdas_debug.h>
00044 
00045 #include "libxdas_impl.h"
00046 
00047 #include <errno.h>
00048 #include <stdio.h>
00049 
00055 #ifdef _WIN32
00056 /* map WSA error codes to unix names */
00057 # define EWOULDBLOCK        WSAEWOULDBLOCK
00058 # define EINPROGRESS        WSAEINPROGRESS
00059 # define EALREADY           WSAEALREADY
00060 # define ENOTSOCK           WSAENOTSOCK
00061 # define EDESTADDRREQ       WSAEDESTADDRREQ
00062 # define EMSGSIZE           WSAEMSGSIZE
00063 # define EPROTOTYPE         WSAEPROTOTYPE
00064 # define ENOPROTOOPT        WSAENOPROTOOPT
00065 # define EPROTONOSUPPORT    WSAEPROTONOSUPPORT
00066 # define ESOCKTNOSUPPORT    WSAESOCKTNOSUPPORT
00067 # define EOPNOTSUPP         WSAEOPNOTSUPP
00068 # define EPFNOSUPPORT       WSAEPFNOSUPPORT
00069 # define EAFNOSUPPORT       WSAEAFNOSUPPORT
00070 # define EADDRINUSE         WSAEADDRINUSE
00071 # define EADDRNOTAVAIL      WSAEADDRNOTAVAIL
00072 # define ENETDOWN           WSAENETDOWN
00073 # define ENETUNREACH        WSAENETUNREACH
00074 # define ENETRESET          WSAENETRESET
00075 # define ECONNABORTED       WSAECONNABORTED
00076 # define ECONNRESET         WSAECONNRESET
00077 # define ENOBUFS            WSAENOBUFS
00078 # define EISCONN            WSAEISCONN
00079 # define ENOTCONN           WSAENOTCONN
00080 # define ESHUTDOWN          WSAESHUTDOWN
00081 # define ETOOMANYREFS       WSAETOOMANYREFS
00082 # define ETIMEDOUT          WSAETIMEDOUT
00083 # define ECONNREFUSED       WSAECONNREFUSED
00084 # define ELOOP              WSAELOOP
00085 # define EHOSTDOWN          WSAEHOSTDOWN
00086 # define EHOSTUNREACH       WSAEHOSTUNREACH
00087 # define EREMOTE            WSAEREMOTE
00088 #else
00089 # include <sys/un.h>
00090 #endif
00091 
00092 #ifndef _WIN32
00093 
00107 static void xdas_get_ipcpath(char * ipcpath, size_t ipcpathsz)
00108 {
00109 #define UNIT_TEST_RUN_PATH_ENVAR "XDAS_UNIT_TEST_RUN_PATH"
00110 
00111    char * runpath = getenv(UNIT_TEST_RUN_PATH_ENVAR);
00112    if (runpath == 0)
00113       snprintf(ipcpath, ipcpathsz, XDASD_RUNPATH "/xdasd.ipc");
00114    else
00115    {
00116       snprintf(ipcpath, ipcpathsz, "%s/xdasd.ipc", runpath);
00117       printf("LIBXDAS: Using dynamic ipc path: %s.\n", ipcpath);
00118    }
00119 }
00120 #endif
00121 
00129 static int xdas_map_network_error_to_minor(void)
00130 {
00131 #ifdef _WIN32
00132    int err = WSAGetLastError();
00133 #else
00134    int err = errno;
00135 #endif
00136    switch(err)
00137    {
00138       case 0:                 return 0;
00139 
00140       case ENOTSOCK:          return OXDAS_MS_NET_BAD_SOCKET;
00141       case ECONNABORTED:      return OXDAS_MS_NET_CONN_ABORTED;
00142       case ECONNRESET:        return OXDAS_MS_NET_CONN_RESET;
00143       case ENOTCONN:          return OXDAS_MS_NET_NOT_CONNECTED;
00144       case ESHUTDOWN:         return OXDAS_MS_NET_SHUTDOWN;
00145       case ETIMEDOUT:         return OXDAS_MS_NET_TIMEDOUT;
00146       case ECONNREFUSED:      return OXDAS_MS_NET_CONN_REFUSED;
00147 
00148       case EWOULDBLOCK:
00149       case EINPROGRESS:
00150       case EALREADY:
00151       case EDESTADDRREQ:
00152       case EMSGSIZE:
00153       case EPROTOTYPE:
00154       case ENOPROTOOPT:
00155       case EPROTONOSUPPORT:   
00156       case ESOCKTNOSUPPORT:
00157       case EOPNOTSUPP:
00158       case EPFNOSUPPORT:
00159       case EAFNOSUPPORT:
00160       case EADDRINUSE:
00161       case EADDRNOTAVAIL:
00162       case ENETDOWN:
00163       case ENETUNREACH:
00164       case ENETRESET:
00165       case ENOBUFS:
00166       case EISCONN:
00167       case ETOOMANYREFS:
00168       case ELOOP:
00169       case EHOSTDOWN:
00170       case EHOSTUNREACH:
00171       case EREMOTE:
00172          break;
00173    }
00174    return OXDAS_MS_NET_GENERAL_ERROR;
00175 }
00176 
00183 void xdas_service_disconnect(xdas_session * xs)
00184 {
00185    if (xs->s != BAD_SOCKET)
00186    {
00187       closesocket(xs->s);
00188       xs->s = BAD_SOCKET;
00189    }
00190 }
00191 
00201 int xdas_service_connect(int * minor, xdas_session * xs)
00202 {
00203    struct sockaddr_storage ss;
00204    int addrsz;
00205 
00206    memset(&ss, 0, sizeof(ss));
00207 
00208 #ifdef _WIN32
00209    {
00210       struct sockaddr_in * v4 = (struct sockaddr_in *)&ss;
00211       v4->sin_family = AF_INET;
00212       v4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00213       v4->sin_port = htons(XDASD_RESERVED_PORT);
00214       addrsz = sizeof(*v4);
00215    }
00216 #else
00217    {
00218       struct sockaddr_un * ud = (struct sockaddr_un *)&ss;
00219 
00220       static char ipcpath[FILENAME_MAX] = "";
00221       if (*ipcpath == 0) 
00222          xdas_get_ipcpath(ipcpath, sizeof(ipcpath));
00223 
00224       ud->sun_family = AF_LOCAL;
00225       strncpy(ud->sun_path, ipcpath, sizeof(ud->sun_path));
00226       addrsz = sizeof(*ud);
00227    }
00228 #endif
00229 
00230    /* close existing connection if open */
00231    xdas_service_disconnect(xs);
00232 
00233    /* connect to xdasd */
00234    xs->s = socket(ss.ss_family, SOCK_STREAM, 0);
00235    if (connect(xs->s, (struct sockaddr *)&ss, addrsz) < 0)
00236    {
00237       *minor = xdas_map_network_error_to_minor();
00238       return XDAS_S_FAILURE;
00239    }
00240    return 0;
00241 }
00242 
00257 int xdas_req_rsp(int * minorp, xdas_session * xs)
00258 {
00259    char peek[4];
00260    int scode, rspsz, bytes;
00261    xdas_buffer rsp;
00262 
00263    /* basic sanity check on parameters */
00264    xdas_assert(minorp && xs && xs->req);
00265    if (!minorp || !xs || !xs->req)
00266       return -1;
00267 
00268    /* establish connection if it was previously closed */
00269    if (xs->s == BAD_SOCKET 
00270          && (scode = xdas_service_connect(minorp, xs)) != 0)
00271       return scode;
00272 
00273    /* send pre-configured request buffer */
00274    if ((bytes = send(xs->s, xs->req->start, 
00275          (int)(xs->req->curpos - xs->req->start), 0)) < 0)
00276       return (*minorp = xdas_map_network_error_to_minor()), XDAS_S_FAILURE;
00277 
00278    /* Peek at return buffer header for buffer size. */
00279    bytes = recv(xs->s, peek, sizeof(peek), MSG_PEEK);
00280    xdas_assert(bytes < 0 || bytes == sizeof(peek));
00281    if (bytes < 0)
00282       return (*minorp = xdas_map_network_error_to_minor()), XDAS_S_FAILURE;
00283 
00284    rspsz = (int)AS_UINT32(peek);
00285 
00286    /* no xdasd response should be greater than 4k, and all xdasd responses 
00287       should have at least 12 bytes - size, scode, and minor status */
00288    xdas_assert(rspsz >= 12 && rspsz < 4096);
00289 
00290    if ((rsp = xdas_buffer_realloc(xs->rsp, rspsz)) == 0)
00291       return (*minorp = OXDAS_MS_OUT_OF_MEMORY), XDAS_S_FAILURE;
00292    rsp->curpos = rsp->start;
00293    xs->rsp = rsp;
00294 
00295    /* read till we have it all, or an error occurs */
00296    while (rspsz && (bytes = recv(xs->s, rsp->curpos, rspsz, 0)) > 0)
00297    {
00298       rsp->curpos += bytes;
00299       rspsz -= bytes;
00300    }
00301 
00302    /* check for error condition (or socket closed) from loop */
00303    if (bytes <= 0)
00304       return (*minorp = xdas_map_network_error_to_minor()), XDAS_S_FAILURE;
00305 
00306    /* parse response buffer for error codes */
00307    rsp->curpos = rsp->start + 4; /* skip rspsz this time */
00308    scode = (int)xdas_buffer_get_uint32(rsp);
00309    *minorp = (int)xdas_buffer_get_uint32(rsp);
00310 
00311    return scode;
00312 }
00313 

Generated on Thu Aug 20 22:33:05 2009 for OpenXDAS by  doxygen 1.5.6