Example #1
0
void do_child(int fd, char* dir){
    int recvLen = 0;
    int p_size = 0;
    std::vector<char> pload;
    char buf[500] = {0};
    memset(buf, '\0', sizeof(buf));
    
    char filepath[100];
    
    struct timeval tv;
    tv.tv_sec = 40;
    tv.tv_usec = 0;
    setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
    std::vector <char> wire;
    std::vector <char> res_wire;
    
    while (true){
    strcpy(filepath, dir);
    bool isdone = false;
    struct timeval tv;
    tv.tv_sec = 30;
    tv.tv_usec = 0;
    setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
    while(1){
        memset(buf, '\0', sizeof(buf));
        if ((recvLen = recv(fd, buf, 500, 0)) == -1) {
            std::cout << "Timeout expires" << std::endl;
            perror("recv");
            close(fd);
            return;
        }
        for (int i =0; i < recvLen; i++)
        {
            wire.push_back(buf[i]);
            if(buf[i] == '\r' && buf[i+1] == '\n' && buf[i+2] == '\r' && buf[i+3] == '\n')
            {
                wire.push_back(buf[i+1]);
                wire.push_back(buf[i+2]);
                wire.push_back(buf[i+3]);
                isdone = true;
                break;
            }
        }
        if(isdone == true)
            break;
    }
        
        std::cout << "Received the request message: "<<std::endl;
        for (int i = 0; i<wire.size(); i++) {
            std::cout << wire[i];
        }
        std::cout << std::endl;
        
        HttpRequest request;
        request.decodeFirstLine(wire);
        request.decodeHeaderline(wire);
        wire.clear();
        HttpResponse response;
        response.setVersion(request.getVersion());
        HttpStatus status;
        bool set_status = false;
    
        if(request.getMap("Connection") == "Keep-Alive")
            response.setHeader("Connection", "Keep-Alive");
        else if(request.getMap("Connection") == "Close")
            response.setHeader("Connection", "Close");
        else
        {
            if(set_status == false){
            status.m_statuscode = "400";
            response.setStatus(status);
            response.setDescription ("Bad Request");
            response.setHeader("Content-Length", "0");
            set_status = true;
            }
        }
    
        std::string recurl = request.getUrl();

        int len = recurl.length();
        int i = 0;
    
        if(recurl[i] == 'h'&& recurl[i+1] == 't' && recurl[i+2] == 't' && recurl[i+3] == 'p' &&recurl[i+4] ==':' && recurl[i+5]=='/' &&recurl[i+6] == '/')
        {
            i+=7;
            char host_check[200] = {'\0'};
            int pt_check = -1;
            int j = 0;
            while (i < len)
            {
                if(recurl[i]!= '/' && recurl[i]!= ':')
                {
                    host_check[j] = recurl[i];
                    j++;
                    i++;
                }
                else
                    break;
            }
            std::string mycheck = host_check;
            if(recurl[i] == ':')
            {
                j = 0;
                i++;
                char po_no[100];
                while (i < len){
                    if(recurl[i] == '/')
                        break;
                    po_no[j] = recurl[i];
                    i++;
                    j++;
                }
                pt_check = atoi(po_no);
            }
            if(mycheck != hostname || (portno != pt_check))
            {
                if(set_status == false){
                status.m_statuscode = "400";
                response.setStatus(status);
                response.setDescription ("Bad Request");
                response.setHeader("Content-Length", "0");
                set_status = true;
                }
            }
            else
                strcat(filepath, recurl.substr(i).c_str());
        }
        else
        {
            if(recurl[i] != '/')
            {
                if(set_status == false){
                status.m_statuscode = "400";
                response.setStatus(status);
                response.setDescription ("Bad Request");
                response.setHeader("Content-Length", "0");
                set_status = true;
                }
            }
            else
            {
                std::string hosturl = request.getMap("Host");
                if (hosturl == "Cannot find this key") {
                    if(set_status == false){
                    status.m_statuscode = "400";
                    response.setStatus(status);
                    response.setDescription ("Bad Request");
                    response.setHeader("Content-Length", "0");
                    set_status = true;
                    }
                }
                else
                {
                    char host_check[200] = {'\0'};
                    int pt_check = -1;
                    i = 0;
                    while (i < hosturl.length())
                    {
                        if(hosturl[i]!= '/' && hosturl[i]!= ':')
                        {
                            host_check[i] = hosturl[i];
                            i++;
                        }
                        else
                            break;
                    }
                    std::string mycheck = host_check;
                    if(hosturl[i] == ':')
                    {
                        //if we hit a colon, check for port number
                        int j = 0;
                        i++;
                        char po_no[100] = {'\0'};
                        while (i < hosturl.length()){
                            po_no[j] = hosturl[i];
                            i++;
                            j++;
                        }
                        pt_check = atoi(po_no);
                    }
                    if(mycheck != hostname || (portno != pt_check))
                    {
                        if(set_status == false){
                        status.m_statuscode = "400";
                        response.setStatus(status);
                        response.setDescription ("Bad Request");
                        response.setHeader("Content-Length", "0");
                        set_status = true;
                        }
                    }
                    else
                        strcat(filepath, recurl.c_str());

                }
            }
        }
    
        
    if(strcmp(request.getVersion().m_versionstr.c_str(), "HTTP/1.0" ) != 0 && strcmp(request.getVersion().m_versionstr.c_str(), "HTTP/1.1" ) != 0)
    {
        if(set_status == false){
        status.m_statuscode = "505";
        response.setStatus(status);
        response.setDescription ("HTTP version not supported");
        response.setHeader("Content-Length", "0");
        set_status = true;
        }
    }

    else if (request.getMethod().m_methodstr != "GET") {
        if(set_status == false){
        status.m_statuscode = "405";
        response.setStatus(status);
        response.setDescription ("Method not allowed");
        response.setHeader("Content-Length", "0");
        set_status = true;
        }
    }
    else if(set_status == false)
    {
        std::ifstream file;
        file.exceptions(
                        std::ifstream::badbit
                        | std::ifstream::eofbit);
        
        file.open(filepath, std::ifstream::in | std::ifstream::binary | std::ifstream::out);

        if (!file.is_open())
        {
            status.m_statuscode = "404";
            response.setStatus(status);
            response.setDescription ("Not Found");
            response.setHeader("Content-Length", "0");
            set_status = true;
        }
        else
        {
            status.m_statuscode = "200";
            response.setStatus(status);
            response.setDescription ("OK");
            set_status = true;
            file.seekg(0, std::ios::end);
            std::streampos length(file.tellg());
            if (length) {
                file.seekg(0, std::ios::beg);
                pload.resize(static_cast<std::size_t>(length));
                file.read(&pload.front(), static_cast<std::size_t>(length));
            }
            file.close();
            response.setPayLoad(pload);
            std::stringstream out;
            p_size = pload.size();
            out << p_size;
            response.setHeader("Content-Length", out.str());
        }
        memset(filepath, '\0', 100);
    }
    res_wire = response.encode();
    int wsize = res_wire.size();
    
    
    memset(buf, '\0', sizeof(buf));
    for (int k1 = 0; k1 < wsize; k1++) {
        buf[k1] = res_wire[k1];
    }
    
    res_wire.clear();
        
    if (send(fd, buf, wsize, 0) == -1) {
        perror("send");
        exit(1);
    }
    
    if(response.getStatus().m_statuscode == "200")
    {
        int divide = p_size/500;
        int remainder = p_size % 500;
        int count = 0;
        for (int k = 0; k < divide; k++) {
            memset(buf, '\0', sizeof(buf));
            for (int k1 = 0; k1 < 500; k1++) {
                buf[k1] = pload[count];
                count ++;
            }

            if (send(fd, buf, 500, 0) == -1) {
                perror("send");
                exit(1);
            }
        }
        if(remainder!=0)
        {
            memset(buf, '\0', sizeof(buf));
            for(int q = 0; q < remainder; q++)
            {
                buf[q] = pload[count];
                count++;
            }
           
            if (send(fd, buf, remainder, 0) == -1) {
                perror("send");
                exit(1);
            }
        }
    }
    pload.clear();
    if(response.getMap("Connection") == "close")
    {
        std::cout << "successfully close the connection" <<std::endl;
        close(fd);
        break;
    }
}

}