00001
00002
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
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; }
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; }
00159 return -1;
00160 }
00161 #endif
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
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
00283 else
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
00301 return ~0;
00302 }
00303 #endif
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
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
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