├── .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 | [](https://travis-ci.org/buaazp/zimg) [](https://app.wercker.com/project/bykey/88aead2017ceb80b32fad3dc8997227a) [](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 | 
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 |
14 |
15 |
--------------------------------------------------------------------------------
/bin/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
24 | Welcome to zimg world!
25 | Upload image(s) to zimg:
26 |
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 |
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 |
--------------------------------------------------------------------------------