socktest: turns into a tool for fetching files via http
authorAlan Cox <alan@linux.intel.com>
Fri, 25 Mar 2016 17:40:02 +0000 (17:40 +0000)
committerAlan Cox <alan@linux.intel.com>
Fri, 25 Mar 2016 17:40:02 +0000 (17:40 +0000)
Handy for debugging

Applications/util/socktest.c

index d2ad1a4..121aa0c 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #define AF_INET                1
 #define SOCK_STREAM    3
 #define IPPROTO_TCP    6
 
-struct in_addr {
-  uint32_t s_addr;
-};
+struct sockaddr_in addr;
+struct sockaddr_in laddr;
 
-struct sockaddr_in {
-  uint16_t sin_family;
-  uint16_t sin_port;
-  struct in_addr sin_addr;
-  uint8_t sin_zero[8];
-};
-
-struct sockaddr_in addr = {
-  AF_INET,
-  0xEA1D,
-  { 0xF400A8C0 },
-};
-
-struct sockaddr_in laddr = {
-  AF_INET,
-  0x0A0A,
-  { 0x010000C0 },
-};
+static int writes(int fd, const char *p)
+{
+       return write(fd, p, strlen(p));
+}
 
 int main(int argc, char *argv[])
 {
-  int fd;
-  int r;
-  char buf[5];
-  
-  fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-  if (fd < 0)
-    perror("af_inet sock_stream pf_tcp");
-  close(fd);
-      
-  fd = socket(AF_INET, SOCK_STREAM, 0);
-  if (fd < 0) {
-    perror("af_inet sock_stream 0");
-    exit(1);
-  }
-  if (bind(fd, (struct sockaddr *)&laddr, sizeof(addr)) < 0) {
-    perror("bind");
-    exit(1);
-  }
-  
-  if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-    perror("connect");
-    exit(1);
-  }
-  if (write(fd, "Hello", 5) == -1) {
-    perror("write");
-    exit(1);
-  }
-  if ((r = read(fd, buf, 5)) < 0) {
-    perror("read");
-    exit(1);
-  }
-  printf("Read %d bytes\n", r);
-  write(1, buf, r);
-  close(fd);
-  return 0;      
+       int fd, fd2;
+       int r;
+       unsigned long t = 0;
+       char buf[512];
+       static char line[81];
+       char *lp;
+       char *p;
+       int state = 0;
+
+       if (argc != 2) {
+               writes(2, argv[0]);
+               write(2, ": url\n", 6);
+               exit(1);
+       }
+
+       if (strncmp(argv[1], "http://", 7)) {
+               writes(2, argv[0]);
+               writes(2, ": only http:// supported.\n");
+               exit(1);
+       }
+
+       p = strchr(argv[1] + 7, '/');
+       if (p == NULL) {
+               writes(2, argv[0]);
+               writes(2, ": no path element.\n");
+               exit(1);
+       }
+       *p++ = 0;
+       lp = strchr(argv[1] + 7, ':');
+       if (lp == NULL)
+               addr.sin_port = htons(80);
+       else {
+               *lp = 0;
+               addr.sin_port = htons(atoi(lp + 1));
+       }
+
+       if (inet_pton(AF_INET, argv[1] + 7, &addr.sin_addr.s_addr) <= 0) {
+               writes(2, argv[1] + 7);
+               writes(2, ": unknown address.\n");
+               exit(1);
+       }
+
+       fd = socket(AF_INET, SOCK_STREAM, 0);
+       if (fd < 0) {
+               perror("af_inet sock_stream 0");
+               exit(1);
+       }
+       laddr.sin_family = AF_INET;
+       laddr.sin_addr.s_addr = htonl(INADDR_ANY);
+       laddr.sin_port = htons(8000);
+
+       if (bind(fd, (struct sockaddr *) &laddr, sizeof(addr)) < 0) {
+               perror("bind");
+               exit(1);
+       }
+
+       addr.sin_family = AF_INET;
+       printf("%lx\n", addr.sin_addr.s_addr);
+
+       if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+               perror("connect");
+               exit(1);
+       }
+       if (writes(fd, "GET /test HTTP/1.1\r\nHost: test.test\r\n\r\n") ==
+           -1) {
+               perror("write");
+               exit(1);
+       }
+
+       lp = line;
+
+       while ((r = read(fd, buf, 512)) > 0) {
+               if (r < 0) {
+                       perror("read");
+                       exit(1);
+               }
+               p = buf;
+               switch (state) {
+               case 0:
+               case 1:
+                       while (p < buf + r) {
+                               if (*p != '\n') {
+                                       if (*p != '\r' && lp != line + 80)
+                                               *lp++ = *p;
+                                       p++;
+                                       continue;
+                               }
+                               /* We have a line */
+                               if (lp != line) {
+                                       *lp = 0;
+                                       write(1, "|", 1);
+                                       writes(1, line);
+                                       write(1, "\n", 1);
+                                       if (state == 0) {
+                                               lp = strchr(line, ' ');
+                                               if (lp == NULL
+                                                   || atoi(lp + 1) != 200)
+                                                       exit(1);
+                                       }
+                                       state = 1;
+                                       lp = line;
+                                       p++;
+                                       continue;
+                               } else {
+                                       p++;
+                                       /* nl/nl end of headers - begin xfer */
+                                       fd2 =
+                                           open("output",
+                                                O_WRONLY | O_TRUNC |
+                                                O_CREAT, 0700);
+                                       if (fd2 == -1) {
+                                               perror("output");
+                                               exit(1);
+                                       }
+                                       r -= (p - buf);
+                                       if (r && write(fd2, p, r) != r) {
+                                               perror("write");
+                                               exit(1);
+                                       }
+                                       state = 2;
+                                       break;
+                               }
+                       }
+                       break;
+               case 2:
+                       if (write(fd2, buf, r) != r) {
+                               perror("write");
+                               exit(1);
+                       }
+                       t += r;
+                       printf("%ld\r", t);
+                       fflush(stdout);
+                       break;
+               }
+       }
+       printf("\nRead %ld bytes\n", t);
+       close(fd);
+       close(fd2);
+       return 0;
 }