00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00079 if (verb != NULL && 0 == strcmp(verb, "kill"))
00080 exit(1);
00081
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 }