• c语言 断点续传


    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <strings.h>
    #include <signal.h>
    #include <locale.h>
    #include <dirent.h>
    #include <sys/mman.h>
    #include <sys/resource.h>
    #include <sbase.h>
    #ifdef HAVE_ZLIB
    #include <zlib.h>
    #endif
    #ifdef HAVE_BZ2LIB
    #include <bzlib.h>
    #endif
    #include "iniparser.h"
    #include "http.h"
    #include "mime.h"
    #include "trie.h"
    #include "stime.h"
    #include "logger.h"
    #define XHTTPD_VERSION       "0.0.1"
    #define HTTP_RESP_OK            "HTTP/1.1 200 OK"
    #define HTTP_BAD_REQUEST        "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n"
    #define HTTP_NOT_FOUND          "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n" 
    #define HTTP_NOT_MODIFIED       "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n"
    #define HTTP_NO_CONTENT         "HTTP/1.1 206 No Content\r\nContent-Length: 0\r\n\r\n"
    #define LL(x) ((long long)x)
    #define UL(x) ((unsigned long int)x)
    static SBASE *sbase = NULL;
    static SERVICE *service = NULL;
    static dictionary *dict = NULL;
    static char *httpd_home = "/tmp/xhttpd/html";
    static char *http_indexes[HTTP_INDEX_MAX];
    static int http_indexes_view = 0;
    static int nindexes = 0;
    static char *http_default_charset = "UTF-8";
    static int httpd_compress = 1;
    static char *httpd_compress_cachedir = "/tmp/xhttpd/cache";
    static HTTP_VHOST httpd_vhosts[HTTP_VHOST_MAX];
    static int nvhosts = 0;
    static int httpd_proxy_timeout = 0;
    static void *namemap = NULL;
    static void *hostmap = NULL;
    static void *urlmap = NULL;
    static void *http_headers_map = NULL;
    static void *logger = NULL;
    
    /* mkdir recursive */
    int xhttpd_mkdir(char *path, int mode)
    {
        char *p = NULL, fullpath[HTTP_PATH_MAX];
        int ret = 0, level = -1;
        struct stat st;
    
        if(path)
        {
            strcpy(fullpath, path);
            p = fullpath;
            while(*p != '\0')
            {
                if(*p == '/' )
                {
                    while(*p != '\0' && *p == '/' && *(p+1) == '/')++p;
                    if(level > 0)
                    {
                        *p = '\0';
                        memset(&st, 0, sizeof(struct stat));
                        ret = stat(fullpath, &st);
                        if(ret == 0 && !S_ISDIR(st.st_mode)) return -1;
                        if(ret != 0 && mkdir(fullpath, mode) != 0) return -1;
                        *p = '/';
                    }
                    level++;
                }
                ++p;
            }
            return 0;
        }
        return -1;
    }
    
    /* xhttpd packet reader */
    int xhttpd_packet_reader(CONN *conn, CB_DATA *buffer)
    {
        return buffer->ndata;
    }
    
    /* xhttpd index view */
    int xhttpd_index_view(CONN *conn, HTTP_REQ *http_req, char *file, char *root, char *end)
    {
        char buf[HTTP_BUF_SIZE], url[HTTP_PATH_MAX], *p = NULL, *e = NULL, *pp = NULL;
        struct dirent *ent = NULL;
        unsigned char *s = NULL;
        struct stat st = {0};
        int len = 0, n = 0, keepalive = 0;
        DIR *dirp = NULL;
    
        if(conn && file && root && end && (dirp = opendir(file)))
        {
            if((p = pp = (char *)calloc(1, HTTP_INDEXES_MAX)))
            {
                p += sprintf(p, "<html><head><title>Indexes Of %s</title>"
                        "<head><body><h1 align=center>xhttpd</h1>", root);
                if(*end == '/') --end;
                while(end > root && *end != '/')--end;
                if(end == root)
                    p += sprintf(p, "<a href='/' >/</a><br>");
                else if(end > root)
                {
                    *end = '\0';
                    p += sprintf(p, "<a href='%s/' >..</a><br>", root);
                }
                p += sprintf(p, "<hr noshade><table><tr align=left>"
                        "<th width=500>Name</th><th width=200>Size</th>"
                        "<th>Last-Modified</th></tr>");
                end = p;
                while((ent = readdir(dirp)) != NULL)
                {
                    if(ent->d_name[0] != '.' && ent->d_reclen > 0)
                    {
                        p += sprintf(p, "<tr>");
                        s = (unsigned char *)ent->d_name;
                        e = url;
                        while(*s != '\0') 
                        {
                            if(*s == 0x20 && *s > 127)
                            {
                                e += sprintf(e, "%%%02x", *s);
                            }else *e++ = *s++;
                        }
                        *e = '\0';
                        if(ent->d_type == DT_DIR)
                        {
                            p += sprintf(p, "<td><a href='%s/' >%s/</a></td>", 
                                    url, ent->d_name);
                        }
                        else
                        {
                            p += sprintf(p, "<td><a href='%s' >%s</a></td>", 
                                    url, ent->d_name);
                        }
                        sprintf(buf, "%s/%s", file, ent->d_name);
                        if(ent->d_type != DT_DIR && lstat(buf, &st) == 0)
                        {
                            if(st.st_size >= (off_t)HTTP_BYTE_G)
                                p += sprintf(p, "<td> %.1fG </td>", 
                                        (double)st.st_size/(double) HTTP_BYTE_G);
                            else if(st.st_size >= (off_t)HTTP_BYTE_M)
                                p += sprintf(p, "<td> %lldM </td>", 
                                        LL(st.st_size/(off_t)HTTP_BYTE_M));
                            else if(st.st_size >= (off_t)HTTP_BYTE_K)
                                p += sprintf(p, "<td> %lldK </td>", 
                                        LL(st.st_size/(off_t)HTTP_BYTE_K));
                            else 
                                p += sprintf(p, "<td> %lldB </td>", LL(st.st_size));
    
                        }
                        else p += sprintf(p, "<td> - </td>");
                        p += sprintf(p, "<td>");
                        p += strdate(st.st_mtime, p);
                        p += sprintf(p, "</td>");
                        p += sprintf(p, "</tr>");
                    }
                }
                p += sprintf(p, "</table>");
                if(end != p) p += sprintf(p, "<hr noshade>");
                p += sprintf(p, "<em></body></html>");
                len = (p - pp);
                p = buf;
                p += sprintf(p, "HTTP/1.1 200 OK\r\nContent-Length:%lld\r\n"
                        "Content-Type: text/html; charset=%s\r\n",
                        LL(len), http_default_charset);
                if((n = http_req->headers[HEAD_GEN_CONNECTION]) > 0)
                {
                    p += sprintf(p, "Connection: %s\r\n", http_req->hlines + n);
                    if((strncasecmp(http_req->hlines + n, "close", 5)) !=0 )
                        keepalive = 1;
                }
                else 
                {
                    p += sprintf(p, "Connection: close\r\n");
                }
                p += sprintf(p, "Date: ");p += GMTstrdate(time(NULL), p);p += sprintf(p, "\r\n");
                p += sprintf(p, "Server: xhttpd/%s\r\n\r\n", XHTTPD_VERSION);
                conn->push_chunk(conn, buf, (p - buf));
                conn->push_chunk(conn, pp, len);
                //fprintf(stdout, "buf:%s pp:%s\n", buf, pp);
                free(pp);
                pp = NULL;
                if(!keepalive) conn->over(conn);
            }
            closedir(dirp);
            return 0;
        }
        else
        {
            fprintf(stderr, "%s::%d open dir:%s file:%p root:%p end:%p failed, %s\n", __FILE__, __LINE__, file, file, root, end, strerror(errno));
        }
        return -1;
    }
    #ifdef HAVE_ZLIB
    int xhttpd_gzip(unsigned char **zstream, unsigned char *in, int inlen, time_t mtime)
    {
        unsigned char *c = NULL, *out = NULL;
        unsigned long crc = 0;
        int outlen = 0;
        z_stream z = {0};
    
        if(in && inlen > 0)
        {
            z.zalloc = Z_NULL;
            z.zfree = Z_NULL;
            z.opaque = Z_NULL;
            if(deflateInit2(&z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 
                        -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
            {
                return -1;
            }
            z.next_in = (unsigned char *)in;
            z.avail_in = inlen;
            z.total_in = 0;
            outlen = (inlen * 1.1) + 12 + 18;
            if((*zstream = out = (unsigned char *)calloc(1, outlen)))
            {
                c = out;
                c[0] = 0x1f;
                c[1] = 0x8b;
                c[2] = Z_DEFLATED;
                c[3] = 0; /* options */
                c[4] = (mtime >>  0) & 0xff;
                c[5] = (mtime >>  8) & 0xff;
                c[6] = (mtime >> 16) & 0xff;
                c[7] = (mtime >> 24) & 0xff;
                c[8] = 0x00; /* extra flags */
                c[9] = 0x03; /* UNIX */
                z.next_out = out + 10;
                z.avail_out = outlen - 10 - 8;
                z.total_out = 0;
                if(deflate(&z, Z_FINISH) != Z_STREAM_END)
                {
                    deflateEnd(&z);
                    free(*zstream);
                    *zstream = NULL;
                    return -1;
                }
                //crc
                crc = http_crc32(in, inlen);
                c = *zstream + 10 + z.total_out;
                c[0] = (crc >>  0) & 0xff;
                c[1] = (crc >>  8) & 0xff;
                c[2] = (crc >> 16) & 0xff;
                c[3] = (crc >> 24) & 0xff;
                c[4] = (z.total_in >>  0) & 0xff;
                c[5] = (z.total_in >>  8) & 0xff;
                c[6] = (z.total_in >> 16) & 0xff;
                c[7] = (z.total_in >> 24) & 0xff;
                outlen = (10 + 8 + z.total_out);
                if(deflateEnd(&z) != Z_OK)
                {
                    free(*zstream);
                    *zstream = NULL;
                    return -1;
                }
                return outlen;
            }
        }
        return -1;
    }
    
    /* deflate */
    int xhttpd_deflate(unsigned char **zstream, unsigned char *in, int inlen)
    {
        unsigned char *out = NULL;
        z_stream z = {0};
        int outlen = 0;
    
        if(in && inlen > 0)
        {
            z.zalloc = Z_NULL;
            z.zfree = Z_NULL;
            z.opaque = Z_NULL;
            if(deflateInit2(&z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 
                        -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
            {
                return -1;
            }
            z.next_in = (unsigned char *)in;
            z.avail_in = inlen;
            z.total_in = 0;
            outlen = (inlen * 1.1) + 12 + 18;
            if((*zstream = out = (unsigned char *)calloc(1, outlen)))
            {
                z.next_out = out;
                z.avail_out = outlen;
                z.total_out = 0;
                if(deflate(&z, Z_FINISH) != Z_STREAM_END)
                {
                    deflateEnd(&z);
                    free(*zstream);
                    *zstream = NULL;
                    return -1;
                }
                outlen = z.total_out;
                if(deflateEnd(&z) != Z_OK)
                {
                    free(*zstream);
                    *zstream = NULL;
                    return -1;
                }
                return outlen;
            }
        }
        return -1;
    }
    #endif
    #ifdef HAVE_BZ2LIB
    int xhttpd_bzip2(unsigned char **zstream, unsigned char *in, int inlen)
    {
        unsigned char *out = NULL;
        bz_stream bz = {0};
        int outlen = 0;
    
        if(in && inlen > 0)
        {
            bz.bzalloc = NULL;
            bz.bzfree = NULL;
            bz.opaque = NULL;
            if(BZ2_bzCompressInit(&bz, 9, 0, 0) != BZ_OK)
            {
                return -1;
            }
            bz.next_in = (char *)in;
            bz.avail_in = inlen;
            bz.total_in_lo32 = 0;
            bz.total_in_hi32 = 0;
            outlen = (inlen * 1.1) + 12;
            if((*zstream = out = (unsigned char *)calloc(1, outlen)))
            {
                bz.next_out = (char *)out;
                bz.avail_out = outlen;
                bz.total_out_lo32 = 0;
                bz.total_out_hi32 = 0;
                if(BZ2_bzCompress(&bz, BZ_FINISH) != BZ_STREAM_END)
                {
                    BZ2_bzCompressEnd(&bz);
                    free(*zstream);
                    *zstream = NULL;
                    return -1;
                }
                if(bz.total_out_hi32)
                {
                    free(*zstream);
                    *zstream = NULL;
                    return -1;
                }
                outlen = bz.total_out_lo32;
                if(BZ2_bzCompressEnd(&bz) != BZ_OK)
                {
                    free(*zstream);
                    *zstream = NULL;
                    return -1;
                }
            }
        }
        return -1;
    }
    #endif
    
    /* httpd file compress */
    int xhttpd_compress_handler(CONN *conn, HTTP_REQ *http_req, char *host, int is_need_compress, int mimeid,
            char *file, char *root, off_t from, off_t to, struct stat *st)
    {
        char zfile[HTTP_PATH_MAX], zoldfile[HTTP_PATH_MAX], linkfile[HTTP_PATH_MAX], 
             buf[HTTP_BUF_SIZE], *encoding = NULL, *outfile = NULL, *p = NULL;
        unsigned char *block = NULL, *in = NULL, *zstream = NULL;
        int fd = 0, inlen = 0, zlen = 0, i = 0, id = 0, keepalive = 0;
        off_t offset = 0, len = 0;
        struct stat zst = {0};
    
        if(is_need_compress)
        {
            if(httpd_compress)
            {
                for(i = 0; i < HTTP_ENCODING_NUM; i++)
                {
                    if(is_need_compress & ((id = (1 << i))))
                    {
                        encoding = (char *)http_encodings[i];
                        if(from == 0 && to == st->st_size)
                        {
                            sprintf(linkfile, "%s/%s%s.%s",  httpd_compress_cachedir,
                                    host, root, encoding);
                        }
                        else
                        {
                            sprintf(linkfile, "%s/%s%s-%lld-%lld.%s", httpd_compress_cachedir, 
                                    host, root, LL(from), LL(to), encoding);
                        }
                        sprintf(zfile, "%s.%lu", linkfile, UL(st->st_mtime));
                        if(access(zfile, F_OK) == 0)
                        {
                            lstat(zfile, &zst);
                            outfile = zfile;
                            from = 0;
                            len = zst.st_size;
                            goto OVER;
                        }
                        else
                        {
                            if(access(linkfile, F_OK))
                            {
                                xhttpd_mkdir(linkfile, 0755);
                            }
                            else 
                            {
                                if(readlink(linkfile, zoldfile, (HTTP_PATH_MAX - 1)))
                                    unlink(zoldfile);
                                unlink(linkfile);
                            }
                            goto COMPRESS;
                        }
                        break;
                    }
                }
            }
    COMPRESS:
            offset = (from/(off_t)HTTP_MMAP_MAX) * HTTP_MMAP_MAX;
            len = to - offset;
            if(len < HTTP_MMAP_MAX && (fd = open(file, O_RDONLY)) > 0)
            {
                if((block = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)))
                {
                    in = block + (from%(off_t)HTTP_MMAP_MAX);
                    inlen = to - from;
    
    #ifdef HAVE_ZLIB
                    if(is_need_compress & HTTP_ENCODING_DEFLATE)
                    {
                        if((zlen = xhttpd_deflate(&zstream, in, inlen)) <= 0)
                            goto err;
                        encoding = "deflate";
                        //compressed |= HTTP_ENCODING_DEFLATE;
                    }
                    else if(is_need_compress & HTTP_ENCODING_GZIP)
                    {
                        if((zlen = xhttpd_gzip(&zstream, in, inlen, 
                                        st->st_mtime)) <= 0) goto err;
                        encoding = "gzip";
                        //compressed |= HTTP_ENCODING_GZIP;
    
                    }
                    /*
                       else if(is_need_compress & HTTP_ENCODING_COMPRESS)
                       {
                       compressed |= HTTP_ENCODING_COMPRESS;
                       }
                       */
    #endif  
    #ifdef HAVE_BZ2LIB
                    if(encoding == NULL && is_need_compress & HTTP_ENCODING_BZIP2)
                    {
                        if((zlen = xhttpd_bzip2(&zstream, in, inlen)) <= 0) goto err;
                        encoding = "bzip2";
                        //compressed |= HTTP_ENCODING_BZIP2;
                    }
    #endif
                    munmap(block, len);
                    block = NULL;
                }
                close(fd);
                if(encoding == NULL) goto err;
                //write to cache file
                if(httpd_compress && zstream && zlen > 0)
                {
                    if((fd = open(zfile, O_CREAT|O_WRONLY, 0644)) > 0)
                    {
                        if(symlink(zfile, linkfile) != 0 || write(fd, zstream, zlen) <= 0 )
                        {
                            FATAL_LOGGER(logger, "symlink/write to %s failed, %s", 
                                    linkfile, strerror(errno));
                        }
                        close(fd); 
                    }
                }
            }
    OVER:
            p = buf;
            if(from > 0)
            {
                p += sprintf(p, "HTTP/1.1 206 Partial Content\r\nAccept-Ranges: bytes\r\n"
                        "Content-Range: bytes %lld-%lld/%lld\r\n", 
                        LL(from), LL(to - 1), LL(st->st_size));
            }
            else
                p += sprintf(p, "HTTP/1.1 200 OK\r\nAccept-Ranges: bytes\r\n");
            p += sprintf(p, "Content-Type: %s; charset=%s\r\n",
                    http_mime_types[mimeid].s, http_default_charset);
            /*
            if((n = http_req->headers[HEAD_GEN_CONNECTION]) > 0)
            {
                p += sprintf(p, "Connection: %s\r\n", http_req->hlines + n);
            }
            */
            p += sprintf(p, "Last-Modified:");
            p += GMTstrdate(st->st_mtime, p);
            p += sprintf(p, "%s", "\r\n");//date end
            if(zstream && zlen > 0) len = zlen;
            if(encoding) p += sprintf(p, "Content-Encoding: %s\r\n", encoding);
            p += sprintf(p, "Content-Length: %lld\r\n", LL(len));
            p += sprintf(p, "Date: ");p += GMTstrdate(time(NULL), p);p += sprintf(p, "\r\n");
            p += sprintf(p, "Connection: close\r\n");
            p += sprintf(p, "Server: xhttpd/%s\r\n\r\n", XHTTPD_VERSION);
            conn->push_chunk(conn, buf, (p - buf));
            if(zstream && zlen > 0)
            {
                conn->push_chunk(conn, zstream, zlen);
            }
            else
            {
                conn->push_file(conn, outfile, from, len);
            }
            if(zstream) free(zstream);
            if(!keepalive)conn->over(conn);
            return 0;
        }
    err:
        return -1;
    }
    
    /* xhttpd bind proxy */
    int xhttpd_bind_proxy(CONN *conn, char *host, int port) 
    {
        CONN *new_conn = NULL;
        SESSION session = {0};
        char *ip = NULL;
    
        if(conn && host && port > 0)
        {
            if(ip)
            {
                session.packet_type = PACKET_PROXY;
                session.timeout = httpd_proxy_timeout;
                if((new_conn = service->newproxy(service, conn, -1, -1, ip, port, &session)))
                {
                    new_conn->start_cstate(new_conn);
                    return 0;
                }
            }
        }
        return -1;
    }
  • 相关阅读:
    require.js使用
    favico是针对网页图标内容更改
    web图片转换小工具制作
    控制显示input隐藏和查看密码
    程序员图片注释字符串制作工具
    c语言基础, , ,
    【理解】column must appear in the GROUP BY clause or be used in an aggregate function
    ps aux命令解析
    while(std::cin>>val)怎么结束的思考
    【转】NativeScript的工作原理:用JavaScript调用原生API实现跨平台
  • 原文地址:https://www.cnblogs.com/zzxap/p/2175780.html
Copyright © 2020-2023  润新知