transport.c

00001 /* * 
00002  * This file is part of libnemesi
00003  *
00004  * Copyright (C) 2007 by LScube team <team@streaming.polito.it>
00005  * See AUTHORS for more details
00006  * 
00007  * libnemesi is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * libnemesi is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with libnemesi; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  *  
00021  * */
00022 
00023 #include "transport.h"
00024 #include "comm.h"
00025 
00026 #ifndef WIN32
00027 #ifdef    HAVE_SOCKADDR_DL_STRUCT
00028 # include    <net/if_dl.h>
00029 #endif
00030 #ifdef    AF_UNIX
00031 #include <sys/un.h>
00032 #endif
00033 #endif
00034 
00035 #ifdef HAVE_LIBSCTP
00036 #include <netinet/sctp.h>
00037 #endif
00038 
00045 int sockaddr_get_nms_addr(const struct sockaddr *sockaddr, nms_addr * retaddr)
00046 {
00047     if (!sockaddr || !retaddr)
00048         return 1;
00049 
00050     retaddr->family = sockaddr->sa_family;
00051     switch (sockaddr->sa_family) {
00052     case AF_INET:
00053         memcpy(&retaddr->addr.in,
00054                &((struct sockaddr_in *) sockaddr)->sin_addr,
00055                sizeof(struct in_addr));
00056         return 0;
00057         break;
00058 #ifdef IPV6
00059     case AF_INET6:
00060         memcpy(&retaddr->addr.in6,
00061                &((struct sockaddr_in6 *) sockaddr)->sin6_addr,
00062                sizeof(struct in6_addr));
00063         return 0;
00064         break;
00065 #endif
00066     default:
00067         retaddr->family = AF_UNSPEC;
00068         break;
00069     }
00070 
00071     return 1;
00072 }
00073 
00074 static int sock_cmp_addr(const struct sockaddr *sa1, const struct sockaddr *sa2)
00075 {
00076     if (sa1->sa_family != sa2->sa_family)
00077         return -1;
00078 
00079     switch (sa1->sa_family) {
00080     case AF_INET:
00081         return (memcmp
00082             (&((struct sockaddr_in *) sa1)->sin_addr,
00083              &((struct sockaddr_in *) sa2)->sin_addr,
00084              sizeof(struct in_addr)));
00085         break;
00086 
00087 #ifdef    IPV6
00088     case AF_INET6:
00089         return (memcmp
00090             (&((struct sockaddr_in6 *) sa1)->sin6_addr,
00091              &((struct sockaddr_in6 *) sa2)->sin6_addr,
00092              sizeof(struct in6_addr)));
00093         break;
00094 #endif
00095 
00096 #if !defined(WIN32) && defined(AF_UNIX)
00097     case AF_UNIX:
00098         return (strcmp
00099             (((struct sockaddr_un *) sa1)->sun_path,
00100              ((struct sockaddr_un *) sa2)->sun_path));
00101         break;
00102 #endif
00103 
00104 #ifdef    HAVE_SOCKADDR_DL_STRUCT
00105     case AF_LINK:
00106         return -1;    /* no idea what to compare here ? */
00107         break;
00108 #endif
00109     default:
00110         return -1;
00111         break;
00112     }
00113     // return -1;
00114 }
00115 
00116 
00117 /*
00118  * The function compares port filed of sock addr structure.
00119  * It recognizes the family of sockaddr struct and compares the rigth field.
00120  * \return 0 if port are equal, -1 if family is not known.
00121  * */
00122 static int sock_cmp_port(const struct sockaddr *sa1, const struct sockaddr *sa2)
00123 {
00124     if (sa1->sa_family != sa2->sa_family)
00125         return -1;
00126 
00127     switch (sa1->sa_family) {
00128     case AF_INET:
00129         return !(((struct sockaddr_in *) sa1)->sin_port ==
00130              ((struct sockaddr_in *) sa2)->sin_port);
00131         break;
00132 
00133 #ifdef    IPV6
00134     case AF_INET6:
00135         return !(((struct sockaddr_in6 *) sa1)->sin6_port ==
00136              ((struct sockaddr_in6 *) sa2)->sin6_port);
00137         break;
00138 #endif
00139     default:
00140         return -1;
00141         break;
00142 
00143     }
00144     // return -1;
00145 }
00146 
00147 /*
00148  * The function that compares two sockaddr structures.
00149  * \param addr1 first sockaddr struct
00150  * \param addr1_len length of first sockaddr struct
00151  * \param addr2 second sockaddr struct
00152  * \param addr1_len length of second sockaddr struct
00153  * \return 0 if the two structires are egual, otherwise an error reflecting the
00154  * first difference encountered. 
00155  */
00156 int sockaddr_cmp(struct sockaddr *addr1, socklen_t addr1_len, struct sockaddr *addr2, socklen_t addr2_len)
00157 {
00158     if (addr1_len != addr2_len)
00159         return WSOCK_ERRSIZE;
00160     if (addr1->sa_family != addr1->sa_family)
00161         return WSOCK_ERRFAMILY;
00162     if (sock_cmp_addr(addr1, addr2 /*, addr1_len */ ))
00163         return WSOCK_ERRADDR;
00164     if (sock_cmp_port(addr1, addr2 /*, addr1_len */ ))
00165         return WSOCK_ERRPORT;
00166 
00167     return 0;
00168 }
00169 
00173 char *nms_addr_ntop(const nms_addr * addr, char *str, size_t len)
00174 {
00175     switch (addr->family) {
00176     case AF_INET:
00177         if (inet_ntop(AF_INET, &addr->addr.in, str, len) == NULL)
00178             return (NULL);
00179         return (str);
00180         break;
00181 #ifdef    IPV6
00182     case AF_INET6:
00183         if (inet_ntop(AF_INET6, &addr->addr.in6, str, len) == NULL)
00184             return (NULL);
00185         return (str);
00186         break;
00187 #endif
00188 
00189 #if 0                // not yet supported by nms_addr
00190 #ifdef    AF_UNIX
00191     case AF_UNIX:
00192         /* OK to have no pathname bound to the socket: happens on
00193          * every connect() unless client calls bind() first. */
00194         if (addr->addr.un_path[0] == 0)
00195             strcpy(str, "(no pathname bound)");
00196         else
00197             snprintf(str, len, "%s", addr->addr.un_path);
00198         return (str);
00199 #endif
00200 
00201 #ifdef    HAVE_SOCKADDR_DL_STRUCT
00202     case AF_LINK:
00203         if (addr->addr.dl_nlen > 0)
00204             snprintf(str, len, "%*s", addr->addr.dl_nlen,
00205                  &addr->addr.dl_data[0]);
00206         else
00207             snprintf(str, len, "AF_LINK, index=%d",
00208                  addr->addr.dl_index);
00209         return (str);
00210 #endif
00211 #endif
00212     default:
00213         snprintf(str, len, "addr_ntop: unknown AF_xxx: %d",
00214              addr->family);
00215         return (str);
00216     }
00217     return (NULL);
00218 }
00219 
00223 int nms_sockaddr_dup(nms_sockaddr * dst, nms_sockaddr * src)
00224 {
00225 
00226     if (!(dst->addr = malloc(src->addr_len)))
00227         return -nms_printf(NMSML_FATAL, "Cannot allocate memory\n");
00228     memcpy(dst->addr, src->addr, src->addr_len);
00229     dst->addr_len = src->addr_len;
00230 
00231     return 0;
00232 }
00233 
00237 int nms_addr_cmp(const nms_addr * addr1, const nms_addr * addr2)
00238 {
00239     if (addr1->family != addr2->family)
00240         return WSOCK_ERRFAMILY;
00241     switch (addr1->family) {
00242     case AF_INET:
00243         if (!memcmp
00244             (&addr1->addr.in, &addr2->addr.in, sizeof(struct in_addr)))
00245             return 0;
00246         else
00247             return WSOCK_ERRADDR;
00248         break;
00249     case AF_INET6:
00250         if (!memcmp
00251             (&addr1->addr.in6, &addr2->addr.in6,
00252              sizeof(struct in6_addr)))
00253             return 0;
00254         else
00255             return WSOCK_ERRADDR;
00256         break;
00257     default:
00258         return WSOCK_ERRFAMILYUNKNOWN;
00259     }
00260 
00261     return 0;
00262 }
00263 
00264 
00265 //Transport Layer Wrappers
00266 int nmst_read(nms_transport * transport, void *buffer, size_t nbytes, void *protodata)
00267 {
00268     switch (transport->sock.socktype) {
00269     case TCP:
00270         return recv(transport->sock.fd, buffer, nbytes, 0);
00271         break;
00272 #ifdef HAVE_LIBSCTP
00273     case SCTP:
00274         if (!protodata) {
00275             return -1;
00276         }
00277         return sctp_recvmsg(transport->sock.fd, buffer, nbytes, NULL, 0,
00278                  (struct sctp_sndrcvinfo *) protodata, NULL);
00279         break;
00280 #endif
00281     default:
00282         break;
00283     }
00284     return -1;
00285 }
00286 
00287 int nmst_write(nms_transport * transport, void *buffer, size_t nbytes, void *protodata)
00288 {
00289 #ifdef HAVE_LIBSCTP
00290     struct sctp_sndrcvinfo sinfo;
00291 #endif
00292     switch (transport->sock.socktype) {
00293     case TCP:
00294         return send(transport->sock.fd, buffer, nbytes, 0);
00295         break;
00296 #ifdef HAVE_LIBSCTP
00297     case SCTP:
00298         if (!protodata) {
00299             protodata = &sinfo;
00300             memset(protodata, 0, sizeof(struct sctp_sndrcvinfo));
00301         }
00302         return sctp_send(transport->sock.fd, buffer, nbytes, 
00303             (struct sctp_sndrcvinfo *) protodata, MSG_EOR);
00304         break;
00305 #endif
00306     default:
00307         break;
00308     }
00309 
00310     return -1;
00311 }
00312 
00313 inline int nmst_is_active(nms_transport * transport)
00314 {
00315     return ((transport->sock.socktype != SOCK_NONE) && (transport->sock.fd >= 0));
00316 }
00317 
00318 void nmst_init(nms_transport * transport)
00319 {
00320     memset(transport, 0, sizeof(nms_transport));
00321 
00322     // TCP is default protocol implemented for RTSP, so I init type to TCP.
00323     transport->sock.socktype = TCP;
00324 
00325     transport->sock.fd = -1;
00326 }
00327 
00328 int nmst_close(nms_transport * transport)
00329 {
00330     if (transport->sock.remote_host)
00331         free(transport->sock.remote_host);
00332 
00333     // TODO should we do something else?
00334     return close(transport->sock.fd);
00335 }
00336 
00337 

Generated on Tue Feb 3 03:10:02 2009 for libnemesi by  doxygen 1.5.4