mandelbrot.c - OpenLearning
// Name:    John Luo, Sean Batongbacal
// Date:    2014 / 04 / 19
// Descr:   A local server that serves inmaes of the Mandelbrot set

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>

#include "mandelbrot.h" 
#include "pixelColor.h"

int waitForConnection (int serverSocket);
int makeServerSocket (int portno);
void serveHTML (int socket,int viewer,double x,double y,int z);
static double exponential2(int exponent);

#define SIMPLE_SERVER_VERSION 2.0
#define REQUEST_BUFFER_SIZE 1000
#define DEFAULT_PORT 7191

#define MAX_STEPS 256
#define SIZE 512 // sides in px

#define LEFT -2.0
#define RIGHT 2.0
#define TOP 2.0
#define BOTTOM -2.0

#define TRUE 1
#define FALSE 0

int main (int argc, char* argv[]) {

    printf ("************************************\n");
    printf ("Starting simple server %f\n", SIMPLE_SERVER_VERSION);
    printf ("Serving mandelbrot sets since 2014\n");
    printf ("Access this server at http://localhost:%d/\n", DEFAULT_PORT);
    printf ("************************************\n");
    int serverSocket = makeServerSocket(DEFAULT_PORT);

    char request[REQUEST_BUFFER_SIZE];

    int numberServed = 0;
    while (TRUE) {

        printf ("*** So far served %d pages ***\n", numberServed);

        // STEP 1. wait for a request to be sent from a web browser,
        // then open a new connection for this conversation
        int connectionSocket = waitForConnection(serverSocket);

        // STEP 2. read the first line of the request
        int bytesRead;
        bytesRead = read (connectionSocket, request, (sizeof(request)-1));
        assert (bytesRead >= 0);
        // check that we were able to read some data from the connection

        // echo entire request to the console for debugging
        printf (" *** Received http request ***\n %s\n", request);
        


        double x = 0;
        double y = 0;
        int z = 7;
        char requestedFile[sizeof(request)];
        int viewer;
        // STEP 3. send the browser a simple html page using http
        printf (" *** Sending http response ***\n");
        sscanf (request," GET %s HTTP/1.1",requestedFile);
        printf ("\n **** THE REQUESTED FILE IS %s ***** \n",requestedFile);
        if(strlen(requestedFile)==1){
            viewer = TRUE;
        } else{
            sscanf (request," GET /tile_x%lf_y%lf_z%d.bmp",&x,&y,&z);
            viewer = FALSE;
        }
        serveHTML(connectionSocket,viewer,x,y,z);

        // STEP 4. close the connection after sending the page- keep aust beautiful
        close (connectionSocket);
        numberServed++;
    }
    // close the server connection after we are done- keep aust beautiful
    printf ("** shutting down the server **\n");
    close (serverSocket);
    return EXIT_SUCCESS;
}

void serveHTML(int socket,int viewer,double x,double y,int z) {
    char* message; // used to be const? --Sean
    // first send the http response header

    // (if you write stings one after another like this on separate
    // lines the c compiler kindly joins them togther for you into
    // one long string)
    if(viewer == FALSE){
        message = "HTTP/1.0 200 OK\r\n"
                    "Content-Type: image/bmp\r\n"
                    "\r\n";
        printf ("about to send=> %s\n", message);
        write (socket, message, strlen (message));
   
        // now send the BMP header
        unsigned char bmpHeader[] = {
                0x42,0x4d,0x36,0x00,0x0c,0x00,0x00,0x00,
                0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
                0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,
                0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x0c,0x00,0x13,0x0b,
                0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00,0x00
            };
        write (socket, bmpHeader, sizeof(bmpHeader));
        
    
        // iterates calculation and sending
        int col = 0;
        int row = SIZE;
        double currentx;
        double currenty;
        int steps;
        double zoom = exponential2(-z+7);
        unsigned char pixelArray[3] = {};
        while(row>0){
            while(col<SIZE){
                currentx = (LEFT + col*(RIGHT-LEFT)/SIZE) * zoom + x;
                currenty = (TOP + row*(BOTTOM-TOP)/SIZE) * zoom + y;
                steps = escapeSteps(currentx,currenty);
                pixelArray[0] = stepsToBlue(steps);
                pixelArray[1] = stepsToGreen(steps);
                pixelArray[2] = stepsToRed(steps);
                col++;
                write(socket,pixelArray, sizeof(pixelArray));
           }
           col = 0;
           row--;
        }
    } else{
        message = "HTTP/1.0 200 OK\r\n"
                    "Content-Type: text/html\r\n"
                    "\r\n";
        char* viewerMessage = "<!DOCTYPE html>"
                                "<script src='http://almondbread.cse.unsw.edu.au/tiles.js'></script>";
        write(socket,message,strlen(message));
        write(socket,viewerMessage,strlen(viewerMessage));
    }
}

// start the server listening on the specified port number
int makeServerSocket (int portNumber) {

    // create socket
    int serverSocket = socket (AF_INET, SOCK_STREAM, 0);
    // check there was no error in opening the socket
    assert (serverSocket >= 0);

    // bind the socket to the listening port (7191 in this case)
    struct sockaddr_in serverAddress;
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    serverAddress.sin_port = htons (portNumber);

    // tell the server to restart immediately after a previous shutdown
    // even if it looks like the socket is still in use
    // otherwise we might have to wait a little while before rerunning the
    // server once it has stopped
    int optionValue = 1; // used to be const? --Sean
    setsockopt (
        serverSocket,
        SOL_SOCKET,
        SO_REUSEADDR,
        &optionValue,
        sizeof (int)
    );
    int bindSuccess =
        bind (
            serverSocket,
            (struct sockaddr*) &serverAddress,
            sizeof (serverAddress)
        );

    assert (bindSuccess >= 0);
    // if this assert fails wait a short while to let the operating
    // system clear the port before trying again

    return serverSocket;
}

// wait for a browser to request a connection,
// returns the socket on which the conversation will take place
int waitForConnection (int serverSocket) {

    // listen for a connection
    const int serverMaxBacklog = 10;
    listen (serverSocket, serverMaxBacklog);

    // accept the connection
    struct sockaddr_in clientAddress;
    socklen_t clientLen = sizeof (clientAddress);
    int connectionSocket =
        accept (
            serverSocket,
            (struct sockaddr*) &clientAddress,
            &clientLen
        );

    // check for connection error
    assert (connectionSocket >= 0);

    return connectionSocket;
}

// our stuff

int escapeSteps (double x, double y) {
    // x = scaled x coordinate of pixel (to lie in Mandelbrot X scale (-2.5,1))
    // y = scaled y coordinate of pixel (to lie in Mandelbrot Y scale (-1,1))
    double x0 = 0.0;
    double y0 = 0.0;
    int iteration = 0;
    double xtemp;
    while ((x0*x0 + y0*y0 < 2*2) && (iteration < MAX_STEPS)) {
        xtemp = x0*x0 - y0*y0 + x;
        y0 = 2*x0*y0 + y;
        x0 = xtemp;
        iteration++;
    }
    // debug code
    // printf ("x is %f, y is %f, %d\n", x0, y0, iteration);
    // old print statement
    // if (x0 * x0 + y0 * y0 <= 4) {
    //     printf ("*");
    // } else {
    //     printf (" ");
    // }
    return iteration;
}
/*
// below should be identical to whats in pixelColor.c?
unsigned char stepsToRed (int steps) {
    unsigned char intensity;
    // here is where we transform steps into intensity
    intensity = steps;
    // we could change this later

    return intensity;
}

unsigned char stepsToBlue (int steps) {
    unsigned char intensity;
    // here is where we transform steps into intensity
    intensity = steps;
    // we could change this later

    return intensity;
}

unsigned char stepsToGreen (int steps) {
    unsigned char intensity;
    // here is where we transform steps into intensity
    intensity = steps;
    // we could change this later

    return intensity;
}
*/
// any other functions must be static


// exp2 -> returns the result of 2^x
static double exponential2(int exponent){
    double z = 1;
    if(exponent > 0){
        while(exponent > 0){
            z = z * 2;
            exponent--;
        }
    } else if(exponent < 0){
        while(exponent < 0){
            z = z / 2;
            exponent++;
        }
    }
    return z;    
}

Download file: mandelbrot.c (8.6 KB)

Comments

Chat