00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <errno.h>
00024 #include <fcntl.h>
00025 #include <limits.h>
00026 #include <netdb.h>
00027 #include <poll.h>
00028 #include <signal.h>
00029 #include <stddef.h>
00030 #include <stdint.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <time.h>
00035 #include <unistd.h>
00036 #include <arpa/inet.h>
00037 #include <sys/time.h>
00038 #include <sys/socket.h>
00039 #include <sys/stat.h>
00040 #include <sys/types.h>
00041 #include <sys/un.h>
00042 #include <netinet/in.h>
00043
00044 #include <ccn/bloom.h>
00045 #include <ccn/ccn.h>
00046 #include <ccn/ccn_private.h>
00047 #include <ccn/charbuf.h>
00048 #include <ccn/face_mgmt.h>
00049 #include <ccn/hashtb.h>
00050 #include <ccn/indexbuf.h>
00051 #include <ccn/schedule.h>
00052 #include <ccn/reg_mgmt.h>
00053 #include <ccn/uri.h>
00054
00055 #include "ccnr_private.h"
00056
00057 #include "ccnr_io.h"
00058
00059 #include "ccnr_forwarding.h"
00060 #include "ccnr_internal_client.h"
00061 #include "ccnr_link.h"
00062 #include "ccnr_msg.h"
00063 #include "ccnr_sendq.h"
00064 #include "ccnr_stats.h"
00065
00066
00067
00068
00069 PUBLIC struct fdholder *
00070 r_io_fdholder_from_fd(struct ccnr_handle *h, unsigned filedesc)
00071 {
00072 unsigned slot = filedesc;
00073 struct fdholder *fdholder = NULL;
00074 if (slot < h->face_limit) {
00075 fdholder = h->fdholder_by_fd[slot];
00076 if (fdholder != NULL && fdholder->filedesc != filedesc)
00077 fdholder = NULL;
00078 }
00079 return(fdholder);
00080 }
00081
00082
00083
00084
00085 PUBLIC struct fdholder *
00086 ccnr_r_io_fdholder_from_fd(struct ccnr_handle *h, unsigned filedesc)
00087 {
00088 return(r_io_fdholder_from_fd(h, filedesc));
00089 }
00090
00091
00092
00093
00094
00095 PUBLIC int
00096 r_io_enroll_face(struct ccnr_handle *h, struct fdholder *fdholder)
00097 {
00098 unsigned i = fdholder->filedesc;
00099 unsigned n = h->face_limit;
00100 struct fdholder **a = h->fdholder_by_fd;
00101 if (i < n && a[i] == NULL) {
00102 if (a[i] == NULL)
00103 goto use_i;
00104 abort();
00105 }
00106 if (i > 65535)
00107 abort();
00108 a = realloc(a, (i + 1) * sizeof(struct fdholder *));
00109 if (a == NULL)
00110 return(-1);
00111 h->face_limit = i + 1;
00112 while (n < h->face_limit)
00113 a[n++] = NULL;
00114 h->fdholder_by_fd = a;
00115 use_i:
00116 a[i] = fdholder;
00117 if (i == 0)
00118 h->face0 = fdholder;
00119 fdholder->filedesc = i;
00120 fdholder->meter[FM_BYTI] = ccnr_meter_create(h, "bytein");
00121 fdholder->meter[FM_BYTO] = ccnr_meter_create(h, "byteout");
00122 fdholder->meter[FM_INTI] = ccnr_meter_create(h, "intrin");
00123 fdholder->meter[FM_INTO] = ccnr_meter_create(h, "introut");
00124 fdholder->meter[FM_DATI] = ccnr_meter_create(h, "datain");
00125 fdholder->meter[FM_DATO] = ccnr_meter_create(h, "dataout");
00126 r_io_register_new_face(h, fdholder);
00127 return (fdholder->filedesc);
00128 }
00129
00130
00131
00132
00133 static void
00134 close_fd(int *pfd)
00135 {
00136 if (*pfd != -1) {
00137 close(*pfd);
00138 *pfd = -1;
00139 }
00140 }
00141
00142
00143
00144
00145 void
00146 ccnr_close_fd(struct ccnr_handle *h, unsigned filedesc, int *pfd)
00147 {
00148 int res;
00149
00150 if (*pfd != -1) {
00151 int linger = 0;
00152 setsockopt(*pfd, SOL_SOCKET, SO_LINGER,
00153 &linger, sizeof(linger));
00154 res = close(*pfd);
00155 if (res == -1)
00156 ccnr_msg(h, "close failed for fdholder %u fd=%d: %s (errno=%d)",
00157 filedesc, *pfd, strerror(errno), errno);
00158 else if (CCNSHOULDLOG(h, io, CCNL_FINE))
00159 ccnr_msg(h, "closing fd %d while finalizing fdholder %u", *pfd, filedesc);
00160 *pfd = -1;
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169 static void
00170 init_face_flags(struct ccnr_handle *h, struct fdholder *fdholder, int setflags)
00171 {
00172 const struct sockaddr *addr;
00173
00174 if ((setflags & (CCNR_FACE_REPODATA)) != 0) {
00175 fdholder->flags |= setflags;
00176 return;
00177 }
00178 addr = (void *)fdholder->name->buf;
00179 if (addr->sa_family == AF_INET6) {
00180 const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
00181 fdholder->flags |= CCNR_FACE_INET6;
00182 #ifdef IN6_IS_ADDR_LOOPBACK
00183 if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr))
00184 fdholder->flags |= CCNR_FACE_LOOPBACK;
00185 #endif
00186 }
00187 else if (addr->sa_family == AF_INET) {
00188 const struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
00189 const unsigned char *rawaddr;
00190 rawaddr = (const unsigned char *)&addr4->sin_addr.s_addr;
00191 fdholder->flags |= CCNR_FACE_INET;
00192 if (rawaddr[0] == 127)
00193 fdholder->flags |= CCNR_FACE_LOOPBACK;
00194 else {
00195
00196
00197 struct sockaddr_in myaddr;
00198 socklen_t myaddrlen = sizeof(myaddr);
00199 if (0 == getsockname(fdholder->filedesc, (struct sockaddr *)&myaddr, &myaddrlen)) {
00200 if (addr4->sin_addr.s_addr == myaddr.sin_addr.s_addr)
00201 fdholder->flags |= CCNR_FACE_LOOPBACK;
00202 }
00203 }
00204 }
00205 else if (addr->sa_family == AF_UNIX)
00206 fdholder->flags |= (CCNR_FACE_GG | CCNR_FACE_LOCAL);
00207 fdholder->flags |= setflags;
00208 }
00209
00210
00211
00212
00213 PUBLIC struct fdholder *
00214 r_io_record_fd(struct ccnr_handle *h, int fd,
00215 void *who, socklen_t wholen,
00216 int setflags)
00217 {
00218 int res;
00219 struct fdholder *fdholder = NULL;
00220
00221 res = fcntl(fd, F_SETFL, O_NONBLOCK);
00222 if (res == -1)
00223 ccnr_msg(h, "fcntl: %s", strerror(errno));
00224 fdholder = calloc(1, sizeof(*fdholder));
00225
00226
00227 if (fdholder == NULL)
00228 return(fdholder);
00229 fdholder->name = ccn_charbuf_create();
00230 if (fdholder->name == NULL)
00231 abort();
00232 if (who != NULL)
00233 ccn_charbuf_append(fdholder->name, who, wholen);
00234 fdholder->filedesc = fd;
00235 init_face_flags(h, fdholder, setflags);
00236 res = r_io_enroll_face(h, fdholder);
00237 if (res == -1) {
00238 ccn_charbuf_destroy(&fdholder->name);
00239 free(fdholder);
00240 fdholder = NULL;
00241 }
00242 return(fdholder);
00243 }
00244
00245
00246
00247
00248
00249 PUBLIC int
00250 r_io_accept_connection(struct ccnr_handle *h, int listener_fd)
00251 {
00252 struct sockaddr_storage who;
00253 socklen_t wholen = sizeof(who);
00254 int fd;
00255 struct fdholder *fdholder;
00256
00257 fd = accept(listener_fd, (struct sockaddr *)&who, &wholen);
00258 if (fd == -1) {
00259 ccnr_msg(h, "accept: %s", strerror(errno));
00260 return(-1);
00261 }
00262 fdholder = r_io_record_fd(h, fd,
00263 (struct sockaddr *)&who, wholen,
00264 CCNR_FACE_UNDECIDED);
00265 if (fdholder == NULL)
00266 close_fd(&fd);
00267 else if (CCNSHOULDLOG(h, io, CCNL_INFO))
00268 ccnr_msg(h, "accepted client fd=%d id=%u", fd, fdholder->filedesc);
00269 return(fd);
00270 }
00271
00272 PUBLIC int
00273 r_io_open_repo_data_file(struct ccnr_handle *h, const char *name, int output)
00274 {
00275 struct ccn_charbuf *temp = NULL;
00276 int fd = -1;
00277 struct fdholder *fdholder = NULL;
00278
00279 temp = ccn_charbuf_create();
00280 ccn_charbuf_putf(temp, "%s/%s", h->directory, name);
00281 fd = open(ccn_charbuf_as_string(temp), output ? (O_CREAT | O_WRONLY | O_APPEND) : O_RDONLY, 0666);
00282 if (fd == -1) {
00283 if (CCNSHOULDLOG(h, sdf, CCNL_FINE))
00284 ccnr_msg(h, "open(%s): %s", ccn_charbuf_as_string(temp), strerror(errno));
00285 ccn_charbuf_destroy(&temp);
00286 return(-1);
00287 }
00288 fdholder = r_io_record_fd(h, fd,
00289 temp->buf, temp->length,
00290 CCNR_FACE_REPODATA | (output ? CCNR_FACE_NORECV : CCNR_FACE_NOSEND));
00291 if (fdholder == NULL)
00292 close_fd(&fd);
00293 else {
00294 if (!output) {
00295
00296 if (fdholder->inbuf == NULL) {
00297 fdholder->inbuf = ccn_charbuf_create();
00298 fdholder->bufoffset = 0;
00299 }
00300 if (fdholder->inbuf != NULL)
00301 ccn_charbuf_reserve(fdholder->inbuf, 256 * 1024);
00302 }
00303 if (CCNSHOULDLOG(h, sdf, CCNL_INFO))
00304 ccnr_msg(h, "opened fd=%d file=%s", fd, ccn_charbuf_as_string(temp));
00305 }
00306 ccn_charbuf_destroy(&temp);
00307 return(fd);
00308 }
00309
00310
00311 PUBLIC int
00312 r_io_repo_data_file_fd(struct ccnr_handle *h, unsigned repofile, int output)
00313 {
00314 if (repofile != 1)
00315 return(-1);
00316 if (output)
00317 return(-1);
00318 if (h->repofile1_fd > 0)
00319 return(h->repofile1_fd);
00320 h->repofile1_fd = r_io_open_repo_data_file(h, "repoFile1", 0);
00321 return(h->repofile1_fd);
00322 }
00323
00324 PUBLIC void
00325 r_io_shutdown_client_fd(struct ccnr_handle *h, int fd)
00326 {
00327 struct fdholder *fdholder = NULL;
00328 enum cq_delay_class c;
00329 int m;
00330 int res;
00331
00332 fdholder = r_io_fdholder_from_fd(h, fd);
00333 if (fdholder == NULL) {
00334 ccnr_msg(h, "no fd holder for fd %d", fd);
00335 return;
00336 }
00337 if (fdholder == h->face0)
00338 (res = 0, h->face0 = NULL);
00339 else if ((fdholder->flags & CCNR_FACE_CCND))
00340 res = ccn_disconnect(h->direct_client);
00341 else
00342 res = close(fd);
00343 if (CCNSHOULDLOG(h, sdfdf, CCNL_INFO))
00344 ccnr_msg(h, "shutdown client fd=%d", fd);
00345 ccn_charbuf_destroy(&fdholder->inbuf);
00346 ccn_charbuf_destroy(&fdholder->outbuf);
00347 for (c = 0; c < CCN_CQ_N; c++)
00348 r_sendq_content_queue_destroy(h, &(fdholder->q[c]));
00349 for (m = 0; m < CCNR_FACE_METER_N; m++)
00350 ccnr_meter_destroy(&fdholder->meter[m]);
00351 if (h->fdholder_by_fd[fd] != fdholder) abort();
00352 h->fdholder_by_fd[fd] = NULL;
00353 ccn_charbuf_destroy(&fdholder->name);
00354 free(fdholder);
00355 if (h->active_in_fd == fd)
00356 h->active_in_fd = -1;
00357 if (h->active_out_fd == fd)
00358 h->active_out_fd = -1;
00359 if (h->repofile1_fd == fd)
00360 h->repofile1_fd = -1;
00361
00362 }
00363
00364
00365
00366
00367
00368 PUBLIC int
00369 r_io_destroy_face(struct ccnr_handle *h, unsigned filedesc)
00370 {
00371 r_io_shutdown_client_fd(h, filedesc);
00372 return(0);
00373 }
00374
00375
00376
00377
00378
00379 PUBLIC void
00380 r_io_register_new_face(struct ccnr_handle *h, struct fdholder *fdholder)
00381 {
00382 if (fdholder->filedesc != 0 && (fdholder->flags & (CCNR_FACE_UNDECIDED | CCNR_FACE_PASSIVE)) == 0) {
00383 ccnr_face_status_change(h, fdholder->filedesc);
00384 }
00385 }
00386
00387
00388
00389
00390
00391 static int
00392 handle_send_error(struct ccnr_handle *h, int errnum, struct fdholder *fdholder,
00393 const void *data, size_t size)
00394 {
00395 int res = -1;
00396 if (errnum == EAGAIN) {
00397 res = 0;
00398 }
00399 else if (errnum == EPIPE) {
00400 fdholder->flags |= CCNR_FACE_NOSEND;
00401 fdholder->outbufindex = 0;
00402 ccn_charbuf_destroy(&fdholder->outbuf);
00403 }
00404 else {
00405 ccnr_msg(h, "send to fd %u failed: %s (errno = %d)",
00406 fdholder->filedesc, strerror(errnum), errnum);
00407 if (errnum == EISCONN)
00408 res = 0;
00409 }
00410 return(res);
00411 }
00412
00413 static int
00414 sending_fd(struct ccnr_handle *h, struct fdholder *fdholder)
00415 {
00416 return(fdholder->filedesc);
00417 }
00418
00419
00420
00421
00422
00423
00424 PUBLIC void
00425 r_io_send(struct ccnr_handle *h,
00426 struct fdholder *fdholder,
00427 const void *data, size_t size,
00428 off_t *offsetp)
00429 {
00430 ssize_t res;
00431 off_t offset;
00432
00433 if (offsetp != NULL)
00434 *offsetp = (off_t)-1;
00435 if ((fdholder->flags & CCNR_FACE_NOSEND) != 0)
00436 return;
00437 if (fdholder->outbuf != NULL) {
00438 ccn_charbuf_append(fdholder->outbuf, data, size);
00439 return;
00440 }
00441 if (fdholder == h->face0) {
00442 ccnr_meter_bump(h, fdholder->meter[FM_BYTO], size);
00443 ccn_dispatch_message(h->internal_client, (void *)data, size);
00444 r_dispatch_process_internal_client_buffer(h);
00445 return;
00446 }
00447 if ((fdholder->flags & CCNR_FACE_CCND) != 0) {
00448
00449 ccnr_meter_bump(h, fdholder->meter[FM_BYTO], size);
00450 res = ccn_put(h->direct_client, data, size);
00451 if (res < 0 && CCNSHOULDLOG(h, r_io_send, CCNL_WARNING))
00452 ccnr_msg(h, "ccn_put failed");
00453 if (res == 1 && CCNSHOULDLOG(h, r_io_send, CCNL_FINEST))
00454 ccnr_msg(h, "ccn_put deferred output for later send");
00455 return;
00456 }
00457 if ((fdholder->flags & CCNR_FACE_REPODATA) != 0) {
00458 offset = lseek(fdholder->filedesc, 0, SEEK_END);
00459 if (offset == (off_t)-1) {
00460 ccnr_msg(h, "lseek(%d): %s", fdholder->filedesc, strerror(errno));
00461 return;
00462 }
00463 if (offsetp != NULL)
00464 *offsetp = offset;
00465 if (fdholder->filedesc == h->active_out_fd) {
00466 if (offset != h->stable && h->stable != 0)
00467 ccnr_msg(h, "expected file size %ju, found %ju",
00468 (uintmax_t)h->stable,
00469 (uintmax_t)offset);
00470 h->stable = offset + size;
00471 }
00472 }
00473 if ((fdholder->flags & CCNR_FACE_DGRAM) == 0)
00474 res = write(fdholder->filedesc, data, size);
00475 else
00476 res = sendto(sending_fd(h, fdholder), data, size, 0,
00477 (struct sockaddr *)fdholder->name->buf,
00478 fdholder->name->length);
00479 if (res > 0)
00480 ccnr_meter_bump(h, fdholder->meter[FM_BYTO], res);
00481 if (res == size)
00482 return;
00483 if (res == -1) {
00484 res = handle_send_error(h, errno, fdholder, data, size);
00485 if (res == -1)
00486 return;
00487 }
00488 if ((fdholder->flags & CCNR_FACE_DGRAM) != 0) {
00489 ccnr_msg(h, "sendto short");
00490 return;
00491 }
00492 fdholder->outbufindex = 0;
00493 fdholder->outbuf = ccn_charbuf_create();
00494 if (fdholder->outbuf == NULL) {
00495 ccnr_msg(h, "do_write: %s", strerror(errno));
00496 return;
00497 }
00498 ccn_charbuf_append(fdholder->outbuf,
00499 ((const unsigned char *)data) + res, size - res);
00500 }
00501
00502
00503
00504
00505 PUBLIC void
00506 r_io_prepare_poll_fds(struct ccnr_handle *h)
00507 {
00508 int i, j, nfds;
00509
00510 for (i = 1, nfds = 0; i < h->face_limit; i++)
00511 if (r_io_fdholder_from_fd(h, i) != NULL)
00512 nfds++;
00513
00514 if (nfds != h->nfds) {
00515 h->nfds = nfds;
00516 h->fds = realloc(h->fds, h->nfds * sizeof(h->fds[0]));
00517 memset(h->fds, 0, h->nfds * sizeof(h->fds[0]));
00518 }
00519 for (i = 1, j = 0; i < h->face_limit; i++) {
00520 struct fdholder *fdholder = r_io_fdholder_from_fd(h, i);
00521 if (fdholder != NULL) {
00522 h->fds[j].fd = fdholder->filedesc;
00523 h->fds[j].events = 0;
00524 if ((fdholder->flags & (CCNR_FACE_NORECV|CCNR_FACE_REPODATA)) == 0)
00525 h->fds[j].events |= POLLIN;
00526 if (fdholder->filedesc == h->active_in_fd)
00527 h->fds[j].events |= POLLIN;
00528 if ((fdholder->outbuf != NULL || (fdholder->flags & CCNR_FACE_CLOSING) != 0))
00529 h->fds[j].events |= POLLOUT;
00530 if ((fdholder->flags & CCNR_FACE_CCND) != 0) {
00531 if (ccn_output_is_pending(h->direct_client)) {
00532 if (CCNSHOULDLOG(h, xxx, CCNL_FINEST))
00533 ccnr_msg(h, "including direct client in poll set");
00534 h->fds[j].events |= POLLOUT;
00535 }
00536 }
00537 j++;
00538 }
00539 }
00540 }
00541
00542
00543
00544
00545 PUBLIC void
00546 r_io_shutdown_all(struct ccnr_handle *h)
00547 {
00548 int i;
00549 for (i = 1; i < h->face_limit; i++) {
00550 if (r_io_fdholder_from_fd(h, i) != NULL)
00551 r_io_shutdown_client_fd(h, i);
00552 }
00553 ccnr_internal_client_stop(h);
00554 r_io_shutdown_client_fd(h, 0);
00555 }