ccndsmoketest.c

Go to the documentation of this file.
00001 /**
00002  * @file ccndsmoketest.c
00003  * Simple program for smoke-test of ccnd.
00004  *
00005  * Copyright (C) 2008-2011 Palo Alto Research Center, Inc.
00006  *
00007  * This work is free software; you can redistribute it and/or modify it under
00008  * the terms of the GNU General Public License version 2 as published by the
00009  * Free Software Foundation.
00010  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00013  * for more details. You should have received a copy of the GNU General Public
00014  * License along with this program; if not, write to the
00015  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016  * Boston, MA 02110-1301, USA.
00017  */
00018 #include <errno.h>
00019 #include <fcntl.h>
00020 #include <netdb.h>
00021 #include <poll.h>
00022 #include <signal.h>
00023 #include <stdint.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <time.h>
00028 #include <unistd.h>
00029 #include <arpa/inet.h>
00030 #include <sys/types.h>
00031 #include <sys/socket.h>
00032 #include <netinet/in.h>
00033 #include <sys/stat.h>
00034 #include <sys/un.h>
00035 
00036 #if defined(NEED_GETADDRINFO_COMPAT)
00037 #include "getaddrinfo.h"
00038 #include "dummyin6.h"
00039 #endif
00040 
00041 #include <ccn/ccnd.h>
00042 #include <ccn/ccn_private.h>
00043 
00044 #define CRLF "\r\n"
00045 
00046 char rawbuf[1024*1024];
00047 
00048 static void
00049 printraw(char *p, int n)
00050 {
00051     int i, l;
00052     while (n > 0) {
00053         l = (n > 40 ? 40 : n);
00054         for (i = 0; i < l; i++)
00055             printf(" %c", (' ' <= p[i] && p[i] <= '~') ? p[i] : '.');
00056         printf("\n");
00057         for (i = 0; i < l; i++)
00058             printf("%02X", (unsigned char)p[i]);
00059         printf("\n");
00060         p += l;
00061         n -= l;
00062     }
00063 }
00064 
00065 static int
00066 open_local(struct sockaddr_un *sa, const char *verb)
00067 {
00068     int sock;
00069     int res;
00070     
00071     sock = socket(AF_UNIX, SOCK_STREAM, 0);
00072     if (sock == -1) {
00073         perror("socket");
00074         exit(1);
00075     }
00076     res = connect(sock, (struct sockaddr *)sa, sizeof(*sa));
00077     if (res == -1 && errno == ENOENT) {
00078         /* Don't wait for startup just to shut it down */
00079         if (verb != NULL && 0 == strcmp(verb, "kill"))
00080             exit(1);
00081         /* Retry after a delay in case ccnd was just starting up. */
00082         sleep(1);
00083         res = connect(sock, (struct sockaddr *)sa, sizeof(*sa));
00084     }
00085     if (res == -1) {
00086         perror((char *)sa->sun_path);
00087         exit(1);
00088     }
00089     return(sock);
00090 }
00091 
00092 static int
00093 open_socket(const char *host, const char *portstr, int sock_type)
00094 {
00095     int res;
00096     int sock = 0;
00097     char canonical_remote[NI_MAXHOST] = "";
00098     struct addrinfo *addrinfo = NULL;
00099     struct addrinfo *myai = NULL;
00100     struct addrinfo hints = {0};
00101     
00102     if (portstr == NULL || portstr[0] == 0)
00103         portstr = CCN_DEFAULT_UNICAST_PORT;
00104     hints.ai_family = AF_UNSPEC;
00105     hints.ai_socktype = sock_type;
00106     hints.ai_flags = 0;
00107 #ifdef AI_ADDRCONFIG
00108     hints.ai_flags |= AI_ADDRCONFIG;
00109 #endif
00110 #ifdef AI_NUMERICSERV
00111     hints.ai_flags |= AI_NUMERICSERV;
00112 #endif
00113     res = getaddrinfo(host, portstr, &hints, &addrinfo);
00114     if (res != 0 || addrinfo == NULL) {
00115         fprintf(stderr, "getaddrinfo(\"%s\", \"%s\", ...): %s\n",
00116                 host, portstr, gai_strerror(res));
00117         exit(1);
00118     }
00119     
00120     res = getnameinfo(addrinfo->ai_addr, addrinfo->ai_addrlen,
00121                       canonical_remote, sizeof(canonical_remote), NULL, 0, 0);
00122     
00123     sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
00124     if (sock == -1) {
00125         perror("socket");
00126         exit(1);
00127     }
00128     hints.ai_family = addrinfo->ai_family;
00129     hints.ai_flags = AI_PASSIVE;
00130 #ifdef AI_NUMERICSERV
00131     hints.ai_flags |= AI_NUMERICSERV;
00132 #endif
00133     res = getaddrinfo(NULL, NULL, &hints, &myai);
00134     if (myai != NULL) {
00135         res = bind(sock, (struct sockaddr *)myai->ai_addr, myai->ai_addrlen);
00136         if (res == -1) {
00137             perror("bind");
00138             exit(1);
00139         }
00140     }
00141     res = connect(sock, (struct sockaddr *)addrinfo->ai_addr, addrinfo->ai_addrlen);
00142     if (res == -1) {
00143         perror(canonical_remote);
00144         exit(1);
00145     }
00146     freeaddrinfo(addrinfo);
00147     if (myai != NULL)
00148         freeaddrinfo(myai);
00149     return (sock);
00150 }
00151 
00152 static void
00153 send_ccnb_file(int sock, FILE *msgs, const char *filename, int is_dgram)
00154 {
00155     ssize_t rawlen;
00156     ssize_t sres;
00157     int fd = 0;
00158     int truncated = 0;
00159     char onemore[1] = {0};
00160     
00161     if (strcmp(filename, "-") != 0) {
00162         fd = open(filename, O_RDONLY);
00163         if (fd == -1) {
00164             perror(filename);
00165             exit(-1);
00166         }
00167     }
00168     for (;;) {
00169         rawlen = read(fd, rawbuf, sizeof(rawbuf));
00170         if (rawlen == -1) {
00171             perror(filename);
00172             exit(-1);
00173         }
00174         if (rawlen == 0 && !is_dgram)
00175             break;
00176         if (is_dgram && rawlen == sizeof(rawbuf))
00177             truncated = read(fd, onemore, 1);
00178         if (truncated == 1)
00179             fprintf(msgs, "TRUNCATED ");
00180         fprintf(msgs, "send %s (%lu bytes)\n", filename, (unsigned long)rawlen);
00181         sres = send(sock, rawbuf, rawlen, 0);
00182         if (sres == -1) {
00183             perror("send");
00184             exit(1);
00185         }
00186         if (is_dgram)
00187             break;
00188     }
00189     if (fd != 0)
00190         close(fd);
00191 }
00192 
00193 static int
00194 is_ccnb_name(const char *s)
00195 {
00196     size_t len = strlen(s);
00197     return (len > 5 && 0 == strcasecmp(s + len - 5, ".ccnb"));
00198 }
00199 
00200 void
00201 write_to_stream(FILE *outstream, const void *rawbuf, size_t rawlen)
00202 {
00203     size_t wlen;
00204     wlen = fwrite(rawbuf, 1, rawlen, outstream);
00205     if (wlen != rawlen)
00206         fprintf(stderr, "short write (%ld of %ld)\n",
00207                 (long)wlen, (long)rawlen);
00208     if (fflush(outstream) != 0)
00209         perror("fflush");
00210 }
00211 
00212 int
00213 main(int argc, char **argv)
00214 {
00215     struct sockaddr_un addr = {0};
00216     int opt;
00217     struct pollfd fds[1];
00218     int res;
00219     ssize_t rawlen;
00220     ssize_t wlen;
00221     int sock;
00222     char *filename = NULL;
00223     const char *portstr;
00224     int msec = 1000;
00225     int argp;
00226     FILE *msgs = stdout;
00227     FILE *outstream = NULL;
00228     int udp = 0;
00229     int tcp = 0;
00230     int recvloop = 0;
00231     int do_pclose = 0;
00232     const char *host = "localhost";
00233     const char *cmd = NULL;
00234     
00235     while ((opt = getopt(argc, argv, "bht:T:u:")) != -1) {
00236         switch (opt) {
00237             case 'b':
00238                 outstream = stdout;
00239                 msgs = stderr;
00240                 break;
00241             case 't':
00242                 msec = atoi(optarg);
00243                 break;
00244             case 'u':
00245                 udp = 1;
00246                 host = optarg;
00247                 break;
00248             case 'T':
00249                 tcp = 1;
00250                 host = optarg;
00251                 break;
00252             case 'h':
00253             default:
00254                 fprintf(stderr, "Usage %s %s\n", argv[0],
00255                         " [-b(inaryout)] "
00256                         " [-u udphost] "
00257                         " [-T tcphost] "
00258                         " [-t millisconds] "
00259                         " ( send <filename>"
00260                         " | <sendfilename>.ccnb"
00261                         " | recv"
00262                         " | kill"
00263                         " | status"
00264                         " | timeo <millisconds>"
00265                         " ) ...");
00266                 exit(1);
00267         }
00268     }
00269     argp = optind;
00270     portstr = getenv(CCN_LOCAL_PORT_ENVNAME);
00271     ccn_setup_sockaddr_un(portstr, &addr);
00272     if (udp)
00273         sock = open_socket(host, portstr, SOCK_DGRAM);
00274     else if (tcp)
00275         sock = open_socket(host, portstr, SOCK_STREAM);
00276     else
00277         sock = open_local(&addr, argv[optind]);
00278     fds[0].fd = sock;
00279     fds[0].events = POLLIN;
00280     fds[0].revents = 0;
00281     for (argp = optind; argv[argp] != NULL; argp++) {
00282         if (0 == strcmp(argv[argp], "send")) {
00283             filename = argv[argp + 1];
00284             if (filename == NULL)
00285                 filename = "-";
00286             else
00287                 argp++;
00288             send_ccnb_file(sock, msgs, filename, udp);
00289         }
00290         else if (is_ccnb_name(argv[argp])) {
00291             filename = argv[argp];
00292             send_ccnb_file(sock, msgs, filename, udp);
00293         }
00294         else if (recvloop || 0 == strcmp(argv[argp], "recv")) {
00295             res = poll(fds, 1, msec);
00296             if (res == -1) {
00297                 perror("poll");
00298                 exit(1);
00299             }
00300             if (res == 0) {
00301                 fprintf(msgs, "recv timed out after %d ms\n", msec);
00302                 recvloop = 0;
00303                 continue;
00304             }
00305             rawlen = recv(sock, rawbuf, sizeof(rawbuf), 0);
00306             if (rawlen == -1) {
00307                 perror("recv");
00308                 exit(1);
00309             }
00310             if (rawlen == 0)
00311                 break;
00312             if (recvloop)
00313                 argp--;
00314             else
00315                 fprintf(msgs, "recv of %lu bytes\n", (unsigned long)rawlen);
00316             if (outstream != NULL)
00317                 write_to_stream(outstream, rawbuf, rawlen);
00318             else
00319                 printraw(rawbuf, rawlen);
00320         }
00321         else if (0 == strcmp(argv[argp], "kill")) {
00322             poll(fds, 1, 1);
00323             res = unlink((char *)addr.sun_path);
00324             if (res == 0) {
00325                 res = open_socket(host, portstr, SOCK_STREAM);
00326                 if (res != -1) {
00327                     wlen = write(res, " ", 1);
00328                     close(res);
00329                 }
00330                 poll(fds, 1, 5000);
00331                 rawlen = recv(sock, rawbuf, sizeof(rawbuf), 0);
00332                 if (rawlen == 0)
00333                     exit(0);
00334                 if (rawlen > 0)
00335                     exit(2);
00336             }
00337             fprintf(stderr, "%s kill (%s) ", argv[0], (char *)addr.sun_path);
00338             perror("failed");
00339             exit(1);
00340         }
00341         else if (0 == strcmp(argv[argp], "timeo")) {
00342             if (argv[argp + 1] != NULL)
00343                 msec = atoi(argv[++argp]);
00344         }
00345         else if (udp == 0 && 0 == strcmp(argv[argp], "status")) {
00346             msgs = stderr;
00347             cmd = ("sed -e 's=[<]style .*/style[>]==g' -e 's=[<][^>]*[>]==g'|"
00348                    "tail -n +7");
00349             outstream = popen(cmd, "w");
00350             wlen = send(sock, "GET / " CRLF , 8, 0);
00351             recvloop = 1;
00352             do_pclose = 1;
00353             argp--;
00354         }
00355         else {
00356             fprintf(stderr, "%s: unknown verb %s, try -h switch for usage\n",
00357                     argv[0], argv[argp]);
00358             exit(1);
00359         }
00360     }
00361     if (do_pclose)
00362         pclose(outstream);
00363     exit(0);
00364 }
Generated on Fri May 13 16:27:01 2011 for Content-Centric Networking in C by  doxygen 1.6.3