Example #1
0
int main(void) {
  Stream * stream;

  stream = Stream_new(0);
  Stream_write_string(stream, "a");
  Stream_write_string(stream, "bc");
  assert(stream->length == 3);
  assert(memcmp(stream->data, "abc", 3) == 0);
  Stream_delete(stream);

  /* test writing chars to stream */
  stream = Stream_new(2);
  Stream_write_char(stream, 'a');
  Stream_write_char(stream, 'b');
  Stream_write_char(stream, 'c');
  assert(stream->length == 3);
  assert(memcmp(stream->data, "abc", 3) == 0);
  Stream_reset(stream);
  Stream_write_char(stream, 'x');
  Stream_write_char(stream, 'y');
  assert(stream->length == 2);
  assert(memcmp(stream->data, "xy", 2) == 0);
  Stream_delete(stream);

  /* test writing file to stream */
  stream = Stream_new(0);
  FILE * f = xfopen("Makefile", "r");
  fseek(f, 0, SEEK_END);
  long file_length = ftell(f);
  fseek(f, 0, SEEK_SET);
  uint8_t * file_contents = xmalloc(file_length);
  fread(file_contents, 1, file_length, f);
  fseek(f, 0, SEEK_SET);
  Stream_write_file_contents(stream, f);
  fclose(f);
  assert(stream->length == (size_t) file_length);
  assert(memcmp(stream->data, file_contents, file_length) == 0);
  free(file_contents);
  Stream_delete(stream);

  stream = Stream_new(0);
  Stream_printf(stream, "%s %d\n", "abc", 123);
  assert(stream->length == 8);
  assert(memcmp(stream->data, "abc 123\n", 8) == 0);
  Stream_delete(stream);

  stream = Stream_new(10);
  size_t length = 0;
  for (int i = 0; i < 100; i++) {
    Stream_printf(stream, "%s %d\n", "abc", i);
    if (i < 10) {
      length += 6;
    }
    else {
      length += 7;
    }
  }
  assert(stream->length == length);
  length = 0;
  for (int i = 0; i < 100; i++) {
    char buffer[8];
    int result = sprintf(buffer, "%s %d\n", "abc", i);
    assert(memcmp(stream->data + length, buffer, result) == 0);
    length += result;
  }
  assert(stream->length == length);
  Stream_delete(stream);

  stream = Stream_new(10);
  char buffer[100];
  for (int i = 0; i < 100; i++) {
    buffer[i] = 'x';
  }
  Stream_write(stream, buffer, 100);
  assert(stream->length == 100);
  for (int i = 0; i < 100; i++) {
    assert(stream->data[i] == 'x');
  }
  Stream_delete(stream);

  exit(EXIT_SUCCESS);
}
int main(void) {
#ifdef __MINGW32__
    WSADATA data;
    if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
        return 1;
    }
#endif

    SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
    assert(s != INVALID_SOCKET);

    int optval = 1;
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));

    struct sockaddr_in a;
    a.sin_family = AF_INET;
    a.sin_port = htons(8000);
    a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    int result = bind(s, (struct sockaddr *) &a, sizeof(a));
    assert(result == 0);

    result = listen(s, 5);
    assert(result == 0);

    for (;;) {
        struct sockaddr_in client_address;
        size_t size = sizeof(client_address);
        int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
        assert(client_socket > 0);

        /* read request */
        Stream * stream = Stream_new(0);
        int state = 0;
        while (state != 2) {
            uint8_t buffer[8192];
            ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
            assert(bytes_read > 0);
            Stream_write(stream, buffer, bytes_read);
            for (int i = 0; i < bytes_read && state != 2; i++) {
                uint8_t byte = buffer[i];
                switch (state) {
                case 0:
                    if (byte == '\n') {
                        state = 1;
                    }
                    break;
                case 1:
                    if (byte == '\n') {
                        state = 2;
                    }
                    else if (byte == '\r') {
                        state = 1;
                    }
                    else {
                        state = 0;
                    }
                    break;
                }
            }
        }

        char * method;
        char * url;
        char * request_line = (char *) stream->data;
        char * first_space = strchr(request_line, ' ');
        assert(first_space != NULL);
        char * second_space = strchr(first_space + 1, ' ');
        assert(second_space != NULL);
        method = xstrndup(request_line, first_space - request_line);
        url = xstrndup(first_space + 1, second_space - (first_space + 1));

        /* send response */
        char * message;
        if (strcmp(url, "http://127.0.0.1:8000/utf-8.js") == 0 || strcmp(url, "/utf-8.js") == 0) {
            message = "HTTP/1.1 200 OK\r\n"
                      "Connection: close\r\n"
                      "Content-type: text/javascript; charset=UTF-8\r\n"
                      "\r\n"
                      "var s = 'eèéΓͺ';\n"
                      "var r = /eèéΓͺ/;\n";
        }
        else if (strcmp(url, "http://127.0.0.1:8000/iso-8859-1.js") == 0 || strcmp(url, "/iso-8859-1.js") == 0) {
            message = "HTTP/1.1 200 OK\r\n"
                      "Connection: close\r\n"
                      "Content-type: text/javascript; charset=ISO-8859-1\r\n"
                      "\r\n"
                      "var s = 'eθικ';\n"
                      "var r = /eθικ/;\n";
        }
        else if (strcmp(url, "http://127.0.0.1:8000/bogus.js") == 0 || strcmp(url, "/bogus.js") == 0) {
            message = "HTTP/1.1 200 OK\r\n"
                      "Connection: close\r\n"
                      "Content-type: text/javascript; charset=BOGUS\r\n"
                      "\r\n"
                      "var s = 'eθικ';\n"
                      "var r = /eθικ/;\n";
        }
        else if (strcmp(url, "http://127.0.0.1:8000/malformed.js") == 0 || strcmp(url, "/malformed.js") == 0) {
            message = "HTTP/1.1 200 OK\r\n"
                      "Connection: close\r\n"
                      "Content-type: text/javascript; charset=UTF-8\r\n"
                      "\r\n"
                      "var s = 'eθικ';\n"
                      "var r = /eθικ/;\n";
        }
        else {
            abort();
        }
        size_t message_length = strlen(message);
        ssize_t bytes_sent = send(client_socket, message, message_length, 0);
        assert(bytes_sent == (ssize_t) message_length);

        closesocket(client_socket);
    }
    return 0;
}