├── .gitignore ├── .travis.yml ├── Doxyfile ├── LICENSE ├── Makefile ├── README.md ├── bin ├── conf │ ├── twemproxy.yml │ └── zimg.lua ├── script │ ├── process.lua │ └── test.lua └── www │ ├── admin.html │ └── index.html ├── deps ├── ImageMagick-6.9.8-4.tar.gz ├── LuaJIT-2.0.3.tar.gz ├── cjson │ ├── LICENSE │ ├── cJSON.c │ └── cJSON.h ├── hiredis │ ├── COPYING │ ├── fmacros.h │ ├── hiredis.c │ ├── hiredis.h │ ├── net.c │ ├── net.h │ ├── sds.c │ └── sds.h ├── libevhtp │ ├── LICENSE │ ├── evhtp-config.h │ ├── evhtp.c │ ├── evhtp.h │ ├── evthr.c │ ├── evthr.h │ ├── htparse.c │ └── htparse.h ├── libjpeg-turbo-1.5.1.tar.gz ├── libwebp-0.6.0.tar.gz └── multipart-parser-c │ ├── LICENSE │ ├── multipart_parser.c │ └── multipart_parser.h ├── doc ├── README.md ├── arch.graphml └── misc │ ├── DoxygenLayout.xml │ ├── doxygenextra.css │ ├── footer.html │ └── header.html ├── specs ├── control ├── md5sums └── zimg.spec ├── src ├── CMakeLists.txt ├── CMakeModules │ ├── BaseConfig.cmake │ ├── FindGraphicsMagick.cmake │ ├── FindLibEvent.cmake │ ├── FindLibHiredis.cmake │ ├── FindLibMemcached.cmake │ ├── FindLuaJIT.cmake │ ├── FindWebP.cmake │ └── Findlibevhtp.cmake ├── count_code.sh ├── main.c ├── zaccess.c ├── zaccess.h ├── zcache.c ├── zcache.h ├── zcommon.h ├── zdb.c ├── zdb.h ├── zhttpd.c ├── zhttpd.h ├── zimg.c ├── zimg.h ├── zlog.c ├── zlog.h ├── zlscale.c ├── zlscale.h ├── zmd5.c ├── zmd5.h ├── zscale.c ├── zscale.h ├── zspinlock.c ├── zspinlock.h ├── zutil.c └── zutil.h ├── test ├── 5f189.jpeg ├── ab-post.sh ├── gen_random_test.sh ├── get.php ├── post.sh ├── testup.jpeg └── upload.go └── wercker.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.s 4 | *.lo 5 | 6 | # Libraries 7 | *.lib 8 | *.a 9 | *.la 10 | 11 | # Shared objects (inc. Windows DLLs) 12 | *.dll 13 | *.so 14 | *.so.* 15 | *.dylib 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.c.swp 22 | *.DS_Store 23 | 24 | .gitignore 25 | tags 26 | 27 | *.swp 28 | *.pc 29 | 30 | *.log 31 | *.dSYM 32 | 33 | doc/html/ 34 | 35 | bin/img/ 36 | bin/log/ 37 | bin/zimg 38 | 39 | bin/conf/debug.lua 40 | build/ 41 | 42 | deps/libjpeg-turbo/ 43 | deps/libwebp/ 44 | deps/ImageMagick/ 45 | deps/LuaJIT/ 46 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | Language: c 2 | compiler: 3 | - gcc 4 | - clang 5 | branches: 6 | only: 7 | - master 8 | - dev 9 | before_install: 10 | - sudo apt-get update -qq 11 | install: 12 | - sudo apt-get install nasm openssl cmake libevent-dev libpng-dev libmemcached-dev 13 | script: 14 | - make 15 | - cd bin 16 | - ./zimg conf/zimg.lua 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 - 2014, 招牌疯子 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX=/usr/local/zimg 2 | PWP=$(shell pwd) 3 | ARCH=$(shell getconf LONG_BIT) 4 | SYSTEM=$(shell uname -s) 5 | 6 | ifeq ($(ARCH),32) 7 | cflag32=--host i686-pc-linux-gnu CFLAGS='-O3 -m32' LDFLAGS=-m32 8 | endif 9 | 10 | libjpeg-turbo=./deps/libjpeg-turbo/.libs/libjpeg.a 11 | libwebp=./deps/libwebp/src/.libs/libwebp.a 12 | libimagickwand=./deps/ImageMagick/wand/.libs/libMagickWand-6.Q8.a 13 | libluajit=./deps/LuaJIT/src/libluajit.a 14 | 15 | ifeq ($(SYSTEM),Darwin) 16 | deps=$(libluajit) 17 | else 18 | deps=$(libjpeg-turbo) $(libwebp) $(libimagickwand) $(libluajit) 19 | endif 20 | 21 | all: $(deps) 22 | mkdir -p build/zimg 23 | cd build/zimg; cmake $(PWD)/src; make -j 4; cp zimg $(PWD)/bin 24 | 25 | debug: $(deps) 26 | mkdir -p build/zimg 27 | cd build/zimg; cmake -DCMAKE_BUILD_TYPE=Debug $(PWD)/src; make; cp zimg $(PWD)/bin 28 | 29 | $(libjpeg-turbo): 30 | cd deps; mkdir libjpeg-turbo; tar zxvf libjpeg-turbo-*.tar.gz -C libjpeg-turbo --strip-components 1; cd libjpeg-turbo; autoreconf -fiv; ./configure --enable-shared=no --enable-static=yes $(cflag32); make -j 4 31 | 32 | $(libwebp): 33 | cd deps; mkdir libwebp; tar zxvf libwebp-*.tar.gz -C libwebp --strip-components 1; cd libwebp; ./autogen.sh; ./configure --enable-shared=no --enable-static=yes --with-jpegincludedir=$(PWD)/deps/libjpeg-turbo --with-jpeglibdir=$(PWD)/deps/libjpeg-turbo/.libs; make -j 4 34 | 35 | $(libimagickwand): 36 | cd deps; mkdir ImageMagick; tar zxf ImageMagick-*.tar.gz -C ImageMagick --strip-components 1; cd ImageMagick; ./configure --disable-dependency-tracking --disable-openmp --disable-shared --without-magick-plus-plus --without-fftw --without-fpx --without-djvu --without-fontconfig --without-freetype --without-gslib --without-gvc --without-jbig --without-lcms --without-openjp2 --without-lqr --without-lzma --without-openexr --without-pango --without-rsvg --without-tiff --without-bzlib --without-wmf --without-xml --without-dps --without-x --enable-delegate-build --with-quantum-depth=8 "CFLAGS=-I$(PWD)/deps/libjpeg-turbo -I$(PWD)/deps/libwebp/src" "LDFLAGS=-L$(PWD)/deps/libjpeg-turbo/.libs -ljpeg -L$(PWD)/deps/libwebp/src/.libs -lwebp"; make -j 4 37 | 38 | $(libluajit): 39 | cd deps; mkdir LuaJIT; tar zxf LuaJIT-*.tar.gz -C LuaJIT --strip-components 1; cd LuaJIT; make -j 4 40 | 41 | clean: 42 | rm -rf build 43 | rm bin/zimg 44 | 45 | cleanall: 46 | rm -rf build 47 | rm -f bin/zimg 48 | rm -rf deps/libjpeg-turbo 49 | rm -rf deps/libwebp 50 | rm -rf deps/ImageMagick 51 | rm -rf deps/LuaJIT 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zimg 2 | 3 | 4 | Project zimg is a lightweight image storage and processing system. It's written in C and it has high performance in image field. The zimg is designed for high concurrency image server. It supports many features for storing and processing images. 5 | 6 | Homepage: [zimg.buaa.us](http://zimg.buaa.us/) 7 | Author: [@招牌疯子](http://weibo.com/819880808) 8 | Contact me: zp@buaa.us 9 | 10 | [![Build Status](https://travis-ci.org/buaazp/zimg.svg?branch=master)](https://travis-ci.org/buaazp/zimg) [![wercker status](https://app.wercker.com/status/88aead2017ceb80b32fad3dc8997227a/s "wercker status")](https://app.wercker.com/project/bykey/88aead2017ceb80b32fad3dc8997227a) [![Join the chat at https://gitter.im/buaazp/zimg](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/buaazp/zimg?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 11 | 12 | ### Versions: 13 | - 05/11/2017 - zimg 3.2.0 Release. Fix build issues with 3rd dependences. 14 | - 09/09/2014 - zimg 3.1.0 Release. New generation. 15 | - 04/26/2014 - zimg 2.0.0 Release. Supported distributed storage backends. 16 | - 08/01/2013 - zimg 1.0.0 Release. 17 | 18 | ### Synopsis 19 | - The zimg is an image storage and processing server. You can get a compressed and scaled image from zimg with the parameters of URL. 20 | http://demo.buaa.us/5f189d8ec57f5a5a0d3dcba47fa797e2?w=500&h=500&g=1&x=0&y=0&r=45&q=75&f=jpeg 21 | 22 | - The parameters contain width, height, resize type, gray, crop position (x, y), rotate, quality and format. And you can control the default type of images by configuration file. 23 | And you can get the information of image in zimg server like this: 24 | http://demo.buaa.us/info?md5=5f189d8ec57f5a5a0d3dcba47fa797e2 25 | 26 | - If you want to customize the transform rule of image you can write a zimg-lua script. Goto [API of zimg-lua](http://zimg.buaa.us/documents/api_of_zimg_lua/) for more information. Use `t=type` parameter in your URL to get the special image: 27 | http://demo.buaa.us/5f189d8ec57f5a5a0d3dcba47fa797e2?t=webp500 28 | 29 | - The concurrent I/O, distributed storage and in time processing ability of zimg is excellent. You needn't nginx in your image server any more. In the benchmark test, zimg can deal with 3000+ image downloading task per second and 90000+ HTTP echo request per second on a high concurrency level. The performance is higher than PHP or other image processing server. More information of zimg is in the documents below. 30 | 31 | ### Supplying: 32 | Uploading, downloading and processing images through HTTP protocol. 33 | High performance in concurrency I/O and compressing image. 34 | Support lua scripts to deal with customize compressing strategy. 35 | Support memcached and redis protocols to save images into distributed storage backends. 36 | Varied config options for operation and maintenance. 37 | 38 | More usages are in [Guidebook of zimg](http://zimg.buaa.us/documents/guidebook/). 39 | 40 | ### Build: 41 | You should build dependences first. If you want to use distributed storage, make sure the optional storage backends beansdb(memcached protocol), or ssdb(redis protocol) is working well. 42 | More information of building zimg is in [Install Guide](http://zimg.buaa.us/documents/install/). 43 | 44 | ``` 45 | git clone https://github.com/buaazp/zimg -b master --depth=1 46 | cd zimg 47 | make 48 | cd bin 49 | ./zimg conf/zimg.lua 50 | ``` 51 | 52 | 53 | ### Thanks to: 54 | > We stand on the shoulders of giants. 55 | 56 | [libevhtp](https://github.com/ellzey/libevhtp): A more flexible replacement for libevent's httpd API. 57 | [LuaJIT](http://luajit.org/): LuaJIT is JIT compiler for the Lua language. 58 | [imagemagick](http://www.imagemagick.org/): A software suite to create, edit, compose, or convert bitmap images. 59 | [hiredis](https://github.com/redis/hiredis): Hiredis is a minimalistic C client library for the Redis database. 60 | [libmemcached](https://github.com/trondn/libmemcached): LibMemcached is designed to provide the greatest number of options to use Memcached. 61 | 62 | **[Optional] For Storage:** 63 | 64 | [memcached](https://github.com/memcached/memcached): A distributed memory object caching system. 65 | [beansdb](https://github.com/douban/beansdb): Beansdb is a distributed key-value storage system designed for large scale online system, aiming for high avaliablility and easy management. 66 | [beanseye](https://github.com/douban/beanseye): Beanseye is proxy and monitor for beansdb, written in Go. 67 | [SSDB](https://github.com/ideawu/ssdb): SSDB is a high performace key-value(key-string, key-zset, key-hashmap) NoSQL database, an alternative to Redis. 68 | [twemproxy](https://github.com/twitter/twemproxy): Twemproxy is a fast and lightweight proxy for memcached and redis protocol. 69 | 70 | 71 | ### Documents: 72 | There are several documents to introduce the design and architecture of zimg: 73 | [Documents of zimg](http://zimg.buaa.us/documents/) 74 | And this picture below shows the architecture of zimg's storage: 75 | 76 | ![architecture_of_zimg_v3](http://ww2.sinaimg.cn/large/4c422e03jw1ejjdk4vdccj20kf0momzd.jpg) 77 | 78 | ### Download: 79 | The source code is licensed under a BSD-like License. 80 | All versions on [Github](https://github.com/buaazp/zimg/releases). 81 | 82 | ### Feedback: 83 | If you have any question, please submit comment in my [BLOG](http://blog.buaa.us/) or mention me on [Weibo](http://weibo.com/819880808), [twitter](https://twitter.com/buaazp). 84 | Technical issues are also welcomed to be submitted on [GitHub Issues](https://github.com/buaazp/zimg/issues). 85 | 86 | 87 | -------------------------------------------------------------------------------- /bin/conf/twemproxy.yml: -------------------------------------------------------------------------------- 1 | beansdb: 2 | listen: 127.0.0.1:22121 3 | hash: fnv1a_64 4 | distribution: ketama 5 | timeout: 400 6 | backlog: 1024 7 | preconnect: true 8 | auto_eject_hosts: true 9 | server_retry_timeout: 2000 10 | server_failure_limit: 3 11 | servers: 12 | - 127.0.0.1:7900:1 beansdb1 13 | - 127.0.0.1:7901:1 beansdb2 14 | 15 | ssdb: 16 | listen: 127.0.0.1:22122 17 | hash: fnv1a_64 18 | distribution: ketama 19 | redis: true 20 | timeout: 400 21 | backlog: 1024 22 | preconnect: true 23 | auto_eject_hosts: true 24 | server_retry_timeout: 2000 25 | server_failure_limit: 3 26 | servers: 27 | - 127.0.0.1:6380:1 ssdb1 28 | - 127.0.0.1:6381:1 ssdb2 29 | -------------------------------------------------------------------------------- /bin/conf/zimg.lua: -------------------------------------------------------------------------------- 1 | --zimg server config 2 | 3 | --server config 4 | --是否后台运行 5 | is_daemon = 1 6 | --绑定IP 7 | ip = '0.0.0.0' 8 | --端口 9 | port = 4869 10 | --运行线程数,默认值为服务器CPU数 11 | --thread_num = 4 12 | backlog_num = 1024 13 | max_keepalives = 1 14 | retry = 3 15 | system = io.popen('uname -sn'):read('*l') 16 | pwd = io.popen('pwd'):read('*l') 17 | 18 | --header config 19 | --返回时所带的HTTP header 20 | headers = 'Cache-Control:max-age=7776000' 21 | --是否启用etag缓存 22 | etag = 1 23 | 24 | --access config 25 | --support mask rules like 'allow 10.1.121.138/24' 26 | --NOTE: remove rule can improve performance 27 | --上传接口的IP控制权限,将权限规则注释掉可以提升服务器处理能力,下同 28 | --upload_rule = 'allow all' 29 | --下载接口的IP控制权限 30 | --download_rule = 'allow all' 31 | --管理接口的IP控制权限 32 | admin_rule = 'allow 127.0.0.1' 33 | 34 | --cache config 35 | --是否启用memcached缓存 36 | cache = 1 37 | --缓存服务器IP 38 | mc_ip = '127.0.0.1' 39 | --缓存服务器端口 40 | mc_port = 11211 41 | 42 | --log config 43 | --log_level output specified level of log to logfile 44 | --[[ 45 | LOG_FATAL 0 System is unusable 46 | LOG_ALERT 1 Action must be taken immediately 47 | LOG_CRIT 2 Critical conditions 48 | LOG_ERROR 3 Error conditions 49 | LOG_WARNING 4 Warning conditions 50 | LOG_NOTICE 5 Normal, but significant 51 | LOG_INFO 6 Information 52 | LOG_DEBUG 7 DEBUG message 53 | ]] 54 | --输出log级别 55 | log_level = 6 56 | --输出log路径 57 | log_name = pwd .. '/log/zimg.log' 58 | 59 | --htdoc config 60 | --默认主页html文件路径 61 | root_path = pwd .. '/www/index.html' 62 | --admin页面html文件路径 63 | admin_path = pwd .. '/www/admin.html' 64 | 65 | --image process config 66 | --禁用URL图片处理 67 | disable_args = 0 68 | --禁用lua脚本图片处理 69 | disable_type = 0 70 | --禁用图片放大 71 | disable_zoom_up = 0 72 | --lua process script 73 | --lua脚本文件路径 74 | script_name = pwd .. '/script/process.lua' 75 | --format value: 'none' for original or other format names 76 | --默认保存新图的格式,字符串'none'表示以原有格式保存,或者是期望使用的格式名 77 | format = 'jpeg' 78 | --quality value: 1~100(default: 75) 79 | --默认保存新图的质量 80 | quality = 75 81 | 82 | --storage config 83 | --zimg support 3 ways for storage images 84 | --value 1 is for local disk storage; 85 | --value 2 is for memcached protocol storage like beansdb; 86 | --value 3 is for redis protocol storage like SSDB. 87 | --存储后端类型,1为本地存储,2为memcached协议后端如beansdb,3为redis协议后端如SSDB 88 | mode = 1 89 | --save_new value: 0.don't save any 1.save all 2.only save types in lua script 90 | --新文件是否存储,0为不存储,1为全都存储,2为只存储lua脚本产生的新图 91 | save_new = 1 92 | --上传图片大小限制,默认100MB 93 | max_size = 100*1024*1024 94 | --允许上传图片类型列表 95 | allowed_type = {'jpeg', 'jpg', 'png', 'gif', 'webp'} 96 | 97 | --mode[1]: local disk mode 98 | --本地存储时的存储路径 99 | img_path = pwd .. '/img' 100 | 101 | --mode[2]: beansdb mode 102 | --beansdb服务器IP 103 | beansdb_ip = '127.0.0.1' 104 | --beansdb服务器端口 105 | beansdb_port = 7900 106 | 107 | --mode[3]: ssdb mode 108 | --SSDB服务器IP 109 | ssdb_ip = '127.0.0.1' 110 | --SSDB服务器端口 111 | ssdb_port = 8888 112 | 113 | --lua conf functions 114 | --部分与配置有关的函数在lua中实现,对性能影响不大 115 | function is_img(type_name) 116 | local found = -1 117 | for _, allowed in pairs(allowed_type) do 118 | if string.lower(type_name) == allowed then 119 | found = 1 120 | break 121 | end 122 | end 123 | return found 124 | end 125 | 126 | -------------------------------------------------------------------------------- /bin/script/process.lua: -------------------------------------------------------------------------------- 1 | local LOG_FATAL = 0 2 | local LOG_ALERT = 1 3 | local LOG_CRIT = 2 4 | local LOG_ERROR = 3 5 | local LOG_WARNING = 4 6 | local LOG_NOTICE = 5 7 | local LOG_INFO = 6 8 | local LOG_DEBUG = 7 9 | 10 | local WI_OK = 1 11 | local WI_FAILED = -1 12 | 13 | local CT_SQUARE = 0 14 | local CT_MAX_WIDTH = 1 15 | local CT_MAX_SIZE = 2 16 | local CT_PROPORTION = 3 17 | local CT_CROP = 4 18 | local CT_NONE = 5 19 | 20 | local WAP_QUALITY = 70 21 | local TEST_QUALITY = 75 22 | local THUMB_QUALITY = 85 23 | local QUALITY_90 = 90 24 | local QUALITY_95 = 95 25 | 26 | local type_list = { 27 | test = { 28 | type = CT_SQUARE, 29 | size = 100, 30 | quality = TEST_QUALITY, 31 | rotate = 90, 32 | gray = 1, 33 | format = 'JPEG', 34 | }, 35 | original = { 36 | type = CT_NONE, 37 | quality = WAP_QUALITY, 38 | }, 39 | thumb300 = { 40 | type = CT_SQUARE, 41 | size = 300, 42 | quality = THUMB_QUALITY, 43 | }, 44 | square = { 45 | type = CT_SQUARE, 46 | size = 500, 47 | quality = THUMB_QUALITY, 48 | }, 49 | thumbnail = { 50 | type = CT_MAX_SIZE, 51 | size = 120, 52 | quality = THUMB_QUALITY, 53 | }, 54 | small = { 55 | type = CT_MAX_SIZE, 56 | size = 200, 57 | quality = THUMB_QUALITY, 58 | ratio = 3.0/10, 59 | }, 60 | middle = { 61 | type = CT_MAX_WIDTH, 62 | size = 440, 63 | quality = QUALITY_90, 64 | }, 65 | large = { 66 | type = CT_MAX_WIDTH, 67 | size = 2048, 68 | quality = QUALITY_95, 69 | }, 70 | webp500 = { 71 | type = CT_MAX_WIDTH, 72 | size = 500, 73 | quality = QUALITY_90, 74 | format = CF_WEBP, 75 | }, 76 | crop200 = { 77 | type = CT_CROP, 78 | size = 200, 79 | quality = QUALITY_90, 80 | }, 81 | } 82 | 83 | local function square(size) 84 | log.print(LOG_DEBUG, "square()...") 85 | log.print(LOG_DEBUG, "size: " .. size) 86 | local ret, x, y, cols 87 | 88 | local im_cols = zimg.cols() 89 | local im_rows = zimg.rows() 90 | log.print(LOG_DEBUG, "im_cols: " .. im_cols) 91 | log.print(LOG_DEBUG, "im_rows: " .. im_rows) 92 | if im_cols > im_rows then 93 | cols = im_rows 94 | y = 0 95 | x = math.ceil((im_cols - im_rows)/2) 96 | else 97 | cols = im_cols 98 | x = 0 99 | y = math.ceil((im_rows - im_cols)/2) 100 | end 101 | log.print(LOG_DEBUG, "x: " .. x) 102 | log.print(LOG_DEBUG, "y: " .. y) 103 | 104 | ret = zimg.crop(x, y, cols, cols) 105 | log.print(LOG_DEBUG, "zimg.crop(" .. x .. ", " .. y .. ", ".. cols .. ", " .. cols .. ") ret = " .. ret) 106 | if ret ~= WI_OK then 107 | return WI_FAILED 108 | end 109 | 110 | ret = zimg.scale(size, size) 111 | log.print(LOG_DEBUG, "zimg.scale(" .. size .. ", " .. size .. ") ret = " .. ret) 112 | if ret ~= WI_OK then 113 | log.print(LOG_DEBUG, "square() failed") 114 | return WI_FAILED 115 | end 116 | 117 | log.print(LOG_DEBUG, "square() succ") 118 | return WI_OK 119 | end 120 | 121 | local function max_width(arg) 122 | log.print(LOG_DEBUG, "max_width()...") 123 | local ret, ratio, cols, rows 124 | local im_cols = zimg.cols() 125 | local im_rows = zimg.rows() 126 | log.print(LOG_DEBUG, "im_cols: " .. im_cols) 127 | log.print(LOG_DEBUG, "im_rows: " .. im_rows) 128 | log.print(LOG_DEBUG, "arg.size: " .. arg.size) 129 | if im_cols <= arg.size then 130 | log.print(LOG_DEBUG, "im_cols <= arg.size return.") 131 | return WI_OK 132 | end 133 | 134 | cols = arg.size 135 | log.print(LOG_DEBUG, "cols = " .. cols) 136 | if arg.ratio then 137 | ratio = im_cols / im_rows 138 | if ratio < arg.ratio then 139 | cols = im_cols 140 | rows = math.ceil(cols / arg.ratio) 141 | if rows > im_rows then 142 | rows = im_rows 143 | end 144 | ret = zimg.crop(0, 0, cols, rows) 145 | log.print(LOG_DEBUG, "zimg.crop(" .. 0 .. ", " .. 0 .. ", ".. cols .. ", " .. rows .. ") ret = " .. ret) 146 | if ret ~= WI_OK then 147 | return WI_FAILED 148 | end 149 | else 150 | cols = math.min(arg.size, im_cols) 151 | rows = im_rows 152 | 153 | ret = zimg.crop(0, 0, cols, rows) 154 | log.print(LOG_DEBUG, "zimg.crop(" .. 0 .. ", " .. 0 .. ", ".. cols .. ", " .. rows .. ") ret = " .. ret) 155 | return ret 156 | end 157 | else 158 | rows = math.ceil((cols / im_cols) * im_rows); 159 | ret = zimg.scale(cols, rows) 160 | log.print(LOG_DEBUG, "zimg.scale(" .. cols .. ", " .. rows .. ") ret = " .. ret) 161 | return ret 162 | end 163 | end 164 | 165 | local function max_size(arg) 166 | log.print(LOG_DEBUG, "max_size()...") 167 | local ret, ratio, rows, cols 168 | local im_cols = zimg.cols(im) 169 | local im_rows = zimg.rows(im) 170 | 171 | if im_cols <= arg.size and im_rows <= arg.size then 172 | return WI_OK 173 | end 174 | 175 | if arg.ratio then 176 | ratio = im_cols / im_rows 177 | log.print(LOG_DEBUG, "ratio = " .. ratio) 178 | if im_cols < (arg.size * arg.ratio) and ratio < arg.ratio then 179 | cols = im_cols 180 | rows = math.min(im_rows, arg.size) 181 | 182 | ret = zimg.crop(0, 0, cols, rows) 183 | log.print(LOG_DEBUG, "zimg.crop(" .. 0 .. ", " .. 0 .. ", ".. cols .. ", " .. rows .. ") ret = " .. ret) 184 | if (ret == WI_OK) then 185 | return WI_OK 186 | else 187 | return WI_FAILED 188 | end 189 | end 190 | if im_rows < (arg.size * arg.ratio) and ratio > (1.0 / arg.ratio) then 191 | rows = im_rows 192 | cols = math.min(im_cols, arg.size) 193 | 194 | ret = zimg.crop(0, 0, cols, rows) 195 | log.print(LOG_DEBUG, "zimg.crop(" .. 0 .. ", " .. 0 .. ", ".. cols .. ", " .. rows .. ") ret = " .. ret) 196 | if (ret == WI_OK) then 197 | return WI_OK 198 | else 199 | return WI_FAILED 200 | end 201 | end 202 | 203 | if im_cols > im_rows and ratio > (1.0 / arg.ratio) then 204 | rows = im_rows 205 | cols = rows / arg.ratio 206 | if (cols > im_cols) then 207 | cols = im_cols 208 | end 209 | 210 | ret = zimg.crop(0, 0, cols, rows) 211 | log.print(LOG_DEBUG, "zimg.crop(" .. 0 .. ", " .. 0 .. ", ".. cols .. ", " .. rows .. ") ret = " .. ret) 212 | if (ret ~= WI_OK) then 213 | return WI_FAILED 214 | end 215 | elseif ratio < arg.ratio then 216 | cols = im_cols 217 | rows = cols / arg.ratio 218 | if (rows > im_rows) then 219 | rows = im_rows 220 | end 221 | ret = zimg.crop(0, 0, cols, rows) 222 | log.print(LOG_DEBUG, "zimg.crop(" .. 0 .. ", " .. 0 .. ", ".. cols .. ", " .. rows .. ") ret = " .. ret) 223 | if (ret ~= WI_OK) then 224 | return WI_FAILED 225 | end 226 | end 227 | end 228 | 229 | if im_cols > im_rows then 230 | cols = arg.size 231 | rows = math.ceil((cols / im_cols) * im_rows); 232 | else 233 | rows = arg.size 234 | cols = math.ceil((rows / im_rows) * im_cols); 235 | end 236 | 237 | ret = zimg.scale(cols, rows) 238 | log.print(LOG_DEBUG, "zimg.scale(" .. cols .. ", " .. rows .. ") ret = " .. ret) 239 | 240 | return ret 241 | end 242 | 243 | local function proportion(arg) 244 | log.print(LOG_DEBUG, "proportion()...") 245 | local ret, ratio, cols, rows 246 | local im_cols = zimg.cols() 247 | local im_rows = zimg.rows() 248 | 249 | ratio = im_cols / im_rows 250 | if arg.ratio and ratio > arg.ratio then 251 | cols = arg.cols 252 | if im_cols < cols then 253 | return WI_OK 254 | end 255 | rows = math.ceil((cols / im_cols) * im_rows); 256 | else 257 | rows = arg.rows 258 | if im_rows < rows then 259 | return WI_OK 260 | end 261 | cols = math.ceil((rows / im_rows) * im_cols); 262 | end 263 | 264 | ret = zimg.scale(cols, rows) 265 | log.print(LOG_DEBUG, "zimg.scale(" .. cols .. ", " .. rows .. ") ret = " .. ret) 266 | return ret 267 | end 268 | 269 | local function crop(arg) 270 | log.print(LOG_DEBUG, "crop()...") 271 | local ret, x, y, cols, rows 272 | local im_cols = zimg.cols() 273 | local im_rows = zimg.rows() 274 | 275 | if arg.cols then 276 | cols = arg.cols 277 | else 278 | cols = arg.size 279 | end 280 | if arg.rows then 281 | rows = arg.rows 282 | else 283 | rows = arg.size 284 | end 285 | 286 | if cols > im_cols then 287 | cols = im_cols 288 | end 289 | if rows > im_rows then 290 | rows = im_rows 291 | end 292 | 293 | x = math.ceil((im_cols - cols) / 2.0); 294 | y = math.ceil((im_rows - rows) / 2.0); 295 | 296 | ret = zimg.crop(x, y, cols, rows) 297 | log.print(LOG_DEBUG, "zimg.crop(" .. x .. ", " .. y .. ", ".. cols .. ", " .. rows .. ") ret = " .. ret) 298 | 299 | return ret 300 | end 301 | 302 | function f() 303 | local code = WI_FAILED 304 | local rtype = zimg.type() 305 | log.print(LOG_DEBUG, "rtype:" .. rtype) 306 | 307 | local arg = type_list[rtype] 308 | if arg then 309 | local ret = WI_FAILED 310 | log.print(LOG_DEBUG, "arg.type = " .. arg.type) 311 | local switch = { 312 | [CT_SQUARE] = function() ret = square(arg.size) end, 313 | [CT_MAX_WIDTH] = function() ret = max_width(arg) end, 314 | [CT_MAX_SIZE] = function() ret = max_size(arg) end, 315 | [CT_PROPORTION] = function() ret = proportion(arg) end, 316 | [CT_CROP] = function() ret = crop(arg) end, 317 | [CT_NONE] = function() ret = WI_OK end, 318 | } 319 | log.print(LOG_DEBUG, "start scale image...") 320 | local action = switch[arg.type] 321 | if action then 322 | action() 323 | if ret == WI_OK then 324 | if arg.rotate then 325 | ret = zimg.rotate(arg.rotate) 326 | log.print(LOG_DEBUG, "zimg.rotate(" .. arg.rotate .. ")") 327 | end 328 | 329 | if arg.gray and arg.gray == 1 then 330 | ret = zimg.gray() 331 | log.print(LOG_DEBUG, "zimg.gray()") 332 | end 333 | 334 | if arg.quality then 335 | ret = zimg.set_quality(arg.quality) 336 | log.print(LOG_DEBUG, "zimg.set_quality(" .. arg.quality .. ")") 337 | end 338 | 339 | if arg.format then 340 | log.print(LOG_DEBUG, "arg.format = " .. arg.format) 341 | ret = zimg.set_format(arg.format) 342 | end 343 | 344 | code = ret 345 | log.print(LOG_DEBUG, "code = " .. code) 346 | else 347 | log.print(LOG_DEBUG, "scale image failed.") 348 | end 349 | else 350 | log.print(LOG_DEBUG, "action = nil") 351 | end 352 | else 353 | log.print(LOG_DEBUG, "arg = nil") 354 | end 355 | 356 | zimg.ret(code) 357 | log.print(LOG_DEBUG, "zimg lua script finished.") 358 | end 359 | 360 | log.print(LOG_DEBUG, "zimg using lua script.") 361 | 362 | -------------------------------------------------------------------------------- /bin/script/test.lua: -------------------------------------------------------------------------------- 1 | 2 | local type_list = { 3 | test = { 4 | cols = 300, 5 | rows = 300, 6 | quality = 75, 7 | rotate = 90, 8 | gray = 1, 9 | format = 'webp', 10 | }, 11 | } 12 | local OK = 1 13 | 14 | function f() --The main function must be named f() for zimg-lua 15 | local code = -1 16 | local rtype = zimg.type() --Get the request type from url argument 17 | 18 | local arg = type_list[rtype] --Find the type details 19 | if not arg then 20 | zimg.ret(code) 21 | end 22 | 23 | local ret = zimg.scale(arg.cols, arg.rows) --Scale image 24 | if ret ~= OK then 25 | zimg.ret(code) 26 | end 27 | 28 | if arg.rotate then 29 | ret = zimg.rotate(arg.rotate) --Rotate image 30 | if ret ~= OK then 31 | zimg.ret(code) 32 | end 33 | end 34 | 35 | if arg.gray and arg.gray == 1 then 36 | ret = zimg.gray() --Grayscale image 37 | if ret ~= OK then 38 | zimg.ret(code) 39 | end 40 | end 41 | 42 | if arg.quality and zimg.quality() > arg.quality then 43 | ret = zimg.set_quality(arg.quality) --Set quality of image 44 | if ret ~= OK then 45 | zimg.ret(code) 46 | end 47 | end 48 | 49 | if arg.format then 50 | ret = zimg.set_format(arg.format) --Set format 51 | if ret ~= OK then 52 | zimg.ret(code) 53 | end 54 | end 55 | 56 | code = OK 57 | zimg.ret(code) --Return the result to zimg 58 | end 59 | -------------------------------------------------------------------------------- /bin/www/admin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Welcome to zimg Admin!

4 |

Manage images in zimg:

5 |

6 | MD5: 7 | 8 | Command: 9 | 12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /bin/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 24 |

Welcome to zimg world!

25 |

Upload image(s) to zimg:

26 |
27 | Choose file: 28 | 29 |
30 | 31 |
32 |

More infomation: zimg.buaa.us

33 | 34 | 35 | -------------------------------------------------------------------------------- /deps/ImageMagick-6.9.8-4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buaazp/zimg/5cd73c5d603f54f47f11a64e23553a4390ed6d39/deps/ImageMagick-6.9.8-4.tar.gz -------------------------------------------------------------------------------- /deps/LuaJIT-2.0.3.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buaazp/zimg/5cd73c5d603f54f47f11a64e23553a4390ed6d39/deps/LuaJIT-2.0.3.tar.gz -------------------------------------------------------------------------------- /deps/cjson/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Dave Gamble 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /deps/cjson/cJSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Dave Gamble 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef cJSON__h 24 | #define cJSON__h 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | /* cJSON Types: */ 32 | #define cJSON_False 0 33 | #define cJSON_True 1 34 | #define cJSON_NULL 2 35 | #define cJSON_Number 3 36 | #define cJSON_String 4 37 | #define cJSON_Array 5 38 | #define cJSON_Object 6 39 | 40 | #define cJSON_IsReference 256 41 | 42 | /* The cJSON structure: */ 43 | typedef struct cJSON { 44 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 45 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 46 | 47 | int type; /* The type of the item, as above. */ 48 | 49 | char *valuestring; /* The item's string, if type==cJSON_String */ 50 | int valueint; /* The item's number, if type==cJSON_Number */ 51 | double valuedouble; /* The item's number, if type==cJSON_Number */ 52 | 53 | char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ 54 | } cJSON; 55 | 56 | typedef struct cJSON_Hooks { 57 | void *(*malloc_fn)(size_t sz); 58 | void (*free_fn)(void *ptr); 59 | } cJSON_Hooks; 60 | 61 | /* Supply malloc, realloc and free functions to cJSON */ 62 | extern void cJSON_InitHooks(cJSON_Hooks* hooks); 63 | 64 | 65 | /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ 66 | extern cJSON *cJSON_Parse(const char *value); 67 | /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ 68 | extern char *cJSON_Print(cJSON *item); 69 | /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ 70 | extern char *cJSON_PrintUnformatted(cJSON *item); 71 | /* Delete a cJSON entity and all subentities. */ 72 | extern void cJSON_Delete(cJSON *c); 73 | 74 | /* Returns the number of items in an array (or object). */ 75 | extern int cJSON_GetArraySize(cJSON *array); 76 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 77 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 78 | /* Get item "string" from object. Case insensitive. */ 79 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 80 | 81 | /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ 82 | extern const char *cJSON_GetErrorPtr(void); 83 | 84 | /* These calls create a cJSON item of the appropriate type. */ 85 | extern cJSON *cJSON_CreateNull(void); 86 | extern cJSON *cJSON_CreateTrue(void); 87 | extern cJSON *cJSON_CreateFalse(void); 88 | extern cJSON *cJSON_CreateBool(int b); 89 | extern cJSON *cJSON_CreateNumber(double num); 90 | extern cJSON *cJSON_CreateString(const char *string); 91 | extern cJSON *cJSON_CreateArray(void); 92 | extern cJSON *cJSON_CreateObject(void); 93 | 94 | /* These utilities create an Array of count items. */ 95 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 96 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 97 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 98 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 99 | 100 | /* Append item to the specified array/object. */ 101 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 102 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 103 | /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ 104 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 105 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 106 | 107 | /* Remove/Detatch items from Arrays/Objects. */ 108 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 109 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 110 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 111 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 112 | 113 | /* Update array items. */ 114 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 115 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 116 | 117 | /* Duplicate a cJSON item */ 118 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 119 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 120 | need to be released. With recurse!=0, it will duplicate any children connected to the item. 121 | The item->next and ->prev pointers are always zero on return from Duplicate. */ 122 | 123 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 124 | extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); 125 | 126 | extern void cJSON_Minify(char *json); 127 | 128 | /* Macros for creating things quickly. */ 129 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 130 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 131 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 132 | #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 133 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 134 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 135 | 136 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 137 | #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /deps/hiredis/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2011, Salvatore Sanfilippo 2 | Copyright (c) 2010-2011, Pieter Noordhuis 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of Redis nor the names of its contributors may be used 17 | to endorse or promote products derived from this software without specific 18 | prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 24 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /deps/hiredis/fmacros.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIREDIS_FMACRO_H 2 | #define __HIREDIS_FMACRO_H 3 | 4 | #if !defined(_BSD_SOURCE) 5 | #define _BSD_SOURCE 6 | #endif 7 | 8 | #if defined(__sun__) 9 | #define _POSIX_C_SOURCE 200112L 10 | #elif defined(__linux__) 11 | #define _XOPEN_SOURCE 600 12 | #else 13 | #define _XOPEN_SOURCE 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /deps/hiredis/hiredis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009-2011, Salvatore Sanfilippo 3 | * Copyright (c) 2010-2011, Pieter Noordhuis 4 | * 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of Redis nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef __HIREDIS_H 33 | #define __HIREDIS_H 34 | #include /* for size_t */ 35 | #include /* for va_list */ 36 | #include /* for struct timeval */ 37 | 38 | #define HIREDIS_MAJOR 0 39 | #define HIREDIS_MINOR 11 40 | #define HIREDIS_PATCH 0 41 | 42 | #define REDIS_ERR -1 43 | #define REDIS_OK 0 44 | 45 | /* When an error occurs, the err flag in a context is set to hold the type of 46 | * error that occured. REDIS_ERR_IO means there was an I/O error and you 47 | * should use the "errno" variable to find out what is wrong. 48 | * For other values, the "errstr" field will hold a description. */ 49 | #define REDIS_ERR_IO 1 /* Error in read or write */ 50 | #define REDIS_ERR_EOF 3 /* End of file */ 51 | #define REDIS_ERR_PROTOCOL 4 /* Protocol error */ 52 | #define REDIS_ERR_OOM 5 /* Out of memory */ 53 | #define REDIS_ERR_OTHER 2 /* Everything else... */ 54 | 55 | /* Connection type can be blocking or non-blocking and is set in the 56 | * least significant bit of the flags field in redisContext. */ 57 | #define REDIS_BLOCK 0x1 58 | 59 | /* Connection may be disconnected before being free'd. The second bit 60 | * in the flags field is set when the context is connected. */ 61 | #define REDIS_CONNECTED 0x2 62 | 63 | /* The async API might try to disconnect cleanly and flush the output 64 | * buffer and read all subsequent replies before disconnecting. 65 | * This flag means no new commands can come in and the connection 66 | * should be terminated once all replies have been read. */ 67 | #define REDIS_DISCONNECTING 0x4 68 | 69 | /* Flag specific to the async API which means that the context should be clean 70 | * up as soon as possible. */ 71 | #define REDIS_FREEING 0x8 72 | 73 | /* Flag that is set when an async callback is executed. */ 74 | #define REDIS_IN_CALLBACK 0x10 75 | 76 | /* Flag that is set when the async context has one or more subscriptions. */ 77 | #define REDIS_SUBSCRIBED 0x20 78 | 79 | /* Flag that is set when monitor mode is active */ 80 | #define REDIS_MONITORING 0x40 81 | 82 | #define REDIS_REPLY_STRING 1 83 | #define REDIS_REPLY_ARRAY 2 84 | #define REDIS_REPLY_INTEGER 3 85 | #define REDIS_REPLY_NIL 4 86 | #define REDIS_REPLY_STATUS 5 87 | #define REDIS_REPLY_ERROR 6 88 | 89 | #define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */ 90 | 91 | #ifdef __cplusplus 92 | extern "C" { 93 | #endif 94 | 95 | /* This is the reply object returned by redisCommand() */ 96 | typedef struct redisReply { 97 | int type; /* REDIS_REPLY_* */ 98 | long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ 99 | int len; /* Length of string */ 100 | char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ 101 | size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ 102 | struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ 103 | } redisReply; 104 | 105 | typedef struct redisReadTask { 106 | int type; 107 | int elements; /* number of elements in multibulk container */ 108 | int idx; /* index in parent (array) object */ 109 | void *obj; /* holds user-generated value for a read task */ 110 | struct redisReadTask *parent; /* parent task */ 111 | void *privdata; /* user-settable arbitrary field */ 112 | } redisReadTask; 113 | 114 | typedef struct redisReplyObjectFunctions { 115 | void *(*createString)(const redisReadTask*, char*, size_t); 116 | void *(*createArray)(const redisReadTask*, int); 117 | void *(*createInteger)(const redisReadTask*, long long); 118 | void *(*createNil)(const redisReadTask*); 119 | void (*freeObject)(void*); 120 | } redisReplyObjectFunctions; 121 | 122 | /* State for the protocol parser */ 123 | typedef struct redisReader { 124 | int err; /* Error flags, 0 when there is no error */ 125 | char errstr[128]; /* String representation of error when applicable */ 126 | 127 | char *buf; /* Read buffer */ 128 | size_t pos; /* Buffer cursor */ 129 | size_t len; /* Buffer length */ 130 | size_t maxbuf; /* Max length of unused buffer */ 131 | 132 | redisReadTask rstack[9]; 133 | int ridx; /* Index of current read task */ 134 | void *reply; /* Temporary reply pointer */ 135 | 136 | redisReplyObjectFunctions *fn; 137 | void *privdata; 138 | } redisReader; 139 | 140 | /* Public API for the protocol parser. */ 141 | redisReader *redisReaderCreate(void); 142 | void redisReaderFree(redisReader *r); 143 | int redisReaderFeed(redisReader *r, const char *buf, size_t len); 144 | int redisReaderGetReply(redisReader *r, void **reply); 145 | 146 | /* Backwards compatibility, can be removed on big version bump. */ 147 | #define redisReplyReaderCreate redisReaderCreate 148 | #define redisReplyReaderFree redisReaderFree 149 | #define redisReplyReaderFeed redisReaderFeed 150 | #define redisReplyReaderGetReply redisReaderGetReply 151 | #define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) 152 | #define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply) 153 | #define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr) 154 | 155 | /* Function to free the reply objects hiredis returns by default. */ 156 | void freeReplyObject(void *reply); 157 | 158 | /* Functions to format a command according to the protocol. */ 159 | int redisvFormatCommand(char **target, const char *format, va_list ap); 160 | int redisFormatCommand(char **target, const char *format, ...); 161 | int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); 162 | 163 | /* Context for a connection to Redis */ 164 | typedef struct redisContext { 165 | int err; /* Error flags, 0 when there is no error */ 166 | char errstr[128]; /* String representation of error when applicable */ 167 | int fd; 168 | int flags; 169 | char *obuf; /* Write buffer */ 170 | redisReader *reader; /* Protocol reader */ 171 | } redisContext; 172 | 173 | redisContext *redisConnect(const char *ip, int port); 174 | redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv); 175 | redisContext *redisConnectNonBlock(const char *ip, int port); 176 | redisContext *redisConnectUnix(const char *path); 177 | redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv); 178 | redisContext *redisConnectUnixNonBlock(const char *path); 179 | int redisSetTimeout(redisContext *c, struct timeval tv); 180 | void redisFree(redisContext *c); 181 | int redisBufferRead(redisContext *c); 182 | int redisBufferWrite(redisContext *c, int *done); 183 | 184 | /* In a blocking context, this function first checks if there are unconsumed 185 | * replies to return and returns one if so. Otherwise, it flushes the output 186 | * buffer to the socket and reads until it has a reply. In a non-blocking 187 | * context, it will return unconsumed replies until there are no more. */ 188 | int redisGetReply(redisContext *c, void **reply); 189 | int redisGetReplyFromReader(redisContext *c, void **reply); 190 | 191 | /* Write a command to the output buffer. Use these functions in blocking mode 192 | * to get a pipeline of commands. */ 193 | int redisvAppendCommand(redisContext *c, const char *format, va_list ap); 194 | int redisAppendCommand(redisContext *c, const char *format, ...); 195 | int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); 196 | 197 | /* Issue a command to Redis. In a blocking context, it is identical to calling 198 | * redisAppendCommand, followed by redisGetReply. The function will return 199 | * NULL if there was an error in performing the request, otherwise it will 200 | * return the reply. In a non-blocking context, it is identical to calling 201 | * only redisAppendCommand and will always return NULL. */ 202 | void *redisvCommand(redisContext *c, const char *format, va_list ap); 203 | void *redisCommand(redisContext *c, const char *format, ...); 204 | void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); 205 | 206 | #ifdef __cplusplus 207 | } 208 | #endif 209 | 210 | #endif 211 | -------------------------------------------------------------------------------- /deps/hiredis/net.c: -------------------------------------------------------------------------------- 1 | /* Extracted from anet.c to work properly with Hiredis error reporting. 2 | * 3 | * Copyright (c) 2006-2011, Salvatore Sanfilippo 4 | * Copyright (c) 2010-2011, Pieter Noordhuis 5 | * 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Redis nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "fmacros.h" 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | #include "net.h" 52 | #include "sds.h" 53 | 54 | /* Defined in hiredis.c */ 55 | void __redisSetError(redisContext *c, int type, const char *str); 56 | 57 | static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { 58 | char buf[128]; 59 | size_t len = 0; 60 | 61 | if (prefix != NULL) 62 | len = snprintf(buf,sizeof(buf),"%s: ",prefix); 63 | strerror_r(errno,buf+len,sizeof(buf)-len); 64 | __redisSetError(c,type,buf); 65 | } 66 | 67 | static int redisSetReuseAddr(redisContext *c, int fd) { 68 | int on = 1; 69 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { 70 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); 71 | close(fd); 72 | return REDIS_ERR; 73 | } 74 | return REDIS_OK; 75 | } 76 | 77 | static int redisCreateSocket(redisContext *c, int type) { 78 | int s; 79 | if ((s = socket(type, SOCK_STREAM, 0)) == -1) { 80 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); 81 | return REDIS_ERR; 82 | } 83 | if (type == AF_INET) { 84 | if (redisSetReuseAddr(c,s) == REDIS_ERR) { 85 | return REDIS_ERR; 86 | } 87 | } 88 | return s; 89 | } 90 | 91 | static int redisSetBlocking(redisContext *c, int fd, int blocking) { 92 | int flags; 93 | 94 | /* Set the socket nonblocking. 95 | * Note that fcntl(2) for F_GETFL and F_SETFL can't be 96 | * interrupted by a signal. */ 97 | if ((flags = fcntl(fd, F_GETFL)) == -1) { 98 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)"); 99 | close(fd); 100 | return REDIS_ERR; 101 | } 102 | 103 | if (blocking) 104 | flags &= ~O_NONBLOCK; 105 | else 106 | flags |= O_NONBLOCK; 107 | 108 | if (fcntl(fd, F_SETFL, flags) == -1) { 109 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)"); 110 | close(fd); 111 | return REDIS_ERR; 112 | } 113 | return REDIS_OK; 114 | } 115 | 116 | static int redisSetTcpNoDelay(redisContext *c, int fd) { 117 | int yes = 1; 118 | if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { 119 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)"); 120 | close(fd); 121 | return REDIS_ERR; 122 | } 123 | return REDIS_OK; 124 | } 125 | 126 | #define __MAX_MSEC (((LONG_MAX) - 999) / 1000) 127 | 128 | static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) { 129 | struct pollfd wfd[1]; 130 | long msec; 131 | 132 | msec = -1; 133 | wfd[0].fd = fd; 134 | wfd[0].events = POLLOUT; 135 | 136 | /* Only use timeout when not NULL. */ 137 | if (timeout != NULL) { 138 | if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { 139 | close(fd); 140 | return REDIS_ERR; 141 | } 142 | 143 | msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000); 144 | 145 | if (msec < 0 || msec > INT_MAX) { 146 | msec = INT_MAX; 147 | } 148 | } 149 | 150 | if (errno == EINPROGRESS) { 151 | int res; 152 | 153 | if ((res = poll(wfd, 1, msec)) == -1) { 154 | __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); 155 | close(fd); 156 | return REDIS_ERR; 157 | } else if (res == 0) { 158 | errno = ETIMEDOUT; 159 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); 160 | close(fd); 161 | return REDIS_ERR; 162 | } 163 | 164 | if (redisCheckSocketError(c, fd) != REDIS_OK) 165 | return REDIS_ERR; 166 | 167 | return REDIS_OK; 168 | } 169 | 170 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); 171 | close(fd); 172 | return REDIS_ERR; 173 | } 174 | 175 | int redisCheckSocketError(redisContext *c, int fd) { 176 | int err = 0; 177 | socklen_t errlen = sizeof(err); 178 | 179 | if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { 180 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)"); 181 | close(fd); 182 | return REDIS_ERR; 183 | } 184 | 185 | if (err) { 186 | errno = err; 187 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); 188 | close(fd); 189 | return REDIS_ERR; 190 | } 191 | 192 | return REDIS_OK; 193 | } 194 | 195 | int redisContextSetTimeout(redisContext *c, struct timeval tv) { 196 | if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) { 197 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)"); 198 | return REDIS_ERR; 199 | } 200 | if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) { 201 | __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)"); 202 | return REDIS_ERR; 203 | } 204 | return REDIS_OK; 205 | } 206 | 207 | int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) { 208 | int s, rv; 209 | char _port[6]; /* strlen("65535"); */ 210 | struct addrinfo hints, *servinfo, *p; 211 | int blocking = (c->flags & REDIS_BLOCK); 212 | 213 | snprintf(_port, 6, "%d", port); 214 | memset(&hints,0,sizeof(hints)); 215 | hints.ai_family = AF_INET; 216 | hints.ai_socktype = SOCK_STREAM; 217 | 218 | if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { 219 | __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); 220 | return REDIS_ERR; 221 | } 222 | for (p = servinfo; p != NULL; p = p->ai_next) { 223 | if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) 224 | continue; 225 | 226 | if (redisSetBlocking(c,s,0) != REDIS_OK) 227 | goto error; 228 | if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { 229 | if (errno == EHOSTUNREACH) { 230 | close(s); 231 | continue; 232 | } else if (errno == EINPROGRESS && !blocking) { 233 | /* This is ok. */ 234 | } else { 235 | if (redisContextWaitReady(c,s,timeout) != REDIS_OK) 236 | goto error; 237 | } 238 | } 239 | if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) 240 | goto error; 241 | if (redisSetTcpNoDelay(c,s) != REDIS_OK) 242 | goto error; 243 | 244 | c->fd = s; 245 | c->flags |= REDIS_CONNECTED; 246 | rv = REDIS_OK; 247 | goto end; 248 | } 249 | if (p == NULL) { 250 | char buf[128]; 251 | snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno)); 252 | __redisSetError(c,REDIS_ERR_OTHER,buf); 253 | goto error; 254 | } 255 | 256 | error: 257 | rv = REDIS_ERR; 258 | end: 259 | freeaddrinfo(servinfo); 260 | return rv; // Need to return REDIS_OK if alright 261 | } 262 | 263 | int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) { 264 | int s; 265 | int blocking = (c->flags & REDIS_BLOCK); 266 | struct sockaddr_un sa; 267 | 268 | if ((s = redisCreateSocket(c,AF_LOCAL)) < 0) 269 | return REDIS_ERR; 270 | if (redisSetBlocking(c,s,0) != REDIS_OK) 271 | return REDIS_ERR; 272 | 273 | sa.sun_family = AF_LOCAL; 274 | strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); 275 | if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { 276 | if (errno == EINPROGRESS && !blocking) { 277 | /* This is ok. */ 278 | } else { 279 | if (redisContextWaitReady(c,s,timeout) != REDIS_OK) 280 | return REDIS_ERR; 281 | } 282 | } 283 | 284 | /* Reset socket to be blocking after connect(2). */ 285 | if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) 286 | return REDIS_ERR; 287 | 288 | c->fd = s; 289 | c->flags |= REDIS_CONNECTED; 290 | return REDIS_OK; 291 | } 292 | -------------------------------------------------------------------------------- /deps/hiredis/net.h: -------------------------------------------------------------------------------- 1 | /* Extracted from anet.c to work properly with Hiredis error reporting. 2 | * 3 | * Copyright (c) 2006-2011, Salvatore Sanfilippo 4 | * Copyright (c) 2010-2011, Pieter Noordhuis 5 | * 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Redis nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef __NET_H 34 | #define __NET_H 35 | 36 | #include "hiredis.h" 37 | 38 | #if defined(__sun) 39 | #define AF_LOCAL AF_UNIX 40 | #endif 41 | 42 | int redisCheckSocketError(redisContext *c, int fd); 43 | int redisContextSetTimeout(redisContext *c, struct timeval tv); 44 | int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout); 45 | int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /deps/hiredis/sds.h: -------------------------------------------------------------------------------- 1 | /* SDSLib, A C dynamic strings library 2 | * 3 | * Copyright (c) 2006-2010, Salvatore Sanfilippo 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef __SDS_H 32 | #define __SDS_H 33 | 34 | #include 35 | #include 36 | 37 | typedef char *sds; 38 | 39 | struct sdshdr { 40 | int len; 41 | int free; 42 | char buf[]; 43 | }; 44 | 45 | static inline size_t sdslen(const sds s) { 46 | struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); 47 | return sh->len; 48 | } 49 | 50 | static inline size_t sdsavail(const sds s) { 51 | struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); 52 | return sh->free; 53 | } 54 | 55 | sds sdsnewlen(const void *init, size_t initlen); 56 | sds sdsnew(const char *init); 57 | sds sdsempty(void); 58 | size_t sdslen(const sds s); 59 | sds sdsdup(const sds s); 60 | void sdsfree(sds s); 61 | size_t sdsavail(sds s); 62 | sds sdsgrowzero(sds s, size_t len); 63 | sds sdscatlen(sds s, const void *t, size_t len); 64 | sds sdscat(sds s, const char *t); 65 | sds sdscpylen(sds s, char *t, size_t len); 66 | sds sdscpy(sds s, char *t); 67 | 68 | sds sdscatvprintf(sds s, const char *fmt, va_list ap); 69 | #ifdef __GNUC__ 70 | sds sdscatprintf(sds s, const char *fmt, ...) 71 | __attribute__((format(printf, 2, 3))); 72 | #else 73 | sds sdscatprintf(sds s, const char *fmt, ...); 74 | #endif 75 | 76 | sds sdstrim(sds s, const char *cset); 77 | sds sdsrange(sds s, int start, int end); 78 | void sdsupdatelen(sds s); 79 | int sdscmp(sds s1, sds s2); 80 | sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count); 81 | void sdsfreesplitres(sds *tokens, int count); 82 | void sdstolower(sds s); 83 | void sdstoupper(sds s); 84 | sds sdsfromlonglong(long long value); 85 | sds sdscatrepr(sds s, char *p, size_t len); 86 | sds *sdssplitargs(char *line, int *argc); 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /deps/libevhtp/LICENSE: -------------------------------------------------------------------------------- 1 | Libevhtp is available for use under the following license, commonly known 2 | as the 3-clause (or "modified") BSD license: 3 | 4 | ============================== 5 | Copyright (c) 2010-2011 Mark Ellzey 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 1. Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | ============================== 29 | 30 | Portions of Libevhtp are based on works by others, also made available by them 31 | under the three-clause BSD license above. The functions include: 32 | 33 | evhtp.c: _evhtp_glob_match(): 34 | Copyright (c) 2006-2009, Salvatore Sanfilippo 35 | -------------------------------------------------------------------------------- /deps/libevhtp/evhtp-config.h: -------------------------------------------------------------------------------- 1 | #ifndef __EVHTP_CONFIG_H__ 2 | #define __EVHTP_CONFIG_H__ 3 | 4 | #undef EVHTP_DISABLE_EVTHR 5 | #undef EVHTP_DISABLE_REGEX 6 | #undef EVHTP_DISABLE_SSL 7 | #undef EVHTP_DISABLE_EVTHR 8 | 9 | /* #undef EVHTP_DISABLE_EVTHR */ 10 | #define EVHTP_DISABLE_REGEX 11 | #define EVHTP_DISABLE_SSL 12 | /* #undef EVHTP_DISABLE_EVTHR */ 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /deps/libevhtp/evthr.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifndef WIN32 11 | #include 12 | #include 13 | #include 14 | #endif 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #include "evthr.h" 23 | 24 | #if (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC__MINOR__ > 4)) && (!defined(__STRICT_ANSI__) || __STRICT_ANSI__ == 0) 25 | #define __unused__ __attribute__((unused)) 26 | #else 27 | #define __unused__ 28 | #endif 29 | 30 | #define _EVTHR_MAGIC 0x03fb 31 | 32 | typedef struct evthr_cmd evthr_cmd_t; 33 | typedef struct evthr_pool_slist evthr_pool_slist_t; 34 | 35 | struct evthr_cmd { 36 | uint8_t stop : 1; 37 | void * args; 38 | evthr_cb cb; 39 | } __attribute__ ((packed)); 40 | 41 | TAILQ_HEAD(evthr_pool_slist, evthr); 42 | 43 | struct evthr_pool { 44 | int nthreads; 45 | evthr_pool_slist_t threads; 46 | }; 47 | 48 | struct evthr { 49 | int cur_backlog; 50 | int max_backlog; 51 | int rdr; 52 | int wdr; 53 | char err; 54 | ev_t * event; 55 | evbase_t * evbase; 56 | pthread_mutex_t lock; 57 | pthread_mutex_t stat_lock; 58 | pthread_mutex_t rlock; 59 | pthread_t * thr; 60 | evthr_init_cb init_cb; 61 | void * arg; 62 | void * aux; 63 | 64 | TAILQ_ENTRY(evthr) next; 65 | }; 66 | 67 | #ifndef TAILQ_FOREACH_SAFE 68 | #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ 69 | for ((var) = TAILQ_FIRST((head)); \ 70 | (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ 71 | (var) = (tvar)) 72 | #endif 73 | 74 | inline void 75 | evthr_inc_backlog(evthr_t * evthr) { 76 | __sync_fetch_and_add(&evthr->cur_backlog, 1); 77 | } 78 | 79 | inline void 80 | evthr_dec_backlog(evthr_t * evthr) { 81 | __sync_fetch_and_sub(&evthr->cur_backlog, 1); 82 | } 83 | 84 | inline int 85 | evthr_get_backlog(evthr_t * evthr) { 86 | return __sync_add_and_fetch(&evthr->cur_backlog, 0); 87 | } 88 | 89 | inline void 90 | evthr_set_max_backlog(evthr_t * evthr, int max) { 91 | evthr->max_backlog = max; 92 | } 93 | 94 | inline int 95 | evthr_set_backlog(evthr_t * evthr, int num) { 96 | int rnum; 97 | 98 | if (evthr->wdr < 0) { 99 | return -1; 100 | } 101 | 102 | rnum = num * sizeof(evthr_cmd_t); 103 | 104 | return setsockopt(evthr->wdr, SOL_SOCKET, SO_RCVBUF, &rnum, sizeof(int)); 105 | } 106 | 107 | static void 108 | _evthr_read_cmd(evutil_socket_t sock, short __unused__ which, void * args) { 109 | evthr_t * thread; 110 | evthr_cmd_t cmd; 111 | ssize_t recvd; 112 | 113 | if (!(thread = (evthr_t *)args)) { 114 | return; 115 | } 116 | 117 | if (pthread_mutex_trylock(&thread->lock) != 0) { 118 | return; 119 | } 120 | 121 | pthread_mutex_lock(&thread->rlock); 122 | 123 | if ((recvd = recv(sock, &cmd, sizeof(evthr_cmd_t), 0)) <= 0) { 124 | pthread_mutex_unlock(&thread->rlock); 125 | if (errno == EAGAIN) { 126 | goto end; 127 | } else { 128 | goto error; 129 | } 130 | } 131 | 132 | if (recvd < (ssize_t)sizeof(evthr_cmd_t)) { 133 | pthread_mutex_unlock(&thread->rlock); 134 | goto error; 135 | } 136 | 137 | pthread_mutex_unlock(&thread->rlock); 138 | 139 | if (recvd != sizeof(evthr_cmd_t)) { 140 | goto error; 141 | } 142 | 143 | if (cmd.stop == 1) { 144 | goto stop; 145 | } 146 | 147 | if (cmd.cb != NULL) { 148 | cmd.cb(thread, cmd.args, thread->arg); 149 | goto done; 150 | } else { 151 | goto done; 152 | } 153 | 154 | stop: 155 | event_base_loopbreak(thread->evbase); 156 | done: 157 | evthr_dec_backlog(thread); 158 | end: 159 | pthread_mutex_unlock(&thread->lock); 160 | return; 161 | error: 162 | pthread_mutex_lock(&thread->stat_lock); 163 | thread->cur_backlog = -1; 164 | thread->err = 1; 165 | pthread_mutex_unlock(&thread->stat_lock); 166 | pthread_mutex_unlock(&thread->lock); 167 | event_base_loopbreak(thread->evbase); 168 | return; 169 | } /* _evthr_read_cmd */ 170 | 171 | static void * 172 | _evthr_loop(void * args) { 173 | evthr_t * thread; 174 | 175 | if (!(thread = (evthr_t *)args)) { 176 | return NULL; 177 | } 178 | 179 | if (thread == NULL || thread->thr == NULL) { 180 | pthread_exit(NULL); 181 | } 182 | 183 | thread->evbase = event_base_new(); 184 | thread->event = event_new(thread->evbase, thread->rdr, 185 | EV_READ | EV_PERSIST, _evthr_read_cmd, args); 186 | 187 | event_add(thread->event, NULL); 188 | 189 | pthread_mutex_lock(&thread->lock); 190 | if (thread->init_cb != NULL) { 191 | thread->init_cb(thread, thread->arg); 192 | } 193 | pthread_mutex_unlock(&thread->lock); 194 | 195 | event_base_loop(thread->evbase, 0); 196 | 197 | if (thread->err == 1) { 198 | fprintf(stderr, "FATAL ERROR!\n"); 199 | } 200 | 201 | pthread_exit(NULL); 202 | } 203 | 204 | evthr_res 205 | evthr_defer(evthr_t * thread, evthr_cb cb, void * arg) { 206 | int cur_backlog; 207 | evthr_cmd_t cmd; 208 | 209 | cur_backlog = evthr_get_backlog(thread); 210 | 211 | if (thread->max_backlog) { 212 | if (cur_backlog + 1 > thread->max_backlog) { 213 | return EVTHR_RES_BACKLOG; 214 | } 215 | } 216 | 217 | if (cur_backlog == -1) { 218 | return EVTHR_RES_FATAL; 219 | } 220 | 221 | /* cmd.magic = _EVTHR_MAGIC; */ 222 | cmd.cb = cb; 223 | cmd.args = arg; 224 | cmd.stop = 0; 225 | 226 | pthread_mutex_lock(&thread->rlock); 227 | 228 | evthr_inc_backlog(thread); 229 | 230 | if (send(thread->wdr, &cmd, sizeof(cmd), 0) <= 0) { 231 | evthr_dec_backlog(thread); 232 | pthread_mutex_unlock(&thread->rlock); 233 | return EVTHR_RES_RETRY; 234 | } 235 | 236 | pthread_mutex_unlock(&thread->rlock); 237 | 238 | return EVTHR_RES_OK; 239 | } 240 | 241 | evthr_res 242 | evthr_stop(evthr_t * thread) { 243 | evthr_cmd_t cmd; 244 | 245 | /* cmd.magic = _EVTHR_MAGIC; */ 246 | cmd.cb = NULL; 247 | cmd.args = NULL; 248 | cmd.stop = 1; 249 | 250 | pthread_mutex_lock(&thread->rlock); 251 | 252 | if (write(thread->wdr, &cmd, sizeof(evthr_cmd_t)) < 0) { 253 | pthread_mutex_unlock(&thread->rlock); 254 | return EVTHR_RES_RETRY; 255 | } 256 | 257 | pthread_mutex_unlock(&thread->rlock); 258 | 259 | return EVTHR_RES_OK; 260 | } 261 | 262 | evbase_t * 263 | evthr_get_base(evthr_t * thr) { 264 | return thr->evbase; 265 | } 266 | 267 | void 268 | evthr_set_aux(evthr_t * thr, void * aux) { 269 | thr->aux = aux; 270 | } 271 | 272 | void * 273 | evthr_get_aux(evthr_t * thr) { 274 | return thr->aux; 275 | } 276 | 277 | evthr_t * 278 | evthr_new(evthr_init_cb init_cb, void * args) { 279 | evthr_t * thread; 280 | int fds[2]; 281 | 282 | if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) { 283 | return NULL; 284 | } 285 | 286 | evutil_make_socket_nonblocking(fds[0]); 287 | evutil_make_socket_nonblocking(fds[1]); 288 | 289 | if (!(thread = calloc(sizeof(evthr_t), 1))) { 290 | return NULL; 291 | } 292 | 293 | thread->thr = malloc(sizeof(pthread_t)); 294 | thread->init_cb = init_cb; 295 | thread->arg = args; 296 | thread->rdr = fds[0]; 297 | thread->wdr = fds[1]; 298 | 299 | if (pthread_mutex_init(&thread->lock, NULL)) { 300 | evthr_free(thread); 301 | return NULL; 302 | } 303 | 304 | if (pthread_mutex_init(&thread->stat_lock, NULL)) { 305 | evthr_free(thread); 306 | return NULL; 307 | } 308 | 309 | if (pthread_mutex_init(&thread->rlock, NULL)) { 310 | evthr_free(thread); 311 | return NULL; 312 | } 313 | 314 | return thread; 315 | } /* evthr_new */ 316 | 317 | int 318 | evthr_start(evthr_t * thread) { 319 | int res; 320 | 321 | if (thread == NULL || thread->thr == NULL) { 322 | return -1; 323 | } 324 | 325 | pthread_key_create(&thread_key, NULL); 326 | 327 | if (pthread_create(thread->thr, NULL, _evthr_loop, (void *)thread)) { 328 | return -1; 329 | } 330 | 331 | res = pthread_detach(*thread->thr); 332 | 333 | return res; 334 | } 335 | 336 | void 337 | evthr_free(evthr_t * thread) { 338 | if (thread == NULL) { 339 | return; 340 | } 341 | 342 | pthread_key_delete(thread_key); 343 | 344 | if (thread->rdr > 0) { 345 | close(thread->rdr); 346 | } 347 | 348 | if (thread->wdr > 0) { 349 | close(thread->wdr); 350 | } 351 | 352 | if (thread->thr) { 353 | free(thread->thr); 354 | } 355 | 356 | if (thread->event) { 357 | event_free(thread->event); 358 | } 359 | 360 | if (thread->evbase) { 361 | event_base_free(thread->evbase); 362 | } 363 | 364 | free(thread); 365 | } /* evthr_free */ 366 | 367 | void 368 | evthr_pool_free(evthr_pool_t * pool) { 369 | evthr_t * thread; 370 | evthr_t * save; 371 | 372 | if (pool == NULL) { 373 | return; 374 | } 375 | 376 | TAILQ_FOREACH_SAFE(thread, &pool->threads, next, save) { 377 | TAILQ_REMOVE(&pool->threads, thread, next); 378 | 379 | evthr_free(thread); 380 | } 381 | 382 | free(pool); 383 | } 384 | 385 | evthr_res 386 | evthr_pool_stop(evthr_pool_t * pool) { 387 | evthr_t * thr; 388 | evthr_t * save; 389 | 390 | if (pool == NULL) { 391 | return EVTHR_RES_FATAL; 392 | } 393 | 394 | TAILQ_FOREACH_SAFE(thr, &pool->threads, next, save) { 395 | evthr_stop(thr); 396 | } 397 | 398 | return EVTHR_RES_OK; 399 | } 400 | 401 | evthr_res 402 | evthr_pool_defer(evthr_pool_t * pool, evthr_cb cb, void * arg) { 403 | evthr_t * min_thr = NULL; 404 | evthr_t * thr = NULL; 405 | 406 | if (pool == NULL) { 407 | return EVTHR_RES_FATAL; 408 | } 409 | 410 | if (cb == NULL) { 411 | return EVTHR_RES_NOCB; 412 | } 413 | 414 | /* find the thread with the smallest backlog */ 415 | TAILQ_FOREACH(thr, &pool->threads, next) { 416 | int thr_backlog = 0; 417 | int min_backlog = 0; 418 | 419 | thr_backlog = evthr_get_backlog(thr); 420 | 421 | if (min_thr) { 422 | min_backlog = evthr_get_backlog(min_thr); 423 | } 424 | 425 | if (min_thr == NULL) { 426 | min_thr = thr; 427 | } else if (thr_backlog == 0) { 428 | min_thr = thr; 429 | break; 430 | } else if (thr_backlog < min_backlog) { 431 | min_thr = thr; 432 | } 433 | 434 | } 435 | 436 | return evthr_defer(min_thr, cb, arg); 437 | } /* evthr_pool_defer */ 438 | 439 | evthr_pool_t * 440 | evthr_pool_new(int nthreads, evthr_init_cb init_cb, void * shared) { 441 | evthr_pool_t * pool; 442 | int i; 443 | 444 | if (nthreads == 0) { 445 | return NULL; 446 | } 447 | 448 | if (!(pool = calloc(sizeof(evthr_pool_t), 1))) { 449 | return NULL; 450 | } 451 | 452 | pool->nthreads = nthreads; 453 | TAILQ_INIT(&pool->threads); 454 | 455 | for (i = 0; i < nthreads; i++) { 456 | evthr_t * thread; 457 | 458 | if (!(thread = evthr_new(init_cb, shared))) { 459 | evthr_pool_free(pool); 460 | return NULL; 461 | } 462 | 463 | TAILQ_INSERT_TAIL(&pool->threads, thread, next); 464 | } 465 | 466 | return pool; 467 | } 468 | 469 | int 470 | evthr_pool_set_backlog(evthr_pool_t * pool, int num) { 471 | evthr_t * thr; 472 | 473 | TAILQ_FOREACH(thr, &pool->threads, next) { 474 | evthr_set_backlog(thr, num); 475 | } 476 | 477 | return 0; 478 | } 479 | 480 | void 481 | evthr_pool_set_max_backlog(evthr_pool_t * pool, int max) { 482 | evthr_t * thr; 483 | 484 | TAILQ_FOREACH(thr, &pool->threads, next) { 485 | evthr_set_max_backlog(thr, max); 486 | } 487 | } 488 | 489 | int 490 | evthr_pool_start(evthr_pool_t * pool) { 491 | evthr_t * evthr = NULL; 492 | 493 | if (pool == NULL) { 494 | return -1; 495 | } 496 | 497 | TAILQ_FOREACH(evthr, &pool->threads, next) { 498 | if (evthr_start(evthr) < 0) { 499 | return -1; 500 | } 501 | 502 | usleep(5000); 503 | } 504 | 505 | return 0; 506 | } 507 | 508 | -------------------------------------------------------------------------------- /deps/libevhtp/evthr.h: -------------------------------------------------------------------------------- 1 | #ifndef _GNU_SOURCE 2 | #define _GNU_SOURCE 1 3 | #endif 4 | #ifndef __EVTHR_H__ 5 | #define __EVTHR_H__ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | enum evthr_res { 18 | EVTHR_RES_OK = 0, 19 | EVTHR_RES_BACKLOG, 20 | EVTHR_RES_RETRY, 21 | EVTHR_RES_NOCB, 22 | EVTHR_RES_FATAL 23 | }; 24 | 25 | pthread_key_t thread_key; 26 | 27 | struct evthr_pool; 28 | struct evthr; 29 | 30 | typedef struct event_base evbase_t; 31 | typedef struct event ev_t; 32 | 33 | typedef struct evthr_pool evthr_pool_t; 34 | typedef struct evthr evthr_t; 35 | typedef enum evthr_res evthr_res; 36 | 37 | typedef void (*evthr_cb)(evthr_t * thr, void * cmd_arg, void * shared); 38 | typedef void (*evthr_init_cb)(evthr_t * thr, void * shared); 39 | 40 | evthr_t * evthr_new(evthr_init_cb init_cb, void * arg); 41 | evbase_t * evthr_get_base(evthr_t * thr); 42 | void evthr_set_aux(evthr_t * thr, void * aux); 43 | void * evthr_get_aux(evthr_t * thr); 44 | int evthr_start(evthr_t * evthr); 45 | evthr_res evthr_stop(evthr_t * evthr); 46 | evthr_res evthr_defer(evthr_t * evthr, evthr_cb cb, void * arg); 47 | void evthr_free(evthr_t * evthr); 48 | void evthr_inc_backlog(evthr_t * evthr); 49 | void evthr_dec_backlog(evthr_t * evthr); 50 | int evthr_get_backlog(evthr_t * evthr); 51 | void evthr_set_max_backlog(evthr_t * evthr, int max); 52 | int evthr_set_backlog(evthr_t *, int); 53 | 54 | evthr_pool_t * evthr_pool_new(int nthreads, evthr_init_cb init_cb, void * shared); 55 | int evthr_pool_start(evthr_pool_t * pool); 56 | evthr_res evthr_pool_stop(evthr_pool_t * pool); 57 | evthr_res evthr_pool_defer(evthr_pool_t * pool, evthr_cb cb, void * arg); 58 | void evthr_pool_free(evthr_pool_t * pool); 59 | void evthr_pool_set_max_backlog(evthr_pool_t * evthr, int max); 60 | int evthr_pool_set_backlog(evthr_pool_t *, int); 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif /* __EVTHR_H__ */ 67 | 68 | -------------------------------------------------------------------------------- /deps/libevhtp/htparse.h: -------------------------------------------------------------------------------- 1 | #ifndef __HTPARSE_H__ 2 | #define __HTPARSE_H__ 3 | 4 | struct htparser; 5 | 6 | enum htp_type { 7 | htp_type_request = 0, 8 | htp_type_response 9 | }; 10 | 11 | enum htp_scheme { 12 | htp_scheme_none = 0, 13 | htp_scheme_ftp, 14 | htp_scheme_http, 15 | htp_scheme_https, 16 | htp_scheme_nfs, 17 | htp_scheme_unknown 18 | }; 19 | 20 | enum htp_method { 21 | htp_method_GET = 0, 22 | htp_method_HEAD, 23 | htp_method_POST, 24 | htp_method_PUT, 25 | htp_method_DELETE, 26 | htp_method_MKCOL, 27 | htp_method_COPY, 28 | htp_method_MOVE, 29 | htp_method_OPTIONS, 30 | htp_method_PROPFIND, 31 | htp_method_PROPPATCH, 32 | htp_method_LOCK, 33 | htp_method_UNLOCK, 34 | htp_method_TRACE, 35 | htp_method_CONNECT, /* RFC 2616 */ 36 | htp_method_PATCH, /* RFC 5789 */ 37 | htp_method_UNKNOWN, 38 | }; 39 | 40 | enum htpparse_error { 41 | htparse_error_none = 0, 42 | htparse_error_too_big, 43 | htparse_error_inval_method, 44 | htparse_error_inval_reqline, 45 | htparse_error_inval_schema, 46 | htparse_error_inval_proto, 47 | htparse_error_inval_ver, 48 | htparse_error_inval_hdr, 49 | htparse_error_inval_chunk_sz, 50 | htparse_error_inval_chunk, 51 | htparse_error_inval_state, 52 | htparse_error_user, 53 | htparse_error_status, 54 | htparse_error_generic 55 | }; 56 | 57 | typedef struct htparser htparser; 58 | typedef struct htparse_hooks htparse_hooks; 59 | 60 | typedef enum htp_scheme htp_scheme; 61 | typedef enum htp_method htp_method; 62 | typedef enum htp_type htp_type; 63 | typedef enum htpparse_error htpparse_error; 64 | 65 | typedef int (*htparse_hook)(htparser *); 66 | typedef int (*htparse_data_hook)(htparser *, const char *, size_t); 67 | 68 | 69 | struct htparse_hooks { 70 | htparse_hook on_msg_begin; 71 | htparse_data_hook method; 72 | htparse_data_hook scheme; /* called if scheme is found */ 73 | htparse_data_hook host; /* called if a host was in the request scheme */ 74 | htparse_data_hook port; /* called if a port was in the request scheme */ 75 | htparse_data_hook path; /* only the path of the uri */ 76 | htparse_data_hook args; /* only the arguments of the uri */ 77 | htparse_data_hook uri; /* the entire uri including path/args */ 78 | htparse_hook on_hdrs_begin; 79 | htparse_data_hook hdr_key; 80 | htparse_data_hook hdr_val; 81 | htparse_data_hook hostname; 82 | htparse_hook on_hdrs_complete; 83 | htparse_hook on_new_chunk; /* called after parsed chunk octet */ 84 | htparse_hook on_chunk_complete; /* called after single parsed chunk */ 85 | htparse_hook on_chunks_complete; /* called after all parsed chunks processed */ 86 | htparse_data_hook body; 87 | htparse_hook on_msg_complete; 88 | }; 89 | 90 | 91 | size_t htparser_run(htparser *, htparse_hooks *, const char *, size_t); 92 | int htparser_should_keep_alive(htparser * p); 93 | htp_scheme htparser_get_scheme(htparser *); 94 | htp_method htparser_get_method(htparser *); 95 | const char * htparser_get_methodstr(htparser *); 96 | const char * htparser_get_methodstr_m(htp_method); 97 | void htparser_set_major(htparser *, unsigned char); 98 | void htparser_set_minor(htparser *, unsigned char); 99 | unsigned char htparser_get_major(htparser *); 100 | unsigned char htparser_get_minor(htparser *); 101 | unsigned char htparser_get_multipart(htparser *); 102 | unsigned int htparser_get_status(htparser *); 103 | uint64_t htparser_get_content_length(htparser *); 104 | uint64_t htparser_get_content_pending(htparser *); 105 | uint64_t htparser_get_total_bytes_read(htparser *); 106 | htpparse_error htparser_get_error(htparser *); 107 | const char * htparser_get_strerror(htparser *); 108 | void * htparser_get_userdata(htparser *); 109 | void htparser_set_userdata(htparser *, void *); 110 | void htparser_init(htparser *, htp_type); 111 | htparser * htparser_new(void); 112 | 113 | #endif 114 | 115 | -------------------------------------------------------------------------------- /deps/libjpeg-turbo-1.5.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buaazp/zimg/5cd73c5d603f54f47f11a64e23553a4390ed6d39/deps/libjpeg-turbo-1.5.1.tar.gz -------------------------------------------------------------------------------- /deps/libwebp-0.6.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buaazp/zimg/5cd73c5d603f54f47f11a64e23553a4390ed6d39/deps/libwebp-0.6.0.tar.gz -------------------------------------------------------------------------------- /deps/multipart-parser-c/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012 Igor Afonov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /deps/multipart-parser-c/multipart_parser.c: -------------------------------------------------------------------------------- 1 | /* Based on node-formidable by Felix Geisendörfer 2 | * Igor Afonov - afonov@gmail.com - 2012 3 | * MIT License - http://www.opensource.org/licenses/mit-license.php 4 | */ 5 | 6 | #include "multipart_parser.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include "zcommon.h" 12 | 13 | /* 14 | static void multipart_log(const char * format, ...) 15 | { 16 | va_list args; 17 | va_start(args, format); 18 | 19 | vfprintf(stderr, format, args); 20 | fprintf(stderr, "\n"); 21 | } 22 | */ 23 | 24 | #define NOTIFY_CB(FOR) \ 25 | do { \ 26 | if (p->settings->on_##FOR) { \ 27 | if (p->settings->on_##FOR(p) != 0) { \ 28 | return i; \ 29 | } \ 30 | } \ 31 | } while (0) 32 | 33 | #define EMIT_DATA_CB(FOR, ptr, len) \ 34 | do { \ 35 | if (p->settings->on_##FOR) { \ 36 | if (p->settings->on_##FOR(p, ptr, len) != 0) { \ 37 | return i; \ 38 | } \ 39 | } \ 40 | } while (0) 41 | 42 | 43 | #define LF 10 44 | #define CR 13 45 | 46 | struct multipart_parser { 47 | void * data; 48 | 49 | size_t index; 50 | size_t boundary_length; 51 | 52 | unsigned char state; 53 | 54 | const multipart_parser_settings* settings; 55 | 56 | char* lookbehind; 57 | char multipart_boundary[1]; 58 | }; 59 | 60 | enum state { 61 | s_uninitialized = 1, 62 | s_start, 63 | s_start_boundary, 64 | s_header_field_start, 65 | s_header_field, 66 | s_headers_almost_done, 67 | s_header_value_start, 68 | s_header_value, 69 | s_header_value_almost_done, 70 | s_part_data_start, 71 | s_part_data, 72 | s_part_data_almost_boundary, 73 | s_part_data_boundary, 74 | s_part_data_almost_end, 75 | s_part_data_end, 76 | s_part_data_final_hyphen, 77 | s_end 78 | }; 79 | 80 | multipart_parser* multipart_parser_init(const char *boundary) { 81 | 82 | multipart_parser* p = malloc(sizeof(multipart_parser) + 83 | strlen(boundary) + 84 | strlen(boundary) + 9); 85 | 86 | strcpy(p->multipart_boundary, boundary); 87 | p->boundary_length = strlen(boundary); 88 | 89 | p->lookbehind = (p->multipart_boundary + p->boundary_length + 1); 90 | 91 | p->index = 0; 92 | p->state = s_start; 93 | p->settings = settings.mp_set; 94 | 95 | return p; 96 | } 97 | 98 | void multipart_parser_free(multipart_parser* p) { 99 | free(p); 100 | } 101 | 102 | void multipart_parser_set_data(multipart_parser *p, void *data) { 103 | p->data = data; 104 | } 105 | 106 | void *multipart_parser_get_data(multipart_parser *p) { 107 | return p->data; 108 | } 109 | 110 | size_t multipart_parser_execute(multipart_parser* p, const char *buf, size_t len) { 111 | size_t i = 0; 112 | size_t mark = 0; 113 | size_t dmark = 0, dbmark = 0; 114 | char c, cl; 115 | int is_last = 0; 116 | 117 | while(i < len) { 118 | c = buf[i]; 119 | is_last = (i == (len - 1)); 120 | switch (p->state) { 121 | case s_start: 122 | p->index = 0; 123 | p->state = s_start_boundary; 124 | 125 | /* fallthrough */ 126 | case s_start_boundary: 127 | if (p->index == p->boundary_length) { 128 | if (c != CR) { 129 | return i; 130 | } 131 | p->index++; 132 | break; 133 | } else if (p->index == (p->boundary_length + 1)) { 134 | if (c != LF) { 135 | return i; 136 | } 137 | p->index = 0; 138 | NOTIFY_CB(part_data_begin); 139 | p->state = s_header_field_start; 140 | break; 141 | } 142 | if (c != p->multipart_boundary[p->index]) { 143 | return i; 144 | } 145 | p->index++; 146 | break; 147 | 148 | case s_header_field_start: 149 | mark = i; 150 | p->state = s_header_field; 151 | 152 | /* fallthrough */ 153 | case s_header_field: 154 | if (c == CR) { 155 | p->state = s_headers_almost_done; 156 | break; 157 | } 158 | 159 | if (c == '-') { 160 | break; 161 | } 162 | 163 | if (c == ':') { 164 | EMIT_DATA_CB(header_field, buf + mark, i - mark); 165 | p->state = s_header_value_start; 166 | break; 167 | } 168 | 169 | cl = tolower(c); 170 | if (cl < 'a' || cl > 'z') { 171 | return i; 172 | } 173 | if (is_last) 174 | EMIT_DATA_CB(header_field, buf + mark, (i - mark) + 1); 175 | break; 176 | 177 | case s_headers_almost_done: 178 | if (c != LF) { 179 | return i; 180 | } 181 | 182 | p->state = s_part_data_start; 183 | break; 184 | 185 | case s_header_value_start: 186 | if (c == ' ') { 187 | break; 188 | } 189 | 190 | mark = i; 191 | p->state = s_header_value; 192 | 193 | /* fallthrough */ 194 | case s_header_value: 195 | if (c == CR) { 196 | EMIT_DATA_CB(header_value, buf + mark, i - mark); 197 | p->state = s_header_value_almost_done; 198 | } 199 | if (is_last) 200 | EMIT_DATA_CB(header_value, buf + mark, (i - mark) + 1); 201 | break; 202 | 203 | case s_header_value_almost_done: 204 | if (c != LF) { 205 | return i; 206 | } 207 | p->state = s_header_field_start; 208 | break; 209 | 210 | case s_part_data_start: 211 | NOTIFY_CB(headers_complete); 212 | mark = i; 213 | dmark = i; 214 | //multipart_log("s_part_data_start @ %d", dmark); 215 | p->state = s_part_data; 216 | 217 | /* fallthrough */ 218 | case s_part_data: 219 | if (c == CR) { 220 | mark = i; 221 | dbmark = i; 222 | p->state = s_part_data_almost_boundary; 223 | p->lookbehind[0] = CR; 224 | break; 225 | } 226 | break; 227 | 228 | case s_part_data_almost_boundary: 229 | if (c == LF) { 230 | p->state = s_part_data_boundary; 231 | p->lookbehind[1] = LF; 232 | p->index = 0; 233 | break; 234 | } 235 | p->state = s_part_data; 236 | mark = i --; 237 | break; 238 | 239 | case s_part_data_boundary: 240 | if (p->multipart_boundary[p->index] != c) { 241 | p->state = s_part_data; 242 | mark = i --; 243 | break; 244 | } 245 | p->lookbehind[2 + p->index] = c; 246 | if ((++ p->index) == p->boundary_length) { 247 | NOTIFY_CB(part_data_end); 248 | p->state = s_part_data_almost_end; 249 | } 250 | break; 251 | 252 | case s_part_data_almost_end: 253 | if (c == '-') { 254 | p->state = s_part_data_final_hyphen; 255 | break; 256 | } 257 | if (c == CR) { 258 | p->state = s_part_data_end; 259 | break; 260 | } 261 | return i; 262 | 263 | case s_part_data_final_hyphen: 264 | //multipart_log("s_part_data_final_hyphen %d~%d", dmark, dbmark); 265 | EMIT_DATA_CB(chunk_data, buf + dmark, dbmark - dmark); 266 | if (c == '-') { 267 | NOTIFY_CB(body_end); 268 | p->state = s_end; 269 | break; 270 | } 271 | return i; 272 | 273 | case s_part_data_end: 274 | if (c == LF) { 275 | //multipart_log("s_part_data_end %d~%d", dmark, dbmark); 276 | EMIT_DATA_CB(chunk_data, buf + dmark, dbmark - dmark); 277 | p->state = s_header_field_start; 278 | NOTIFY_CB(part_data_begin); 279 | break; 280 | } 281 | return i; 282 | 283 | case s_end: 284 | break; 285 | 286 | default: 287 | return 0; 288 | } 289 | ++ i; 290 | } 291 | 292 | return len; 293 | } 294 | -------------------------------------------------------------------------------- /deps/multipart-parser-c/multipart_parser.h: -------------------------------------------------------------------------------- 1 | /* Based on node-formidable by Felix Geisendörfer 2 | * Igor Afonov - afonov@gmail.com - 2012 3 | * MIT License - http://www.opensource.org/licenses/mit-license.php 4 | */ 5 | #ifndef _multipart_parser_h 6 | #define _multipart_parser_h 7 | 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | 13 | #include 14 | #include 15 | 16 | typedef struct multipart_parser multipart_parser; 17 | typedef struct multipart_parser_settings multipart_parser_settings; 18 | typedef struct multipart_parser_state multipart_parser_state; 19 | 20 | typedef int (*multipart_data_cb) (multipart_parser*, const char *at, size_t length); 21 | typedef int (*multipart_notify_cb) (multipart_parser*); 22 | 23 | struct multipart_parser_settings { 24 | multipart_data_cb on_header_field; 25 | multipart_data_cb on_header_value; 26 | multipart_data_cb on_part_data; 27 | multipart_data_cb on_chunk_data; 28 | 29 | multipart_notify_cb on_part_data_begin; 30 | multipart_notify_cb on_headers_complete; 31 | multipart_notify_cb on_part_data_end; 32 | multipart_notify_cb on_body_end; 33 | }; 34 | 35 | multipart_parser* multipart_parser_init(const char *boundary); 36 | 37 | void multipart_parser_free(multipart_parser* p); 38 | 39 | size_t multipart_parser_execute(multipart_parser* p, const char *buf, size_t len); 40 | 41 | void multipart_parser_set_data(multipart_parser* p, void* data); 42 | void * multipart_parser_get_data(multipart_parser* p); 43 | 44 | #ifdef __cplusplus 45 | } /* extern "C" */ 46 | #endif 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | ### Documents 2 | 3 | All the documents of zimg are in this page: 4 | [Documents of zimg](http://zimg.buaa.us/documents/) -------------------------------------------------------------------------------- /doc/misc/DoxygenLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /doc/misc/doxygenextra.css: -------------------------------------------------------------------------------- 1 | body code { 2 | margin: 0; 3 | border: 1px solid #ddd; 4 | background-color: #f8f8f8; 5 | border-radius: 3px; 6 | padding: 0; 7 | } 8 | 9 | a { 10 | color: #4183c4; 11 | } 12 | 13 | a.el { 14 | font-weight: normal; 15 | } 16 | 17 | body, table, div, p, dl { 18 | color: #333333; 19 | font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; 20 | font-size: 15px; 21 | font-style: normal; 22 | font-variant: normal; 23 | font-weight: normal; 24 | line-height: 25.5px; 25 | } 26 | 27 | body { 28 | background-color: #eee; 29 | } 30 | 31 | div.header { 32 | background-image: none; 33 | background-color: white; 34 | margin: 0px; 35 | border: 0px; 36 | } 37 | 38 | div.headertitle { 39 | width: 858px; 40 | margin: 30px; 41 | padding: 0px; 42 | } 43 | 44 | div.toc { 45 | background-color: #f8f8f8; 46 | border-color: #ddd; 47 | margin-right: 10px; 48 | margin-left: 20px; 49 | } 50 | div.toc h3 { 51 | color: #333333; 52 | font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; 53 | font-size: 18px; 54 | font-style: normal; 55 | font-variant: normal; 56 | font-weight: normal; 57 | } 58 | div.toc li { 59 | color: #333333; 60 | font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; 61 | font-size: 12px; 62 | font-style: normal; 63 | font-variant: normal; 64 | font-weight: normal; 65 | } 66 | 67 | .title { 68 | font-size: 2.5em; 69 | line-height: 63.75px; 70 | border-bottom: 1px solid #ddd; 71 | margin-bottom: 15px; 72 | margin-left: 0px; 73 | margin-right: 0px; 74 | margin-top: 0px; 75 | } 76 | 77 | body h1 { 78 | font-size: 2em; 79 | line-height: 1.7; 80 | border-bottom: 1px solid #eee; 81 | margin: 1em 0 15px; 82 | padding: 0; 83 | overflow: hidden; 84 | } 85 | 86 | body h2 { 87 | font-size: 1.5em; 88 | line-height: 1.7; 89 | margin: 1em 0 15px; 90 | padding: 0; 91 | } 92 | 93 | pre.fragment { 94 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; 95 | font-size: 13px; 96 | font-style: normal; 97 | font-variant: normal; 98 | font-weight: normal; 99 | line-height: 19px; 100 | } 101 | 102 | table.doxtable th { 103 | background-color: #f8f8f8; 104 | color: #333333; 105 | font-size: 15px; 106 | } 107 | 108 | table.doxtable td, table.doxtable th { 109 | border: 1px solid #ddd; 110 | } 111 | 112 | #doc-content { 113 | background-color: #fff; 114 | width: 918px; 115 | height: auto !important; 116 | } 117 | 118 | div.contents { 119 | width: 858px; 120 | margin: 30px; 121 | } 122 | 123 | div.line { 124 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; 125 | font-size: 13px; 126 | font-style: normal; 127 | font-variant: normal; 128 | font-weight: normal; 129 | line-height: 19px; 130 | } 131 | 132 | tt, code, pre { 133 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; 134 | font-size: 12px; 135 | } 136 | 137 | div.fragment { 138 | background-color: #f8f8f8; 139 | border: 1px solid #ddd; 140 | font-size: 13px; 141 | line-height: 19px; 142 | overflow: auto; 143 | padding: 6px 10px; 144 | border-radius: 3px; 145 | } 146 | 147 | #topbanner { 148 | position: fixed; 149 | margin: 15px; 150 | z-index: 101; 151 | } 152 | 153 | #projectname 154 | { 155 | font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; 156 | font-size: 38px; 157 | font-weight: bold; 158 | line-height: 63.75px; 159 | margin: 0px; 160 | padding: 2px 0px; 161 | } 162 | 163 | #projectbrief 164 | { 165 | font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; 166 | font-size: 16px; 167 | line-height: 22.4px; 168 | margin: 0px 0px 13px 0px; 169 | padding: 2px; 170 | } 171 | 172 | /* side bar and search */ 173 | 174 | #side-nav 175 | { 176 | padding: 10px 0px 20px 20px; 177 | border-top: 60px solid #2980b9; 178 | background-color: #343131; 179 | width: 250px !important; 180 | position: fixed 181 | } 182 | 183 | #nav-tree 184 | { 185 | background-color: transparent; 186 | background-image: none; 187 | height: 100% !important; 188 | } 189 | 190 | #nav-tree .label 191 | { 192 | font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; 193 | line-height: 25.5px; 194 | font-size: 15px; 195 | } 196 | 197 | #nav-tree 198 | { 199 | color: #b3b3b3; 200 | } 201 | 202 | #nav-tree .selected { 203 | background-image: none; 204 | } 205 | 206 | #nav-tree a 207 | { 208 | color: #b3b3b3; 209 | } 210 | 211 | #github 212 | { 213 | position: fixed; 214 | left: auto; 215 | right: auto; 216 | width: 250px; 217 | } 218 | 219 | #MSearchBox 220 | { 221 | margin: 20px; 222 | left: 40px; 223 | right: auto; 224 | position: fixed; 225 | width: 180px; 226 | } 227 | 228 | #MSearchField 229 | { 230 | width: 121px; 231 | } 232 | 233 | #MSearchResultsWindow 234 | { 235 | left: 45px !important; 236 | } 237 | 238 | #nav-sync 239 | { 240 | display: none; 241 | } 242 | 243 | .ui-resizable .ui-resizable-handle 244 | { 245 | width: 0px; 246 | } 247 | 248 | #nav-path 249 | { 250 | display: none; 251 | } 252 | 253 | /* external link icon */ 254 | div.contents a[href ^= "http"]:after { 255 | content: " " url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=); 256 | } 257 | 258 | .githublogo { 259 | content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RERCMUIwOUY4NkNFMTFFM0FBNTJFRTMzNTJEMUJDNDYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RERCMUIwOUU4NkNFMTFFM0FBNTJFRTMzNTJEMUJDNDYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU1MTc4QTJBOTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU1MTc4QTJCOTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+jUqS1wAAApVJREFUeNq0l89rE1EQx3e3gVJoSPzZeNEWPKgHoa0HBak0iHiy/4C3WvDmoZ56qJ7txVsPQu8qlqqHIhRKJZceesmhioQEfxTEtsoSpdJg1u/ABJ7Pmc1m8zLwgWTmzcw3L+/te+tHUeQltONgCkyCi2AEDHLsJ6iBMlgHL8FeoqokoA2j4CloRMmtwTmj7erHBXPgCWhG6a3JNXKdCiDl1cidVbXZkJoXQRi5t5BrxwoY71FzU8S4JuAIqFkJ2+BFSlEh525b/hr3+k/AklDkNsf6wTT4yv46KIMNpsy+iMdMc47HNWxbsgVcUn7FmLAzzoFAWDsBx+wVP6bUpp5ewI+DOeUx0Wd9D8F70BTGNjkWtqnhmT1JQAHcUgZd8Lo3rQb1LAT8eJVUfgGvHQigGp+V2Z0iAUUl8QH47kAA1XioxIo+bRN8OG8F/oBjwv+Z1nJgX5jpdzQDw0LCjsPmrcW7I/iHScCAEDj03FtD8A0EyuChHgg4KTlJQF3wZ7WELppnBX+dBFSVpJsOBWi1qiRgSwnOgoyD5hmuJdkWCVhTgnTvW3AgYIFrSbZGh0UW/Io5Vp+DQoK7o80pztWMemZbgxeNwCNwDbw1fIfgGZjhU6xPaJgBV8BdsMw5cbZoHsenwYFxkZzl83xTSKTiviCAfCsJLysH3POfC8m8NegyGAGfLP/VmGmfSChgXroR0RSWjEFv2J/nG84cuKFMf4sTCZqXuJd4KaXFVjEG3+tw4eXbNK/YC9oXXs3O8NY8y99L4BXY5cvLY/Bb2VZ58EOJVcB18DHJq9lRsKr8inyKGVjlmh29mtHs3AHfuhCwy1vXT/Nu2GKQt+UHsGdctyX6eQyNvc+5sfX9Dl7Pe2J/BRgAl2CpwmrsHR0AAAAASUVORK5CYII=); 260 | } -------------------------------------------------------------------------------- /doc/misc/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /doc/misc/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $projectname: $title 9 | $title 10 | 11 | 12 | 13 | $treeview 14 | $search 15 | $mathjax 16 | 17 | $extrastylesheet 18 | 19 | 20 |
21 |
22 | $searchbox 23 | 24 | 25 | -------------------------------------------------------------------------------- /specs/control: -------------------------------------------------------------------------------- 1 | Package: zimg 2 | Version: 3.1.0-stable-1ubuntu1 3 | Architecture: amd64 4 | Maintainer: Peter Zhao 5 | Installed-Size: 764 6 | Depends: openssl, libevent-dev (>=2.0.20), libjpeg-dev, libgif-dev, libpng-dev, libwebp-dev, libmagickcore5, libmagickwand5, libmemcached-dev (>=1.0.8) 7 | Section: utils 8 | Priority: optional 9 | Homepage: http://zimg.buaa.us 10 | Description: image storage and processing system 11 | zimg - A lightweight and high performance image storage and processing system. 12 | -------------------------------------------------------------------------------- /specs/md5sums: -------------------------------------------------------------------------------- 1 | 816ea05051da3c8e08d53889f8bddaae usr/local/zimg/conf/zimg.lua 2 | 18a1984c77e66772715bc837e07ab069 usr/local/zimg/conf/twemproxy.yml 3 | 684bc197f1b0d8500f369ccda7cefbf4 usr/local/zimg/zimg 4 | f7d2c7759de804c43b9dc3c63ea8a1f4 usr/local/zimg/script/test.lua 5 | 5cc139d0b673c67e9bc2311ae1b5688b usr/local/zimg/script/process.lua 6 | 5c8a3cc79664f2b73b638c8cade53069 usr/local/zimg/www/index.html 7 | b9e634ca70e1e2b6defc361dd2526214 usr/local/zimg/www/admin.html 8 | -------------------------------------------------------------------------------- /specs/zimg.spec: -------------------------------------------------------------------------------- 1 | Name: zimg 2 | Version: 3.1.0 3 | Release: Release 4 | Summary: zimg - A lightweight and high performance image storage and processing system. 5 | Group: System Environment/Deamons 6 | License: BSDv3 7 | Url: http://zimg.buaa.us 8 | Packager: zp@buaa.us 9 | Source: %{name}-%{version}.tar.gz 10 | BuildRoot:%{_tmppath}/%{name}-%{version}-%{release}-root 11 | Requires: openssl-devel,libevent-devel >= 2.0.20,libjpeg-devel,giflib-devel,libpng-devel,libwebp-devel,ImageMagick-devel,libmemcached-devel >= 1.0.8 12 | Prefix: %{_prefix} 13 | Prefix: %{_sysconfdir} 14 | %define zimgpath /usr/local/zimg 15 | 16 | %description 17 | Project zimg's rpm suite. 18 | 19 | %prep 20 | %setup -c 21 | 22 | %install 23 | install -d $RPM_BUILD_ROOT%{zimgpath} 24 | cp -a %{name}-%{version}/* $RPM_BUILD_ROOT%{zimgpath} 25 | chmod -R 777 $RPM_BUILD_ROOT%{zimgpath} 26 | 27 | %postun 28 | rm -rf $RPM_BUILD_ROOT%{zimgpath} 29 | 30 | %clean 31 | rm -rf $RPM_BUILD_ROOT 32 | rm -rf $RPM_BUILD_DIR/%{name}-%{version} 33 | 34 | %files 35 | %defattr(-,root,root) 36 | %{zimgpath} 37 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(zimg) 3 | 4 | set (PROJECT_MAJOR_VERSION 3) 5 | set (PROJECT_MINOR_VERSION 2) 6 | set (PROJECT_PATCH_VERSION 0) 7 | 8 | set (PROJECT_VERSION ${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION}) 9 | set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules) 10 | 11 | set (CMAKE_INCLUDE_CURRENT_DIR ON) 12 | 13 | INCLUDE (CheckFunctionExists) 14 | INCLUDE (CheckIncludeFiles) 15 | INCLUDE (CheckTypeSize) 16 | 17 | # -DEVHTP_DISABLE_SSL:STRING=ON 18 | OPTION(EVHTP_DISABLE_SSL "Disable ssl support" OFF) 19 | 20 | # -DEVHTP_DISABLE_EVTHR:STRING=ON 21 | OPTION(EVHTP_DISABLE_EVTHR "Disable evthread support" OFF) 22 | 23 | # -DEVHTP_DISABLE_REGEX:STRING=ON 24 | OPTION(EVHTP_DISABLE_REGEX "Disable regex support" OFF) 25 | 26 | # -DEVHTP_USE_DEFER_ACCEPT:STRING=ON 27 | OPTION(EVHTP_USE_DEFER_ACCEPT "Enable TCP_DEFER_ACCEPT" OFF) 28 | 29 | if (EVHTP_USE_DEFER_ACCEPT) 30 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_DEFER_ACCEPT") 31 | set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DUSE_DEFER_ACCEPT") 32 | set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DUSE_DEFER_ACCEPT") 33 | endif(EVHTP_USE_DEFER_ACCEPT) 34 | 35 | include(BaseConfig) 36 | 37 | find_package(LibEvent REQUIRED) 38 | if (NOT LIBEVENT_OPENSSL_LIBRARY) 39 | set (EVHTP_DISABLE_SSL ON) 40 | endif() 41 | if (NOT EVHTP_DISABLE_SSL) 42 | find_package (OpenSSL) 43 | endif() 44 | find_path(LIBEVENT_INCLUDE_DIR event2/event.h REQUIRED) 45 | 46 | if (NOT EVHTP_DISABLE_REGEX) 47 | find_library (HAS_SYS_ONIG onig) 48 | if (NOT HAS_SYS_ONIG) 49 | set (ONIG_SOURCES "") 50 | set (ONIG_LIBS "") 51 | set (ONIG_INCLUDE_DIR "") 52 | set (EVHTP_DISABLE_REGEX ON) 53 | else() 54 | message("-- Using system libonig") 55 | set (ONIG_SOURCES "") 56 | set (ONIG_LIBS ${HAS_SYS_ONIG}) 57 | set (ONIG_INCLUDE_DIR "") 58 | endif (NOT HAS_SYS_ONIG) 59 | else() 60 | set (ONIG_SOURCES "") 61 | set (ONIG_LIBS "") 62 | set (ONIG_INCLUDE_DIR "") 63 | endif() 64 | 65 | if (NOT OPENSSL_FOUND) 66 | message ("Diabling SSL") 67 | set (EVHTP_DISABLE_SSL ON) 68 | set (OPENSSL_CRYPTO_LIBRARY "") 69 | set (OPENSSL_INCLUDE_DIR "") 70 | set (OPENSSL_LIBRARIES "") 71 | set (LIBEVENT_OPENSSL_LIBRARY "") 72 | endif() 73 | 74 | find_package (LibMemcached REQUIRED) 75 | find_package (PNG REQUIRED) 76 | set (DEPS_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../deps") 77 | 78 | if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 79 | find_package (JPEG REQUIRED) 80 | find_package (WebP REQUIRED) 81 | find_package (ImageMagick COMPONENTS MagickCore REQUIRED) 82 | find_package (ImageMagick COMPONENTS MagickWand REQUIRED) 83 | else() 84 | set (JPEG_INCLUDE_DIRS ${DEPS_SOURCE_DIR}/libjpeg-turbo) 85 | set (JPEG_LIBRARIES ${DEPS_SOURCE_DIR}/libjpeg-turbo/.libs/libjpeg.a) 86 | set (WEBP_INCLUDE_DIRS ${DEPS_SOURCE_DIR}/libwebp/src) 87 | set (WEBP_LIBRARIES ${DEPS_SOURCE_DIR}/libwebp/src/.libs/libwebp.a) 88 | set (ImageMagick_INCLUDE_DIRS ${DEPS_SOURCE_DIR}/ImageMagick) 89 | set (ImageMagick_MagickCore_LIBRARY ${DEPS_SOURCE_DIR}/ImageMagick/wand/.libs/libMagickWand-6.Q8.a) 90 | set (ImageMagick_MagickWand_LIBRARY ${DEPS_SOURCE_DIR}/ImageMagick/magick/.libs/libMagickCore-6.Q8.a) 91 | endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 92 | 93 | set (LUAJIT_INCLUDE_DIR ${DEPS_SOURCE_DIR}/LuaJIT/src) 94 | set (LUAJIT_LIBRARIES ${DEPS_SOURCE_DIR}/LuaJIT/src/libluajit.a) 95 | 96 | include_directories( 97 | ${OPENSSL_INCLUDE_DIR} 98 | ${LIBEVENT_INCLUDE_DIR} 99 | ${LIBMEMCACHED_INCLUDE_DIRS} 100 | ${LUAJIT_INCLUDE_DIR} 101 | ${JPEG_INCLUDE_DIRS} 102 | ${PNG_INCLUDE_DIRS} 103 | ${WEBP_INCLUDE_DIRS} 104 | ${ImageMagick_INCLUDE_DIRS} 105 | ) 106 | 107 | set (ZIMG_EXTERNAL_LIBS 108 | ${OPENSSL_LIBRARIES} 109 | ${LIBEVENT_LIBRARY} 110 | ${LIBEVENT_PTHREADS_LIBRARY} 111 | ${LIBEVENT_OPENSSL_LIBRARY} 112 | ${LUAJIT_LIBRARIES} 113 | ${LIBMEMCACHED_LIBRARIES} 114 | ${ImageMagick_MagickCore_LIBRARY} 115 | ${ImageMagick_MagickWand_LIBRARY} 116 | ${WEBP_LIBRARIES} 117 | ${PNG_LIBRARIES} 118 | ${JPEG_LIBRARIES} 119 | "m" 120 | "z" 121 | "dl" 122 | ) 123 | 124 | if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 125 | set (ZIMG_EXTERNAL_LIBS ${ZIMG_EXTERNAL_LIBS} readline) 126 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Qunused-arguments -Wall -DPROJECT_VERSION=${PROJECT_VERSION} -pagezero_size 10000 -image_base 100000000") 127 | endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 128 | 129 | if (NOT ${LIBEVENT_PTHREADS_FOUND}) 130 | set (EVHTP_DISABLE_EVTHR ON) 131 | endif(NOT ${LIBEVENT_PTHREADS_FOUND}) 132 | 133 | if (NOT EVHTP_DISABLE_EVTHR) 134 | set (ZIMG_EXTERNAL_LIBS ${ZIMG_EXTERNAL_LIBS} pthread) 135 | set (LIBEVHTP_SOURCES ${LIBEVHTP_SOURCES} ${DEPS_SOURCE_DIR}/libevhtp/evthr.c) 136 | endif(NOT EVHTP_DISABLE_EVTHR) 137 | 138 | set (LIBEVHTP_SOURCES ${LIBEVHTP_SOURCES} ${DEPS_SOURCE_DIR}/libevhtp/evhtp.c ${DEPS_SOURCE_DIR}/libevhtp/htparse.c) 139 | aux_source_directory (${PROJECT_SOURCE_DIR} ZIMG_SOURCES) 140 | aux_source_directory (${DEPS_SOURCE_DIR}/hiredis LIBHIREDIS_SOURCE_DIR) 141 | aux_source_directory (${DEPS_SOURCE_DIR}/cjson LIBCJSON_SOURCE_DIR) 142 | aux_source_directory (${DEPS_SOURCE_DIR}/multipart-parser-c MULTIPART_SOURCE_DIR) 143 | set (SOURCES ${ZIMG_SOURCES} ${LIBEVHTP_SOURCES} ${LIBHIREDIS_SOURCE_DIR} ${LIBCJSON_SOURCE_DIR} ${MULTIPART_SOURCE_DIR}) 144 | 145 | if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") 146 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -DDEBUG") 147 | endif (${CMAKE_BUILD_TYPE} STREQUAL "Debug") 148 | 149 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wno-unused-function -Wno-deprecated -DMAGICKCORE_HDRI_ENABLE -DMAGICKCORE_QUANTUM_DEPTH=8") 150 | message("Build Type: ${CMAKE_BUILD_TYPE}") 151 | message("Std CFLAGS: ${CMAKE_C_FLAGS}") 152 | 153 | include_directories(${DEPS_SOURCE_DIR}) 154 | link_directories("/usr/lib" "/usr/local/lib") 155 | add_executable(zimg ${SOURCES}) 156 | target_link_libraries(zimg ${ZIMG_EXTERNAL_LIBS}) 157 | -------------------------------------------------------------------------------- /src/CMakeModules/BaseConfig.cmake: -------------------------------------------------------------------------------- 1 | if (CMAKE_COMPILER_IS_GNUCC) 2 | 3 | set(RSN_BASE_C_FLAGS "-Wall -fno-strict-aliasing") 4 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${RSN_BASE_C_FLAGS} -DPROJECT_VERSION=\"${PROJECT_VERSION}\"") 5 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${RSN_BASE_C_FLAGS} -ggdb") 6 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${RSN_BASE_C_FLAGS}") 7 | 8 | if(APPLE) 9 | # Newer versions of OSX will spew a bunch of warnings about deprecated ssl functions, 10 | # this should be addressed at some point in time, but for now, just ignore them. 11 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_BSD_SOURCE -Wno-deprecated-declarations") 12 | elseif(UNIX) 13 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112") 14 | endif(APPLE) 15 | 16 | endif(CMAKE_COMPILER_IS_GNUCC) 17 | 18 | if (EVHTP_DISABLE_EVTHR) 19 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DEVHTP_DISABLE_EVTHR") 20 | endif(EVHTP_DISABLE_EVTHR) 21 | 22 | if (EVHTP_DISABLE_SSL) 23 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DEVHTP_DISABLE_SSL") 24 | endif(EVHTP_DISABLE_SSL) 25 | 26 | if (NOT CMAKE_BUILD_TYPE) 27 | set(CMAKE_BUILD_TYPE Release) 28 | endif(NOT CMAKE_BUILD_TYPE) 29 | 30 | -------------------------------------------------------------------------------- /src/CMakeModules/FindGraphicsMagick.cmake: -------------------------------------------------------------------------------- 1 | #-*-cmake-*- 2 | # 3 | # Test for GraphicsMagick libraries, unlike CMake's FindGraphicsMagick.cmake which 4 | # tests for GraphicsMagick's binary utilities 5 | # 6 | # Once loaded this will define 7 | # MAGICK_FOUND - system has GraphicsMagick 8 | # MAGICK_INCLUDE_DIR - include directory for GraphicsMagick 9 | # MAGICK_LIBRARY_DIR - library directory for GraphicsMagick 10 | # MAGICK_LIBRARIES - libraries you need to link to 11 | # 12 | # MAGICK++_FOUND - system has GraphicsMagick 13 | # MAGICK++_INCLUDE_DIR - include directory for GraphicsMagick 14 | # MAGICK++_LIBRARY_DIR - library directory for GraphicsMagick 15 | # MAGICK++_LIBRARIES - libraries you need to link to 16 | # 17 | # MAGICKWAND_FOUND - system has GraphicsMagick 18 | # MAGICKWAND_INCLUDE_DIR - include directory for GraphicsMagick 19 | # MAGICKWAND_LIBRARY_DIR - library directory for GraphicsMagick 20 | # MAGICKWAND_LIBRARIES - libraries you need to link to 21 | # 22 | 23 | SET(MAGICK_FOUND "NO" ) 24 | SET(MAGICK++_FOUND "NO" ) 25 | SET(MAGICKWAND_FOUND "NO" ) 26 | 27 | FIND_PATH( MAGICK_INCLUDE_DIR 28 | NAMES "magick/magick.h" 29 | PATHS 30 | "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GraphicsMagick\\Current;BinPath]/include" 31 | "$ENV{MAGICK_LOCATION}" 32 | "$ENV{MAGICK_LOCATION}/include" 33 | "$ENV{MAGICK_LOCATION}/include/GraphicsMagick" 34 | "$ENV{MAGICK_HOME}/include" 35 | /usr/include/ 36 | /usr/include/GraphicsMagick 37 | /usr/local/include 38 | /usr/local/include/GraphicsMagick 39 | /opt/local/include/GraphicsMagick 40 | ) 41 | 42 | FIND_PATH( MAGICK++_INCLUDE_DIR 43 | NAMES "Magick++/Magick++.h" 44 | PATHS 45 | "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GraphicsMagick\\Current;BinPath]/include" 46 | "$ENV{MAGICK++_LOCATION}" 47 | "$ENV{MAGICK++_LOCATION}/include" 48 | "$ENV{MAGICK_LOCATION}" 49 | "$ENV{MAGICK_LOCATION}/include" 50 | "$ENV{MAGICK_LOCATION}/include/GraphicsMagick" 51 | "$ENV{MAGICK_HOME}/include" 52 | /usr/include/ 53 | /usr/include/GraphicsMagick 54 | /usr/local/include 55 | /usr/local/include/GraphicsMagick 56 | /opt/local/include/GraphicsMagick 57 | ) 58 | 59 | FIND_PATH( MAGICKWAND_INCLUDE_DIR 60 | NAMES "wand/magick_wand.h" 61 | PATHS 62 | "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GraphicsMagick\\Current;BinPath]/include" 63 | "$ENV{MAGICKWAND_LOCATION}" 64 | "$ENV{MAGICKWAND_LOCATION}/include" 65 | "$ENV{MAGICK_LOCATION}" 66 | "$ENV{MAGICK_LOCATION}/include" 67 | "$ENV{MAGICK_LOCATION}/include/GraphicsMagick" 68 | "$ENV{MAGICK_HOME}/include" 69 | /usr/include/ 70 | /usr/include/GraphicsMagick 71 | /usr/local/include 72 | /usr/local/include/GraphicsMagick 73 | /opt/local/include/GraphicsMagick 74 | ) 75 | 76 | FIND_LIBRARY( Magick 77 | NAMES GraphicsMagick CORE_RL_magick_ 78 | PATHS 79 | "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GraphicsMagick\\Current;BinPath]/lib" 80 | "$ENV{MAGICK_LOCATION}/magick/.libs" 81 | "$ENV{MAGICK_LOCATION}/lib" 82 | "$ENV{MAGICK_HOME}/lib" 83 | /usr/lib64 84 | /usr/local/lib64 85 | /opt/local/lib64 86 | /usr/lib 87 | /usr/local/lib 88 | /opt/local/lib 89 | DOC "GraphicsMagick magic library" 90 | ) 91 | 92 | FIND_LIBRARY( Magick++ 93 | NAMES GraphicsMagick++ CORE_RL_Magick++_ 94 | PATHS 95 | "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GraphicsMagick\\Current;BinPath]/lib" 96 | "$ENV{MAGICK++_LOCATION}/.libs" 97 | "$ENV{MAGICK_LOCATION}/.libs" 98 | "$ENV{MAGICK++_LOCATION}/lib" 99 | "$ENV{MAGICK_LOCATION}/lib" 100 | "$ENV{MAGICK_HOME}/lib" 101 | /opt/local/lib64 102 | /usr/lib64 103 | /usr/local/lib64 104 | /opt/local/lib 105 | /usr/lib 106 | /usr/local/lib 107 | DOC "GraphicsMagick Magick++ library" 108 | ) 109 | 110 | FIND_LIBRARY( MagickWand 111 | NAMES GraphicsMagickWand CORE_RL_MagickWand_ 112 | PATHS 113 | "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GraphicsMagick\\Current;BinPath]/lib" 114 | "$ENV{MAGICKWAND_LOCATION}/.libs" 115 | "$ENV{MAGICK_LOCATION}/.libs" 116 | "$ENV{MAGICKWAND_LOCATION}/lib" 117 | "$ENV{MAGICK_LOCATION}/lib" 118 | "$ENV{MAGICK_HOME}/lib" 119 | /opt/local/lib64 120 | /usr/lib64 121 | /usr/local/lib64 122 | /opt/local/lib 123 | /usr/lib 124 | /usr/local/lib 125 | DOC "GraphicsMagick MagickWand library" 126 | ) 127 | 128 | SET(MAGICK_LIBRARIES ${Magick} ) 129 | SET(MAGICK++_LIBRARIES ${Magick++} ) 130 | SET(MAGICKWAND_LIBRARIES ${MagickWand} ) 131 | 132 | IF (MAGICK_INCLUDE_DIR) 133 | IF(MAGICK_LIBRARIES) 134 | SET(MAGICK_FOUND "YES") 135 | GET_FILENAME_COMPONENT(MAGICK_LIBRARY_DIR ${Magick} PATH) 136 | ENDIF(MAGICK_LIBRARIES) 137 | ENDIF(MAGICK_INCLUDE_DIR) 138 | 139 | IF (MAGICK++_INCLUDE_DIR) 140 | IF(MAGICK++_LIBRARIES) 141 | SET(MAGICK++_FOUND "YES") 142 | GET_FILENAME_COMPONENT(MAGICK++_LIBRARY_DIR ${Magick++} PATH) 143 | ENDIF(MAGICK++_LIBRARIES) 144 | ENDIF(MAGICK++_INCLUDE_DIR) 145 | 146 | IF (MAGICKWAND_INCLUDE_DIR) 147 | IF(MAGICKWAND_LIBRARIES) 148 | SET(MAGICKWAND_FOUND "YES") 149 | GET_FILENAME_COMPONENT(MAGICKWAND_LIBRARY_DIR ${MagickWand} PATH) 150 | ENDIF(MAGICKWAND_LIBRARIES) 151 | ENDIF(MAGICKWAND_INCLUDE_DIR) 152 | 153 | IF(NOT MAGICK_FOUND) 154 | # make FIND_PACKAGE friendly 155 | IF(NOT Magick_FIND_QUIETLY) 156 | IF(Magick_FIND_REQUIRED) 157 | MESSAGE(FATAL_ERROR 158 | "GraphicsMagick required, please specify it's location with MAGICK_HOME, MAGICK_LOCATION or MAGICK++_LOCATION") 159 | ELSE(Magick_FIND_REQUIRED) 160 | MESSAGE(STATUS "GraphicsMagick was not found.") 161 | ENDIF(Magick_FIND_REQUIRED) 162 | ENDIF(NOT Magick_FIND_QUIETLY) 163 | ENDIF(NOT MAGICK_FOUND) 164 | 165 | ##### 166 | -------------------------------------------------------------------------------- /src/CMakeModules/FindLibEvent.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the LibEvent config processing library 2 | # Once done this will define 3 | # 4 | # LIBEVENT_FOUND - System has LibEvent 5 | # LIBEVENT_INCLUDE_DIR - the LibEvent include directory 6 | # LIBEVENT_LIBRARIES 0 The libraries needed to use LibEvent 7 | 8 | FIND_PATH(LIBEVENT_INCLUDE_DIR NAMES event.h) 9 | FIND_LIBRARY(LIBEVENT_LIBRARY NAMES event) 10 | FIND_LIBRARY(LIBEVENT_CORE_LIBRARY NAMES event_core) 11 | FIND_LIBRARY(LIBEVENT_PTHREADS_LIBRARY NAMES event_pthreads) 12 | FIND_LIBRARY(LIBEVENT_EXTRA_LIBRARY NAMES event_extra) 13 | FIND_LIBRARY(LIBEVENT_OPENSSL_LIBRARY NAMES event_openssl) 14 | 15 | 16 | INCLUDE(FindPackageHandleStandardArgs) 17 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEvent DEFAULT_MSG LIBEVENT_LIBRARY LIBEVENT_INCLUDE_DIR) 18 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEventPthreads DEFAULT_MSG LIBEVENT_PTHREADS_LIBRARY LIBEVENT_INCLUDE_DIR) 19 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEventCore DEFAULT_MSG LIBEVENT_CORE_LIBRARY LIBEVENT_INCLUDE_DIR) 20 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEventExtra DEFAULT_MSG LIBEVENT_EXTRA_LIBRARY LIBEVENT_INCLUDE_DIR) 21 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEventOpenssl DEFAULT_MSG LIBEVENT_OPENSSL_LIBRARY LIBEVENT_INCLUDE_DIR) 22 | 23 | MARK_AS_ADVANCED(LIBEVENT_INCLUDE_DIR LIBEVENT_LIBRARY LIBEVENT_PTHREADS_LIBRARY LIBEVENT_OPENSSL_LIBRARY LIBEVENT_CORE_LIBRARY LIBEVENT_EXTRA_LIBRARY) 24 | -------------------------------------------------------------------------------- /src/CMakeModules/FindLibHiredis.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the LIBHIREDIS config processing library 2 | # Once done this will define 3 | # 4 | # LIBHIREDIS_FOUND - System has LIBHIREDIS 5 | # LIBHIREDIS_INCLUDE_DIR - the LIBHIREDIS include directory 6 | # LIBHIREDIS_LIBRARIES 0 The libraries needed to use LIBHIREDIS 7 | 8 | FIND_PATH(LIBHIREDIS_INCLUDE_DIR NAMES hiredis/hiredis.h PATHS "${CMAKE_CURRENT_SOURCE_DIR}/include") 9 | FIND_LIBRARY(LIBHIREDIS_LIBRARY NAMES hiredis PATHS "${CMAKE_CURRENT_SOURCE_DIR}/lib" /usr/lib /usr/local/lib) 10 | 11 | IF(LIBHIREDIS_INCLUDE_DIR AND LIBHIREDIS_LIBRARY) 12 | SET(LIBHIREDIS_FOUND 1) 13 | ELSE (LIBHIREDIS_INCLUDE_DIR AND LIBHIREDIS_LIBRARY) 14 | SET(LIBHIREDIS_FOUND 0) 15 | ENDIF (LIBHIREDIS_INCLUDE_DIR AND LIBHIREDIS_LIBRARY) 16 | 17 | # Report the results. 18 | IF (NOT LIBHIREDIS_FOUND) 19 | SET(LIBHIREDIS_DIR_MESSAGE "LibHiredis was not found.") 20 | ENDIF (NOT LIBHIREDIS_FOUND) 21 | 22 | 23 | INCLUDE(FindPackageHandleStandardArgs) 24 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBHIREDIS DEFAULT_MSG LIBHIREDIS_LIBRARY LIBHIREDIS_INCLUDE_DIR) 25 | 26 | MARK_AS_ADVANCED(LIBHIREDIS_INCLUDE_DIR LIBHIREDIS_LIBRARY) 27 | -------------------------------------------------------------------------------- /src/CMakeModules/FindLibMemcached.cmake: -------------------------------------------------------------------------------- 1 | # Try to find the libmemcached 2 | # 3 | # LIBMEMCACHED_FOUND - system has the libmemcached library 4 | # LIBMEMCACHED_INCLUDE_DIR - the libmemcached include directory 5 | # LIBMEMCACHED_LIBRARIES - The libraries needed to use libmemcached 6 | 7 | IF (LIBMEMCACHED_INCLUDE_DIRS) 8 | # Already in cache, be silent 9 | SET(LIBMEMCACHED_FIND_QUIETLY TRUE) 10 | ENDIF () 11 | 12 | FIND_PATH(LIBMEMCACHED_INCLUDE_DIR libmemcached/memcached.h) 13 | 14 | FIND_LIBRARY(LIBMEMCACHED_LIBRARY memcached) 15 | 16 | # handle the QUIETLY and REQUIRED arguments and set Libmemcached_FOUND to TRUE if 17 | # all listed variables are TRUE 18 | INCLUDE(FindPackageHandleStandardArgs) 19 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(Libmemcached DEFAULT_MSG LIBMEMCACHED_LIBRARY LIBMEMCACHED_INCLUDE_DIR) 20 | 21 | IF(LIBMEMCACHED_FOUND) 22 | SET(LIBMEMCACHED_LIBRARIES ${LIBMEMCACHED_LIBRARY}) 23 | SET(LIBMEMCACHED_INCLUDE_DIRS ${LIBMEMCACHED_INCLUDE_DIR}) 24 | ELSE() 25 | SET(LIBMEMCACHED_LIBRARIES) 26 | SET(LIBMEMCACHED_INCLUDE_DIRS) 27 | ENDIF() 28 | 29 | MARK_AS_ADVANCED(LIBMEMCACHED_LIBRARIES LIBMEMCACHED_INCLUDE_DIRS) 30 | -------------------------------------------------------------------------------- /src/CMakeModules/FindLuaJIT.cmake: -------------------------------------------------------------------------------- 1 | # Locate Lua library 2 | # This module defines 3 | # LUAJIT_FOUND, if false, do not try to link to Lua 4 | # LUAJIT_LIBRARIES 5 | # LUAJIT_INCLUDE_DIR, where to find lua.h 6 | # 7 | # Note that the expected include convention is 8 | # #include "lua.h" 9 | # and not 10 | # #include 11 | # This is because, the lua location is not standardized and may exist 12 | # in locations other than lua/ 13 | 14 | #============================================================================= 15 | # Copyright 2007-2009 Kitware, Inc. 16 | # 17 | # Distributed under the OSI-approved BSD License (the "License"); 18 | # see accompanying file Copyright.txt for details. 19 | # 20 | # This software is distributed WITHOUT ANY WARRANTY; without even the 21 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 22 | # See the License for more information. 23 | #============================================================================= 24 | # (To distributed this file outside of CMake, substitute the full 25 | # License text for the above reference.) 26 | # 27 | # ################ 28 | # 2010 - modified for cronkite to find luajit instead of lua, as it was before. 29 | # 30 | 31 | FIND_PATH(LUAJIT_INCLUDE_DIR luajit.h 32 | HINTS 33 | $ENV{LUAJIT_DIR} 34 | PATH_SUFFIXES include/luajit-2.1 include/luajit2.1 include/luajit include 35 | PATHS 36 | ~/Library/Frameworks 37 | /Library/Frameworks 38 | /usr/local 39 | /usr 40 | /sw # Fink 41 | /opt/local # DarwinPorts 42 | /opt/csw # Blastwave 43 | /opt 44 | ) 45 | 46 | FIND_LIBRARY(LUAJIT_LIBRARY 47 | NAMES luajit-51 luajit-5.1 luajit luajit-5.1.2 48 | HINTS 49 | $ENV{LUAJIT_DIR} 50 | PATH_SUFFIXES lib64 lib 51 | PATHS 52 | ~/Library/Frameworks 53 | /Library/Frameworks 54 | /usr/local 55 | /usr 56 | /sw 57 | /opt/local 58 | /opt/csw 59 | /opt 60 | ) 61 | 62 | IF(LUAJIT_LIBRARY) 63 | # include the math library for Unix 64 | IF(UNIX AND NOT APPLE) 65 | FIND_LIBRARY(LUAJIT_MATH_LIBRARY m) 66 | SET( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY};${LUAJIT_MATH_LIBRARY}" CACHE STRING "Lua Libraries") 67 | # For Windows and Mac, don't need to explicitly include the math library 68 | ELSE(UNIX AND NOT APPLE) 69 | SET( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY}" CACHE STRING "Lua Libraries") 70 | ENDIF(UNIX AND NOT APPLE) 71 | ENDIF(LUAJIT_LIBRARY) 72 | 73 | INCLUDE(FindPackageHandleStandardArgs) 74 | # handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if 75 | # all listed variables are TRUE 76 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT DEFAULT_MSG LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR) 77 | 78 | MARK_AS_ADVANCED(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARIES LUAJIT_LIBRARY LUAJIT_MATH_LIBRARY) 79 | -------------------------------------------------------------------------------- /src/CMakeModules/FindWebP.cmake: -------------------------------------------------------------------------------- 1 | # - Find WebP library 2 | # Find the native WebP headers and libraries. 3 | # 4 | # WEBP_INCLUDE_DIRS - where to find webp/decode.h, etc. 5 | # WEBP_LIBRARIES - List of libraries when using webp. 6 | # WEBP_FOUND - True if webp is found. 7 | 8 | #============================================================================= 9 | #Copyright 2000-2009 Kitware, Inc., Insight Software Consortium 10 | #All rights reserved. 11 | # 12 | #Redistribution and use in source and binary forms, with or without 13 | # modification, are permitted provided that the following conditions are met: 14 | # 15 | #* Redistributions of source code must retain the above copyright notice, 16 | #this list of conditions and the following disclaimer. 17 | # 18 | #* Redistributions in binary form must reproduce the above copyright notice, 19 | #this list of conditions and the following disclaimer in the documentation 20 | #and/or other materials provided with the distribution. 21 | # 22 | #* Neither the names of Kitware, Inc., the Insight Software Consortium, nor 23 | #the names of their contributors may be used to endorse or promote products 24 | #derived from this software without specific prior written permission. 25 | # 26 | #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 | #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 30 | #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | #POSSIBILITY OF SUCH DAMAGE. 37 | #============================================================================= 38 | 39 | # Look for the header file. 40 | FIND_PATH(WEBP_INCLUDE_DIR NAMES webp/decode.h) 41 | MARK_AS_ADVANCED(WEBP_INCLUDE_DIR) 42 | 43 | # Look for the library. 44 | FIND_LIBRARY(WEBP_LIBRARY NAMES webp) 45 | MARK_AS_ADVANCED(WEBP_LIBRARY) 46 | 47 | # handle the QUIETLY and REQUIRED arguments and set WEBFOUND_FOUND to TRUE if 48 | # all listed variables are TRUE 49 | INCLUDE(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) 50 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(WebP DEFAULT_MSG WEBP_LIBRARY WEBP_INCLUDE_DIR) 51 | 52 | SET(WEBP_LIBRARIES ${WEBP_LIBRARY}) 53 | SET(WEBP_INCLUDE_DIRS ${WEBP_INCLUDE_DIR}) 54 | 55 | SET(_WEBP_RQ_INCLUDES ${CMAKE_REQUIRED_INCLUDES}) 56 | 57 | if(NOT DEFINED _WEBP_COMPILATION_TEST) 58 | INCLUDE (CheckCSourceCompiles) 59 | SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${WEBP_INCLUDE_DIRS}) 60 | CHECK_C_SOURCE_COMPILES("#include 61 | int main(void) { 62 | #if WEBP_DECODER_ABI_VERSION < 0x0200 63 | error; // Deliberate compile-time error 64 | #endif 65 | }" 66 | _WEBP_COMPILATION_TEST) 67 | SET(CMAKE_REQUIRED_INCLUDES ${_WEBP_RQ_INCLUDES}) 68 | endif() 69 | 70 | if(NOT _WEBP_COMPILATION_TEST) 71 | set( USE_INTERNAL_WEBP 1 ) 72 | endif() 73 | -------------------------------------------------------------------------------- /src/CMakeModules/Findlibevhtp.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the libevhtp 2 | # Once done this will define 3 | 4 | # LIBEVHTP_FOUND - System has libevhtp 5 | # LIBEVHTP_INCLUDE_DIR - the libevhtp include directory 6 | # LIBEVHTP_LIBRARY 0 The library needed to use libevhtp 7 | 8 | FIND_PATH(LIBEVHTP_INCLUDE_DIR NAMES evhtp.h PATHS "${CMAKE_CURRENT_SOURCE_DIR}/include") 9 | FIND_LIBRARY(LIBEVHTP_LIBRARY NAMES evhtp PATHS "${CMAKE_CURRENT_SOURCE_DIR}/lib" /usr/lib /usr/local/lib) 10 | 11 | IF(LIBEVHTP_INCLUDE_DIR AND LIBEVHTP_LIBRARY) 12 | SET(LIBEVHTP_FOUND 1) 13 | ELSE (LIBEVHTP_INCLUDE_DIR AND LIBEVHTP_LIBRARY) 14 | SET(LIBEVHTP_FOUND 0) 15 | ENDIF (LIBEVHTP_INCLUDE_DIR AND LIBEVHTP_LIBRARY) 16 | 17 | # Report the results. 18 | IF (NOT LIBEVHTP_FOUND) 19 | SET(LIBEVHTP_DIR_MESSAGE "Libevhtp was not found.") 20 | ENDIF (NOT LIBEVHTP_FOUND) 21 | 22 | INCLUDE(FindPackageHandleStandardArgs) 23 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(libevhtp DEFAULT_MSG LIBEVHTP_LIBRARY LIBEVHTP_INCLUDE_DIR) 24 | MARK_AS_ADVANCED(LIBEVHTP_INCLUDE_DIR LIBEVHTP_LIBRARY) 25 | 26 | -------------------------------------------------------------------------------- /src/count_code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | find . -name '*.lua' |xargs wc -l 3 | find . -name '*.c' |xargs wc -l 4 | find . -name '*.h' |xargs wc -l 5 | -------------------------------------------------------------------------------- /src/zaccess.c: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zaccess.c 15 | * @brief IP access control module in zimg. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include "zaccess.h" 25 | #include "zlog.h" 26 | 27 | static int zimg_atoi(u_char *line, size_t n); 28 | static u_char * zimg_strlchr(u_char *p, u_char *last, u_char c); 29 | static in_addr_t zimg_inet_addr(u_char *text, size_t len); 30 | static int stor(u_char *text, size_t text_len, zimg_rule_t *rule); 31 | zimg_access_conf_t * conf_get_rules(const char *acc_str); 32 | int zimg_access_inet(zimg_access_conf_t *cf, in_addr_t addr); 33 | void free_access_conf(zimg_access_conf_t *cf); 34 | 35 | /** 36 | * @brief zimg_atoi convert string to int 37 | * 38 | * @param line ipnut string 39 | * @param n string length 40 | * 41 | * @return int 42 | */ 43 | static int zimg_atoi(u_char *line, size_t n) { 44 | int value; 45 | 46 | if (n == 0) { 47 | return ZIMG_ERROR; 48 | } 49 | 50 | for (value = 0; n--; line++) { 51 | if (*line < '0' || *line > '9') { 52 | return ZIMG_ERROR; 53 | } 54 | 55 | value = value * 10 + (*line - '0'); 56 | } 57 | 58 | if (value < 0) { 59 | return ZIMG_ERROR; 60 | 61 | } else { 62 | return value; 63 | } 64 | } 65 | 66 | /** 67 | * @brief zimg_strlchr find char in string 68 | * 69 | * @param p input string 70 | * @param last end of the string 71 | * @param c the char to find 72 | * 73 | * @return postion of char, NULL for not found 74 | */ 75 | static u_char * zimg_strlchr(u_char *p, u_char *last, u_char c) { 76 | while (p < last) { 77 | 78 | if (*p == c) { 79 | return p; 80 | } 81 | 82 | p++; 83 | } 84 | 85 | return NULL; 86 | } 87 | 88 | //transfer "10.77.121.137" to in_addr_t 89 | /** 90 | * @brief zimg_inet_addr convert string to in_addr_t 91 | * 92 | * @param text input text 93 | * @param len text length 94 | * 95 | * @return in_addr_t 96 | */ 97 | static in_addr_t zimg_inet_addr(u_char *text, size_t len) { 98 | u_char *p, c; 99 | in_addr_t addr; 100 | uint octet, n; 101 | 102 | addr = 0; 103 | octet = 0; 104 | n = 0; 105 | 106 | for (p = text; p < text + len; p++) { 107 | 108 | c = *p; 109 | 110 | if (c >= '0' && c <= '9') { 111 | octet = octet * 10 + (c - '0'); 112 | continue; 113 | } 114 | if (c == '.' && octet < 256) { 115 | addr = (addr << 8) + octet; 116 | octet = 0; 117 | n++; 118 | continue; 119 | } 120 | return INADDR_NONE; 121 | } 122 | 123 | if (n == 3 && octet < 256) { 124 | addr = (addr << 8) + octet; 125 | return htonl(addr); 126 | } 127 | return INADDR_NONE; 128 | } 129 | 130 | /** 131 | * @brief stor convert string to zimg rule 132 | * 133 | * @param text input text 134 | * @param text_len text length 135 | * @param rule zimg rule 136 | * 137 | * @return 0 for succ and -1 for failed 138 | */ 139 | static int stor(u_char *text, size_t text_len, zimg_rule_t *rule) { 140 | u_char *addr, *mask, *last; 141 | size_t len; 142 | int shift; 143 | addr = text; 144 | last = addr + text_len; 145 | 146 | mask = zimg_strlchr(addr, last, '/'); 147 | len = (mask ? mask : last) - addr; 148 | 149 | rule->addr = zimg_inet_addr(addr, len); 150 | 151 | if (rule->addr != INADDR_NONE) { 152 | 153 | if (mask == NULL) { 154 | rule->mask = 0xffffffff; 155 | return ZIMG_OK; 156 | } 157 | } else { 158 | return ZIMG_ERROR; 159 | } 160 | 161 | mask++; 162 | 163 | shift = zimg_atoi(mask, last - mask); 164 | if (shift == ZIMG_ERROR) { 165 | return ZIMG_ERROR; 166 | } 167 | if (shift > 32) { 168 | return ZIMG_ERROR; 169 | } 170 | if (shift) { 171 | rule->mask = htonl((uint32_t) (0xffffffffu << (32 - shift))); 172 | } else { 173 | /* 174 | * x86 compilers use a shl instruction that 175 | * shifts by modulo 32 176 | */ 177 | rule->mask = 0; 178 | } 179 | 180 | if (rule->addr == (rule->addr & rule->mask)) { 181 | return ZIMG_OK; 182 | } 183 | rule->addr &= rule->mask; 184 | 185 | return ZIMG_OK; 186 | } 187 | 188 | /** 189 | * @brief conf_get_rules read rules from conf 190 | * 191 | * @param acc_str rules string 192 | * 193 | * @return zimg conf 194 | */ 195 | zimg_access_conf_t * conf_get_rules(const char *acc_str) { 196 | if (acc_str == NULL) 197 | return NULL; 198 | zimg_access_conf_t *acconf = (zimg_access_conf_t *)malloc(sizeof(zimg_access_conf_t)); 199 | if (acconf == NULL) 200 | return NULL; 201 | acconf->n = 0; 202 | acconf->rules = NULL; 203 | size_t acc_len = strlen(acc_str); 204 | char *acc = (char *)malloc(acc_len); 205 | if (acc == NULL) { 206 | return NULL; 207 | } 208 | strncpy(acc, acc_str, acc_len); 209 | char *start = acc, *end; 210 | while (start <= acc + acc_len) { 211 | end = strchr(start, ';'); 212 | end = (end) ? end : acc + acc_len; 213 | char *mode = start; 214 | char *range = strchr(mode, ' '); 215 | if (range) { 216 | zimg_rule_t *this_rule = (zimg_rule_t *)malloc(sizeof(zimg_rule_t)); 217 | if (this_rule == NULL) { 218 | start = end + 1; 219 | continue; 220 | } 221 | (void) memset(this_rule, 0, sizeof(zimg_rule_t)); 222 | this_rule->deny = (mode[0] == 'd') ? 1 : 0; 223 | size_t range_len; 224 | range++; 225 | range_len = end - range; 226 | 227 | uint all = (range_len == 3 && strstr(range, "all") == range); 228 | 229 | if (!all) { 230 | int rc; 231 | rc = stor((unsigned char *)range, range_len, this_rule); 232 | if (rc == ZIMG_ERROR) { 233 | start = end + 1; 234 | continue; 235 | } 236 | } 237 | 238 | zimg_rules_t *rules = (zimg_rules_t *)malloc(sizeof(zimg_rules_t)); 239 | if (rules == NULL) { 240 | start = end + 1; 241 | continue; 242 | } 243 | 244 | rules->value = this_rule; 245 | rules->next = acconf->rules; 246 | acconf->rules = rules; 247 | acconf->n++; 248 | } 249 | start = end + 1; 250 | } 251 | free(acc); 252 | return acconf; 253 | } 254 | 255 | //judge request by conf 256 | /** 257 | * @brief zimg_access_inet judge ip by conf 258 | * 259 | * @param cf zimg access conf 260 | * @param addr address of request 261 | * 262 | * @return 0 for allow and -1 for forbidden 263 | */ 264 | int zimg_access_inet(zimg_access_conf_t *cf, in_addr_t addr) { 265 | zimg_rules_t *rules = cf->rules; 266 | if (rules == NULL) { 267 | LOG_PRINT(LOG_DEBUG, "rules nil"); 268 | return ZIMG_OK; 269 | } 270 | LOG_PRINT(LOG_DEBUG, "rules: %p", rules); 271 | 272 | while (rules) { 273 | LOG_PRINT(LOG_DEBUG, "addr: %d", addr); 274 | LOG_PRINT(LOG_DEBUG, "rules->value->addr: %d", rules->value->addr); 275 | LOG_PRINT(LOG_DEBUG, "rules->value->mask: %d", rules->value->mask); 276 | if ((addr & rules->value->mask) == rules->value->addr) { 277 | if (rules->value->deny) { 278 | //LOG_PRINT(LOG_INFO, "deny"); 279 | return ZIMG_FORBIDDEN; 280 | } 281 | return ZIMG_OK; 282 | } 283 | rules = rules->next; 284 | } 285 | 286 | return ZIMG_FORBIDDEN; 287 | } 288 | 289 | 290 | /** 291 | * @brief free_access_conf release conf 292 | * 293 | * @param cf the conf to free 294 | */ 295 | void free_access_conf(zimg_access_conf_t *cf) { 296 | if (cf == NULL) 297 | return; 298 | zimg_rules_t *rules = cf->rules; 299 | while (rules) { 300 | cf->rules = rules->next; 301 | free(rules->value); 302 | free(rules); 303 | rules = cf->rules; 304 | } 305 | free(cf); 306 | } 307 | 308 | -------------------------------------------------------------------------------- /src/zaccess.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zaccess.h 15 | * @brief IP access control module in zimg header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZACCESS_H 22 | #define ZACCESS_H 23 | 24 | #include 25 | #include 26 | 27 | #define ZIMG_OK 0 28 | #define ZIMG_ERROR -1 29 | #define ZIMG_FORBIDDEN -2 30 | 31 | #ifndef INADDR_NONE /* Solaris */ 32 | #define INADDR_NONE ((unsigned int) -1) 33 | #endif 34 | 35 | typedef struct zimg_rules_s zimg_rules_t; 36 | 37 | typedef struct { 38 | in_addr_t mask; 39 | in_addr_t addr; 40 | uint deny; /* unsigned deny:1; */ 41 | } zimg_rule_t; 42 | 43 | struct zimg_rules_s { 44 | zimg_rule_t *value; 45 | zimg_rules_t *next; 46 | }; 47 | 48 | typedef struct { 49 | uint n; 50 | zimg_rules_t *rules; 51 | } zimg_access_conf_t; 52 | 53 | zimg_access_conf_t * conf_get_rules(const char *acc_str); 54 | int zimg_access_inet(zimg_access_conf_t *cf, in_addr_t addr); 55 | void free_access_conf(zimg_access_conf_t *cf); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/zcache.c: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zcache.c 15 | * @brief memcached functions 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #include "zcache.h" 22 | #include "zutil.h" 23 | #include "zlog.h" 24 | 25 | void retry_cache(thr_arg_t *thr_arg); 26 | int exist_cache(thr_arg_t *thr_arg, const char *key); 27 | int find_cache(memcached_st *memc, const char *key, char *value); 28 | int set_cache(memcached_st *memc, const char *key, const char *value); 29 | int find_cache_bin(thr_arg_t *thr_arg, const char *key, char **value_ptr, size_t *len); 30 | int set_cache_bin(thr_arg_t *thr_arg, const char *key, const char *value, const size_t len); 31 | int del_cache(thr_arg_t *thr_arg, const char *key); 32 | 33 | /** 34 | * @brief retry_cache Reconnect to the cache server. 35 | * 36 | * @param thr_arg Thread arg. 37 | */ 38 | void retry_cache(thr_arg_t *thr_arg) { 39 | if (thr_arg->cache_conn != NULL) 40 | memcached_free(thr_arg->cache_conn); 41 | 42 | memcached_st *memc; 43 | memc = memcached_create(NULL); 44 | 45 | char mserver[32]; 46 | snprintf(mserver, 32, "%s:%d", settings.cache_ip, settings.cache_port); 47 | memcached_server_st *servers = memcached_servers_parse(mserver); 48 | 49 | memcached_server_push(memc, servers); 50 | memcached_server_list_free(servers); 51 | memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); 52 | memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1); 53 | memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1); 54 | memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_KEEPALIVE, 1); 55 | thr_arg->cache_conn = memc; 56 | 57 | evthr_set_aux(thr_arg->thread, thr_arg); 58 | } 59 | 60 | /** 61 | * @brief exist_cache Check a key is exist in memcached. 62 | * 63 | * @param thr_arg The arg of thread. 64 | * @param key The string of the key. 65 | * 66 | * @return 1 for yes and -1 for no. 67 | */ 68 | int exist_cache(thr_arg_t *thr_arg, const char *key) { 69 | int rst = -1; 70 | if (settings.cache_on == false) 71 | return rst; 72 | if (thr_arg->cache_conn == NULL) 73 | return rst; 74 | 75 | memcached_st *memc = thr_arg->cache_conn; 76 | memcached_return rc; 77 | 78 | size_t valueLen = 0; 79 | uint32_t flags; 80 | char *value = memcached_get(memc, key, strlen(key), &valueLen, &flags, &rc); 81 | //rc = memcached_exist(memc, key, strlen(key)); 82 | 83 | if (rc == MEMCACHED_SUCCESS) { 84 | LOG_PRINT(LOG_DEBUG, "Cache Key[%s] Exist.", key); 85 | rst = 1; 86 | } else if (rc == MEMCACHED_CONNECTION_FAILURE) { 87 | LOG_PRINT(LOG_DEBUG, "Cache Conn Failed!"); 88 | //retry_cache(thr_arg); 89 | } else { 90 | const char *str_rc = memcached_strerror(memc, rc); 91 | LOG_PRINT(LOG_DEBUG, "Cache Result: %s", str_rc); 92 | } 93 | free(value); 94 | 95 | return rst; 96 | } 97 | 98 | /** 99 | * @brief find_cache Connect to a memcached server and find a key's value. 100 | * 101 | * @param memc The connection to beansdb. 102 | * @param key The string of the key you want to find. 103 | * @param value It contains the string of the key's value. 104 | * 105 | * @return 1 for success and -1 for fail. 106 | */ 107 | int find_cache(memcached_st *memc, const char *key, char *value) { 108 | int rst = -1; 109 | if (memc == NULL) 110 | return rst; 111 | 112 | size_t valueLen; 113 | uint32_t flags; 114 | memcached_return rc; 115 | 116 | char *pvalue = memcached_get(memc, key, strlen(key), &valueLen, &flags, &rc); 117 | 118 | if (rc == MEMCACHED_SUCCESS) { 119 | LOG_PRINT(LOG_DEBUG, "Cache Find Key[%s] Value: %s", key, pvalue); 120 | str_lcpy(value, pvalue, sizeof(value)); 121 | free(pvalue); 122 | rst = 1; 123 | } else if (rc == MEMCACHED_NOTFOUND) { 124 | LOG_PRINT(LOG_DEBUG, "Cache Key[%s] Not Find!", key); 125 | rst = -1; 126 | } else { 127 | const char *str_rc = memcached_strerror(memc, rc); 128 | LOG_PRINT(LOG_DEBUG, "Cache Result: %s", str_rc); 129 | } 130 | 131 | return rst; 132 | } 133 | 134 | /** 135 | * @brief set_cache Set a key with the value input. 136 | * 137 | * @param memc The connection to beansdb. 138 | * @param key The key you want to set a new value. 139 | * @param value The value of the key. 140 | * 141 | * @return 1 for success and -1 for fail. 142 | */ 143 | int set_cache(memcached_st *memc, const char *key, const char *value) { 144 | int rst = -1; 145 | if (memc == NULL) 146 | return rst; 147 | 148 | memcached_return rc; 149 | 150 | rc = memcached_set(memc, key, strlen(key), value, strlen(value), 0, 0); 151 | 152 | if (rc == MEMCACHED_SUCCESS) { 153 | LOG_PRINT(LOG_DEBUG, "Cache Set Successfully. Key[%s] Value: %s", key, value); 154 | rst = 1; 155 | } else if (rc == MEMCACHED_CONNECTION_FAILURE) { 156 | LOG_PRINT(LOG_DEBUG, "Cache Connection Failed!"); 157 | } else { 158 | LOG_PRINT(LOG_DEBUG, "Cache Set(Key: %s Value: %s) Failed!", key, value); 159 | const char *str_rc = memcached_strerror(memc, rc); 160 | LOG_PRINT(LOG_DEBUG, "Cache Result: %s", str_rc); 161 | rst = -1; 162 | } 163 | 164 | return rst; 165 | } 166 | 167 | /** 168 | * @brief find_cache_bin Find a key's BINARY value. 169 | * 170 | * @param thr_arg The arg of thread. 171 | * @param key The key you want to find. 172 | * @param value_ptr It will be alloc and contains the binary value. 173 | * @param len It will change to the length of the value. 174 | * 175 | * @return 1 for success and -1 for fail. 176 | */ 177 | int find_cache_bin(thr_arg_t *thr_arg, const char *key, char **value_ptr, size_t *len) { 178 | int rst = -1; 179 | if (settings.cache_on == false) 180 | return rst; 181 | if (thr_arg->cache_conn == NULL) { 182 | LOG_PRINT(LOG_DEBUG, "thr_arg->cache_conn nil."); 183 | return rst; 184 | } 185 | 186 | uint32_t flags; 187 | memcached_st *memc = thr_arg->cache_conn; 188 | memcached_return rc; 189 | 190 | *value_ptr = memcached_get(memc, key, strlen(key), len, &flags, &rc); 191 | 192 | if (rc == MEMCACHED_SUCCESS) { 193 | LOG_PRINT(LOG_DEBUG, "Binary Cache Find Key[%s], Len: %d.", key, *len); 194 | rst = 1; 195 | } else if (rc == MEMCACHED_CONNECTION_FAILURE) { 196 | LOG_PRINT(LOG_DEBUG, "Cache Conn Failed!"); 197 | //retry_cache(thr_arg); 198 | } else if (rc == MEMCACHED_NOTFOUND) { 199 | LOG_PRINT(LOG_DEBUG, "Binary Cache Key[%s] Not Find!", key); 200 | rst = -1; 201 | } else { 202 | const char *str_rc = memcached_strerror(memc, rc); 203 | LOG_PRINT(LOG_DEBUG, "Cache Result: %s", str_rc); 204 | } 205 | 206 | //memcached_free(memc); 207 | return rst; 208 | } 209 | 210 | /** 211 | * @brief set_cache_bin Set a new BINARY value of a key. 212 | * 213 | * @param thr_arg The arg of thread. 214 | * @param key The key. 215 | * @param value A char * buffer you want to set. 216 | * @param len The length of the buffer above, 217 | * 218 | * @return 1 for success and -1 for fial. 219 | */ 220 | int set_cache_bin(thr_arg_t *thr_arg, const char *key, const char *value, const size_t len) { 221 | int rst = -1; 222 | if (settings.cache_on == false) 223 | return rst; 224 | if (thr_arg->cache_conn == NULL) 225 | return rst; 226 | 227 | memcached_st *memc = thr_arg->cache_conn; 228 | memcached_return rc; 229 | 230 | rc = memcached_set(memc, key, strlen(key), value, len, 0, 0); 231 | 232 | if (rc == MEMCACHED_SUCCESS) { 233 | LOG_PRINT(LOG_DEBUG, "Binary Cache Set Successfully. Key[%s] Len: %d.", key, len); 234 | rst = 1; 235 | } else if (rc == MEMCACHED_CONNECTION_FAILURE) { 236 | LOG_PRINT(LOG_DEBUG, "Cache Conn Failed!"); 237 | //retry_cache(thr_arg); 238 | } else { 239 | LOG_PRINT(LOG_DEBUG, "Binary Cache Set Key[%s] Failed!", key); 240 | const char *str_rc = memcached_strerror(memc, rc); 241 | LOG_PRINT(LOG_DEBUG, "Cache Result: %s", str_rc); 242 | rst = -1; 243 | } 244 | 245 | return rst; 246 | } 247 | 248 | 249 | /** 250 | * @brief del_cache This function delete a key and its value in memcached. 251 | * 252 | * @param thr_arg The arg of thread. 253 | * @param key The key. 254 | * 255 | * @return 1 for success and -1 for fail. 256 | */ 257 | int del_cache(thr_arg_t *thr_arg, const char *key) { 258 | int rst = -1; 259 | if (settings.cache_on == false) 260 | return rst; 261 | if (thr_arg->cache_conn == NULL) 262 | return rst; 263 | 264 | memcached_st *memc = thr_arg->cache_conn; 265 | memcached_return rc; 266 | 267 | rc = memcached_delete(memc, key, strlen(key), 0); 268 | 269 | if (rc == MEMCACHED_SUCCESS) { 270 | LOG_PRINT(LOG_DEBUG, "Cache Key[%s] Delete Successfully.", key); 271 | rst = 1; 272 | } else if (rc == MEMCACHED_CONNECTION_FAILURE) { 273 | LOG_PRINT(LOG_DEBUG, "Cache Conn Failed!"); 274 | //retry_cache(thr_arg); 275 | } else { 276 | LOG_PRINT(LOG_DEBUG, "Cache Key[%s] Delete Failed!", key); 277 | const char *str_rc = memcached_strerror(memc, rc); 278 | LOG_PRINT(LOG_DEBUG, "Cache Result: %s", str_rc); 279 | rst = -1; 280 | } 281 | 282 | return rst; 283 | } 284 | -------------------------------------------------------------------------------- /src/zcache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zcache.h 15 | * @brief memcached functions header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZCACHE_H 22 | #define ZCACHE_H 23 | 24 | #include "zcommon.h" 25 | 26 | void retry_cache(thr_arg_t *thr_arg); 27 | int exist_cache(thr_arg_t *thr_arg, const char *key); 28 | int find_cache(memcached_st *memc, const char *key, char *value); 29 | int set_cache(memcached_st *memc, const char *key, const char *value); 30 | int find_cache_bin(thr_arg_t *thr_arg, const char *key, char **value_ptr, size_t *len); 31 | int set_cache_bin(thr_arg_t *thr_arg, const char *key, const char *value, const size_t len); 32 | int del_cache(thr_arg_t *thr_arg, const char *key); 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /src/zcommon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zcommon.h 15 | * @brief common data structs header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZCOMMON_H 22 | #define ZCOMMON_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "libevhtp/evhtp.h" 32 | #include "zaccess.h" 33 | #include "zhttpd.h" 34 | #include "multipart-parser-c/multipart_parser.h" 35 | 36 | #ifndef PROJECT_VERSION 37 | #define PROJECT_VERSION "3.2.0" 38 | #endif 39 | 40 | #define MAX_LINE 1024 41 | #define CACHE_MAX_SIZE 1048576 //1024*1024 42 | #define RETRY_TIME_WAIT 1000 43 | #define CACHE_KEY_SIZE 128 44 | #define PATH_MAX_SIZE 512 45 | 46 | typedef struct thr_arg_s { 47 | evthr_t *thread; 48 | memcached_st *cache_conn; 49 | memcached_st *beansdb_conn; 50 | redisContext *ssdb_conn; 51 | lua_State* L; 52 | } thr_arg_t; 53 | 54 | typedef struct zimg_req_s { 55 | char *md5; 56 | char *type; 57 | int width; 58 | int height; 59 | int proportion; 60 | int gray; 61 | int x; 62 | int y; 63 | int rotate; 64 | int quality; 65 | char *fmt; 66 | int sv; 67 | thr_arg_t *thr_arg; 68 | } zimg_req_t; 69 | 70 | struct setting { 71 | lua_State *L; 72 | int is_daemon; 73 | char ip[128]; 74 | int port; 75 | int num_threads; 76 | int backlog; 77 | int max_keepalives; 78 | int retry; 79 | char version[128]; 80 | char server_name[128]; 81 | zimg_headers_conf_t *headers; 82 | int etag; 83 | zimg_access_conf_t *up_access; 84 | zimg_access_conf_t *down_access; 85 | zimg_access_conf_t *admin_access; 86 | int cache_on; 87 | char cache_ip[128]; 88 | int cache_port; 89 | int log_level; 90 | char log_name[512]; 91 | char root_path[512]; 92 | char admin_path[512]; 93 | int disable_args; 94 | int disable_type; 95 | int disable_zoom_up; 96 | int script_on; 97 | char script_name[512]; 98 | char format[16]; 99 | int quality; 100 | int mode; 101 | int save_new; 102 | int max_size; 103 | char img_path[512]; 104 | char beansdb_ip[128]; 105 | int beansdb_port; 106 | char ssdb_ip[128]; 107 | int ssdb_port; 108 | multipart_parser_settings *mp_set; 109 | int (*get_img)(zimg_req_t *, evhtp_request_t *); 110 | int (*info_img)(evhtp_request_t *, thr_arg_t *, char *); 111 | int (*admin_img)(evhtp_request_t *, thr_arg_t *, char *, int); 112 | } settings; 113 | 114 | #define LOG_FATAL 0 /* System is unusable */ 115 | #define LOG_ALERT 1 /* Action must be taken immediately */ 116 | #define LOG_CRIT 2 /* Critical conditions */ 117 | #define LOG_ERROR 3 /* Error conditions */ 118 | #define LOG_WARNING 4 /* Warning conditions */ 119 | #define LOG_NOTICE 5 /* Normal, but significant */ 120 | #define LOG_INFO 6 /* Information */ 121 | #define LOG_DEBUG 7 /* DEBUG message */ 122 | 123 | #ifdef DEBUG 124 | #define LOG_PRINT(level, fmt, ...) \ 125 | do { \ 126 | int log_id = log_open(settings.log_name, "a"); \ 127 | log_printf0(log_id, level, "%s:%d %s() "fmt, \ 128 | __FILE__, __LINE__, __FUNCTION__, \ 129 | ##__VA_ARGS__); \ 130 | log_close(log_id); \ 131 | }while(0) 132 | #else 133 | #define LOG_PRINT(level, fmt, ...) \ 134 | do { \ 135 | if (level <= settings.log_level) { \ 136 | int log_id = log_open(settings.log_name, "a"); \ 137 | log_printf0(log_id, level, fmt, ##__VA_ARGS__) ; \ 138 | log_close(log_id); \ 139 | } \ 140 | }while(0) 141 | #endif 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /src/zdb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zdb.h 15 | * @brief Get and save image for ssdb/redis and beansdb/memcachedb backend functions header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZDB_H 22 | #define ZDB_H 23 | 24 | #include "zcommon.h" 25 | 26 | int get_img_mode_db(zimg_req_t *req, evhtp_request_t *request); 27 | int get_img_db(thr_arg_t *thr_arg, const char *cache_key, char **buff, size_t *len); 28 | int get_img_beansdb(memcached_st *memc, const char *key, char **value_ptr, size_t *len); 29 | int get_img_ssdb(redisContext* c, const char *cache_key, char **buff, size_t *len); 30 | int save_img_db(thr_arg_t *thr_arg, const char *cache_key, const char *buff, const size_t len); 31 | int save_img_beansdb(memcached_st *memc, const char *key, const char *value, const size_t len); 32 | int save_img_ssdb(redisContext* c, const char *cache_key, const char *buff, const size_t len); 33 | int admin_img_mode_db(evhtp_request_t *req, thr_arg_t *thr_arg, char *md5, int t); 34 | int info_img_mode_db(evhtp_request_t *request, thr_arg_t *thr_arg, char *md5); 35 | int exist_db(thr_arg_t *thr_arg, const char *cache_key); 36 | int exist_beansdb(memcached_st *memc, const char *key); 37 | int exist_ssdb(redisContext* c, const char *cache_key); 38 | int del_db(thr_arg_t *thr_arg, const char *cache_key); 39 | int del_beansdb(memcached_st *memc, const char *key); 40 | int del_ssdb(redisContext* c, const char *cache_key); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/zhttpd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zhttpd.h 15 | * @brief http protocol parse functions header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZHTTPD_H 22 | #define ZHTTPD_H 23 | 24 | #include 25 | #include "libevhtp/evhtp.h" 26 | #include "multipart-parser-c/multipart_parser.h" 27 | 28 | typedef struct zimg_headers_s zimg_headers_t; 29 | 30 | typedef struct { 31 | char key[128]; 32 | char value[512]; 33 | } zimg_header_t; 34 | 35 | struct zimg_headers_s { 36 | zimg_header_t *value; 37 | zimg_headers_t *next; 38 | }; 39 | 40 | typedef struct { 41 | uint n; 42 | zimg_headers_t *headers; 43 | } zimg_headers_conf_t; 44 | 45 | int on_header_field(multipart_parser* p, const char *at, size_t length); 46 | int on_header_value(multipart_parser* p, const char *at, size_t length); 47 | int on_chunk_data(multipart_parser* p, const char *at, size_t length); 48 | int zimg_etag_set(evhtp_request_t *request, char *buff, size_t len); 49 | zimg_headers_conf_t * conf_get_headers(const char *hdr_str); 50 | void free_headers_conf(zimg_headers_conf_t *hcf); 51 | void add_info(MagickWand *im, evhtp_request_t *req); 52 | void dump_request_cb(evhtp_request_t *req, void *arg); 53 | void echo_cb(evhtp_request_t *req, void *arg); 54 | void post_request_cb(evhtp_request_t *req, void *arg); 55 | void get_request_cb(evhtp_request_t *req, void *arg); 56 | void admin_request_cb(evhtp_request_t *req, void *arg); 57 | void info_request_cb(evhtp_request_t *req, void *arg); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/zimg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zimg.h 15 | * @brief Convert, get and save image functions header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZIMG_H 22 | #define ZIMG_H 23 | 24 | #include "zcommon.h" 25 | 26 | int save_img(thr_arg_t *thr_arg, const char *buff, const int len, char *md5); 27 | int new_img(const char *buff, const size_t len, const char *save_name); 28 | int get_img(zimg_req_t *req, evhtp_request_t *request); 29 | int admin_img(evhtp_request_t *req, thr_arg_t *thr_arg, char *md5, int t); 30 | int info_img(evhtp_request_t *request, thr_arg_t *thr_arg, char *md5); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/zlog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zlog.c 15 | * @brief zimg log functions. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "zlog.h" 27 | 28 | static int log_valid(int log_id); 29 | void log_init(void); 30 | int log_open(const char *path, const char* mode); 31 | void log_handler(const char *msg); 32 | void log_printf0(int log_id, int log_level, const char *fmt, ...); 33 | void log_flush(int log_id); 34 | void log_close(int log_id); 35 | 36 | struct log_level_desc { 37 | enum LOG_LEVEL level; 38 | char* endesc; 39 | wchar_t* cndesc; 40 | }; 41 | 42 | static struct log_level_desc log_level_descs[] = { 43 | { LOG_LEVEL_FATAL, "FATAL", L"致命" }, 44 | { LOG_LEVEL_ALERT, "ALERT", L"危急" }, 45 | { LOG_LEVEL_CRIT, "CRITICAL", L"紧急" }, 46 | { LOG_LEVEL_ERROR, "ERROR", L"错误" }, 47 | { LOG_LEVEL_WARNING, "WARNING", L"警告" }, 48 | { LOG_LEVEL_NOTICE, "NOTICE", L"注意" }, 49 | { LOG_LEVEL_INFO, "INFO", L"消息" }, 50 | { LOG_LEVEL_DEBUG, "DEBUG", L"调试" }, 51 | }; 52 | 53 | static FILE* log_files[MAX_LOGS + 1]; 54 | static spin_lock_t log_locks[MAX_LOGS + 1]; 55 | 56 | /** 57 | * @brief log_valid check log is valid 58 | * 59 | * @param log_id the log id 60 | * 61 | * @return 1 for OK and 0 for fail 62 | */ 63 | static int log_valid(int log_id) { 64 | if (log_id < 0 || log_id > MAX_LOGS) 65 | return 0; 66 | 67 | return 1; 68 | } 69 | 70 | /** 71 | * @brief log_init init log 72 | */ 73 | void log_init(void) { 74 | int i; 75 | 76 | for (i = 0; i < MAX_LOGS + 1; i++) { 77 | log_files[i] = NULL; 78 | spin_init(&log_locks[i], NULL); 79 | } 80 | } 81 | 82 | /** 83 | * @brief log_open open a log file 84 | * 85 | * @param path the path of log 86 | * @param mode the mode of open 87 | * 88 | * @return log open id for OK and -1 for fail 89 | */ 90 | int log_open(const char *path, const char* mode) { 91 | int i; 92 | 93 | for (i = LOG_USER; i < MAX_LOGS + 1; i++) { 94 | spin_lock(&log_locks[i]); 95 | 96 | if (log_files[i] == NULL) { 97 | log_files[i] = fopen(path, mode); 98 | 99 | if (log_files[i]) { 100 | spin_unlock(&log_locks[i]); 101 | return i; 102 | } 103 | } 104 | 105 | spin_unlock(&log_locks[i]); 106 | } 107 | 108 | return LOG_INVALID; 109 | } 110 | 111 | /* Log a fixed message without printf-alike capabilities, in a way that is 112 | * safe to call from a signal handler. 113 | * 114 | * We actually use this only for signals that are not fatal from the point 115 | * of view of Redis. Signals that are going to kill the server anyway and 116 | * where we need printf-alike features are served by redisLog(). */ 117 | void log_handler(const char *msg) { 118 | int fd; 119 | int log_to_stdout = settings.log_level == -1; 120 | 121 | fd = log_to_stdout ? STDOUT_FILENO : 122 | open(settings.log_name, O_APPEND | O_CREAT | O_WRONLY, 0644); 123 | if (fd == -1) return; 124 | if (write(fd, msg, strlen(msg)) == -1) goto err; 125 | if (write(fd, "\n", 1) == -1) goto err; 126 | err: 127 | if (!log_to_stdout) close(fd); 128 | } 129 | 130 | /** 131 | * @brief log_printf0 print log to file function 132 | * 133 | * @param log_id log id 134 | * @param log_level log level 135 | * @param fmt format of string 136 | * @param ... other args 137 | */ 138 | void log_printf0(int log_id, int log_level, const char *fmt, ...) { 139 | FILE *fp; 140 | time_t t; 141 | char tmbuf[30]; 142 | const char *p; 143 | va_list args; 144 | int level; 145 | 146 | if (!log_valid(log_id)) 147 | fp = stdout; 148 | else { 149 | spin_lock(&log_locks[log_id]); 150 | if (!(fp = log_files[log_id])) { 151 | spin_unlock(&log_locks[log_id]); 152 | return; 153 | } 154 | } 155 | 156 | if (log_level > LOG_LEVEL_DEBUG) 157 | level = LOG_LEVEL_DEBUG; 158 | else if (log_level < LOG_LEVEL_FATAL) 159 | level = LOG_LEVEL_FATAL; 160 | else 161 | level = log_level; 162 | 163 | t = time(NULL); 164 | struct timeval tv; 165 | gettimeofday(&tv , NULL); 166 | memset(tmbuf, 0, sizeof(tmbuf)); 167 | strftime(tmbuf, sizeof(tmbuf), "%Y/%m/%d %H:%M:%S", localtime(&t)); 168 | fprintf (fp, "%s:%.6d ", tmbuf, (int)tv.tv_usec); 169 | 170 | #ifdef DEBUG 171 | fprintf(fp, "Thread ID: %lu ", (unsigned long)pthread_self()); 172 | #endif 173 | 174 | fprintf(fp, "[%s] ", log_level_descs[level].endesc); 175 | 176 | va_start(args, fmt); 177 | vfprintf(fp, fmt, args); 178 | va_end(args); 179 | 180 | p = fmt + strlen(fmt) - 1; 181 | if (*p != '\n') 182 | fputc('\n', fp); 183 | 184 | if (log_valid(log_id)) { 185 | fflush(fp); 186 | spin_unlock(&log_locks[log_id]); 187 | } 188 | } 189 | 190 | /** 191 | * @brief log_flush flush log string to file 192 | * 193 | * @param log_id log id 194 | */ 195 | void log_flush(int log_id) { 196 | if (!log_valid(log_id)) 197 | return; 198 | 199 | spin_lock(&log_locks[log_id]); 200 | 201 | if (log_files[log_id]) 202 | fflush(log_files[log_id]); 203 | 204 | spin_unlock(&log_locks[log_id]); 205 | } 206 | 207 | /** 208 | * @brief log_close close the log 209 | * 210 | * @param log_id the log id 211 | */ 212 | void log_close(int log_id) { 213 | if (!log_valid(log_id)) 214 | return; 215 | 216 | spin_lock(&log_locks[log_id]); 217 | 218 | if (log_files[log_id]) { 219 | fclose(log_files[log_id]); 220 | log_files[log_id] = NULL; 221 | } 222 | 223 | spin_unlock(&log_locks[log_id]); 224 | } 225 | -------------------------------------------------------------------------------- /src/zlog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zlog.h 15 | * @brief zimg log functions header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZLOG_H 22 | #define ZLOG_H 23 | 24 | #include 25 | #include "zcommon.h" 26 | #include "zspinlock.h" 27 | 28 | #define MAX_LOGS 100 29 | 30 | #define LOG_INVALID -1 31 | #define LOG_SYSTEM 0 32 | #define LOG_USER 1 33 | 34 | enum LOG_LEVEL { 35 | LOG_LEVEL_FATAL = 0, /* System is unusable */ 36 | LOG_LEVEL_ALERT, /* Action must be taken immediately */ 37 | LOG_LEVEL_CRIT, /* Critical conditions */ 38 | LOG_LEVEL_ERROR, /* Error conditions */ 39 | LOG_LEVEL_WARNING, /* Warning conditions */ 40 | LOG_LEVEL_NOTICE, /* Normal, but significant */ 41 | LOG_LEVEL_INFO, /* Information */ 42 | LOG_LEVEL_DEBUG, /* DEBUG message */ 43 | }; 44 | 45 | void log_init(void); 46 | int log_open(const char *path, const char* mode); 47 | void log_handler(const char *msg); 48 | void log_printf0(int log_id, int level, const char *fmt, ...); 49 | void log_flush(int log_id); 50 | void log_close(int log_id); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/zlscale.c: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zlscale.c 15 | * @brief processing image with lua script. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "zcommon.h" 26 | #include "zlog.h" 27 | #include "zlscale.h" 28 | 29 | int lua_convert(MagickWand *im, zimg_req_t *req); 30 | 31 | static int get_wi_cols(lua_State *L) { 32 | lua_arg *larg = pthread_getspecific(thread_key); 33 | unsigned long cols = MagickGetImageWidth(larg->img); 34 | lua_pushnumber(L, cols); 35 | return 1; 36 | } 37 | 38 | static int get_wi_rows(lua_State *L) { 39 | lua_arg *larg = pthread_getspecific(thread_key); 40 | unsigned long rows = MagickGetImageHeight(larg->img); 41 | lua_pushnumber(L, rows); 42 | return 1; 43 | } 44 | 45 | static int get_wi_quality(lua_State *L) { 46 | lua_arg *larg = pthread_getspecific(thread_key); 47 | int quality = MagickGetImageCompressionQuality(larg->img); 48 | quality = (quality == 0 ? 100 : quality); 49 | lua_pushnumber(L, quality); 50 | return 1; 51 | } 52 | 53 | static int get_wi_format(lua_State *L) { 54 | lua_arg *larg = pthread_getspecific(thread_key); 55 | char *format = MagickGetImageFormat(larg->img); 56 | LOG_PRINT(LOG_DEBUG, "get_wi_format: %s", format); 57 | lua_pushstring(L, format); 58 | free(format); 59 | return 1; 60 | } 61 | 62 | static int scale_wi(lua_State *L) { 63 | double cols = lua_tonumber(L, 1); 64 | double rows = lua_tonumber(L, 2); 65 | 66 | LOG_PRINT(LOG_DEBUG, "cols = %f rows = %f", cols, rows); 67 | lua_arg *larg = pthread_getspecific(thread_key); 68 | int ret = MagickResizeImage(larg->img, cols, rows, LanczosFilter, 1.0); 69 | //int ret = MagickScaleImage(larg->img, cols, rows); 70 | lua_pushnumber(L, ret); 71 | return 1; 72 | } 73 | 74 | static int crop_wi(lua_State *L) { 75 | double x = lua_tonumber(L, 1); 76 | double y = lua_tonumber(L, 2); 77 | double cols = lua_tonumber(L, 3); 78 | double rows = lua_tonumber(L, 4); 79 | 80 | lua_arg *larg = pthread_getspecific(thread_key); 81 | int ret = MagickCropImage(larg->img, cols, rows, x, y); 82 | lua_pushnumber(L, ret); 83 | return 1; 84 | } 85 | 86 | static int rotate_wi(lua_State *L) { 87 | int ret = -1; 88 | double rotate = lua_tonumber(L, 1); 89 | 90 | lua_arg *larg = pthread_getspecific(thread_key); 91 | LOG_PRINT(LOG_DEBUG, "wi_rotate(im, %d)", rotate); 92 | PixelWand *background = NewPixelWand(); 93 | if (background == NULL) { 94 | lua_pushnumber(L, ret); 95 | return 1; 96 | } 97 | ret = PixelSetColor(background, "white"); 98 | if (ret != MagickTrue) { 99 | DestroyPixelWand(background); 100 | lua_pushnumber(L, ret); 101 | return 1; 102 | } 103 | ret = MagickRotateImage(larg->img, background, rotate); 104 | LOG_PRINT(LOG_DEBUG, "rotate() ret = %d", ret); 105 | 106 | DestroyPixelWand(background); 107 | lua_pushnumber(L, ret); 108 | return 1; 109 | } 110 | 111 | static int gray_wi(lua_State *L) { 112 | lua_arg *larg = pthread_getspecific(thread_key); 113 | int ret = MagickSetImageType(larg->img, GrayscaleType); 114 | LOG_PRINT(LOG_DEBUG, "gray_wi: ret = %d", ret); 115 | lua_pushnumber(L, ret); 116 | return 1; 117 | } 118 | 119 | static int set_wi_quality(lua_State *L) { 120 | int quality = lua_tonumber(L, 1); 121 | 122 | lua_arg *larg = pthread_getspecific(thread_key); 123 | int ret = MagickSetImageCompressionQuality(larg->img, quality); 124 | lua_pushnumber(L, ret); 125 | return 1; 126 | } 127 | 128 | static int set_wi_format(lua_State *L) { 129 | const char *format = lua_tostring(L, 1); 130 | 131 | lua_arg *larg = pthread_getspecific(thread_key); 132 | int ret = MagickSetImageFormat(larg->img, format); 133 | LOG_PRINT(LOG_DEBUG, "set_wi_format: %s ret = %d", format, ret); 134 | lua_pushnumber(L, ret); 135 | return 1; 136 | } 137 | 138 | static int zimg_type(lua_State *L) { 139 | lua_arg *larg = pthread_getspecific(thread_key); 140 | lua_pushstring(L, larg->trans_type); 141 | LOG_PRINT(LOG_DEBUG, "zimg_type: %s", larg->trans_type); 142 | return 1; 143 | } 144 | 145 | static int zimg_ret(lua_State *L) { 146 | lua_arg *larg = pthread_getspecific(thread_key); 147 | larg->lua_ret = lua_tonumber(L, 1); 148 | return 0; 149 | } 150 | 151 | const struct luaL_reg zimg_lib[] = { 152 | //{"__gc", destroy_wi_image }, 153 | {"cols", get_wi_cols }, 154 | {"rows", get_wi_rows }, 155 | {"quality", get_wi_quality }, 156 | {"format", get_wi_format }, 157 | {"scale", scale_wi }, 158 | {"crop", crop_wi }, 159 | {"rotate", rotate_wi }, 160 | {"gray", gray_wi }, 161 | {"set_quality", set_wi_quality }, 162 | {"set_format", set_wi_format }, 163 | {"type", zimg_type }, 164 | {"ret", zimg_ret }, 165 | {NULL, NULL } 166 | }; 167 | 168 | static int lua_log_print(lua_State *L) { 169 | int log_level = lua_tonumber(L, 1); 170 | const char *log_str = lua_tostring(L, 2); 171 | LOG_PRINT(log_level, "zimg_lua: %s", log_str); 172 | return 0; 173 | } 174 | 175 | const struct luaL_Reg loglib[] = { 176 | {"print", lua_log_print }, 177 | {NULL, NULL } 178 | }; 179 | 180 | /** 181 | * @brief lua_convert the function of convert image by lua 182 | * 183 | * @param im the im object which will be convert 184 | * @param req the zimg request 185 | * 186 | * @return 1 for OK and -1 for fail 187 | */ 188 | int lua_convert(MagickWand *im, zimg_req_t *req) { 189 | int ret = -1; 190 | LOG_PRINT(LOG_DEBUG, "lua_convert: %s", req->type); 191 | MagickResetIterator(im); 192 | MagickSetImageOrientation(im, TopLeftOrientation); 193 | 194 | if (req->thr_arg->L != NULL) { 195 | lua_arg *larg = (lua_arg *)malloc(sizeof(lua_arg)); 196 | if (larg == NULL) 197 | return -1; 198 | larg->lua_ret = ret; 199 | larg->trans_type = req->type; 200 | larg->img = im; 201 | pthread_setspecific(thread_key, larg); 202 | //luaL_dofile(req->thr_arg->L, settings.script_name); 203 | lua_getglobal(req->thr_arg->L, "f"); 204 | if (lua_pcall(req->thr_arg->L, 0, 0, 0) != 0) { 205 | LOG_PRINT(LOG_WARNING, "lua f() failed!"); 206 | } 207 | 208 | ret = larg->lua_ret; 209 | free(larg); 210 | } else 211 | LOG_PRINT(LOG_WARNING, "no lua_stats, lua_convert failed!"); 212 | 213 | return ret; 214 | } 215 | -------------------------------------------------------------------------------- /src/zlscale.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zlscale.h 15 | * @brief processing image with lua script header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZLSCALE_H 22 | #define ZLSCALE_H 23 | 24 | #include 25 | 26 | typedef struct lua_arg_s { 27 | MagickWand *img; 28 | char *trans_type; 29 | int lua_ret; 30 | } lua_arg; 31 | 32 | int lua_convert(MagickWand *im, zimg_req_t *req); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/zmd5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zmd5.h 15 | * @brief calculate md5 functions header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZMD5_H 22 | #define ZMD5_H 23 | 24 | #include 25 | 26 | /* use OpenSSL functions when available */ 27 | #ifdef HAVE_SSL 28 | #include 29 | 30 | #define md5_state_t MD5_CTX 31 | #define md5_init(c) MD5_Init(c) 32 | #define md5_append(c, data, len) MD5_Update(c, data, len); 33 | #define md5_finish(c, md) MD5_Final(md, c) 34 | 35 | #else 36 | /* 37 | * This package supports both compile-time and run-time determination of CPU 38 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 39 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 40 | * defined as non-zero, the code will be compiled to run only on big-endian 41 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 42 | * run on either big- or little-endian CPUs, but will run slightly less 43 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 44 | */ 45 | 46 | typedef uint8_t md5_byte_t; /* 8-bit byte */ 47 | typedef uint32_t md5_word_t; /* 32-bit word */ 48 | 49 | /* Define the state of the MD5 Algorithm. */ 50 | typedef struct md5_state_s { 51 | md5_word_t count[2]; /* message length in bits, lsw first */ 52 | md5_word_t abcd[4]; /* digest buffer */ 53 | md5_byte_t buf[64]; /* accumulate block */ 54 | } md5_state_t; 55 | 56 | #ifdef __cplusplus 57 | extern "C" 58 | { 59 | #endif 60 | 61 | /* Initialize the algorithm. */ 62 | void md5_init(md5_state_t *pms); 63 | 64 | /* Append a string to the message. */ 65 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 66 | 67 | /* Finish the message and return the digest. */ 68 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 69 | 70 | #ifdef __cplusplus 71 | } /* end extern "C" */ 72 | #endif 73 | 74 | #endif /* md5_INCLUDED */ 75 | 76 | #endif /* HAVE_SSL */ 77 | -------------------------------------------------------------------------------- /src/zscale.c: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zscale.c 15 | * @brief scale image functions by graphicsmagick. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "zlog.h" 28 | #include "zcommon.h" 29 | #include "zscale.h" 30 | 31 | static int proportion(MagickWand *im, int p_type, int cols, int rows); 32 | static int crop(MagickWand *im, int x, int y, int cols, int rows); 33 | int convert(MagickWand *im, zimg_req_t *req); 34 | 35 | /** 36 | * @brief proportion proportion function 37 | * 38 | * @param im the image 39 | * @param p_type p type 40 | * @param cols width of target image 41 | * @param rows height of target image 42 | * 43 | * @return 0 for OK and -1 for fail 44 | */ 45 | static int proportion(MagickWand *im, int p_type, int cols, int rows) { 46 | int ret = -1; 47 | unsigned long im_cols = MagickGetImageWidth(im); 48 | unsigned long im_rows = MagickGetImageHeight(im); 49 | 50 | if (settings.disable_zoom_up == 1) { 51 | if (p_type == 3) { 52 | cols = cols > 100 ? 100 : cols; 53 | rows = rows > 100 ? 100 : rows; 54 | } else { 55 | cols = cols > im_cols ? im_cols : cols; 56 | rows = rows > im_rows ? im_rows : rows; 57 | } 58 | } 59 | 60 | if (p_type == 1) { 61 | if (cols == 0 || rows == 0) { 62 | if (cols > 0) { 63 | rows = (uint32_t)round(((double)cols / im_cols) * im_rows); 64 | } else { 65 | cols = (uint32_t)round(((double)rows / im_rows) * im_cols); 66 | } 67 | ret = MagickResizeImage(im, cols, rows, LanczosFilter, 1.0); 68 | LOG_PRINT(LOG_DEBUG, "p=1, wi_scale(im, %d, %d) ret = %d", cols, rows, ret); 69 | //ret = MagickScaleImage(im, cols, rows); 70 | } else { 71 | uint32_t x = 0, y = 0, s_cols, s_rows; 72 | double cols_rate = (double)cols / im_cols; 73 | double rows_rate = (double)rows / im_rows; 74 | 75 | if (cols_rate > rows_rate) { 76 | s_cols = cols; 77 | s_rows = (uint32_t)round(cols_rate * im_rows); 78 | y = (uint32_t)floor((s_rows - rows) / 2.0); 79 | } else { 80 | s_cols = (uint32_t)round(rows_rate * im_cols); 81 | s_rows = rows; 82 | x = (uint32_t)floor((s_cols - cols) / 2.0); 83 | } 84 | ret = MagickResizeImage(im, s_cols, s_rows, LanczosFilter, 1.0); 85 | LOG_PRINT(LOG_DEBUG, "p=2, wi_scale(im, %d, %d) ret = %d", s_cols, s_rows, ret); 86 | //ret = MagickScaleImage(im, s_cols, s_rows); 87 | 88 | ret = MagickCropImage(im, cols, rows, x, y); 89 | LOG_PRINT(LOG_DEBUG, "p=2, wi_crop(im, %d, %d, %d, %d) ret = %d", x, y, cols, rows, ret); 90 | } 91 | } else if (p_type == 2) { 92 | uint32_t x, y; 93 | x = (uint32_t)floor((im_cols - cols) / 2.0); 94 | y = (uint32_t)floor((im_rows - rows) / 2.0); 95 | ret = MagickCropImage(im, cols, rows, x, y); 96 | LOG_PRINT(LOG_DEBUG, "p=2, wi_crop(im, %d, %d, %d, %d) ret = %d", x, y, cols, rows, ret); 97 | } else if (p_type == 3) { 98 | if (cols == 0 || rows == 0) { 99 | int rate = cols > 0 ? cols : rows; 100 | rows = (uint32_t)round(im_rows * (double)rate / 100); 101 | cols = (uint32_t)round(im_cols * (double)rate / 100); 102 | ret = MagickResizeImage(im, cols, rows, LanczosFilter, 1.0); 103 | LOG_PRINT(LOG_DEBUG, "p=3, wi_scale(im, %d, %d) ret = %d", cols, rows, ret); 104 | //ret = MagickScaleImage(im, cols, rows); 105 | } else { 106 | rows = (uint32_t)round(im_rows * (double)rows / 100); 107 | cols = (uint32_t)round(im_cols * (double)cols / 100); 108 | ret = MagickResizeImage(im, cols, rows, LanczosFilter, 1.0); 109 | LOG_PRINT(LOG_DEBUG, "p=3, wi_scale(im, %d, %d) ret = %d", cols, rows, ret); 110 | //ret = MagickScaleImage(im, cols, rows); 111 | } 112 | } else if (p_type == 0) { 113 | ret = MagickResizeImage(im, cols, rows, LanczosFilter, 1.0); 114 | LOG_PRINT(LOG_DEBUG, "p=0, wi_scale(im, %d, %d) ret = %d", cols, rows, ret); 115 | //ret = MagickScaleImage(im, cols, rows); 116 | } else if (p_type == 4) { 117 | double rate = 1.0; 118 | if (cols == 0 || rows == 0) { 119 | rate = cols > 0 ? (double)cols / im_cols : (double)rows / im_rows; 120 | } else { 121 | double rate_col = (double)cols / im_cols; 122 | double rate_row = (double)rows / im_rows; 123 | rate = rate_col < rate_row ? rate_col : rate_row; 124 | } 125 | cols = (uint32_t)round(im_cols * rate); 126 | rows = (uint32_t)round(im_rows * rate); 127 | ret = MagickResizeImage(im, cols, rows, LanczosFilter, 1.0); 128 | LOG_PRINT(LOG_DEBUG, "p=4, wi_scale(im, %d, %d) ret = %d", cols, rows, ret); 129 | } 130 | 131 | return ret; 132 | } 133 | 134 | /** 135 | * @brief crop crop an image 136 | * 137 | * @param im the image 138 | * @param x position x 139 | * @param y position y 140 | * @param cols target width 141 | * @param rows target height 142 | * 143 | * @return 0 for OK and -1 for fail 144 | */ 145 | static int crop(MagickWand *im, int x, int y, int cols, int rows) { 146 | int ret = -1; 147 | unsigned long im_cols = MagickGetImageWidth(im); 148 | unsigned long im_rows = MagickGetImageHeight(im); 149 | if (x < 0) x = 0; 150 | if (y < 0) y = 0; 151 | if (x >= im_cols || y >= im_rows) return -1; 152 | if (cols == 0 || im_cols < x + cols) cols = im_cols - x; 153 | if (rows == 0 || im_rows < y + rows) rows = im_rows - y; 154 | ret = MagickCropImage(im, cols, rows, x, y); 155 | LOG_PRINT(LOG_DEBUG, "wi_crop(im, %d, %d, %d, %d) ret = %d", x, y, cols, rows, ret); 156 | return ret; 157 | } 158 | 159 | /** 160 | * @brief convert convert image function 161 | * 162 | * @param im the image 163 | * @param req the zimg request 164 | * 165 | * @return 1 for OK and -1 for fail 166 | */ 167 | int convert(MagickWand *im, zimg_req_t *req) { 168 | int result = 1, ret = -1; 169 | 170 | MagickResetIterator(im); 171 | 172 | int orientation = MagickGetImageOrientation(im); 173 | if (orientation > 1) { 174 | ret = MagickAutoOrientImage(im); 175 | LOG_PRINT(LOG_DEBUG, "orientation: %d auto_orientat() ret = %d", orientation, ret); 176 | if (ret != MagickTrue) return -1; 177 | } 178 | 179 | int x = req->x, y = req->y, cols = req->width, rows = req->height; 180 | if (!(cols == 0 && rows == 0)) { 181 | /* crop and scale */ 182 | if (x == -1 && y == -1) { 183 | ret = proportion(im, req->proportion, cols, rows); 184 | LOG_PRINT(LOG_DEBUG, "proportion(im, %d, %d, %d) ret = %d", req->proportion, cols, rows, ret); 185 | if (ret != MagickTrue) return -1; 186 | } else { 187 | ret = crop(im, x, y, cols, rows); 188 | LOG_PRINT(LOG_DEBUG, "crop(im, %d, %d, %d, %d) ret = %d", x, y, cols, rows, ret); 189 | if (ret != MagickTrue) return -1; 190 | } 191 | } 192 | 193 | /* rotate image */ 194 | if (req->rotate != 0) { 195 | PixelWand *background = NewPixelWand(); 196 | if (background == NULL) return -1; 197 | ret = PixelSetColor(background, "white"); 198 | LOG_PRINT(LOG_DEBUG, "pixelwand setcolor() ret = %d", ret); 199 | if (ret != MagickTrue) { 200 | DestroyPixelWand(background); 201 | return -1; 202 | } 203 | ret = MagickRotateImage(im, background, req->rotate); 204 | LOG_PRINT(LOG_DEBUG, "wi_rotate(im, %d) ret = %d", req->rotate, ret); 205 | DestroyPixelWand(background); 206 | if (ret != MagickTrue) return -1; 207 | } 208 | 209 | /* set gray */ 210 | if (req->gray == 1) { 211 | LOG_PRINT(LOG_DEBUG, "wi_gray(im)"); 212 | //several ways to grayscale an image: 213 | //ret = MagickSetImageColorspace(im, GRAYColorspace); 214 | //ret = MagickQuantizeImage(im, 256, GRAYColorspace, 0, MagickFalse, MagickFalse); 215 | //ret = MagickSeparateImageChannel(im, GrayChannel); 216 | ret = MagickSetImageType(im, GrayscaleType); 217 | LOG_PRINT(LOG_DEBUG, "gray() ret = %d", ret); 218 | if (ret != MagickTrue) return -1; 219 | } 220 | 221 | /* set quality */ 222 | int quality = MagickGetImageCompressionQuality(im); 223 | if (quality == 0 || quality > req->quality) { 224 | ret = MagickSetImageCompressionQuality(im, req->quality); 225 | LOG_PRINT(LOG_DEBUG, "wi_set_quality(im, %d) ret = %d", req->quality, ret); 226 | if (ret != MagickTrue) return -1; 227 | } 228 | 229 | /* set format */ 230 | if (strncmp(req->fmt, "none", 4) != 0) { 231 | ret = MagickSetImageFormat(im, req->fmt); 232 | LOG_PRINT(LOG_DEBUG, "wi_set_format(im, %s) ret = %d", req->fmt, ret); 233 | if (ret != MagickTrue) return -1; 234 | } 235 | 236 | /* strip image metadata */ 237 | ret = MagickStripImage(im); 238 | LOG_PRINT(LOG_DEBUG, "strip_image() ret = %d", ret); 239 | if (ret != MagickTrue) return -1; 240 | 241 | LOG_PRINT(LOG_DEBUG, "convert(im, req) %d", result); 242 | return result; 243 | } 244 | -------------------------------------------------------------------------------- /src/zscale.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zscale.h 15 | * @brief scale image functions by graphicsmagick header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZSCALE_H 22 | #define ZSCALE_H 23 | 24 | #include "zcommon.h" 25 | #include 26 | 27 | int convert(MagickWand *im, zimg_req_t *req); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/zspinlock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zspinlock.c 15 | * @brief Spinlock functions used for log. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #include "zspinlock.h" 22 | 23 | #ifdef _MSC_VER 24 | #include 25 | #elif defined(__GNUC__) 26 | #if __GNUC__<4 || (__GNUC__==4 && __GNUC_MINOR__<1) 27 | #error GCC version must be greater or equal than 4.1.2 28 | #endif 29 | #include 30 | #else 31 | #error Currently only windows and linux os are supported 32 | #endif 33 | 34 | void spin_init(spin_lock_t* lock, long* flag); 35 | void spin_lock(spin_lock_t* lock); 36 | int spin_trylock(spin_lock_t* lock); 37 | void spin_unlock(spin_lock_t* lock); 38 | int spin_is_lock(spin_lock_t* lock); 39 | 40 | void spin_init(spin_lock_t* lock, long* flag) { 41 | #ifdef _MSC_VER 42 | InterlockedExchange((volatile long*)&lock->spin_, 0); 43 | //InterlockedExchange((long*)&lock->spin_,flag?(long)flag:(long)&lock->flag_); 44 | #elif defined(__GNUC__) 45 | __sync_and_and_fetch((long*)&lock->spin_, 0); 46 | //__sync_lock_test_and_set((long*)&lock->spin_,flag?(long)flag:(long)&lock->flag_); 47 | #endif 48 | } 49 | 50 | void spin_lock(spin_lock_t* lock) { 51 | #ifdef _MSC_VER 52 | for (; 0 != InterlockedExchange((volatile long*)&lock->spin_, 1);) { 53 | ; 54 | } 55 | #elif defined(__GNUC__) 56 | for (; 0 != __sync_fetch_and_or((long*)&lock->spin_, 1);) { 57 | ; 58 | } 59 | #endif 60 | } 61 | 62 | int spin_trylock(spin_lock_t* lock) { 63 | #ifdef _MSC_VER 64 | return !InterlockedExchange((volatile long*)&lock->spin_, 1); 65 | #elif defined(__GNUC__) 66 | return !__sync_fetch_and_or((long*)&lock->spin_, 1); 67 | #endif 68 | } 69 | 70 | void spin_unlock(spin_lock_t* lock) { 71 | #ifdef _MSC_VER 72 | InterlockedExchange((volatile long*)&lock->spin_, 0); 73 | #elif defined(__GNUC__) 74 | __sync_and_and_fetch((long*)&lock->spin_, 0); 75 | #endif 76 | } 77 | 78 | int spin_is_lock(spin_lock_t* lock) { 79 | #ifdef _MSC_VER 80 | return InterlockedExchangeAdd((volatile long*)&lock->spin_, 0); 81 | #elif defined(__GNUC__) 82 | return __sync_add_and_fetch((long*)&lock->spin_, 0); 83 | #endif 84 | } 85 | -------------------------------------------------------------------------------- /src/zspinlock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zspinlock.h 15 | * @brief Spinlock functions used for log header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZSPINLOCK_H 22 | #define ZSPINLOCK_H 23 | 24 | #include "zcommon.h" 25 | 26 | typedef struct { 27 | volatile long spin_; 28 | volatile long flag_; 29 | } spin_lock_t; 30 | 31 | void spin_init(spin_lock_t* lock, long* flag); 32 | void spin_lock(spin_lock_t* lock); 33 | void spin_unlock(spin_lock_t* lock); 34 | int spin_trylock(spin_lock_t* lock); 35 | int spin_is_lock(spin_lock_t* lock); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/zutil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zimg - high performance image storage and processing system. 3 | * http://zimg.buaa.us 4 | * 5 | * Copyright (c) 2013-2014, Peter Zhao . 6 | * All rights reserved. 7 | * 8 | * Use and distribution licensed under the BSD license. 9 | * See the LICENSE file for full text. 10 | * 11 | */ 12 | 13 | /** 14 | * @file zutil.h 15 | * @brief the util functions used by zimg header. 16 | * @author 招牌疯子 zp@buaa.us 17 | * @version 3.0.0 18 | * @date 2014-08-14 19 | */ 20 | 21 | #ifndef ZUTIL_H 22 | #define ZUTIL_H 23 | 24 | #include "zcommon.h" 25 | 26 | char * strnchr(const char *p, char c, size_t n); 27 | char * strnstr(const char *s, const char *find, size_t slen); 28 | size_t str_lcat(char *dst, const char *src, size_t size); 29 | size_t str_lcpy(char *dst, const char *src, size_t size); 30 | int bind_check(int port); 31 | pid_t gettid(void); 32 | int get_cpu_cores(void); 33 | int get_type(const char *filename, char *type); 34 | int is_file(const char *filename); 35 | int is_img(const char *filename); 36 | int is_dir(const char *path); 37 | int is_special_dir(const char *path); 38 | void get_file_path(const char *path, const char *file_name, char *file_path); 39 | int mk_dir(const char *path); 40 | int mk_dirs(const char *dir); 41 | int mk_dirf(const char *filename); 42 | int delete_file(const char *path); 43 | int is_md5(char *s); 44 | int str_hash(const char *str); 45 | int gen_key(char *key, char *md5, ...); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /test/5f189.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buaazp/zimg/5cd73c5d603f54f47f11a64e23553a4390ed6d39/test/5f189.jpeg -------------------------------------------------------------------------------- /test/ab-post.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ab -c 1 -n 1 -v 3 -H "Connection: close" -T "multipart/form-data; boundary=---1234abcd" -p testup_ab.txt http://127.0.0.1:4869/upload 3 | -------------------------------------------------------------------------------- /test/gen_random_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for ((w=3500;w<=3600;w++)); do 4 | for ((h=2600;h<=2700;h++)); do 5 | #echo "GET http://127.0.0.1:4869/5f189d8ec57f5a5a0d3dcba47fa797e2?w=$w&h=$h&p=0&g=1"; 6 | echo "GET http://127.0.0.1:4869/dedd6ff1e146ac104f190baac091f567?w=$w&h=$h"; 7 | done; 8 | done; 9 | -------------------------------------------------------------------------------- /test/get.php: -------------------------------------------------------------------------------- 1 | '; 9 | global $imagick; 10 | $imagick->readImage($image); 11 | $w = $imagick->getImageWidth(); 12 | $h = $imagick->getImageHeight(); 13 | //echo 'w = ' . $w . '
h = ' . $h . '
'; 14 | if($gray == '1') 15 | { 16 | $imagick->setImageColorspace(imagick::COLORSPACE_GRAY); 17 | } 18 | if($width == '0' && $height == '0') 19 | { 20 | //$imagick->setImageFormat(‘JPEG’); 21 | $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); 22 | $a = $imagick->getImageCompressionQuality() * 0.75; 23 | if ($a == 0) { 24 | $a = 75; 25 | } 26 | $imagick->setImageCompressionQuality($a); 27 | $imagick->stripImage(); 28 | $imagick->writeImage($width . '_' . $height . '_' . $propor .'_' . $gray); 29 | $rst = 1; 30 | } 31 | else if(($width != '0' && $w > $width) || ($height != '0' && $h > $height)) 32 | { 33 | if($propor == '0') 34 | { 35 | if($width == '0' || $height == '0') 36 | { 37 | $rst = -1; 38 | return $rst; 39 | } 40 | else 41 | { 42 | //echo 'width = ' . $width . '
height = ' . $height . '
'; 43 | $imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1, false); 44 | } 45 | } 46 | else 47 | { 48 | if($width == '0') 49 | { 50 | $width = $height * $w / $h; 51 | } 52 | if($height == '0') 53 | { 54 | $height = $width * $h / $w; 55 | } 56 | //echo 'width = ' . $width . '
height = ' . $height . '
'; 57 | $imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1, true); 58 | } 59 | //$imagick->setImageFormat(‘JPEG’); 60 | $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); 61 | $a = $imagick->getImageCompressionQuality() * 0.75; 62 | if ($a == 0) { 63 | $a = 75; 64 | } 65 | $imagick->setImageCompressionQuality($a); 66 | $imagick->stripImage(); 67 | $imagick->writeImage($width . '_' . $height . '_' . $propor .'_' . $gray); 68 | $rst = 1; 69 | } 70 | else if($gray == '1') 71 | { 72 | //$imagick->setImageFormat(‘JPEG’); 73 | $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); 74 | $a = $imagick->getImageCompressionQuality() * 0.75; 75 | if ($a == 0) { 76 | $a = 75; 77 | } 78 | $imagick->setImageCompressionQuality($a); 79 | $imagick->stripImage(); 80 | $imagick->writeImage($width . '_' . $height . '_' . $propor .'_' . $gray); 81 | $rst = 1; 82 | } 83 | else 84 | { 85 | $rst = 2; 86 | } 87 | 88 | return $rst; 89 | } 90 | 91 | if(is_array($_GET) && count($_GET)>0) 92 | { 93 | if(isset($_GET["md5"])) 94 | { 95 | $md5 = $_GET[md5]; 96 | if(isset($_GET["w"])) 97 | { 98 | $width = $_GET[w]; 99 | } 100 | else 101 | { 102 | $width = '0'; 103 | } 104 | if(isset($_GET["h"])) 105 | { 106 | $height = $_GET[h]; 107 | } 108 | else 109 | { 110 | $height = '0'; 111 | } 112 | if(isset($_GET["p"])) 113 | { 114 | $propor = $_GET[p]; 115 | } 116 | else 117 | { 118 | $propor = '1'; 119 | } 120 | if(isset($_GET["g"])) 121 | { 122 | $gray = $_GET[g]; 123 | } 124 | else 125 | { 126 | $gray = '0'; 127 | } 128 | 129 | $file_name = './'. $md5 . '.jpeg'; 130 | //echo $file_name . '
'; 131 | if($width == '0' && $height == '0' && $gray == '0') 132 | { 133 | $imagick->readImage($file_name); 134 | header( "Content-Type: image/jpeg" ); 135 | echo $imagick; 136 | } 137 | else 138 | { 139 | $rst = convert($file_name, $width, $height, $propor, $gray); 140 | //echo 'rst = ' . $rst . '
'; 141 | if($rst == 1) 142 | { 143 | header( "Content-Type: image/jpeg" ); 144 | echo $imagick; 145 | } 146 | else if($rst == 2) 147 | { 148 | $imagick->readImage($file_name); 149 | header( "Content-Type: image/jpeg" ); 150 | echo $imagick; 151 | } 152 | else 153 | { 154 | header( "Content-Type: text/html" ); 155 | echo "

404 Not Found!

"; 156 | } 157 | } 158 | } 159 | else 160 | { 161 | header( "Content-Type: text/html" ); 162 | echo "

404 Not Found!

"; 163 | } 164 | } 165 | else 166 | { 167 | echo "

404 Not Found!

"; 168 | } 169 | 170 | 171 | $imagick->clear(); 172 | $imagick->destroy(); 173 | ?> 174 | 175 | -------------------------------------------------------------------------------- /test/post.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for i in `seq 10000` 4 | do 5 | echo "====================start" >> press.up 6 | curl -F "blob=@testup.jpeg;type=image/jpeg" "http://127.0.0.1:4869/upload" >> press.up 7 | echo "=====================done" >> press.up 8 | done 9 | 10 | -------------------------------------------------------------------------------- /test/testup.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buaazp/zimg/5cd73c5d603f54f47f11a64e23553a4390ed6d39/test/testup.jpeg -------------------------------------------------------------------------------- /test/upload.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "log" 9 | "mime/multipart" 10 | "net/http" 11 | "os" 12 | ) 13 | 14 | // 获取大小的接口 15 | type Sizer interface { 16 | Size() int64 17 | } 18 | 19 | // hello world, the web server 20 | func HelloServer(w http.ResponseWriter, r *http.Request) { 21 | if "POST" == r.Method { 22 | for k, v := range r.Header { 23 | for _, vv := range v { 24 | fmt.Printf("k: %v v: %v\n", k, vv) 25 | } 26 | } 27 | 28 | b1, err := ioutil.ReadAll(r.Body) 29 | n1 := len(b1) 30 | if err != nil { 31 | http.Error(w, err.Error(), 500) 32 | return 33 | } 34 | fmt.Printf("%d bytes:\n%s\n", n1, string(b1)) 35 | 36 | /* 37 | file, header, err := r.FormFile("filename") 38 | if err != nil { 39 | http.Error(w, err.Error(), 500) 40 | return 41 | } 42 | defer file.Close() 43 | 44 | f, err := os.Create("gosvr." + header.Filename) 45 | defer f.Close() 46 | io.Copy(f, file) 47 | */ 48 | 49 | w.Header().Add("Content-Type", "text/html") 50 | w.WriteHeader(200) 51 | //fmt.Fprintf(w, "上传文件的大小为: %d
\n", file.(Sizer).Size()) 52 | fmt.Fprintf(w, "HTTP包体的大小为: %d
\n", n1) 53 | return 54 | } 55 | 56 | // 上传页面 57 | w.Header().Add("Content-Type", "text/html") 58 | w.WriteHeader(200) 59 | html := ` 60 |
61 | Send this file: 62 | 63 |
64 | ` 65 | io.WriteString(w, html) 66 | } 67 | 68 | func sendHandler(w http.ResponseWriter, r *http.Request) { 69 | Upload() 70 | } 71 | 72 | func main() { 73 | http.HandleFunc("/send", sendHandler) 74 | http.HandleFunc("/", HelloServer) 75 | err := http.ListenAndServe(":12345", nil) 76 | if err != nil { 77 | log.Fatal("ListenAndServe: ", err) 78 | } 79 | } 80 | 81 | func Upload() (err error) { 82 | // Create buffer 83 | buf := new(bytes.Buffer) // caveat IMO dont use this for large files, \ 84 | // create a tmpfile and assemble your multipart from there (not tested) 85 | w := multipart.NewWriter(buf) 86 | 87 | upload_target := "http://127.0.0.1:12345/" 88 | filename := "5f189.jpeg" 89 | 90 | // Create file field 91 | fw, err := w.CreateFormFile("file", filename) //这里的file很重要,必须和服务器端的FormFile一致 92 | if err != nil { 93 | fmt.Println("c") 94 | return err 95 | } 96 | fd, err := os.Open(filename) 97 | if err != nil { 98 | fmt.Println("d") 99 | return err 100 | } 101 | 102 | defer fd.Close() 103 | // Write file field from file to upload 104 | _, err = io.Copy(fw, fd) 105 | if err != nil { 106 | fmt.Println("e") 107 | return err 108 | } 109 | // Important if you do not close the multipart writer you will not have a 110 | // terminating boundry 111 | w.Close() 112 | 113 | req, err := http.NewRequest("POST", upload_target, buf) 114 | if err != nil { 115 | fmt.Println("f") 116 | return err 117 | } 118 | req.Header.Set("Content-Type", w.FormDataContentType()) 119 | var client http.Client 120 | res, err := client.Do(req) 121 | if err != nil { 122 | fmt.Println("g") 123 | return err 124 | } 125 | io.Copy(os.Stderr, res.Body) // Replace this with Status.Code check 126 | fmt.Println("h") 127 | 128 | return err 129 | } 130 | -------------------------------------------------------------------------------- /wercker.yml: -------------------------------------------------------------------------------- 1 | # This references a standard debian container from the 2 | # Docker Hub https://registry.hub.docker.com/_/debian/ 3 | # Read more about containers on our dev center 4 | # http://devcenter.wercker.com/docs/containers/index.html 5 | box: ubuntu 6 | # You can also use services such as databases. Read more on our dev center: 7 | # http://devcenter.wercker.com/docs/services/index.html 8 | # services: 9 | # - postgres 10 | # http://devcenter.wercker.com/docs/services/postgresql.html 11 | 12 | # - mongodb 13 | # http://devcenter.wercker.com/docs/services/mongodb.html 14 | 15 | # This is the build pipeline. Pipelines are the core of wercker 16 | # Read more about pipelines on our dev center 17 | # http://devcenter.wercker.com/docs/pipelines/index.html 18 | build: 19 | # Steps make up the actions in your pipeline 20 | # Read more about steps on our dev center: 21 | # http://devcenter.wercker.com/docs/steps/index.html 22 | steps: 23 | # Update the apt-get 24 | - script: 25 | name: apt-get update 26 | code: | 27 | sudo apt-get update -qq 28 | 29 | # Get the dependencies 30 | - script: 31 | name: apt-get install 32 | code: | 33 | sudo apt-get install -y build-essential autoconf libtool 34 | sudo apt-get install -y nasm openssl cmake libevent-dev libpng-dev libmemcached-dev 35 | 36 | # Build the program 37 | - script: 38 | name: make 39 | code: | 40 | make 41 | 42 | # Run the program 43 | - script: 44 | name: run 45 | code: | 46 | cd bin 47 | ./zimg conf/zimg.lua 48 | 49 | # Check the program 50 | - script: 51 | name: check 52 | code: | 53 | cd bin 54 | ls -l 55 | ps aux|grep zimg 56 | 57 | --------------------------------------------------------------------------------