轻量web服务器开发日记04-buffile结构体的实现

除了日记03所介绍的bufstr结构体,现在准备介绍的buffile结构体也是使用mempool内存池来存放服务器处理信息的。
buffile结构体主要是用于存放响应信息的主体部分文件内容(html、text、jpg等类型文件),并且记录文件的相关属性。
(1)buffile结构体的具体实现:

typedef struct {
    //文件内容
    memblock *fcontent;
    //文件名字
    bufstr *fname;
    //文件类型(扩展名)
    bufstr *ftype;
    //文件属性信息 
    struct stat *fstat;
    //是否url被改写,访问资源错误,返回error.html
    int is_rewrite;
    //文件大小(字节)
    int fused; 
    //内存块数目
    int fmbnum;
    //总共内存空间大小(字节)
    int size; 
} buffile;

(2)下面是buffile结构体的初始化和释放操作:

buffile *buffile_init(mempool *mpool)
{
    int mbsize;
    buffile *temp;
    mbsize = MBSIZE;
    temp = calloc(1,sizeof(buffile));
    temp->fcontent = mempool_take_mblocks(mpool,1);
    temp->fstat = (struct stat *)calloc(1,sizeof(struct stat));
    temp->fused = 0;
    temp->fmbnum = 1;
    temp->size = mbsize * temp->fmbnum;
    return temp;
}



void buffile_free(mempool *mpool,buffile *bf)
{
    mempool_put_mblocks(mpool,bf->fcontent);
    if(bf->fname)
    {
        bufstr_free(mpool,bf->fname);
    }
    if(bf->ftype)
    {
        bufstr_free(mpool,bf->ftype);
    }

    free(bf->fstat);
    free(bf);
}

当服务器解析http报文的起始行中url后,通过该url判断本地是否有该文件,若存在则构建该文件的buffile结构体,否则构建出错页面的buffile结构体。
(3)构建指定文件的buffile结构体操作具体实现:

/*
当指定的是文件时,在/www下存在,则返回相应文件,否则返回error.html文件
当指定的是目录时,若是/www下返回index.html文件,否则返回error.html文件
*/
buffile *buffile_create(mempool *mpool,char *docroot,bufstr *furl)
{
    char url[100];
    char url1[100];
    char *temp =NULL;
    char *buff =NULL;
    int readn =0,mbsize;
    buffile *ftemp =NULL;
    FILE *fp=NULL;
    mbsize = MBSIZE;
    buff =(char*)calloc(mbsize,sizeof(char));
    ftemp = buffile_init(mpool);
    if(furl ==NULL)
    {
        free(buff);
        buffile_free(mpool,ftemp);
        return NULL;
    }
    strcpy(url,docroot);
    temp = read_string_bufstr(furl);
    strcat(url,temp);
    if(lstat(url,ftemp->fstat) != -1)
    {
        if(S_ISREG(ftemp->fstat->st_mode))
        {
            fp = fopen(url,"r");
            if(fp == NULL) 
            {
                printf("bufstr_init:open file error!\n");
                free(temp);
                free(buff);
                buffile_free(mpool,ftemp);
                return NULL;
            }
            while((readn = fread(buff,1,mbsize,fp)) > 0)
            {
                buffile_append_string_len(mpool,ftemp,buff,readn);
            }
            ftemp->fname = bufstr_copy_filename(mpool,url);
            ftemp->ftype = bufstr_copy_etrname(mpool,url);
            ftemp->is_rewrite =0;
            fclose(fp);
            free(buff);
            free(temp);
            return ftemp;
        }
        //若是/www,则返回该目录下的index.html
        if(S_ISDIR(ftemp->fstat->st_mode))
        {
            if(bufstr_compare_string(furl,"/"))
            {
                strcpy(url1,docroot);
                strcat(url1,"/index.html");
                printf("url:%s\n",url1);
                fp = fopen(url1,"r");
                if(fp == NULL) 
                {
                    printf("buffile_init:open file error!\n");
                    free(temp);
                    free(buff);
                    buffile_free(mpool,ftemp);
                    return NULL;
                }
                while((readn = fread(buff,1,mbsize,fp)) > 0)
                {
                    buffile_append_string_len(mpool,ftemp,buff,readn);
                }
                ftemp->fname = bufstr_copy_filename(mpool,url1);
                ftemp->ftype = bufstr_copy_etrname(mpool,url1);
                ftemp->is_rewrite =0;
                fclose(fp);
                free(buff);
                free(temp);
                return ftemp;
            }
            //不是指定/www目录,则返回error.html文件
            else
            {
                strcpy(url1,docroot);
                strcat(url1,"/error_404.html");
                fp = fopen(url1,"r");
                if(fp == NULL) 
                {
                    printf("buffile_init:open file error!\n");
                    free(temp);
                    free(buff);
                    buffile_free(mpool,ftemp);
                    return NULL;
                }
                while((readn = fread(buff,1,mbsize,fp)) > 0)
                {
                    buffile_append_string_len(mpool,ftemp,buff,readn);
                }
                ftemp->fname = bufstr_copy_filename(mpool,url1);
                ftemp->ftype = bufstr_copy_etrname(mpool,url1);
                ftemp->is_rewrite =1;
                fclose(fp);
                free(buff);
                free(temp);
                return ftemp;
            }
        }
    }
    //不存在资源,则返回error.html文件
    strcpy(url1,docroot);
    strcat(url1,"/error_404.html");
    printf("url:%s\n",url1);
    fp = fopen(url1,"r");
    if(fp == NULL) 
    {
        printf("buffile_init:open file error!\n");
        free(temp);
        free(buff);
        buffile_free(mpool,ftemp);
        return NULL;
    }
    while((readn = fread(buff,1,mbsize,fp)) > 0)
    {
        buffile_append_string_len(mpool,ftemp,buff,readn);
    }
    ftemp->fname = bufstr_copy_filename(mpool,url1);
    ftemp->ftype = bufstr_copy_etrname(mpool,url1);
    ftemp->is_rewrite =1;
    fclose(fp);
    free(buff);
    free(temp);
    return ftemp;
}

(4)而服务器最终是以bufstr结构体的形式来发送响应报文的,而当我们把起始行和首部构建好后,我们需要将buffile结构体的内容放入存放响应报文的bufstr的内容后面。
该操作的具体实现:

//将buffile结构体des的数据添加到bufstr结构体src的尾后,去掉src最后的'\0'
int bufstr_append_buffile(mempool *mpool,bufstr *des,buffile *src)
{
    int slen,total,mbsize,smbnum,scnum,dmbnum,dcnum,n,count;
    memblock * temp =NULL;
    if(des==NULL||src==NULL||des->used == 0)
    {
        return 0;
    } 
    mbsize = MBSIZE;
    slen = src->fused;
    temp = src->fcontent;
    smbnum = des->used / mbsize;
    scnum = des->used % mbsize;
    count = mbsize-scnum+1;
    for(;;)
    {   
        total = des->size - des->used + 1;
        if(total>=slen)
        {
            if(scnum > 0)
            {
                //'\0':&des-ptr[b->used / mbsize][(b->used % mbsize)-1]
                if(count >= slen)
                {   
                    memcpy((&des->ptr[smbnum][scnum-1]),temp->memptr,slen);
                }
                else
                {
                    memcpy((&des->ptr[smbnum][scnum-1]),temp->memptr,count);
                    dmbnum =  (slen - count) / mbsize;
                    dcnum = (slen - count) % mbsize;
                    n=0;
                    while(n<dmbnum)
                    {
                        memcpy(des->ptr[smbnum+1+n],&temp->memptr[count],mbsize - count);
                        temp = temp->next;
                        memcpy(&des->ptr[smbnum+1+n][mbsize - count],temp->memptr,count);
                        n++;
                    }
                    if(dcnum>0)
                    {
                        if(scnum == 1 && count == mbsize)
                        {
                            temp = temp->next;
                            memcpy(des->ptr[smbnum+1+n],temp->memptr,dcnum);
                        }
                        else
                        {
                            memcpy(des->ptr[smbnum+1+n],&temp->memptr[count],dcnum);
                        }
                    }
                }   
            }
            else
            {
                //'\0':&des-ptr[(b->used / mbsize)-1][mbsize-1]
                memcpy((&des->ptr[smbnum-1][mbsize- 1]),temp->memptr,1);
                dmbnum = (slen - 1) / mbsize;
                dcnum = (slen - 1) % mbsize;
                n=0;
                while(n<dmbnum)
                {
                    memcpy(des->ptr[smbnum+n],&temp->memptr[1],mbsize-1);
                    temp = temp->next;
                    memcpy(&des->ptr[smbnum+n][mbsize-1],temp->memptr,1);
                    n++;
                //  exit(0);
                }
                if(dcnum>0)
                {
                    memcpy(des->ptr[smbnum+n],&temp->memptr[1],dcnum);
                }
            }
            des->used+=slen;
            return 1;
        }
        else
        {
            bufstr_prepare_size(mpool,des,slen);
        }
    }   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值