Main Page | Modules | Data Structures | File List | Data Fields

net.c

00001 /* 
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. - All rights reserved.  
00003  */
00004 
00005 static const char rcsid[] =
00006     "$Id: net.c,v 1.10 2006/04/21 11:59:41 tat Exp $";
00007 
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <errno.h>
00011 #include <unistd.h>
00012 #include <string.h>
00013 
00014 #include <u/net.h>
00015 #include <u/uri.h>
00016 #include <u/carpal.h>
00017 #include <u/misc.h>
00018 #include <u/memory.h>
00019 #include <u/os.h>
00020 
00052 int u_net_sock (const char *uri, int mode)
00053 {
00054     int sd = -1;
00055     u_net_addr_t *addr = NULL;
00056 
00057     dbg_return_if (uri == NULL, -1);
00058     dbg_return_if (mode != U_NET_SSOCK && mode != U_NET_CSOCK, -1);
00059     
00060     dbg_err_if (u_net_uri2addr(uri, &addr));
00061 
00062     switch (addr->type)
00063     {
00064         case U_NET_TCP4:
00065 #ifndef NO_IPV6
00066         case U_NET_TCP6:
00067 #endif
00068             sd = u_net_sock_tcp(addr, mode);
00069             break;
00070 #ifndef NO_UNIXSOCK
00071         case U_NET_UNIX:
00072             sd = u_net_sock_unix(addr, mode);
00073             break;
00074 #endif /* NO_UNIXSOCK */
00075         case U_NET_UDP4:
00076         case U_NET_UDP6:
00077         default:
00078            warn_err("access method not implemented");
00079     }
00080 
00081     dbg_if (sd == -1);
00082     u_net_addr_free(addr);
00083     return sd;
00084 
00085 err:
00086     if (addr)
00087         u_net_addr_free(addr);
00088     return -1;
00089 }
00090 
00091 static int u_net_sock_tcp4 (u_net_addr_t *a,  int mode)
00092 {
00093     dbg_return_if (a == NULL, -1);
00094     dbg_return_if (a->type != U_NET_TCP4 && a->type != U_NET_TCP6, -1);
00095 
00096     switch (mode)
00097     {
00098         case U_NET_CSOCK:
00099             return u_net_tcp4_csock(&a->sa.sin);
00100         case U_NET_SSOCK:
00101             return u_net_tcp4_ssock(&a->sa.sin, 0, U_NET_BACKLOG);
00102         default:
00103             warn("unknown socket mode");
00104             return -1;
00105     }
00106 }
00107 
00108 #ifndef NO_IPV6
00109 static int u_net_sock_tcp6 (u_net_addr_t *a,  int mode)
00110 {
00111     dbg_return_if (a == NULL, -1);
00112     dbg_return_if (a->type != U_NET_TCP4 && a->type != U_NET_TCP6, -1);
00113 
00114     switch (mode)
00115     {
00116         case U_NET_CSOCK:
00117                 return u_net_tcp6_csock(&a->sa.sin6);
00118         case U_NET_SSOCK:
00119                 return u_net_tcp6_ssock(&a->sa.sin6, 0, U_NET_BACKLOG);
00120         default:
00121             warn("unknown socket mode");
00122             return -1;
00123     }
00124 }
00125 #endif
00126 
00127 int u_net_sock_tcp (u_net_addr_t *a,  int mode)
00128 {
00129     dbg_return_if (a == NULL, -1);
00130     dbg_return_if (a->type != U_NET_TCP4 && a->type != U_NET_TCP6, -1);
00131 
00132     switch (a->type)
00133     {
00134         case U_NET_TCP4:
00135             return u_net_sock_tcp4(a, mode);
00136 #ifndef NO_IPV6
00137         case U_NET_TCP6:
00138             return u_net_sock_tcp6(a, mode);
00139 #endif
00140         default:
00141             warn("unknown or unsupported socket type");
00142             return -1;
00143     }
00144 }
00145 
00146 #ifndef NO_UNIXSOCK
00147 int u_net_sock_unix (u_net_addr_t *a, int mode)
00148 {
00149     dbg_return_if (a == NULL, -1);
00150     switch (mode) { default: break; } /* TODO */
00151     return -1;
00152 }
00153 
00154 int u_net_sock_udp (u_net_addr_t *a,  int mode)
00155 {
00156     dbg_return_if (a == NULL, -1);
00157     dbg_return_if (a->type != U_NET_UDP4 && a->type != U_NET_UDP6, -1);
00158     switch (mode) { default: break; }  /* TODO */
00159     return -1;
00160 }
00161 #endif /* NO_UNIXSOCK */
00162 
00163 #ifndef NO_IPV6
00164 int u_net_tcp6_ssock (struct sockaddr_in6 *sad, int reuse, int backlog)
00165 {
00166     int rv, lsd = -1;
00167     int on = reuse ? 1 : 0;
00168 
00169     dbg_return_if (sad == NULL, -1);
00170     
00171     lsd = socket(AF_INET6, SOCK_STREAM, 0);
00172     dbg_err_if (lsd == -1);
00173 
00174     rv = setsockopt(lsd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
00175     dbg_err_if (rv == -1);
00176 
00177     rv = bind(lsd, (struct sockaddr *) sad, sizeof *sad);
00178     dbg_err_if (rv == -1);
00179 
00180     rv = listen(lsd, backlog);
00181     dbg_err_if (rv == -1);
00182 
00183     return lsd;
00184 
00185 err:
00186     dbg_strerror(errno);
00187     U_CLOSE(lsd);
00188     return -1;
00189 }
00190 
00191 int u_net_tcp6_csock (struct sockaddr_in6 *sad)
00192 {
00193     int csd = -1;
00194     int rv;
00195 
00196     dbg_return_if (sad == NULL, -1);
00197 
00198     csd = socket(AF_INET6, SOCK_STREAM, 0);
00199     dbg_err_if (csd == -1);
00200 
00201     rv = connect(csd, (struct sockaddr *) sad, sizeof *sad);
00202     dbg_err_if (rv == -1);
00203 
00204     return csd;
00205 
00206 err:
00207     dbg_strerror(errno);
00208     U_CLOSE(csd);
00209     return -1;
00210 }
00211 #endif /* NO_IPV6 */
00212 
00213 int u_net_tcp4_ssock (struct sockaddr_in *sad, int reuse, int backlog)
00214 {
00215     int rv, lsd = -1;
00216     int on = reuse ? 1 : 0;
00217 
00218     dbg_return_if (sad == NULL, -1);
00219     
00220     lsd = socket(AF_INET, SOCK_STREAM, 0);
00221     dbg_err_if (lsd == -1);
00222 
00223     rv = setsockopt(lsd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof on);
00224     dbg_err_if (rv == -1);
00225 
00226     rv = bind(lsd, (struct sockaddr *) sad, sizeof *sad);
00227     dbg_err_if (rv == -1);
00228 
00229     rv = listen(lsd, backlog);
00230     dbg_err_if (rv == -1);
00231 
00232     return lsd;
00233 
00234 err:
00235     dbg_strerror(errno);
00236     U_CLOSE(lsd);
00237     return -1;
00238 }
00239 
00240 int u_net_tcp4_csock (struct sockaddr_in *sad)
00241 {
00242     int csd = -1;
00243 
00244     dbg_return_if (sad == NULL, -1);
00245 
00246     csd = socket(AF_INET, SOCK_STREAM, 0);
00247     dbg_err_if (csd == -1);
00248 
00249     dbg_err_if (connect(csd, (struct sockaddr *) sad, sizeof *sad) == -1);
00250 
00251     return csd;
00252 
00253 err:
00254     dbg_strerror(errno);
00255     U_CLOSE(csd);
00256     return -1;
00257 }
00258 
00259 int u_net_uri2addr (const char *uri, u_net_addr_t **pa)
00260 {
00261     u_uri_t *u = NULL;
00262     u_net_addr_t *a = NULL;
00263     
00264     dbg_return_if (uri == NULL, ~0);
00265     dbg_return_if (pa == NULL, ~0);
00266 
00267     *pa = NULL;
00268     
00269     dbg_err_if (u_uri_parse(uri, &u));
00270 
00271     if (!strcasecmp(u->scheme, "tcp4"))
00272     {
00273         dbg_err_if (u_net_addr_new(U_NET_TCP4, &a));
00274         dbg_err_if (u_net_uri2sin(u, &a->sa.sin));
00275     }
00276 #ifndef NO_UNIXSOCK
00277     else if (!strcasecmp(u->scheme, "unix"))
00278     {    
00279         dbg_err_if (u_net_addr_new(U_NET_UNIX, &a));
00280         dbg_err_if (u_net_uri2sun(u, &a->sa.sun));
00281     }
00282 #endif /* NO_UNIXSOCK */    
00283     else /* tcp6, udp[46] unsupported */
00284         warn_err("unsupported URI scheme: %s", u->scheme); 
00285     
00286     *pa = a;
00287     u_uri_free(u);
00288     return 0;
00289 err:
00290     if (a) u_net_addr_free(a);
00291     if (u) u_uri_free(u);
00292     return ~0;
00293 }
00294 
00295 #ifndef NO_UNIXSOCK
00296 int u_net_uri2sun (u_uri_t *uri, struct sockaddr_un *sad)
00297 {
00298     dbg_return_if (uri == NULL, ~0);
00299     dbg_return_if (sad == NULL, ~0);
00300     /* TODO */
00301     return ~0;
00302 }
00303 #endif /* OS_UNIX */
00304 
00305 int u_net_addr_new (int type, u_net_addr_t **pa)
00306 {
00307     u_net_addr_t *a = NULL;
00308 
00309     dbg_return_if (pa == NULL, ~0);
00310     dbg_return_if (type <= U_NET_TYPE_MIN || type >= U_NET_TYPE_MAX, ~0);
00311 
00312     a = u_zalloc(sizeof(u_net_addr_t));
00313     dbg_err_if (a == NULL);
00314     a->type = type;
00315     *pa = a;
00316 
00317     return 0;
00318 
00319 err:
00320     if (a) u_net_addr_free(a);
00321     return ~0;
00322 }
00323 
00324 void u_net_addr_free (u_net_addr_t *a)
00325 {
00326     U_FREE(a);
00327     return;
00328 }
00329    
00330 /* translate u_uri_t into struct sockaddr_in */
00331 int u_net_uri2sin (u_uri_t *uri, struct sockaddr_in *sad)
00332 {
00333     struct hostent *hp = NULL;
00334     in_addr_t saddr;
00335 
00336     dbg_return_if (uri == NULL, ~0);
00337     dbg_return_if (sad == NULL, ~0);
00338 
00339     memset((char *) sad, 0, sizeof(struct sockaddr_in));
00340     sad->sin_port = htons(uri->port);
00341     sad->sin_family = AF_INET;
00342 
00343     hp = gethostbyname(uri->host);
00344 
00345     if (hp && hp->h_addrtype == AF_INET)
00346         memcpy(&sad->sin_addr.s_addr, hp->h_addr, sizeof(in_addr_t));
00347     else if ((saddr = inet_addr(uri->host)) != INADDR_NONE)
00348         sad->sin_addr.s_addr = saddr;
00349     else
00350         warn_err("invalid host name: \'%s\'", uri->host);
00351 
00352     return 0;
00353 err:
00354     return ~0;    
00355 }
00356 
00379 int u_net_io (iof_t f, int sd, void *buf, size_t l, ssize_t *n, int *eof)
00380 {
00381 #define SET_PPTR(pptr, val) do {if ((pptr)) *(pptr) = (val);} while (0);
00382     ssize_t nret;
00383     size_t nleft = l;
00384     char *p = buf;
00385 
00386     SET_PPTR(n, 0);
00387     SET_PPTR(eof, 0);
00388 
00389     while (nleft > 0) 
00390     {
00391         if ((nret = (f) (sd, p, nleft)) == -1)
00392         {
00393             if (errno == EINTR || errno == EAGAIN)
00394                 continue;
00395             else
00396             {
00397                 warn_strerror(errno);
00398                 goto end;
00399             }
00400         }
00401 
00402         /* test EOF */
00403         if (nret == 0)
00404         {
00405             SET_PPTR(eof, 1);
00406             goto end;
00407         }
00408         
00409         nleft -= nret;
00410         p += nret;
00411     }
00412 
00413 end:
00414     SET_PPTR(n, l - nleft);
00415     return nleft ? ~0 : 0;
00416 #undef SET_PPTR
00417 }
00418 

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved