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

net.c

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

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