Advertisement
Guest User

Untitled

a guest
Dec 12th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.69 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <netdb.h>
  5. #include <arpa/inet.h>
  6. #include <sys/socket.h>
  7. #include <poll.h>
  8. #include <stdlib.h>
  9. #include <aio.h>
  10.  
  11. #define DEFAULTPORT 80
  12. #define BUFFERSIZE (16 * 1024)
  13. #define DNS_TIMEOUT 3
  14.  
  15. void *work(int httpSocket) {
  16. char *buffers[2];
  17. buffers[0] = (char *) malloc(BUFFERSIZE);
  18. buffers[1] = (char *) malloc(BUFFERSIZE);
  19.  
  20. struct aiocb aioSocket;
  21. memset(&aioSocket, 0, sizeof(aioSocket));
  22. aioSocket.aio_fildes = httpSocket;
  23. aioSocket.aio_buf = buffers[1];
  24. aioSocket.aio_nbytes = BUFFERSIZE;
  25.  
  26. const struct aiocb *aioQueue[1];
  27.  
  28. aioQueue[0] = &aioSocket;
  29.  
  30. int linesWritten = 0;
  31. int allowedToStop = 0;
  32.  
  33. if (0 != aio_read(&aioSocket)) {
  34. perror("aio_read error");
  35. exit(EXIT_FAILURE);
  36. }
  37.  
  38. for (int iteration = 0; !allowedToStop; ++iteration) {
  39. if (-1 == aio_suspend(aioQueue, 1, NULL)) {
  40. perror("aio_suspend error");
  41. exit(EXIT_FAILURE);
  42. }
  43.  
  44. size_t end = aio_return(&aioSocket);
  45. size_t start = 0;
  46.  
  47. if (0 == end) {
  48. allowedToStop = 1;
  49. }
  50. else if (end > 0) {
  51. aioSocket.aio_buf = buffers[iteration % 2];
  52. if (0 != aio_read(&aioSocket)) {
  53. perror("aio_read error");
  54. exit(EXIT_FAILURE);
  55. }
  56.  
  57. char *current = buffers[(iteration + 1) % 2];
  58.  
  59. while (start < end) {
  60. char *enter = strchr(current + start, '\n');
  61.  
  62. size_t lineEnd;
  63.  
  64. if (NULL == enter) {
  65. lineEnd = end;
  66. }
  67. else {
  68. lineEnd = enter - current + 1;
  69. }
  70.  
  71. int written = write(STDOUT_FILENO, current + start, lineEnd - start);
  72.  
  73. if (-1 == written) {
  74. perror("Write error");
  75. exit(EXIT_FAILURE);
  76. }
  77. else {
  78. start += written;
  79.  
  80. if (start == lineEnd && enter != NULL) {
  81. linesWritten++;
  82. }
  83. }
  84.  
  85. if (linesWritten == 25) {
  86. char temp;
  87.  
  88. printf("Press enter to scroll down\n");
  89. do {
  90. if (-1 == read(STDIN_FILENO, &temp, 1)) {
  91. perror("Cannot read from terminal");
  92. }
  93. } while (temp != '\n');
  94.  
  95. linesWritten = 0;
  96. }
  97. }
  98.  
  99. memset(current, 0, end);
  100. }
  101. else {
  102. perror("aio_return error");
  103. exit(EXIT_FAILURE);
  104. }
  105. }
  106.  
  107. free(buffers[0]);
  108. free(buffers[1]);
  109. }
  110.  
  111. void sighandler(int signum) {
  112. fprintf(stderr, "Dns request timed out\n");
  113. exit(EXIT_FAILURE);
  114. }
  115.  
  116. int makeConnection(const char *hostName) {
  117. signal(SIGALRM, sighandler);
  118. alarm(DNS_TIMEOUT);
  119. struct hostent *hostInfo = gethostbyname(hostName);
  120. alarm(0);
  121.  
  122. if (NULL == hostInfo) {
  123. fprintf(stderr, "Cannot get host by name\n");
  124. exit(EXIT_FAILURE);
  125. }
  126.  
  127. struct sockaddr_in destinationAddress;
  128.  
  129. destinationAddress.sin_family = AF_INET;
  130. destinationAddress.sin_port = htons(DEFAULTPORT);
  131. memcpy(&destinationAddress.sin_addr, hostInfo->h_addr, hostInfo->h_length);
  132.  
  133. int httpSocket = socket(AF_INET, SOCK_STREAM, 0);
  134.  
  135.  
  136. if (-1 == httpSocket) {
  137. perror("Cannot create socket");
  138. exit(EXIT_FAILURE);
  139. }
  140.  
  141. if (-1 == connect(httpSocket, (struct sockaddr *) &destinationAddress, sizeof(destinationAddress))) {
  142. perror("Cannot connect");
  143. exit(EXIT_FAILURE);
  144. }
  145.  
  146. return httpSocket;
  147. }
  148.  
  149. void sendRequest(const char *path, const char *host, int httpSocket) {
  150. char pattern[] = "GET %s HTTP/1.0\nHost: %s\n\n\0";
  151. char *buffer = (char *) malloc(BUFFERSIZE);
  152.  
  153. if (NULL == buffer) {
  154. perror("Cannot allocate memory for buffer");
  155. exit(EXIT_FAILURE);
  156. }
  157.  
  158. sprintf(buffer, pattern, path, host);
  159.  
  160. if (-1 == send(httpSocket, buffer, strlen(buffer), 0)) {
  161. perror("Cannot send request");
  162. exit(EXIT_FAILURE);
  163. }
  164.  
  165. free(buffer);
  166. }
  167.  
  168. void checkCountArguments(int argc) {
  169. if (argc != 2) {
  170. perror("Wrong count of arguments");
  171. exit(EXIT_FAILURE);
  172. }
  173. }
  174.  
  175. int main(int argc, char *argv[]) {
  176. checkCountArguments(argc);
  177.  
  178. char *url = argv[1];
  179. char *protocolEnd = strstr(url, "://");
  180. char *hostEnd = strchr(protocolEnd + 3, '/');
  181. size_t hostLength = 0;
  182. char protocol[protocolEnd - url + 1];
  183.  
  184. protocol[protocolEnd - url] = 0;
  185. strncpy(protocol, url, strlen(protocol));
  186. if (strcmp(protocol, "http") != 0 && strcmp(protocol, "https") != 0) {
  187. fprintf(stderr, "Unsupported protocol\n");
  188. exit(EXIT_FAILURE);
  189. }
  190.  
  191. if (NULL == hostEnd) {
  192. hostLength = strlen(protocolEnd + 3);
  193. }
  194. else {
  195. hostLength = hostEnd - (protocolEnd + 3);
  196. }
  197.  
  198. char *hostName = (char *) malloc(hostLength + 1);
  199.  
  200. if (NULL == hostName) {
  201. perror("Cannot allocate memory for hostname");
  202. exit(EXIT_FAILURE);
  203. }
  204.  
  205. strncpy(hostName, protocolEnd + 3, hostLength);
  206. hostName[hostLength] = 0;
  207.  
  208. int httpSocket = makeConnection(hostName);
  209. if (hostEnd == NULL) {
  210. sendRequest("/", hostName, httpSocket);
  211. }
  212. else {
  213. sendRequest(hostEnd, hostName, httpSocket);
  214. }
  215. work(httpSocket);
  216.  
  217. free(hostName);
  218. putchar('\n');
  219.  
  220. return EXIT_SUCCESS;
  221. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement