Advertisement
Guest User

main.c

a guest
Apr 20th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.49 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <assert.h>
  4.  
  5. #include <sys/socket.h>
  6. #include <sys/types.h>
  7. #include <unistd.h>
  8.  
  9. #include "server.h"
  10. #include "http.h"
  11. #include "util.h"
  12. #include "mandelbrot.h"
  13.  
  14. #define DEFAULT_PORT 1917
  15. #define BACKLOG_SIZE 10
  16.  
  17. #define IMG_WIDTH  512
  18. #define IMG_HEIGHT 512
  19.  
  20. #define BASE_VISIBLE 2
  21.  
  22. int main(void) {
  23.     int sockfd, theirfd;
  24.     int quit = FALSE;
  25.     char buf[BUF_SIZE];
  26.     int read;
  27.     struct triordinate t;
  28.     int sent;
  29.     /* I can't use global variables so this is what you get.
  30.        TODO: Move the headers to separate functions. */
  31.     char HTTPHeader[] = "HTTP/1.0 200 OK\r\n"
  32.                        "Content-Type: image/bmp\r\n"
  33.                        "\r\n";
  34.     /* Contains both bitmap file and DIB headers.
  35.        NOTE: This uses the OS/2 variant of DIB headers.
  36.        See: en.wikipedia.org/wiki/BMP_file_format#DIB_header_(bitmap_information_header) */
  37.     unsigned char BMPHeader[] = {
  38.         /* Bitmap file header */
  39.          'B',  'M', 0x1a, 0x00, 0x0c, 0xc0, 0xde, 0xd0,
  40.         0x0d, 0x00, 0x1a,
  41.         /* DIB header */
  42.         0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43.             /* Image width and height (offset 0x12 and 0x14 respectively). */
  44.             0x00, 0x02, 0x00, 0x02,
  45.         0x01, 0x00, 0x18, 0x00
  46.     };
  47.     double wunit, hunit, x, y, xlimit, ylimit;
  48.     struct complex c;
  49.  
  50.     /* Create and bind network socket and get its file descriptor. */
  51.     sockfd = initServer(DEFAULT_PORT);
  52.     assert(sockfd != -1 && fuck("initServer")); // See util.c
  53.  
  54.     /* Begin listening on the socket. */
  55.     while (!quit) {
  56.         /* Get client file descriptor. */
  57.         theirfd = serve(sockfd, BACKLOG_SIZE);
  58.         /* When serve (i.e listen() or accept()) fails, it is fatal.
  59.            See listen(3P) and accept(3P) for details. */
  60.         assert(theirfd != -1 && fuck("serve"));
  61.  
  62.         /* Read HTTP request into a buffer for parsing. */
  63.         buf[BUF_SIZE - 1] = '\0';
  64.         read = recv(theirfd, buf, BUF_SIZE - 1, 0);
  65.         /* When recv fails, it is usually fatal.
  66.            See recv(3P) for details. */
  67.         assert(read != -1 && fuck("recv"));
  68.         fprintf(stderr, "request received:\n%s\n", buf);
  69.        
  70.         /* Ensure the request path follows the correct pattern
  71.            parsing, and parse it. */
  72.         if (!matchString(buf)) {
  73.             /* Send a 404. */
  74.             fputs("error 404\n", stderr);
  75.             /* TODO: Add error 404 page */
  76.         } else {
  77.             t = parseRequest(buf);
  78.             fprintf(stderr,
  79.                     "triordinate received: "
  80.                     "{ .zoom = %d, .x = %f , .y = %f }\n",
  81.                     t.zoom, t.x, t.y
  82.             );
  83.             /* Send HTTP response header. */
  84.             sent = send(
  85.                 theirfd,
  86.                 HTTPHeader,
  87.                 sizeof(HTTPHeader) + 1,
  88.                 0
  89.             );
  90.             fprintf(stderr,
  91.                     "HTTP response header transmitted:\n%s\n",
  92.                     HTTPHeader
  93.             );
  94.             /* When send fails, it is usually fatal.
  95.                See send(3P) for details. */
  96.             assert(sent != -1 && fuck("send"));
  97.             /* This should never happen. */
  98.             assert(sent == sizeof(HTTPHeader) + 1 && "impossible");
  99.  
  100.             /* Set width and height fields in the BMP header.
  101.  
  102.                Because integers are stored in little-endian, the bytes of the
  103.                dimension must be stored in reverse. Casting to unsigned char
  104.                truncates the integer to its least significant byte.*/
  105.             BMPHeader[0x12] = (unsigned char)IMG_WIDTH;
  106.             BMPHeader[0x13] = (unsigned char)bitshiftRight(IMG_WIDTH, CHAR_BIT);
  107.             BMPHeader[0x14] = (unsigned char)IMG_HEIGHT;
  108.             BMPHeader[0x15] = (unsigned char)bitshiftRight(IMG_HEIGHT, CHAR_BIT);
  109.  
  110.             /* Send BMP header. */
  111.             sent = send(
  112.                 theirfd,
  113.                 BMPHeader,
  114.                 sizeof(BMPHeader) + 1,
  115.                 0
  116.             );
  117.             /* See above. */
  118.             assert(sent != -1 && fuck("send"));
  119.             /* This should also never happen. */
  120.             assert(sent == sizeof(BMPHeader) + 1 && "impossible");
  121.  
  122.             /* Generate BMP pixel array. */
  123.             fputs("Generating pixel array...", stderr);
  124.             wunit = BASE_VISIBLE / t.zoom / IMG_WIDTH;
  125.             hunit = BASE_VISIBLE / t.zoom / IMG_HEIGHT;
  126.             /* The pixel array starts with the bottom left. */
  127.             x = t.x - (IMG_WIDTH / 2 * wunit);
  128.             y = t.y + (IMG_HEIGHT / 2 * hunit);
  129.             xlimit = x + IMG_WIDTH * wunit;
  130.             ylimit = y - IMG_HEIGHT * hunit;
  131.  
  132.             /* Begin sending each pixel to the client. */
  133.             while (x < xlimit) {
  134.                 while (y > ylimit) {
  135.                     c.real = x;
  136.                     c.imag = y;
  137.                     int escape = escapeSteps(c);
  138.  
  139.                     /* TODO: Add colours. */
  140.                     unsigned char colourbuf[3] = { escape, escape, escape };
  141.                     send(theirfd, colourbuf, sizeof(colourbuf), 0);
  142.  
  143.                     y -= hunit;
  144.                 }
  145.                 x += wunit;
  146.             }
  147.             fputs("\nDone.\n", stderr);
  148.         }
  149.        
  150.         /* Close server connection. Keep Australia beautiful. */
  151.         close(theirfd);
  152.     }
  153.  
  154.     /* Close the socket. Keep Australia beautiful. */
  155.     close(sockfd);
  156.  
  157.     return EXIT_SUCCESS;
  158. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement