Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <poll.h>
- #include <stdlib.h>
- #include <aio.h>
- #define DEFAULTPORT 80
- #define BUFFERSIZE (16 * 1024)
- #define DNS_TIMEOUT 3
- void *work(int httpSocket) {
- char *buffers[2];
- buffers[0] = (char *) malloc(BUFFERSIZE);
- buffers[1] = (char *) malloc(BUFFERSIZE);
- struct aiocb aioSocket;
- memset(&aioSocket, 0, sizeof(aioSocket));
- aioSocket.aio_fildes = httpSocket;
- aioSocket.aio_buf = buffers[1];
- aioSocket.aio_nbytes = BUFFERSIZE;
- const struct aiocb *aioQueue[1];
- aioQueue[0] = &aioSocket;
- int linesWritten = 0;
- int allowedToStop = 0;
- if (0 != aio_read(&aioSocket)) {
- perror("aio_read error");
- exit(EXIT_FAILURE);
- }
- for (int iteration = 0; !allowedToStop; ++iteration) {
- if (-1 == aio_suspend(aioQueue, 1, NULL)) {
- perror("aio_suspend error");
- exit(EXIT_FAILURE);
- }
- size_t end = aio_return(&aioSocket);
- size_t start = 0;
- if (0 == end) {
- allowedToStop = 1;
- }
- else if (end > 0) {
- aioSocket.aio_buf = buffers[iteration % 2];
- if (0 != aio_read(&aioSocket)) {
- perror("aio_read error");
- exit(EXIT_FAILURE);
- }
- char *current = buffers[(iteration + 1) % 2];
- while (start < end) {
- char *enter = strchr(current + start, '\n');
- size_t lineEnd;
- if (NULL == enter) {
- lineEnd = end;
- }
- else {
- lineEnd = enter - current + 1;
- }
- int written = write(STDOUT_FILENO, current + start, lineEnd - start);
- if (-1 == written) {
- perror("Write error");
- exit(EXIT_FAILURE);
- }
- else {
- start += written;
- if (start == lineEnd && enter != NULL) {
- linesWritten++;
- }
- }
- if (linesWritten == 25) {
- char temp;
- printf("Press enter to scroll down\n");
- do {
- if (-1 == read(STDIN_FILENO, &temp, 1)) {
- perror("Cannot read from terminal");
- }
- } while (temp != '\n');
- linesWritten = 0;
- }
- }
- memset(current, 0, end);
- }
- else {
- perror("aio_return error");
- exit(EXIT_FAILURE);
- }
- }
- free(buffers[0]);
- free(buffers[1]);
- }
- void sighandler(int signum) {
- fprintf(stderr, "Dns request timed out\n");
- exit(EXIT_FAILURE);
- }
- int makeConnection(const char *hostName) {
- signal(SIGALRM, sighandler);
- alarm(DNS_TIMEOUT);
- struct hostent *hostInfo = gethostbyname(hostName);
- alarm(0);
- if (NULL == hostInfo) {
- fprintf(stderr, "Cannot get host by name\n");
- exit(EXIT_FAILURE);
- }
- struct sockaddr_in destinationAddress;
- destinationAddress.sin_family = AF_INET;
- destinationAddress.sin_port = htons(DEFAULTPORT);
- memcpy(&destinationAddress.sin_addr, hostInfo->h_addr, hostInfo->h_length);
- int httpSocket = socket(AF_INET, SOCK_STREAM, 0);
- if (-1 == httpSocket) {
- perror("Cannot create socket");
- exit(EXIT_FAILURE);
- }
- if (-1 == connect(httpSocket, (struct sockaddr *) &destinationAddress, sizeof(destinationAddress))) {
- perror("Cannot connect");
- exit(EXIT_FAILURE);
- }
- return httpSocket;
- }
- void sendRequest(const char *path, const char *host, int httpSocket) {
- char pattern[] = "GET %s HTTP/1.0\nHost: %s\n\n\0";
- char *buffer = (char *) malloc(BUFFERSIZE);
- if (NULL == buffer) {
- perror("Cannot allocate memory for buffer");
- exit(EXIT_FAILURE);
- }
- sprintf(buffer, pattern, path, host);
- if (-1 == send(httpSocket, buffer, strlen(buffer), 0)) {
- perror("Cannot send request");
- exit(EXIT_FAILURE);
- }
- free(buffer);
- }
- void checkCountArguments(int argc) {
- if (argc != 2) {
- perror("Wrong count of arguments");
- exit(EXIT_FAILURE);
- }
- }
- int main(int argc, char *argv[]) {
- checkCountArguments(argc);
- char *url = argv[1];
- char *protocolEnd = strstr(url, "://");
- char *hostEnd = strchr(protocolEnd + 3, '/');
- size_t hostLength = 0;
- char protocol[protocolEnd - url + 1];
- protocol[protocolEnd - url] = 0;
- strncpy(protocol, url, strlen(protocol));
- if (strcmp(protocol, "http") != 0 && strcmp(protocol, "https") != 0) {
- fprintf(stderr, "Unsupported protocol\n");
- exit(EXIT_FAILURE);
- }
- if (NULL == hostEnd) {
- hostLength = strlen(protocolEnd + 3);
- }
- else {
- hostLength = hostEnd - (protocolEnd + 3);
- }
- char *hostName = (char *) malloc(hostLength + 1);
- if (NULL == hostName) {
- perror("Cannot allocate memory for hostname");
- exit(EXIT_FAILURE);
- }
- strncpy(hostName, protocolEnd + 3, hostLength);
- hostName[hostLength] = 0;
- int httpSocket = makeConnection(hostName);
- if (hostEnd == NULL) {
- sendRequest("/", hostName, httpSocket);
- }
- else {
- sendRequest(hostEnd, hostName, httpSocket);
- }
- work(httpSocket);
- free(hostName);
- putchar('\n');
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement