├── .gitignore ├── .gitmodules ├── .travis.yml ├── EXPERIMENTAL ├── Makefile.frag ├── README.md ├── TODO.md ├── config.m4 ├── config.w32 ├── examples ├── async.php ├── check.php ├── chmod.php ├── debug_timer.php ├── fingerd.php ├── fs.php ├── fs_poll.php ├── fs_truncate.php ├── fsevevnt.php ├── fstat.php ├── fsw.php ├── getaddrinfo.php ├── gethostbyname.php ├── http.php ├── http_server.php ├── idle.php ├── lstat.php ├── mkdir.php ├── pipe.php ├── pipe_bind_connect.php ├── poll.php ├── prepare.php ├── queue.php ├── readdir.php ├── readlink.php ├── rename.php ├── request.php ├── rmdir.php ├── run_once.php ├── sendfile.php ├── simple_http_server.php ├── spawn.php ├── spawn_fd.php ├── stat.php ├── tcp_bind.php ├── tcp_bind6.php ├── timer.php ├── tty.php ├── udp_bind.php ├── unlink.php └── utime.php ├── php_uv.c ├── php_uv.h ├── phpunit.xml.dist ├── phpuv_dtrace.d ├── tests ├── 000-load.phpt ├── 001-constants.phpt ├── 010-uv_ip4_addr.phpt ├── 010-uv_ip4_name.phpt ├── 010-uv_ip6_addr.phpt ├── 010-uv_ip6_name.phpt ├── 100-uv_async.phpt ├── 100-uv_check.phpt ├── 100-uv_prepare.phpt ├── 100-uv_stop.phpt ├── 100-uv_timer.phpt ├── 101-uv-idle.phpt ├── 200-ares_getaddrinfo.phpt ├── 300-fs.phpt ├── 310-fs-mkdir.phpt ├── 311-fs-rmdir.phpt ├── 320-fs-event.phpt ├── 320-fs-poll.phpt ├── 320-fs-sendfile.phpt ├── 330-poll.phpt ├── 399-fs-stat-regression-no14.phpt ├── 400-tcp_bind.phpt ├── 400-tcp_bind6.phpt ├── 500-udp_bind.phpt ├── 500-udp_bind6.phpt ├── 600-pipe_bind.phpt ├── 700-uv_rwlock.phpt ├── 700-uv_wrlock.phpt ├── 701-uv_mutex.phpt ├── 800-uv_queue_work.phpt ├── 800-uv_spawn.phpt ├── 800-uv_tty.phpt ├── 999-uv_chdir.phpt ├── 999-uv_cpu_info.phpt ├── 999-uv_cpuinfo.phpt ├── 999-uv_cwd.phpt ├── 999-uv_exepath.phpt ├── 999-uv_get_free_memory.phpt ├── 999-uv_get_total_memory.phpt ├── 999-uv_hrtime.phpt ├── 999-uv_http_parser.phpt ├── 999-uv_loadavg.phpt ├── 999-uv_resident_set_memory.phpt ├── 999-uv_uptime.phpt └── fixtures │ └── hello.data ├── uv.c ├── uv_http_parser.c └── uv_http_parser.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | 3 | # ignore phpized files 4 | Makefile.global 5 | acinclude.m4 6 | aclocal.m4 7 | autom4te.cache 8 | build 9 | configure 10 | configure* 11 | install-sh 12 | iltmain.sh 13 | missing 14 | mkinstalldirs 15 | run-tests.php 16 | *.lo 17 | *.o 18 | .deps 19 | .libs 20 | libtool 21 | Makefile 22 | Makefile.fragments 23 | Makefile.objects 24 | modules 25 | ltmain.sh 26 | *.la 27 | tmp-php.ini 28 | php_test_results* 29 | config.guess 30 | config.h 31 | config.h.in 32 | config.log 33 | config.nice 34 | config.status 35 | config.sub 36 | 37 | 38 | # ignore dtrace header 39 | phpuv_dtrace.h 40 | 41 | # ignore test outputs 42 | tests/*.diff 43 | tests/*.exp 44 | tests/*.log 45 | tests/*.php 46 | tests/*.sh 47 | tests/*.out 48 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "http-parser"] 2 | path = http-parser 3 | url = https://github.com/joyent/http-parser.git 4 | ignore = dirty 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.4 5 | - 5.5 6 | - 5.6 7 | 8 | before_script: 9 | - sudo apt-add-repository -y ppa:linuxjedi/ppa 10 | - sudo apt-get update -qq 11 | - sudo apt-get -y install libuv-dev 12 | - phpize && ./configure --with-uv --enable-httpparser && make && sudo make install 13 | - echo "extension=uv.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` 14 | 15 | notifications: 16 | email: false 17 | irc: 18 | channels: 19 | - "irc.freenode.org#php-uv" 20 | skip_join: true 21 | use_notice: true 22 | -------------------------------------------------------------------------------- /EXPERIMENTAL: -------------------------------------------------------------------------------- 1 | this extension is experimental, 2 | its functions may change their names 3 | or move to extension all together 4 | so do not rely to much on them 5 | you have been warned! -------------------------------------------------------------------------------- /Makefile.frag: -------------------------------------------------------------------------------- 1 | phpuv_dtrace.h: 2 | dtrace -h -s $(srcdir)/phpuv_dtrace.d; \ 3 | 4 | $(srcdir)/libuv/libuv.a: 5 | $(MAKE) -C $(srcdir)/libuv 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-uv 2 | 3 | [![Build Status](https://secure.travis-ci.org/chobie/php-uv.png)](http://travis-ci.org/chobie/php-uv) 4 | 5 | interface to libuv for php (experimental). also supports http-parser. 6 | 7 | # Experimental 8 | 9 | This extension is experimental, its functions may change their names 10 | or move to extension all together so do not rely to much on them you have been warned! 11 | 12 | # Install 13 | 14 | ```` 15 | git clone https://github.com/chobie/php-uv.git --recursive 16 | cd php-uv 17 | make -C libuv 18 | # Note: please use `make -C libuv CFLAGS=-fPIC` instead of `make` on 64bit box. 19 | phpize 20 | ./configure 21 | make 22 | make install 23 | # add `extension=uv.so` to your php.ini 24 | ```` 25 | 26 | # Examples 27 | 28 | see examples and tests directory. 29 | 30 | ````php 31 | 3) { 873 | uv_idle_stop($idle); 874 | } 875 | sleep(1); 876 | }); 877 | 878 | uv_run(); 879 | ```` 880 | 881 | 882 | 883 | ### void uv_idle_stop(resource $idle) 884 | 885 | ##### *Description* 886 | 887 | stop idle callback. 888 | 889 | ##### *Parameters* 890 | 891 | *resource $idle*: uv_idle resource. 892 | 893 | ##### *Return Value* 894 | 895 | *long result*: 896 | 897 | ##### *Example* 898 | 899 | ````php 900 | 3) { 910 | uv_idle_stop($idle); 911 | } 912 | sleep(1); 913 | }); 914 | 915 | uv_run(); 916 | ```` 917 | 918 | 919 | 920 | ### void uv_getaddrinfo(resource $loop, callable $callback, string $node, string $service, array $hints) 921 | 922 | 923 | ### resource uv_tcp_init([resource $loop]) 924 | 925 | ##### *Description* 926 | 927 | create a tcp socket. 928 | 929 | ##### *Parameters* 930 | 931 | *resource $loop*: loop resource or null. if not specified loop resource then use uv_default_loop resource. 932 | 933 | ##### *Return Value* 934 | 935 | *resource php_uv*: uv resource which initialized for tcp. 936 | 937 | ##### *Example* 938 | 939 | ````php 940 | 1506 | // float(1.7421875) 1507 | // [1]=> 1508 | // float(1.427734375) 1509 | // [2]=> 1510 | // float(1.3955078125) 1511 | //} 1512 | ```` 1513 | 1514 | ##### *Note* 1515 | 1516 | returns array on windows box. (does not support load average on windows) 1517 | 1518 | 1519 | 1520 | ### double uv_uptime(void) 1521 | 1522 | ##### *Description* 1523 | 1524 | returns current uptime. 1525 | 1526 | ##### *Parameters* 1527 | 1528 | ##### *Return Value* 1529 | 1530 | *long $uptime*: 1531 | 1532 | ##### *Example* 1533 | 1534 | ````php 1535 | 1659 | // array(3) { 1660 | // ["model"]=> 1661 | // string(13) "MacBookPro8,2" 1662 | // ["speed"]=> 1663 | // int(2200) 1664 | // ["times"]=> 1665 | // array(5) { 1666 | // ["sys"]=> 1667 | // int(69952140) 1668 | // ["user"]=> 1669 | // int(38153450) 1670 | // ["idle"]=> 1671 | // int(776709120) 1672 | // ["irq"]=> 1673 | // int(0) 1674 | // ["nice"]=> 1675 | // int(0) 1676 | // } 1677 | // }... 1678 | ```` 1679 | 1680 | 1681 | 1682 | ### array uv_interface_addresses(void) 1683 | 1684 | ### resource uv_stdio_new(zval $fd, long $flags) 1685 | 1686 | ### resource uv_spawn(resource $loop, string $command, array $args, array $stdio, string $cwd, array $env = array(), callable $callback [,long $flags, array $options]) 1687 | 1688 | 1689 | ### void uv_process_kill(resource $handle, long $signal) 1690 | 1691 | ##### *Description* 1692 | 1693 | send signal to specified uv process resource. 1694 | 1695 | ##### *Parameters* 1696 | 1697 | *resource $handle*: uv resource handle (process) 1698 | 1699 | *long $signal*: 1700 | 1701 | ##### *Return Value* 1702 | 1703 | *void*: 1704 | 1705 | ##### *Example* 1706 | 1707 | 1708 | 1709 | ### void uv_kill(long $pid, long $signal) 1710 | 1711 | ##### *Description* 1712 | 1713 | send signal to specified pid. 1714 | 1715 | ##### *Parameters* 1716 | 1717 | *long $pid*: process id 1718 | 1719 | *long $signal*: 1720 | 1721 | ##### *Return Value* 1722 | 1723 | *void*: 1724 | 1725 | ##### *Example* 1726 | 1727 | 1728 | 1729 | ### bool uv_chdir(string $directory) 1730 | 1731 | ##### *Description* 1732 | 1733 | change working directory. 1734 | 1735 | ##### *Parameters* 1736 | 1737 | *string $directory*: 1738 | 1739 | ##### *Return Value* 1740 | 1741 | *bool *: 1742 | 1743 | ##### *Example* 1744 | 1745 | 1746 | 1747 | ### resource uv_rwlock_init(void) 1748 | 1749 | ##### *Description* 1750 | 1751 | initialize rwlock resource 1752 | 1753 | ##### *Parameters* 1754 | 1755 | ##### *Return Value* 1756 | 1757 | *resource $rwlock*: returns uv rwlock resource 1758 | 1759 | ##### *Example* 1760 | 1761 | 1762 | 1763 | ### uv_rwlock_rdlock(resource $handle) 1764 | 1765 | ##### *Description* 1766 | 1767 | set read lock 1768 | 1769 | ##### *Parameters* 1770 | 1771 | *resource $handle*: uv resource handle (uv rwlock) 1772 | 1773 | ##### *Return Value* 1774 | 1775 | *void *: 1776 | 1777 | ##### *Example* 1778 | 1779 | 1780 | 1781 | ### bool uv_rwlock_tryrdlock(resource $handle) 1782 | 1783 | ##### *TODO* 1784 | 1785 | * implemnt this correctly 1786 | 1787 | 1788 | 1789 | ### void uv_rwlock_rdunlock(resource $handle) 1790 | 1791 | ##### *Description* 1792 | 1793 | unlock read lock 1794 | 1795 | ##### *Parameters* 1796 | 1797 | *resource $handle*: uv resource handle (uv rwlock) 1798 | 1799 | ##### *Return Value* 1800 | 1801 | *void*: 1802 | 1803 | ##### *Example* 1804 | 1805 | 1806 | 1807 | ### uv_rwlock_wrlock(resource $handle) 1808 | 1809 | ##### *Description* 1810 | 1811 | set write lock 1812 | 1813 | ##### *Parameters* 1814 | 1815 | *resource $handle*: uv resource handle (uv rwlock) 1816 | 1817 | ##### *Return Value* 1818 | 1819 | *void *: 1820 | 1821 | ##### *Example* 1822 | 1823 | 1824 | 1825 | ### uv_rwlock_trywrlock(resource $handle) 1826 | 1827 | ##### *TODO* 1828 | 1829 | * implement this correctly 1830 | 1831 | 1832 | 1833 | ### uv_rwlock_wrunlock(resource $handle) 1834 | 1835 | ##### *Description* 1836 | 1837 | unlock write lock 1838 | 1839 | ##### *Parameters* 1840 | 1841 | *resource $handle*: uv resource handle (uv rwlock) 1842 | 1843 | ##### *Return Value* 1844 | 1845 | *void*: 1846 | 1847 | ##### *Example* 1848 | 1849 | 1850 | 1851 | ### uv_lock uv_mutex_init(void) 1852 | 1853 | ##### *Description* 1854 | 1855 | initialize mutex resource 1856 | 1857 | ##### *Parameters* 1858 | 1859 | ##### *Return Value* 1860 | 1861 | *resource $uv_mutex*: uv mutex resource 1862 | 1863 | ##### *Example* 1864 | 1865 | 1866 | 1867 | ### void uv_mutex_lock(uv_lock $lock) 1868 | 1869 | ##### *Description* 1870 | 1871 | lock mutex 1872 | 1873 | ##### *Parameters* 1874 | 1875 | *resource $handle*: uv resource handle (uv mutex) 1876 | 1877 | ##### *Return Value* 1878 | 1879 | *void*: 1880 | 1881 | ##### *Example* 1882 | 1883 | 1884 | 1885 | ### bool uv_mutex_trylock(uv_lock $lock) 1886 | 1887 | ##### *TODO* 1888 | 1889 | * implement this correctly 1890 | 1891 | 1892 | 1893 | ### uv_lock uv_sem_init(long $value) 1894 | 1895 | ##### *Description* 1896 | 1897 | initialize semaphore resource 1898 | 1899 | ##### *Parameters* 1900 | 1901 | ##### *Return Value* 1902 | 1903 | *resource $uv_sem*: 1904 | 1905 | ##### *Example* 1906 | 1907 | 1908 | 1909 | ### void uv_sem_post(uv_lock $sem) 1910 | 1911 | ##### *Description* 1912 | 1913 | post semaphore 1914 | 1915 | ##### *Parameters* 1916 | 1917 | *resource $handle*: uv resource handle (uv sem) 1918 | 1919 | ##### *Return Value* 1920 | 1921 | *void*: 1922 | 1923 | ##### *Example* 1924 | 1925 | 1926 | 1927 | ### void uv_sem_wait(uv_lock $sem) 1928 | 1929 | ##### *Todo* 1930 | 1931 | * implemnt this correctly 1932 | 1933 | 1934 | 1935 | ### void uv_sem_trywait(uv_lock $sem) 1936 | 1937 | ##### *Todo* 1938 | 1939 | * implment this correctly 1940 | 1941 | 1942 | 1943 | ### resource uv_prepare_init(resource $loop) 1944 | 1945 | ##### *Description* 1946 | 1947 | initialize prepare resource 1948 | 1949 | ##### *Parameters* 1950 | 1951 | *resource $loop*: uv loop handle 1952 | 1953 | ##### *Return Value* 1954 | 1955 | *resource $uv_prepare*: 1956 | 1957 | ##### *Example* 1958 | 1959 | ````php 1960 | 3) { 2065 | uv_idle_stop($idle); 2066 | } 2067 | sleep(1); 2068 | }); 2069 | 2070 | uv_check_start($check, function($check, $status){ 2071 | echo "Hello"; 2072 | uv_check_stop($check); 2073 | }); 2074 | 2075 | uv_run(); 2076 | ```` 2077 | 2078 | 2079 | ### void uv_check_stop(resource $handle) 2080 | 2081 | ##### *Description* 2082 | 2083 | stop check callback 2084 | 2085 | ##### *Parameters* 2086 | 2087 | *resource $check*: uv resource handle (check) 2088 | 2089 | ##### *Return Value* 2090 | 2091 | *void *: 2092 | 2093 | 2094 | 2095 | ### resource uv_async_init(resource $loop, callable $callback) 2096 | 2097 | ##### *Description* 2098 | 2099 | setup async callback 2100 | 2101 | ##### *Parameters* 2102 | 2103 | *resource $loop*: uv loop resource 2104 | 2105 | *callback $callback*: 2106 | 2107 | ##### *Return Value* 2108 | 2109 | *resource *: uv async resource 2110 | 2111 | ##### *Example* 2112 | 2113 | 2114 | 2115 | ### void uv_async_send(resource $handle) 2116 | 2117 | ##### *Description* 2118 | 2119 | send async callback immidiately 2120 | 2121 | ##### *Parameters* 2122 | 2123 | *resource $handle*: uv async handle 2124 | 2125 | ##### *Return Value* 2126 | 2127 | *void*: 2128 | 2129 | ##### *Example* 2130 | 2131 | 2132 | ### void uv_queue_work(resource $loop, callable $callback, callable $after_callback) 2133 | 2134 | ##### *Description* 2135 | 2136 | execute callbacks in another thread (requires Thread Safe enabled PHP) 2137 | 2138 | 2139 | ### resource uv_fs_open(resource $loop, string $path, long $flag, long $mode, callable $callback) 2140 | 2141 | ##### *Description* 2142 | 2143 | open specified file 2144 | 2145 | ##### *Parameters* 2146 | 2147 | *resource $loop*: uv_loop resource. 2148 | 2149 | *string $path*: file path 2150 | 2151 | *long $flag*: file flag. this should be UV::O_RDONLY and some constants flag. 2152 | 2153 | *long $mode*: mode flag. this should be UV::S_IRWXU and some mode flag. 2154 | 2155 | *callable $calback*: this callback parameter expects (resource $stream) 2156 | 2157 | 2158 | ##### *Return Value* 2159 | 2160 | *void*: 2161 | 2162 | ##### *Example* 2163 | 2164 | ````php 2165 | 2959 | // array(8) { 2960 | // ["Host"]=> 2961 | // string(10) "chobie.net" 2962 | // ["User-Agent"]=> 2963 | // string(81) "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20100101 Firefox/12.0" 2964 | // ["Accept-Language"]=> 2965 | // string(14) "en-us,en;q=0.5" 2966 | // ["Accept-Encoding"]=> 2967 | // string(13) "gzip, deflate" 2968 | // ["Connection"]=> 2969 | // string(10) "keep-alive" 2970 | // ["Referer"]=> 2971 | // string(18) "http://chobie.net/" 2972 | // ["Cookie"]=> 2973 | // string(9) "key=value" 2974 | // ["Cache-Control"]=> 2975 | // string(9) "max-age=0" 2976 | // } 2977 | // ["QUERY_STRING"]=> 2978 | // string(35) "/img/http-parser.png?key=value#frag" 2979 | // ["path"]=> 2980 | // string(20) "/img/http-parser.png" 2981 | // ["query"]=> 2982 | // string(9) "key=value" 2983 | // ["fragment"]=> 2984 | // string(4) "frag" 2985 | // ["REQUEST_METHOD"]=> 2986 | // string(3) "GET" 2987 | //} 2988 | } 2989 | 2990 | ```` 2991 | 2992 | 2993 | ### void uv_stop([resource $uv_loop]) 2994 | 2995 | ##### *Description* 2996 | 2997 | ##### *Parameters* 2998 | 2999 | *resource $uv_loop*: uv loop handle 3000 | 3001 | ##### *Return Value* 3002 | 3003 | *void*: 3004 | 3005 | ##### *Example* 3006 | 3007 | 3008 | ### resource uv_signal_init([resource $uv_loop]) 3009 | 3010 | ##### *Description* 3011 | 3012 | ##### *Parameters* 3013 | 3014 | *resource $uv_loop*: uv loop handle 3015 | 3016 | ##### *Return Value* 3017 | 3018 | *resource*: 3019 | 3020 | ##### *Example* 3021 | 3022 | ### void uv_signal_start(resource $sig_handle, callable $sig_callback, int $sig_num) 3023 | 3024 | ##### *Description* 3025 | 3026 | ##### *Parameters* 3027 | 3028 | *resource $sig_handle*: 3029 | 3030 | *callable $callable*: signal callback 3031 | 3032 | *int $sig_num*: signal 3033 | 3034 | ##### *Return Value* 3035 | 3036 | *void*: 3037 | 3038 | ##### *Example* 3039 | 3040 | ### int uv_signal_stop(resource $sig_handle) 3041 | 3042 | ##### *Description* 3043 | 3044 | ##### *Parameters* 3045 | 3046 | *resource $sig_handle*: 3047 | 3048 | ##### *Return Value* 3049 | 3050 | *int $sig_num*: 3051 | 3052 | ##### *Example* 3053 | 3054 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | * implement all test cases. 4 | * improve source code.(avoids copy and paste) 5 | * more error handling 6 | * buffer allocator 7 | * documents 8 | 9 | # Known Issues 10 | 11 | * something wrong on OSX box. (corrupted queue, fs event...) 12 | * windows support (currently, this can build. but not fully tested). 13 | 14 | # functions (not implemented or not tested) 15 | 16 | * UV_EXTERN int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[],int bufcnt, uv_stream_t* send_handle, uv_write_cb cb); 17 | * UV_EXTERN int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb, uv_after_work_cb after_work_cb); 18 | * UV_EXTERN int uv_is_closing(const uv_handle_t* handle); 19 | 20 | # Not support 21 | 22 | * UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void)); 23 | we don't support thread. so this function does not need. 24 | 25 | * UV_EXTERN uv_buf_t uv_buf_init(char* base, size_t len); 26 | * UV_EXTERN size_t uv_strlcpy(char* dst, const char* src, size_t size); 27 | * UV_EXTERN size_t uv_strlcat(char* dst, const char* src, size_t size); 28 | 29 | * UV_EXTERN uv_err_t uv_dlopen(const char* filename, uv_lib_t* library); 30 | * UV_EXTERN uv_err_t uv_dlclose(uv_lib_t library); 31 | * UV_EXTERN uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr); 32 | * UV_EXTERN const char *uv_dlerror(uv_lib_t library); 33 | * UV_EXTERN void uv_dlerror_free(uv_lib_t library, const char *msg); 34 | 35 | * UV_EXTERN char** uv_setup_args(int argc, char** argv); 36 | * UV_EXTERN uv_err_t uv_get_process_title(char* buffer, size_t size); 37 | * UV_EXTERN uv_err_t uv_set_process_title(const char* title); 38 | 39 | * UV_EXTERN int uv_thread_create(uv_thread_t *tid,void (*entry)(void *arg), void *arg); 40 | * UV_EXTERN int uv_thread_join(uv_thread_t *tid); 41 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(uv, Whether to include "uv" support, 2 | [ --with-uv[=DIR] Include "uv" support]) 3 | 4 | PHP_ARG_ENABLE(httpparser, Whether to enable the "httpparser" module, 5 | [ --enable-httpparser Enable "httpparser" module support], no, no) 6 | 7 | PHP_ARG_ENABLE(uv-debug, for uv debug support, 8 | [ --enable-uv-debug Enable enable uv debug support], no, no) 9 | 10 | PHP_ARG_ENABLE(dtrace, Whether to enable the "dtrace" debug, 11 | [ --enable-dtrace Enable "dtrace" support], no, no) 12 | 13 | 14 | if test -z "$PHP_DEBUG"; then 15 | AC_ARG_ENABLE(debug, 16 | [ --enable-debug compile with debugging symbols],[ 17 | PHP_DEBUG=$enableval 18 | ],[ PHP_DEBUG=no 19 | ]) 20 | fi 21 | 22 | if test "$PHP_UV_DEBUG" != "no"; then 23 | CFLAGS="$CFLAGS -Wall -g -ggdb -O0 -DPHP_UV_DEBUG=1" 24 | AC_DEFINE(PHP_UV_DEBUG, 1, [Enable uv debug support]) 25 | fi 26 | 27 | if test "$PHP_DTRACE" != "no"; then 28 | dnl TODO: we should move this line to Makefile.frag or somewhere. 29 | case $host in 30 | *darwin*) 31 | dtrace -h -s phpuv_dtrace.d 32 | UV_SHARED_DEPENDENCIES=phpuv_dtrace.h 33 | PHP_ADD_LIBRARY(dtrace, UV_SHARED_LIBADD) 34 | AC_DEFINE(PHP_UV_DTRACE, 1, [Enable uv dtrace support]) 35 | PHP_SUBST(UV_SHARED_DEPENDENCIES) 36 | PHP_ADD_MAKEFILE_FRAGMENT 37 | ;; 38 | *linux*) 39 | echo "dtrace does not support this machine. currently OSX only" 40 | esac 41 | fi 42 | 43 | if test $PHP_UV != "no"; then 44 | SOURCES="" 45 | 46 | if test $PHP_HTTPPARSER != "no"; then 47 | SOURCES=" uv_http_parser.c http-parser/http_parser.c" 48 | AC_DEFINE([ENABLE_HTTPPARSER], [1], [ Enable http parser]) 49 | fi 50 | 51 | PHP_NEW_EXTENSION(uv, php_uv.c uv.c $SOURCES, $ext_shared) 52 | 53 | PHP_ADD_EXTENSION_DEP(uv, sockets) 54 | 55 | if test $PHP_HTTPPARSER != "no"; then 56 | PHP_ADD_INCLUDE([$ext_srcdir/http-parser]) 57 | fi 58 | 59 | SEARCH_PATH="/usr/local /usr" 60 | SEARCH_FOR="/include/uv.h" 61 | if test -r $PHP_UV/$SEARCH_FOR; then # path given as parameter 62 | UV_DIR=$PHP_UV 63 | else # search default path list 64 | AC_MSG_CHECKING([for libuv files in default path]) 65 | for i in $SEARCH_PATH ; do 66 | if test -r $i/$SEARCH_FOR; then 67 | UV_DIR=$i 68 | AC_MSG_RESULT(found in $i) 69 | fi 70 | done 71 | fi 72 | 73 | PHP_ADD_INCLUDE($UV_DIR/include) 74 | 75 | PHP_CHECK_LIBRARY(uv, uv_version, 76 | [ 77 | PHP_ADD_LIBRARY_WITH_PATH(uv, $UV_DIR/lib, UV_SHARED_LIBADD) 78 | AC_DEFINE(HAVE_UVLIB,1,[ ]) 79 | ],[ 80 | AC_MSG_ERROR([wrong uv library version or library not found]) 81 | ],[ 82 | -L$UV_DIR/lib -lm 83 | ]) 84 | 85 | case $host in 86 | *linux*) 87 | CFLAGS="$CFLAGS -lrt" 88 | esac 89 | 90 | PHP_SUBST([CFLAGS]) 91 | PHP_SUBST(UV_SHARED_LIBADD) 92 | fi 93 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | 2 | // vim:ft=javascript 3 | 4 | ARG_ENABLE("uv", "for uv support", "no"); 5 | ARG_ENABLE("uv-httpparser", "for httpparser support in the uv extension", "yes"); 6 | 7 | if (PHP_UV != "no") { 8 | var libuv_target_dir = ".\\libuv\\Release"; 9 | if (PHP_DEBUG == "yes") { 10 | libuv_target_dir = ".\\libuv\\Debug" 11 | } 12 | 13 | if (CHECK_HEADER_ADD_INCLUDE("uv.h", "CFLAGS_UV", PHP_EXTRA_INCLUDES + ';' + configure_module_dirname + "\\libuv\\include") && 14 | CHECK_LIB("uv.lib;libuv.lib", "uv", PHP_EXTRA_LIBS + ';' + libuv_target_dir) 15 | ) { 16 | if (PHP_UV_HTTPPARSER == "yes") { 17 | CHECK_HEADER_ADD_INCLUDE("http_parser.h", "CFLAGS_UV", configure_module_dirname + "\\http-parser") 18 | ADD_SOURCES(configure_module_dirname + ".\\http-parser", "http_parser.c", "uv") 19 | EXTENSION('uv', 'php_uv.c uv.c'); 20 | } else { 21 | EXTENSION('uv', 'php_uv.c uv.c'); 22 | } 23 | } else { 24 | WARNING("uv not enabled; libraries and/or headers not found. You have to execute vcbuild.bat first"); 25 | } 26 | 27 | CHECK_LIB("Iphlpapi.lib","uv", PHP_UV); 28 | CHECK_LIB("psapi.lib","uv", PHP_UV); 29 | CHECK_LIB("Ws2_32.lib","uv", PHP_UV); 30 | 31 | if (PHP_SOCKETS != "no") { 32 | ADD_EXTENSION_DEP('uv', 'sockets', false); 33 | } else { 34 | ERROR('uv depends on the sockets extension'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/async.php: -------------------------------------------------------------------------------- 1 | 3) { 13 | uv_idle_stop($idle); 14 | } 15 | sleep(1); 16 | }); 17 | 18 | uv_check_start($check, function($check, $status){ 19 | echo "Hello"; 20 | uv_check_stop($check); 21 | }); 22 | 23 | uv_run(); 24 | -------------------------------------------------------------------------------- /examples/chmod.php: -------------------------------------------------------------------------------- 1 | "chobie", 8 | "name" => "Shuhei Tanuma", 9 | "twitter" => "chobi_e", 10 | ), 11 | ); 12 | 13 | function pad($str) 14 | { 15 | return str_pad($str, 20, ' ',STR_PAD_RIGHT); 16 | } 17 | 18 | uv_listen($tcp,100, function($server) use ($users){ 19 | $client = uv_tcp_init(); 20 | uv_accept($server, $client); 21 | uv_read_start($client, function($socket, $nread, $buffer) use ($users){ 22 | $buffer = str_replace("/W","",$buffer); 23 | if ($buffer == "\r\n") { 24 | $data = ""; 25 | $keys = array("Login","Name","Twitter"); 26 | $data .= join("",array_map("pad",$keys)) . "\r\n"; 27 | foreach($users as $user) { 28 | $data .= join("", array_map("pad",array_values($user))) . "\r\n"; 29 | } 30 | 31 | uv_write($socket, $data, function($client, $stat){ 32 | uv_close($client); 33 | }); 34 | } else { 35 | var_dump($buffer); 36 | uv_close($socket); 37 | } 38 | }); 39 | }); 40 | 41 | uv_run(); -------------------------------------------------------------------------------- /examples/fs.php: -------------------------------------------------------------------------------- 1 | UV::AF_UNSPEC 6 | )); 7 | 8 | uv_run(); 9 | -------------------------------------------------------------------------------- /examples/gethostbyname.php: -------------------------------------------------------------------------------- 1 | array( 4 | "8.8.8.8" 5 | ), 6 | "port"=>53 7 | ),null); 8 | 9 | ares_gethostbyname($uv,"google.com",AF_INET, function($name, $addr){ 10 | var_dump($name); 11 | var_dump($addr); 12 | }); 13 | 14 | uv_run(); 15 | -------------------------------------------------------------------------------- /examples/http.php: -------------------------------------------------------------------------------- 1 | addListener($closure); 10 | 11 | return $server; 12 | } 13 | 14 | class HttpResponse 15 | { 16 | protected $server; 17 | protected $client; 18 | 19 | protected $code = 200; 20 | protected $headers = array(); 21 | protected $body = array(); 22 | protected $http_version = "1.0"; 23 | 24 | public function __construct($server, $client) 25 | { 26 | $this->server = $server; 27 | $this->client = $client; 28 | } 29 | 30 | public function writeHead($code, array $headers) 31 | { 32 | $this->code = $code; 33 | $this->headers = $headers; 34 | } 35 | 36 | public function write($data) 37 | { 38 | $this->body[] = $data; 39 | } 40 | 41 | public function end() 42 | { 43 | // Todo: implement correctly 44 | $buffer = "HTTP/1.0 200 OK\r\n"; 45 | foreach ($this->headers as $key => $value) { 46 | $buffer .= $key . ": " . $value . "\r\n"; 47 | } 48 | $buffer .= "\r\n"; 49 | $buffer .= join("", $this->body); 50 | 51 | uv_write($this->client, $buffer, array($this->server, "onWrite")); 52 | } 53 | } 54 | 55 | class HttpServer 56 | { 57 | protected $server; 58 | 59 | protected $clients = array(); 60 | protected $parsers = array(); 61 | protected $closure; 62 | 63 | public function __construct() 64 | { 65 | $this->server = uv_tcp_init(); 66 | } 67 | 68 | public function addListener($closure) 69 | { 70 | $this->closure = $closure; 71 | } 72 | 73 | public function onShutdown($handle, $status) 74 | { 75 | uv_close($handle, array($this, "onClose")); 76 | } 77 | 78 | public function onClose($handle) 79 | { 80 | unset($this->clients[(int)$handle]); 81 | unset($this->parsers[(int)$handle]); 82 | 83 | } 84 | 85 | public function onWrite($client, $status) 86 | { 87 | if ($status == 0) { 88 | uv_shutdown($client, array($this, "onShutdown")); 89 | } else { 90 | echo "[write_failed]"; 91 | } 92 | 93 | } 94 | 95 | public function onRead($client, $nread, $buffer) 96 | { 97 | //echo $buffer; 98 | //echo "--Error: " . uv_err_name(uv_last_error(uv_default_loop())) . PHP_EOL; 99 | 100 | if ($nread < 0) { 101 | //echo "[NREAD={$nread}]\n"; 102 | uv_shutdown($client, array($this, "onShutdown")); 103 | } else if ($nread == 0) { 104 | // nothing to do. 105 | //echo "[NREAD=0]\n"; 106 | } else { 107 | $result = array(); 108 | 109 | if (uv_http_parser_execute($this->parsers[(int)($client)], $buffer, $result)){ 110 | $response = new HttpResponse($this, $client); 111 | 112 | $closure = $this->closure; 113 | $closure($result, $response); 114 | } else { 115 | // nothing to do. (waiting next buffer) 116 | } 117 | } 118 | } 119 | 120 | public function onConnect($server, $status) 121 | { 122 | $client = uv_tcp_init(); 123 | uv_tcp_nodelay($client, 1); 124 | uv_accept($server,$client); 125 | 126 | $this->clients[(int)$client] = $client; 127 | $this->parsers[(int)($client)] = uv_http_parser_init(); 128 | 129 | uv_read_start($client, array($this, "onRead")); 130 | } 131 | 132 | public function listen($port) 133 | { 134 | uv_tcp_nodelay($this->server, 1); 135 | uv_tcp_bind6($this->server, uv_ip6_addr("::1",$port)); 136 | uv_listen($this->server, 511, array($this, "onConnect")); 137 | 138 | uv_run(uv_default_loop()); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /examples/http_server.php: -------------------------------------------------------------------------------- 1 | writeHead(200, array("Content-Type" => "text/plain")); 7 | $response->write("Hello World"); 8 | $response->end(); 9 | })->listen(8888); 10 | -------------------------------------------------------------------------------- /examples/idle.php: -------------------------------------------------------------------------------- 1 | 3) { 11 | uv_idle_stop($idle); 12 | uv_unref($idle); 13 | } 14 | sleep(1); 15 | }); 16 | 17 | uv_run(); 18 | 19 | echo "finished"; 20 | -------------------------------------------------------------------------------- /examples/lstat.php: -------------------------------------------------------------------------------- 1 | array( 11 | "8.8.8.8" 12 | ), 13 | "port"=>53 14 | ),null); 15 | 16 | ares_gethostbyname($uv,$domain, AF_INET, function($name, $addr) use ($path, $host){ 17 | $a = array_shift($addr); 18 | $address = uv_ip4_addr($a,"80"); 19 | $tcp = uv_tcp_init(); 20 | 21 | uv_tcp_connect($tcp, $address, function($client, $stat) use ($path, $host){ 22 | var_dump(uv_tcp_getpeername($client)); 23 | 24 | $request = <<"hello"), 15 | function($process, $stat, $signal){ 16 | uv_close($process,function(){}); 17 | 18 | }, $flags); 19 | 20 | uv_read2_start($out, function($out, $nread, $buffer, $stat){ 21 | echo $buffer; 22 | 23 | uv_close($out,function(){}); 24 | }); 25 | 26 | uv_run(); 27 | -------------------------------------------------------------------------------- /examples/spawn_fd.php: -------------------------------------------------------------------------------- 1 | "hello"), 16 | function($process, $stat, $signal){ 17 | uv_close($process,function(){}); 18 | 19 | }, $flags); 20 | 21 | 22 | uv_run(); -------------------------------------------------------------------------------- /examples/stat.php: -------------------------------------------------------------------------------- 1 | 3) { 11 | uv_timer_stop($timer); 12 | uv_unref($timer); 13 | } 14 | }); 15 | 16 | uv_run(); 17 | 18 | echo "finished"; -------------------------------------------------------------------------------- /examples/tty.php: -------------------------------------------------------------------------------- 1 | 14 | #include 15 | #include 16 | #include 17 | #endif 18 | 19 | #ifndef PHP_UV_DTRACE 20 | #define PHP_UV_DTRACE 0 21 | #endif 22 | 23 | #if PHP_UV_DTRACE >= 1 24 | #include 25 | #include 26 | #include "phpuv_dtrace.h" 27 | #define PHP_UV_PROBE(PROBE) PHPUV_TRACE_##PROBE(); 28 | #else 29 | #define PHP_UV_PROBE(PROBE) 30 | #endif 31 | 32 | #include "php.h" 33 | #include "uv.h" 34 | 35 | #ifdef ENABLE_HTTPPARSER 36 | #include "uv_http_parser.h" 37 | #endif 38 | 39 | #include "php_network.h" 40 | #include "php_streams.h" 41 | 42 | #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3) 43 | #include "ext/sockets/php_sockets.h" 44 | #endif 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | 59 | /* Define the entry point symbol 60 | * Zend will use when loading this module 61 | */ 62 | extern zend_module_entry uv_module_entry; 63 | #define phpext_uv_ptr &uv_module_entry 64 | 65 | extern zend_class_entry *uv_class_entry; 66 | 67 | enum php_uv_lock_type{ 68 | IS_UV_RWLOCK = 1, 69 | IS_UV_RWLOCK_RD = 2, 70 | IS_UV_RWLOCK_WR = 3, 71 | IS_UV_MUTEX = 4, 72 | IS_UV_SEMAPHORE = 5, 73 | }; 74 | 75 | enum php_uv_resource_type{ 76 | IS_UV_TCP = 0, 77 | IS_UV_UDP = 1, 78 | IS_UV_PIPE = 2, 79 | IS_UV_IDLE = 3, 80 | IS_UV_TIMER = 4, 81 | IS_UV_ASYNC = 5, 82 | IS_UV_LOOP = 6, 83 | IS_UV_HANDLE = 7, 84 | IS_UV_STREAM = 8, 85 | IS_UV_ADDRINFO = 9, 86 | IS_UV_PROCESS = 10, 87 | IS_UV_PREPARE = 11, 88 | IS_UV_CHECK = 12, 89 | IS_UV_WORK = 13, 90 | IS_UV_FS = 14, 91 | IS_UV_FS_EVENT = 15, 92 | IS_UV_TTY = 16, 93 | IS_UV_FS_POLL = 17, 94 | IS_UV_POLL = 18, 95 | IS_UV_SIGNAL = 19, 96 | IS_UV_MAX = 20 97 | }; 98 | 99 | enum php_uv_callback_type{ 100 | PHP_UV_LISTEN_CB = 0, 101 | PHP_UV_READ_CB = 1, 102 | PHP_UV_READ2_CB = 2, 103 | PHP_UV_WRITE_CB = 3, 104 | PHP_UV_SHUTDOWN_CB = 4, 105 | PHP_UV_CLOSE_CB = 5, 106 | PHP_UV_TIMER_CB = 6, 107 | PHP_UV_IDLE_CB = 7, 108 | PHP_UV_CONNECT_CB = 8, 109 | PHP_UV_GETADDR_CB = 9, 110 | PHP_UV_RECV_CB = 10, 111 | PHP_UV_SEND_CB = 11, 112 | PHP_UV_PIPE_CONNECT_CB = 12, 113 | PHP_UV_PROC_CLOSE_CB = 13, 114 | PHP_UV_PREPARE_CB = 14, 115 | PHP_UV_CHECK_CB = 15, 116 | PHP_UV_ASYNC_CB = 16, 117 | PHP_UV_WORK_CB = 17, 118 | PHP_UV_AFTER_WORK_CB = 18, 119 | PHP_UV_FS_CB = 19, 120 | PHP_UV_FS_EVENT_CB = 20, 121 | PHP_UV_FS_POLL_CB = 21, 122 | PHP_UV_POLL_CB = 22, 123 | PHP_UV_SIGNAL_CB = 23, 124 | PHP_UV_CB_MAX = 24 125 | }; 126 | 127 | typedef struct { 128 | zend_fcall_info fci; 129 | zend_fcall_info_cache fcc; 130 | } php_uv_cb_t; 131 | 132 | typedef struct { 133 | int in_free; 134 | #ifdef ZTS 135 | void ***thread_ctx; 136 | #endif 137 | int resource_id; 138 | int type; 139 | uv_os_sock_t sock; 140 | union { 141 | uv_tcp_t tcp; 142 | uv_udp_t udp; 143 | uv_pipe_t pipe; 144 | uv_idle_t idle; 145 | uv_timer_t timer; 146 | uv_async_t async; 147 | uv_loop_t loop; 148 | uv_handle_t handle; 149 | uv_stream_t stream; 150 | uv_getaddrinfo_t addrinfo; 151 | uv_prepare_t prepare; 152 | uv_check_t check; 153 | uv_process_t process; 154 | uv_work_t work; 155 | uv_fs_t fs; 156 | uv_fs_event_t fs_event; 157 | uv_tty_t tty; 158 | uv_fs_poll_t fs_poll; 159 | uv_poll_t poll; 160 | uv_signal_t signal; 161 | } uv; 162 | char *buffer; 163 | zval *address; 164 | zval *fs_fd; 165 | php_uv_cb_t *callback[PHP_UV_CB_MAX]; 166 | } php_uv_t; 167 | 168 | typedef struct { 169 | int is_ipv4; 170 | int resource_id; 171 | union { 172 | struct sockaddr_in ipv4; 173 | struct sockaddr_in6 ipv6; 174 | } addr; 175 | } php_uv_sockaddr_t; 176 | 177 | typedef struct { 178 | int locked; 179 | enum php_uv_lock_type type; 180 | int resource_id; 181 | union { 182 | uv_rwlock_t rwlock; 183 | uv_mutex_t mutex; 184 | uv_sem_t semaphore; 185 | } lock; 186 | } php_uv_lock_t; 187 | 188 | typedef struct { 189 | int resource_id; 190 | int fd; 191 | zval *stream; 192 | int flags; 193 | } php_uv_stdio_t; 194 | 195 | #define PHP_UV_RESOURCE_NAME "uv" 196 | #define PHP_UV_SOCKADDR_RESOURCE_NAME "uv_sockaddr" 197 | #define PHP_UV_LOOP_RESOURCE_NAME "uv_loop" 198 | #define PHP_UV_ARES_RESOURCE_NAME "uv_ares" 199 | #define PHP_UV_LOCK_RESOURCE_NAME "uv_lock" 200 | #define PHP_UV_MUTEX_RESOURCE_NAME "uv_mutex" 201 | #define PHP_UV_STDIO_RESOURCE_NAME "uv_stdio" 202 | 203 | 204 | #if PHP_VERSION_ID>=50399 205 | #define PHP_UV_LIST_INSERT(type, handle) zend_list_insert(type, handle TSRMLS_CC) 206 | #else 207 | #define PHP_UV_LIST_INSERT(type, handle) zend_list_insert(type, handle) 208 | #endif 209 | 210 | 211 | /* File/directory stat mode constants*/ 212 | #ifdef PHP_WIN32 213 | #define S_IFDIR _S_IFDIR 214 | #define S_IFREG _S_IFREG 215 | #else 216 | #ifndef S_IFDIR 217 | #define S_IFDIR 0040000 218 | #endif 219 | #ifndef S_IFREG 220 | #define S_IFREG 0100000 221 | #endif 222 | #endif 223 | 224 | /* TODO: remove these macro when libuv provides uv_inet_ntop & uv_inet_pton */ 225 | #ifdef PHP_WIN32 226 | # include "libuv/src/ares/inet_net_pton.h" 227 | # include 228 | # define uv_inet_pton ares_inet_pton 229 | # define uv_inet_ntop ares_inet_ntop 230 | #else 231 | # include 232 | # define uv_inet_pton inet_pton 233 | # define uv_inet_ntop inet_ntop 234 | #endif 235 | 236 | #endif /* PHP_UV_H */ 237 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | ./tests/ 9 | 10 | 11 | -------------------------------------------------------------------------------- /phpuv_dtrace.d: -------------------------------------------------------------------------------- 1 | provider phpuv { 2 | probe trace__minit(); 3 | }; -------------------------------------------------------------------------------- /tests/000-load.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for php-uv presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 3) { 15 | uv_idle_stop($idle); 16 | } 17 | }); 18 | 19 | uv_check_start($check, function($check, $status){ 20 | echo "Hello"; 21 | uv_check_stop($check); 22 | }); 23 | 24 | uv_run(); 25 | --EXPECT-- 26 | Hello -------------------------------------------------------------------------------- /tests/100-uv_prepare.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for uv_prepare 3 | --FILE-- 4 | 3) { 14 | uv_stop($loop); 15 | } 16 | }); 17 | 18 | uv_run(); 19 | 20 | echo "finished" . PHP_EOL; 21 | --EXPECT-- 22 | count: 0 23 | count: 1 24 | count: 2 25 | count: 3 26 | finished -------------------------------------------------------------------------------- /tests/100-uv_timer.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for uv_timer_init and uv_timer_start 3 | --FILE-- 4 | 3) { 16 | uv_timer_stop($timer); 17 | uv_unref($timer); 18 | } 19 | }); 20 | 21 | uv_run(); 22 | 23 | echo "finished"; 24 | --EXPECT-- 25 | count: 0 26 | count: 1 27 | count: 2 28 | count: 3 29 | finished -------------------------------------------------------------------------------- /tests/101-uv-idle.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for uv_idle_init and uv_idle_start 3 | --FILE-- 4 | 3) { 16 | uv_idle_stop($idle); 17 | } 18 | }); 19 | 20 | uv_run(); 21 | 22 | echo "finished"; 23 | --EXPECT-- 24 | count: 0 25 | count: 1 26 | count: 2 27 | count: 3 28 | finished 29 | -------------------------------------------------------------------------------- /tests/200-ares_getaddrinfo.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for ares_getaddrinfo 3 | --FILE-- 4 | UV::AF_UNSPEC 14 | )); 15 | 16 | uv_getaddrinfo(uv_default_loop(),function($status,$names){ 17 | echo "status: " . $status . PHP_EOL; 18 | if (is_array($names)) { 19 | echo "OK" . PHP_EOL; 20 | } else { 21 | echo "FAILED: 2nd parameter does not array" . PHP_EOL; 22 | } 23 | },"php.net", NULL ,array( 24 | "ai_family" => UV::AF_UNSPEC 25 | )); 26 | 27 | uv_run(); 28 | --EXPECT-- 29 | status: 0 30 | OK 31 | status: 0 32 | OK -------------------------------------------------------------------------------- /tests/300-fs.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for fs read and close 3 | --FILE-- 4 | 3) { 16 | uv_fs_poll_stop($rsc); 17 | uv_unref($rsc); 18 | } 19 | $i++; 20 | }, FIXTURE_PATH, 1); 21 | 22 | $timer = uv_timer_init(); 23 | uv_timer_start($timer, 100, 100, function($timer) use (&$i){ 24 | $fp = fopen(FIXTURE_PATH, "w+"); 25 | fwrite($fp,"hoge"); 26 | fclose($fp); 27 | 28 | if ($i > 4) { 29 | uv_timer_stop($timer); 30 | uv_unref($timer); 31 | } 32 | }); 33 | 34 | uv_run(); 35 | --EXPECT-- 36 | OKOKOKOKOK -------------------------------------------------------------------------------- /tests/320-fs-sendfile.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for fs_send_file 3 | --FILE-- 4 | "hello"), 17 | function($process, $stat, $signal){ 18 | uv_close($process,function(){}); 19 | 20 | }, $flags); 21 | 22 | uv_read2_start($out, function($out, $nread, $buffer, $stat){ 23 | echo $buffer; 24 | 25 | uv_close($out,function(){}); 26 | }); 27 | 28 | uv_run(); 29 | 30 | --EXPECT-- 31 | HELLO WORLD -------------------------------------------------------------------------------- /tests/800-uv_tty.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for uv_tty 3 | --FILE-- 4 | = 0) { 9 | echo "OK\n"; 10 | } 11 | if ($height >= 0) { 12 | echo "OK\n"; 13 | } 14 | }); 15 | 16 | uv_run(); 17 | --EXPECT-- 18 | OK 19 | OK -------------------------------------------------------------------------------- /tests/999-uv_chdir.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for uv_chdir 3 | --FILE-- 4 | 5 | --FILE-- 6 | 75 | string(5) "/demo" 76 | ["PATH"]=> 77 | string(5) "/demo" 78 | ["REQUEST_METHOD"]=> 79 | string(3) "GET" 80 | ["UPGRADE"]=> 81 | int(1) 82 | ["HEADERS"]=> 83 | array(6) { 84 | ["UPGRADE"]=> 85 | string(9) "WebSocket" 86 | ["CONNECTION"]=> 87 | string(7) "Upgrade" 88 | ["HOST"]=> 89 | string(11) "example.com" 90 | ["ORIGIN"]=> 91 | string(18) "http://example.com" 92 | ["WEBSOCKET_PROTOCOL"]=> 93 | string(6) "sample" 94 | ["VERSION"]=> 95 | string(3) "1.1" 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /tests/999-uv_loadavg.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for uv_loadavg 3 | --FILE-- 4 | 0) { 8 | echo "OK"; 9 | } else { 10 | echo "FAILED: {resident_mem} should be greater than 0 (maybe)"; 11 | } 12 | --EXPECT-- 13 | OK -------------------------------------------------------------------------------- /tests/999-uv_uptime.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for uv_uptime 3 | --FILE-- 4 | | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | #include "php_uv.h" 20 | #include 21 | 22 | void php_uv_init(TSRMLS_D); 23 | zend_class_entry *uv_class_entry; 24 | 25 | /* TODO: will be add soon */ 26 | static zend_function_entry php_uv_methods[] = { 27 | {NULL, NULL, NULL} 28 | }; 29 | 30 | static int php_uv_class_init(TSRMLS_D) 31 | { 32 | zend_class_entry ce; 33 | INIT_CLASS_ENTRY(ce, "UV", php_uv_methods); 34 | uv_class_entry = zend_register_internal_class(&ce TSRMLS_CC); 35 | //uv_class_entry->create_object = php_uv_new; 36 | 37 | zend_declare_class_constant_long(uv_class_entry, "RUN_DEFAULT", sizeof("RUN_DEFAULT")-1, UV_RUN_DEFAULT TSRMLS_CC); 38 | zend_declare_class_constant_long(uv_class_entry, "RUN_ONCE", sizeof("RUN_ONCE")-1, UV_RUN_ONCE TSRMLS_CC); 39 | zend_declare_class_constant_long(uv_class_entry, "RUN_NOWAIT", sizeof("RUN_NOWAIT")-1, UV_RUN_NOWAIT TSRMLS_CC); 40 | 41 | zend_declare_class_constant_long(uv_class_entry, "CHANGE", sizeof("CHANGE")-1, UV_CHANGE TSRMLS_CC); 42 | zend_declare_class_constant_long(uv_class_entry, "RENAME", sizeof("RENAME")-1, UV_RENAME TSRMLS_CC); 43 | zend_declare_class_constant_long(uv_class_entry, "READABLE",sizeof("READABLE")-1, UV_READABLE TSRMLS_CC); 44 | zend_declare_class_constant_long(uv_class_entry, "WRITABLE",sizeof("WRITABLE")-1, UV_WRITABLE TSRMLS_CC); 45 | 46 | zend_declare_class_constant_long(uv_class_entry, "O_RDONLY", sizeof("O_RDONLY")-1, O_RDONLY TSRMLS_CC); 47 | zend_declare_class_constant_long(uv_class_entry, "O_WRONLY", sizeof("O_WRONLY")-1, O_WRONLY TSRMLS_CC); 48 | zend_declare_class_constant_long(uv_class_entry, "O_RDWR", sizeof("O_RDWR")-1, O_RDWR TSRMLS_CC); 49 | zend_declare_class_constant_long(uv_class_entry, "O_CREAT", sizeof("O_CREAT")-1, O_CREAT TSRMLS_CC); 50 | zend_declare_class_constant_long(uv_class_entry, "O_EXCL", sizeof("O_EXCL")-1, O_EXCL TSRMLS_CC); 51 | zend_declare_class_constant_long(uv_class_entry, "O_TRUNC", sizeof("O_TRUNC")-1, O_TRUNC TSRMLS_CC); 52 | zend_declare_class_constant_long(uv_class_entry, "O_APPEND", sizeof("O_APPEND")-1, O_APPEND TSRMLS_CC); 53 | 54 | zend_declare_class_constant_long(uv_class_entry, "S_IFDIR", sizeof("S_IFDIR")-1, S_IFDIR TSRMLS_CC); 55 | zend_declare_class_constant_long(uv_class_entry, "S_IFREG", sizeof("S_IFREG")-1, S_IFREG TSRMLS_CC); 56 | 57 | #ifndef PHP_WIN32 58 | zend_declare_class_constant_long(uv_class_entry, "O_NOCTTY", sizeof("O_NOCTTY")-1, O_NOCTTY TSRMLS_CC); 59 | 60 | zend_declare_class_constant_long(uv_class_entry, "S_IRWXU", sizeof("S_IRWXU")-1, S_IRWXU TSRMLS_CC); 61 | zend_declare_class_constant_long(uv_class_entry, "S_IRUSR", sizeof("S_IRUSR")-1, S_IRUSR TSRMLS_CC); 62 | zend_declare_class_constant_long(uv_class_entry, "S_IWUSR", sizeof("S_IWUSR")-1, S_IWUSR TSRMLS_CC); 63 | zend_declare_class_constant_long(uv_class_entry, "S_IXUSR", sizeof("S_IXUSR")-1, S_IXUSR TSRMLS_CC); 64 | zend_declare_class_constant_long(uv_class_entry, "S_IRWXG", sizeof("S_IRWXG")-1, S_IRWXG TSRMLS_CC); 65 | zend_declare_class_constant_long(uv_class_entry, "S_IRGRP", sizeof("S_IRGRP")-1, S_IRGRP TSRMLS_CC); 66 | zend_declare_class_constant_long(uv_class_entry, "S_IWGRP", sizeof("S_IWGRP")-1, S_IWGRP TSRMLS_CC); 67 | zend_declare_class_constant_long(uv_class_entry, "S_IXGRP", sizeof("S_IXGRP")-1, S_IXGRP TSRMLS_CC); 68 | zend_declare_class_constant_long(uv_class_entry, "S_IRWXO", sizeof("S_IRWXO")-1, S_IRWXO TSRMLS_CC); 69 | zend_declare_class_constant_long(uv_class_entry, "S_IROTH", sizeof("S_IROTH")-1, S_IROTH TSRMLS_CC); 70 | zend_declare_class_constant_long(uv_class_entry, "S_IWOTH", sizeof("S_IWOTH")-1, S_IWOTH TSRMLS_CC); 71 | zend_declare_class_constant_long(uv_class_entry, "S_IXOTH", sizeof("S_IXOTH")-1, S_IXOTH TSRMLS_CC); 72 | 73 | /* Non-windows Signal Constants */ 74 | zend_declare_class_constant_long(uv_class_entry, "SIG_IGN", sizeof("SIG_IGN")-1, (long) SIG_IGN TSRMLS_CC); 75 | zend_declare_class_constant_long(uv_class_entry, "SIG_DFL", sizeof("SIG_DFL")-1, (long) SIG_DFL TSRMLS_CC); 76 | zend_declare_class_constant_long(uv_class_entry, "SIG_ERR", sizeof("SIG_ERR")-1, (long) SIG_ERR TSRMLS_CC); 77 | zend_declare_class_constant_long(uv_class_entry, "SIGHUP", sizeof("SIGHUP")-1, (long) SIGHUP TSRMLS_CC); 78 | zend_declare_class_constant_long(uv_class_entry, "SIGINT", sizeof("SIGINT")-1, (long) SIGINT TSRMLS_CC); 79 | zend_declare_class_constant_long(uv_class_entry, "SIGQUIT", sizeof("SIGQUIT")-1, (long) SIGQUIT TSRMLS_CC); 80 | zend_declare_class_constant_long(uv_class_entry, "SIGILL", sizeof("SIGILL")-1, (long) SIGILL TSRMLS_CC); 81 | zend_declare_class_constant_long(uv_class_entry, "SIGTRAP", sizeof("SIGTRAP")-1, (long) SIGTRAP TSRMLS_CC); 82 | zend_declare_class_constant_long(uv_class_entry, "SIGABRT", sizeof("SIGABRT")-1, (long) SIGABRT TSRMLS_CC); 83 | #ifdef SIGIOT 84 | zend_declare_class_constant_long(uv_class_entry, "SIGIOT", sizeof("SIGIOT")-1, (long) SIGIOT TSRMLS_CC); 85 | #endif 86 | zend_declare_class_constant_long(uv_class_entry, "SIGBUS", sizeof("SIGBUS")-1, (long) SIGBUS TSRMLS_CC); 87 | zend_declare_class_constant_long(uv_class_entry, "SIGFPE", sizeof("SIGFPE")-1, (long) SIGFPE TSRMLS_CC); 88 | zend_declare_class_constant_long(uv_class_entry, "SIGKILL", sizeof("SIGKILL")-1, (long) SIGKILL TSRMLS_CC); 89 | zend_declare_class_constant_long(uv_class_entry, "SIGUSR1", sizeof("SIGUSR1")-1, (long) SIGUSR1 TSRMLS_CC); 90 | zend_declare_class_constant_long(uv_class_entry, "SIGSEGV", sizeof("SIGSEGV")-1, (long) SIGSEGV TSRMLS_CC); 91 | zend_declare_class_constant_long(uv_class_entry, "SIGUSR2", sizeof("SIGUSR2")-1, (long) SIGUSR2 TSRMLS_CC); 92 | zend_declare_class_constant_long(uv_class_entry, "SIGPIPE", sizeof("SIGPIPE")-1, (long) SIGPIPE TSRMLS_CC); 93 | zend_declare_class_constant_long(uv_class_entry, "SIGALRM", sizeof("SIGALRM")-1, (long) SIGALRM TSRMLS_CC); 94 | zend_declare_class_constant_long(uv_class_entry, "SIGTERM", sizeof("SIGTERM")-1, (long) SIGTERM TSRMLS_CC); 95 | #ifdef SIGSTKFLT 96 | zend_declare_class_constant_long(uv_class_entry, "SIGSTKFLT",sizeof("SIGSTKFLT")-1, (long) SIGSTKFLT TSRMLS_CC); 97 | #endif 98 | #ifdef SIGCLD 99 | zend_declare_class_constant_long(uv_class_entry, "SIGCLD", sizeof("SIGCLD")-1, (long) SIGCLD TSRMLS_CC); 100 | #endif 101 | #ifdef SIGCHLD 102 | zend_declare_class_constant_long(uv_class_entry, "SIGCHLD", sizeof("SIGCHLD")-1, (long) SIGCHLD TSRMLS_CC); 103 | #endif 104 | zend_declare_class_constant_long(uv_class_entry, "SIGCONT", sizeof("SIGCONT")-1, (long) SIGCONT TSRMLS_CC); 105 | zend_declare_class_constant_long(uv_class_entry, "SIGSTOP", sizeof("SIGSTOP")-1, (long) SIGSTOP TSRMLS_CC); 106 | zend_declare_class_constant_long(uv_class_entry, "SIGTSTP", sizeof("SIGTSTP")-1, (long) SIGTSTP TSRMLS_CC); 107 | zend_declare_class_constant_long(uv_class_entry, "SIGTTIN", sizeof("SIGTTIN")-1, (long) SIGTTIN TSRMLS_CC); 108 | zend_declare_class_constant_long(uv_class_entry, "SIGTTOU", sizeof("SIGTTOU")-1, (long) SIGTTOU TSRMLS_CC); 109 | zend_declare_class_constant_long(uv_class_entry, "SIGURG", sizeof("SIGURG")-1, (long) SIGURG TSRMLS_CC); 110 | zend_declare_class_constant_long(uv_class_entry, "SIGXCPU", sizeof("SIGXCPU")-1, (long) SIGXCPU TSRMLS_CC); 111 | zend_declare_class_constant_long(uv_class_entry, "SIGXFSZ", sizeof("SIGXFSZ")-1, (long) SIGXFSZ TSRMLS_CC); 112 | zend_declare_class_constant_long(uv_class_entry, "SIGVTALRM",sizeof("SIGVTALRM")-1, (long) SIGVTALRM TSRMLS_CC); 113 | zend_declare_class_constant_long(uv_class_entry, "SIGPROF", sizeof("SIGPROF")-1, (long) SIGPROF TSRMLS_CC); 114 | zend_declare_class_constant_long(uv_class_entry, "SIGWINCH", sizeof("SIGWINCH")-1, (long) SIGWINCH TSRMLS_CC); 115 | #ifdef SIGPOLL 116 | zend_declare_class_constant_long(uv_class_entry, "SIGPOLL", sizeof("SIGPOLL")-1, (long) SIGPOLL TSRMLS_CC); 117 | #endif 118 | zend_declare_class_constant_long(uv_class_entry, "SIGIO", sizeof("SIGIO")-1, (long) SIGIO TSRMLS_CC); 119 | #ifdef SIGPWR 120 | zend_declare_class_constant_long(uv_class_entry, "SIGPWR", sizeof("SIGPWR")-1, (long) SIGPWR TSRMLS_CC); 121 | #endif 122 | #ifdef SIGSYS 123 | zend_declare_class_constant_long(uv_class_entry, "SIGSYS", sizeof("SIGSYS")-1, (long) SIGSYS TSRMLS_CC); 124 | zend_declare_class_constant_long(uv_class_entry, "SIGBABY", sizeof("SIGBABY")-1, (long) SIGSYS TSRMLS_CC); 125 | #endif 126 | 127 | #else 128 | /* Windows Signal Constants */ 129 | zend_declare_class_constant_long(uv_class_entry, "SIGBREAK", sizeof("SIGBREAK")-1, (long) SIGBREAK TSRMLS_CC); 130 | zend_declare_class_constant_long(uv_class_entry, "SIGINT", sizeof("SIGINT")-1, (long) SIGINT TSRMLS_CC); 131 | zend_declare_class_constant_long(uv_class_entry, "SIGHUP", sizeof("SIGHUP")-1, (long) SIGHUP TSRMLS_CC); 132 | zend_declare_class_constant_long(uv_class_entry, "SIGWINCH", sizeof("SIGWINCH")-1, (long) SIGWINCH TSRMLS_CC); 133 | #endif 134 | 135 | zend_declare_class_constant_long(uv_class_entry, "AF_INET", sizeof("AF_INET")-1, AF_INET TSRMLS_CC); 136 | zend_declare_class_constant_long(uv_class_entry, "AF_INET6", sizeof("AF_INET6")-1, AF_INET6 TSRMLS_CC); 137 | zend_declare_class_constant_long(uv_class_entry, "AF_UNSPEC", sizeof("AF_UNSPEC")-1, AF_UNSPEC TSRMLS_CC); 138 | 139 | zend_declare_class_constant_long(uv_class_entry, "LEAVE_GROUP", sizeof("LEAVE_GROUP")-1, UV_LEAVE_GROUP TSRMLS_CC); 140 | zend_declare_class_constant_long(uv_class_entry, "JOIN_GROUP", sizeof("JOIN_GROUP")-1, UV_JOIN_GROUP TSRMLS_CC); 141 | 142 | /* for uv_handle_type */ 143 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_TCP", sizeof("IS_UV_TCP")-1, IS_UV_TCP TSRMLS_CC); 144 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_UDP", sizeof("IS_UV_UDP")-1, IS_UV_UDP TSRMLS_CC); 145 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_PIPE", sizeof("IS_UV_PIPE")-1, IS_UV_PIPE TSRMLS_CC); 146 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_IDLE", sizeof("IS_UV_IDLE")-1, IS_UV_IDLE TSRMLS_CC); 147 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_TIMER", sizeof("IS_UV_TIMER")-1, IS_UV_TIMER TSRMLS_CC); 148 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_ASYNC", sizeof("IS_UV_ASYNC")-1, IS_UV_ASYNC TSRMLS_CC); 149 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_LOOP", sizeof("IS_UV_LOOP")-1, IS_UV_LOOP TSRMLS_CC); 150 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_HANDLE", sizeof("IS_UV_HANDLE")-1, IS_UV_HANDLE TSRMLS_CC); 151 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_STREAM", sizeof("IS_UV_STREAM")-1, IS_UV_STREAM TSRMLS_CC); 152 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_ADDRINFO", sizeof("IS_UV_ADDRINFO")-1, IS_UV_ADDRINFO TSRMLS_CC); 153 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_PROCESS", sizeof("IS_UV_PROCESS")-1, IS_UV_PROCESS TSRMLS_CC); 154 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_PREPARE", sizeof("IS_UV_PREPARE")-1, IS_UV_PREPARE TSRMLS_CC); 155 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_CHECK", sizeof("IS_UV_CHECK")-1, IS_UV_CHECK TSRMLS_CC); 156 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_WORK", sizeof("IS_UV_WORK")-1, IS_UV_WORK TSRMLS_CC); 157 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_FS", sizeof("IS_UV_FS")-1, IS_UV_FS TSRMLS_CC); 158 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_FS_EVENT", sizeof("IS_UV_FS_EVENT")-1, IS_UV_FS_EVENT TSRMLS_CC); 159 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_TTY", sizeof("IS_UV_TTY")-1, IS_UV_TTY TSRMLS_CC); 160 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_FS_POLL", sizeof("IS_UV_FS_POLL")-1, IS_UV_FS_POLL TSRMLS_CC); 161 | zend_declare_class_constant_long(uv_class_entry, "IS_UV_POLL", sizeof("IS_UV_POLL")-1, IS_UV_POLL TSRMLS_CC); 162 | 163 | /* for guess handle */ 164 | zend_declare_class_constant_long(uv_class_entry, "UNKNOWN_HANDLE", sizeof("UNKNOWN_HANDLE")-1, UV_UNKNOWN_HANDLE TSRMLS_CC); 165 | zend_declare_class_constant_long(uv_class_entry, "FILE", sizeof("FILE")-1, UV_FILE TSRMLS_CC); 166 | #define XX(uc, lc) zend_declare_class_constant_long(uv_class_entry, #uc, sizeof(#uc)-1, UV_##uc TSRMLS_CC); 167 | UV_HANDLE_TYPE_MAP(XX) 168 | #undef XX 169 | zend_declare_class_constant_long(uv_class_entry, "HANDLE_TYPE_MAX", sizeof("HANDLE_TYPE_MAX")-1, UV_HANDLE_TYPE_MAX TSRMLS_CC); 170 | 171 | 172 | /* stdio flags */ 173 | zend_declare_class_constant_long(uv_class_entry, "IGNORE", sizeof("IGNORE")-1, UV_IGNORE TSRMLS_CC); 174 | zend_declare_class_constant_long(uv_class_entry, "CREATE_PIPE", sizeof("CREATE_PIPE")-1, UV_CREATE_PIPE TSRMLS_CC); 175 | zend_declare_class_constant_long(uv_class_entry, "INHERIT_FD", sizeof("INHERIT_FD")-1, UV_INHERIT_FD TSRMLS_CC); 176 | zend_declare_class_constant_long(uv_class_entry, "INHERIT_STREAM", sizeof("INHERIT_STREAM")-1, UV_INHERIT_STREAM TSRMLS_CC); 177 | zend_declare_class_constant_long(uv_class_entry, "READABLE_PIPE", sizeof("READABLE_PIPE")-1, UV_READABLE_PIPE TSRMLS_CC); 178 | zend_declare_class_constant_long(uv_class_entry, "WRITABLE_PIPE", sizeof("WRITABLE_PIPE")-1, UV_WRITABLE_PIPE TSRMLS_CC); 179 | 180 | /* process */ 181 | zend_declare_class_constant_long(uv_class_entry, "PROCESS_SETUID", sizeof("PROCESS_SETUID")-1, UV_PROCESS_SETUID TSRMLS_CC); 182 | zend_declare_class_constant_long(uv_class_entry, "PROCESS_SETGID", sizeof("PROCESS_SETGID")-1, UV_PROCESS_SETGID TSRMLS_CC); 183 | zend_declare_class_constant_long(uv_class_entry, "PROCESS_WINDOWS_VERBATIM_ARGUMENTS", sizeof("PROCESS_WINDOWS_VERBATIM_ARGUMENTS")-1, UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS TSRMLS_CC); 184 | zend_declare_class_constant_long(uv_class_entry, "PROCESS_DETACHED", sizeof("PROCESS_DETACHED")-1, UV_PROCESS_DETACHED TSRMLS_CC); 185 | 186 | #ifdef ENABLE_HTTPPARSER 187 | /* http parser */ 188 | zend_declare_class_constant_long(uv_class_entry, "HTTP_BOTH", sizeof("HTTP_BOTH")-1, HTTP_BOTH TSRMLS_CC); 189 | zend_declare_class_constant_long(uv_class_entry, "HTTP_REQUEST", sizeof("HTTP_REQUEST")-1, HTTP_REQUEST TSRMLS_CC); 190 | zend_declare_class_constant_long(uv_class_entry, "HTTP_RESPONSE", sizeof("HTTP_RESPONSE")-1, HTTP_RESPONSE TSRMLS_CC); 191 | #endif 192 | 193 | #define PHP_UV_ERRNO_GEN(code_notused, name, msg_notused) zend_declare_class_constant_long(uv_class_entry, #name, sizeof(#name)-1, UV_##name TSRMLS_CC); 194 | UV_ERRNO_MAP(PHP_UV_ERRNO_GEN) 195 | #undef PHP_UV_ERRNO_GEN 196 | 197 | return 0; 198 | } 199 | 200 | void php_uv_init(TSRMLS_D) 201 | { 202 | php_uv_class_init(TSRMLS_C); 203 | } 204 | -------------------------------------------------------------------------------- /uv_http_parser.c: -------------------------------------------------------------------------------- 1 | #include "uv_http_parser.h" 2 | 3 | static int uv_httpparser_handle; 4 | 5 | void destruct_httpparser(zend_rsrc_list_entry *rsrc TSRMLS_DC) 6 | { 7 | php_http_parser_context *obj = (php_http_parser_context *)rsrc->ptr; 8 | 9 | if (obj->headers) { 10 | zval_ptr_dtor(&obj->headers); 11 | } 12 | if (obj->data) { 13 | zval_ptr_dtor(&obj->data); 14 | } 15 | 16 | efree(obj); 17 | } 18 | 19 | void register_httpparser(int module_number) 20 | { 21 | uv_httpparser_handle = zend_register_list_destructors_ex(destruct_httpparser, NULL, PHP_UV_HTTPPARSER_RESOURCE_NAME, module_number); 22 | } 23 | 24 | /* http parser callbacks */ 25 | static int on_message_begin(http_parser *p) 26 | { 27 | return 0; 28 | } 29 | 30 | static int on_headers_complete(http_parser *p) 31 | { 32 | return 0; 33 | } 34 | 35 | static int on_message_complete(http_parser *p) 36 | { 37 | php_http_parser_context *result = p->data; 38 | result->finished = 1; 39 | 40 | if (result->tmp != NULL) { 41 | efree(result->tmp); 42 | result->tmp = NULL; 43 | result->tmp_len = 0; 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | #define PHP_HTTP_PARSER_PARSE_URL(flag, name) \ 50 | if (result->handle.field_set & (1 << flag)) { \ 51 | const char *tmp_name = at+result->handle.field_data[flag].off; \ 52 | int length = result->handle.field_data[flag].len; \ 53 | add_assoc_stringl(data, #name, (char*)tmp_name, length, 1); \ 54 | } 55 | 56 | static int on_url_cb(http_parser *p, const char *at, size_t len) 57 | { 58 | php_http_parser_context *result = p->data; 59 | zval *data = result->data; 60 | 61 | http_parser_parse_url(at, len, 0, &result->handle); 62 | add_assoc_stringl(data, "QUERY_STRING", (char*)at, len, 1); 63 | 64 | PHP_HTTP_PARSER_PARSE_URL(UF_SCHEMA, SCHEME); 65 | PHP_HTTP_PARSER_PARSE_URL(UF_HOST, HOST); 66 | PHP_HTTP_PARSER_PARSE_URL(UF_PORT, PORT); 67 | PHP_HTTP_PARSER_PARSE_URL(UF_PATH, PATH); 68 | PHP_HTTP_PARSER_PARSE_URL(UF_QUERY, QUERY); 69 | PHP_HTTP_PARSER_PARSE_URL(UF_FRAGMENT, FRAGMENT); 70 | 71 | return 0; 72 | } 73 | 74 | static int on_status_cb(http_parser *p, const char *at, size_t len) 75 | { 76 | return 0; 77 | } 78 | 79 | char *php_uv_strtoupper(char *s, size_t len) 80 | { 81 | unsigned char *c, *e; 82 | 83 | c = (unsigned char *)s; 84 | e = (unsigned char *)c+len; 85 | 86 | while (c < e) { 87 | *c = toupper(*c); 88 | if (*c == '-') *c = '_'; 89 | c++; 90 | } 91 | return s; 92 | } 93 | 94 | 95 | static int header_field_cb(http_parser *p, const char *at, size_t len) 96 | { 97 | php_http_parser_context *result = p->data; 98 | 99 | if (result->was_header_value) { 100 | if (result->tmp != NULL) { 101 | efree(result->tmp); 102 | result->tmp = NULL; 103 | result->tmp_len = 0; 104 | } 105 | result->tmp = estrndup(at, len); 106 | php_uv_strtoupper(result->tmp, len); 107 | result->tmp_len = len; 108 | } else { 109 | result->tmp = erealloc(result->tmp, len + result->tmp_len + 1); 110 | memcpy(result->tmp + result->tmp_len, at, len); 111 | result->tmp[result->tmp_len + len] = '\0'; 112 | result->tmp_len = result->tmp_len + len; 113 | } 114 | 115 | result->was_header_value = 0; 116 | return 0; 117 | } 118 | 119 | static int header_value_cb(http_parser *p, const char *at, size_t len) 120 | { 121 | php_http_parser_context *result = p->data; 122 | zval *data = result->headers; 123 | 124 | if (result->was_header_value) { 125 | zval **element; 126 | 127 | if (zend_hash_find(Z_ARRVAL_P(data), result->tmp, result->tmp_len+1, (void **)&element) == SUCCESS) { 128 | Z_STRVAL_PP(element) = erealloc(Z_STRVAL_PP(element), Z_STRLEN_PP(element) + len + 1); 129 | memcpy(Z_STRVAL_PP(element) + Z_STRLEN_PP(element), at, len); 130 | 131 | Z_STRVAL_PP(element)[Z_STRLEN_PP(element)+len] = '\0'; 132 | Z_STRLEN_PP(element) = Z_STRLEN_PP(element) + len; 133 | } 134 | } else { 135 | add_assoc_stringl(data, result->tmp, (char*)at, len, 1); 136 | } 137 | 138 | result->was_header_value = 1; 139 | return 0; 140 | } 141 | 142 | static int on_body_cb(http_parser *p, const char *at, size_t len) 143 | { 144 | php_http_parser_context *result = p->data; 145 | zval *data = result->headers; 146 | 147 | add_assoc_stringl(data, "BODY", (char*)at, len, 1); 148 | 149 | return 0; 150 | } 151 | /* end of callback */ 152 | 153 | /* {{{ proto resource uv_http_parser_init(long $target = UV::HTTP_REQUEST) 154 | */ 155 | PHP_FUNCTION(uv_http_parser_init) 156 | { 157 | long target = HTTP_REQUEST; 158 | zval *header, *result; 159 | php_http_parser_context *ctx = NULL; 160 | 161 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 162 | "|l",&target) == FAILURE) { 163 | return; 164 | } 165 | 166 | ctx = emalloc(sizeof(php_http_parser_context)); 167 | http_parser_init(&ctx->parser, target); 168 | 169 | MAKE_STD_ZVAL(header); 170 | array_init(header); 171 | 172 | MAKE_STD_ZVAL(result); 173 | array_init(result); 174 | 175 | ctx->data = result; 176 | ctx->headers = header; 177 | ctx->finished = 0; 178 | ctx->was_header_value = 1; 179 | ctx->tmp = NULL; 180 | ctx->tmp_len = 0; 181 | 182 | if (target == HTTP_RESPONSE) { 183 | ctx->is_response = 1; 184 | } else { 185 | ctx->is_response = 0; 186 | } 187 | 188 | memset(&ctx->handle, 0, sizeof(struct http_parser_url)); 189 | 190 | /* setup callback */ 191 | ctx->settings.on_message_begin = on_message_begin; 192 | ctx->settings.on_header_field = header_field_cb; 193 | ctx->settings.on_header_value = header_value_cb; 194 | ctx->settings.on_url = on_url_cb; 195 | ctx->settings.on_status = on_status_cb; 196 | ctx->settings.on_body = on_body_cb; 197 | ctx->settings.on_headers_complete = on_headers_complete; 198 | ctx->settings.on_message_complete = on_message_complete; 199 | 200 | ZEND_REGISTER_RESOURCE(return_value, ctx, uv_httpparser_handle); 201 | } 202 | 203 | /* {{{ proto bool uv_http_parser_execute(resource $parser, string $body, array &$result) 204 | */ 205 | PHP_FUNCTION(uv_http_parser_execute) 206 | { 207 | zval *z_parser = NULL, *result = NULL, *version = NULL, *headers = NULL; 208 | php_http_parser_context *context; 209 | char *body; 210 | int body_len; 211 | char version_buffer[4] = {0}; 212 | size_t nparsed = 0; 213 | 214 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 215 | "rs/a", &z_parser, &body, &body_len, &result) == FAILURE) { 216 | return; 217 | } 218 | 219 | ZEND_FETCH_RESOURCE(context, php_http_parser_context*, &z_parser, -1, PHP_UV_HTTPPARSER_RESOURCE_NAME, uv_httpparser_handle); 220 | 221 | if (context->finished == 1) { 222 | php_error_docref(NULL TSRMLS_CC, E_NOTICE, "passed uv_parser resource has already finished."); 223 | RETURN_FALSE; 224 | } 225 | 226 | context->parser.data = context; 227 | nparsed = http_parser_execute(&context->parser, &context->settings, body, body_len); 228 | 229 | if (result) { 230 | zval_dtor(result); 231 | } 232 | 233 | if (nparsed != body_len) { 234 | zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "parse failed"); 235 | return; 236 | } 237 | 238 | ZVAL_ZVAL(result, context->data, 1, 0); 239 | if (context->is_response == 0) { 240 | add_assoc_string(result, "REQUEST_METHOD", (char*)http_method_str(context->parser.method), 1); 241 | } else { 242 | add_assoc_long(result, "STATUS_CODE", (long)context->parser.status_code); 243 | } 244 | add_assoc_long(result, "UPGRADE", (long)context->parser.upgrade); 245 | 246 | MAKE_STD_ZVAL(version); 247 | snprintf(version_buffer, 4, "%d.%d", context->parser.http_major, context->parser.http_minor); 248 | ZVAL_STRING(version, version_buffer, 1); 249 | 250 | MAKE_STD_ZVAL(headers); 251 | ZVAL_ZVAL(headers, context->headers, 1, 0); 252 | 253 | add_assoc_zval(headers, "VERSION", version); 254 | add_assoc_zval(result, "HEADERS", headers); 255 | 256 | RETURN_BOOL(context->finished); 257 | } 258 | 259 | -------------------------------------------------------------------------------- /uv_http_parser.h: -------------------------------------------------------------------------------- 1 | #ifndef UV_HTTPPARSER_H 2 | #define UV_HTTPPARSER_H 3 | 4 | #include "php.h" 5 | #include "zend_exceptions.h" 6 | 7 | #include "http_parser.h" 8 | 9 | typedef struct { 10 | struct http_parser parser; 11 | struct http_parser_url handle; 12 | struct http_parser_settings settings; 13 | int is_response; 14 | int was_header_value; 15 | int finished; 16 | zval *data; 17 | zval *headers; 18 | char *tmp; 19 | size_t tmp_len; 20 | } php_http_parser_context; 21 | 22 | #define PHP_UV_HTTPPARSER_RESOURCE_NAME "uv_httpparser" 23 | 24 | void register_httpparser(int module_number); 25 | 26 | /* HTTP PARSER */ 27 | ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_http_parser_init, 0, 0, 1) 28 | ZEND_ARG_INFO(0, target) 29 | ZEND_END_ARG_INFO() 30 | 31 | ZEND_BEGIN_ARG_INFO_EX(arginfo_uv_http_parser_execute, 0, 0, 3) 32 | ZEND_ARG_INFO(0, resource) 33 | ZEND_ARG_INFO(0, buffer) 34 | ZEND_ARG_INFO(0, setting) 35 | ZEND_END_ARG_INFO() 36 | 37 | PHP_FUNCTION(uv_http_parser_init); 38 | PHP_FUNCTION(uv_http_parser_execute); 39 | 40 | #endif 41 | --------------------------------------------------------------------------------