[
  {
    "path": ".clang-format",
    "content": "SortIncludes: false\nBasedOnStyle: Google\nColumnLimit: 0\nIndentWidth: 4\n"
  },
  {
    "path": ".gitattributes",
    "content": "lib/aes_acc/asm/* linguist-vendored\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "#note: experimental\n#      currently only used for generating `compile_commands.json` for clangd.\n#      to build this project, it's suggested to use `makefile` instead\n\ncmake_minimum_required(VERSION 3.7)\nproject(udp2raw)\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n\nset(CMAKE_CXX_STANDARD 11)\n\nset(SOURCE_FILES\n        main.cpp \n        lib/md5.cpp\n        lib/pbkdf2-sha1.cpp\n        lib/pbkdf2-sha256.cpp\n        encrypt.cpp\n        log.cpp\n        network.cpp\n        common.cpp\n        connection.cpp\n        misc.cpp\n        fd_manager.cpp\n        client.cpp\n        server.cpp\n        lib/aes_faster_c/aes.cpp\n        lib/aes_faster_c/wrapper.cpp\n        my_ev.cpp\n)\nset(CMAKE_CXX_FLAGS \"-Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers -O2 -g -fsanitize=address,undefined\")\n\nadd_executable(udp2raw ${SOURCE_FILES})\ntarget_link_libraries(udp2raw rt)\ntarget_link_libraries(udp2raw pthread)\ninclude_directories(SYSTEM \"libev\")\ninclude_directories(\".\")\n"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "content": "English Only.\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2017 Yu Wang (wangyucn at gmail.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Udp2raw-tunnel\n\n\nA Tunnel which turns UDP Traffic into Encrypted FakeTCP/UDP/ICMP Traffic by using Raw Socket, helps you Bypass UDP FireWalls(or Unstable UDP Environment).\n\nWhen used alone,udp2raw tunnels only UDP traffic. Nevertheless,if you used udp2raw + any UDP-based VPN together,you can tunnel any traffic(include TCP/UDP/ICMP),currently OpenVPN/L2TP/ShadowVPN and [tinyfecVPN](https://github.com/wangyu-/tinyfecVPN) are confirmed to be supported.\n\n\n![image0](images/image0.PNG)\n\nor\n\n![image_vpn](images/udp2rawopenvpn.PNG)\n\n[udp2raw wiki](https://github.com/wangyu-/udp2raw-tunnel/wiki)\n\n[简体中文](/doc/README.zh-cn.md)\n\n\n# Support Platforms\nLinux host (including desktop Linux,Android phone/tablet,OpenWRT router,or Raspberry PI) with root account or cap_net_raw capability.\n\nFor Windows and MacOS users, use the udp2raw in [this repo](https://github.com/wangyu-/udp2raw-multiplatform).\n\n# Features\n### Send/Receive UDP Packets with ICMP/FakeTCP/UDP headers\nICMP/FakeTCP headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. In ICMP header mode,udp2raw works like an ICMP tunnel.\n\nUDP headers are also supported. In UDP header mode, it behaves just like a normal UDP tunnel, and you can just make use of the other features (such as encryption, anti-replay, or connection stabilization).\n\n### Simulated TCP with Real-time/Out-of-Order Delivery\nIn FakeTCP header mode,udp2raw simulates 3-way handshake while establishing a connection,simulates seq and ack_seq while data transferring. It also simulates a few TCP options such as: `MSS`, `sackOk`, `TS`, `TS_ack`, `wscale`. Firewalls will regard FakeTCP as a TCP connection, but its essentially UDP: it supports real-time/out-of-order delivery(just as normal UDP does), no congestion control or re-transmission. So there wont be any TCP over TCP problem when using OpenVPN.\n\n### Encryption, Anti-Replay\n* Encrypt your traffic with AES-128-CBC.\n* Protect data integrity by HMAC-SHA1 (or weaker MD5/CRC32).\n* Defense replay attack with anti-replay window.\n\n[Notes on encryption](https://github.com/wangyu-/udp2raw-tunnel/wiki/Notes-on-encryption)\n\n### Failure Dectection & Stabilization (Connection Recovery)\nConection failures are detected by heartbeats. If timed-out, client will automatically change port number and reconnect. If reconnection is successful, the previous connection will be recovered, and all existing UDP conversations will stay vaild.\n\nFor example, if you use udp2raw + OpenVPN, OpenVPN won't lose connection after any reconnect, **even if network cable is re-plugged or WiFi access point is changed**.\n\n### Other Features\n* **Multiplexing** One client can handle multiple UDP connections, all of which share the same raw connection.\n\n* **Multiple Clients** One server can have multiple clients.\n\n* **NAT Support** All of the 3 modes work in NAT environments.\n\n* **OpenVZ Support** Tested on BandwagonHost VPS.\n\n* **Easy to Build** No dependencies.To cross-compile udp2raw,all you need to do is just to download a toolchain,modify makefile to point at the toolchain,run `make cross` then everything is done.(Note:Pre-compiled binaries for Desktop,RaspberryPi,Android,some Openwrt Routers are already included in [Releases](https://github.com/wangyu-/udp2raw-tunnel/releases))\n\n### Keywords\n`Bypass UDP QoS` `Bypass UDP Blocking` `Bypass OpenVPN TCP over TCP problem` `OpenVPN over ICMP` `UDP to ICMP tunnel` `UDP to TCP tunnel` `UDP over ICMP` `UDP over TCP`\n\n# Getting Started\n### Installing\nDownload binary release from https://github.com/wangyu-/udp2raw-tunnel/releases\n\n### Running\nAssume your UDP is blocked or being QOS-ed or just poorly supported. Assume your server ip is 44.55.66.77, you have a service listening on udp port 7777.\n\n```bash\n# Run at server side:\n./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777    -k \"passwd\" --raw-mode faketcp -a\n\n# Run at client side\n./udp2raw_amd64 -c -l0.0.0.0:3333  -r44.55.66.77:4096  -k \"passwd\" --raw-mode faketcp -a\n```\n(The above commands need to be run as root. For better security, with some extra steps, you can run udp2raw as non-root. Check [this link](https://github.com/wangyu-/udp2raw-tunnel/wiki/run-udp2raw-as-non-root) for more info  )\n\n###### Server Output:\n![](images/output_server.PNG)\n###### Client Output:\n![](images/output_client.PNG)\n\nNow,an encrypted raw tunnel has been established between client and server through TCP port 4096. Connecting to UDP port 3333 at the client side is equivalent to connecting to port 7777 at the server side. No UDP traffic will be exposed.\n\n### Note\nTo run on Android, check [Android_Guide](https://github.com/wangyu-/udp2raw/wiki/Android-Guide)\n\n`-a` option automatically adds an iptables rule (or a few iptables rules) for you, udp2raw relies on this iptables rule to work stably. Be aware you dont forget `-a` (its a common mistake). If you dont want udp2raw to add iptables rule automatically, you can add it manually(take a look at `-g` option) and omit `-a`.\n\n\n# Advanced Topic\n### Usage\n```\nudp2raw-tunnel\ngit version:4623f878e0    build date:Nov  3 2024 23:15:46\nrepository: https://github.com/wangyu-/udp2raw-tunnel\n\nusage:\n    run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port  [options]\n    run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port  [options]\n\ncommon options,these options must be same on both side:\n    --raw-mode            <string>        available values:faketcp(default),udp,icmp and easy-faketcp\n    -k,--key              <string>        password to gen symetric key,default:\"secret key\"\n    --cipher-mode         <string>        available values:aes128cfb,aes128cbc(default),xor,none\n    --auth-mode           <string>        available values:hmac_sha1,md5(default),crc32,simple,none\n    -a,--auto-rule                        auto add (and delete) iptables rule\n    -g,--gen-rule                         generate iptables rule then exit,so that you can copy and\n                                          add it manually.overrides -a\n    --disable-anti-replay                 disable anti-replay,not suggested\n    --fix-gro                             try to fix huge packet caused by GRO. this option is at an early stage.\n                                          make sure client and server are at same version.\nclient options:\n    --source-ip           <ip>            force source-ip for raw socket\n    --source-port         <port>          force source-port for raw socket,tcp/udp only\n                                          this option disables port changing while re-connecting\nother options:\n    --conf-file           <string>        read options from a configuration file instead of command line.\n                                          check example.conf in repo for format\n    --fifo                <string>        use a fifo(named pipe) for sending commands to the running program,\n                                          check readme.md in repository for supported commands.\n    --log-level           <number>        0:never    1:fatal   2:error   3:warn\n                                          4:info (default)     5:debug   6:trace\n    --log-position                        enable file name,function name,line number in log\n    --disable-color                       disable log color\n    --disable-bpf                         disable the kernel space filter,most time its not necessary\n                                          unless you suspect there is a bug\n    --dev                 <string>        bind raw socket to a device, not necessary but improves performance\n    --sock-buf            <number>        buf size for socket,>=10 and <=10240,unit:kbyte,default:1024\n    --force-sock-buf                      bypass system limitation while setting sock-buf\n    --seq-mode            <number>        seq increase mode for faketcp:\n                                          0:static header,do not increase seq and ack_seq\n                                          1:increase seq for every packet,simply ack last seq\n                                          2:increase seq randomly, about every 3 packets,simply ack last seq\n                                          3:simulate an almost real seq/ack procedure(default)\n                                          4:similiar to 3,but do not consider TCP Option Window_Scale,\n                                          maybe useful when firewall doesnt support TCP Option\n    --lower-level         <string>        send packets at OSI level 2, format:'if_name#dest_mac_adress'\n                                          ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain\n                                          the parameter automatically,specify it manually if 'auto' failed\n    --wait-lock                           wait for xtables lock while invoking iptables, need iptables v1.4.20+\n    --gen-add                             generate iptables rule and add it permanently,then exit.overrides -g\n    --keep-rule                           monitor iptables and auto re-add if necessary.implys -a\n    --hb-len              <number>        length of heart-beat packet, >=0 and <=1500\n    --mtu-warn            <number>        mtu warning threshold, unit:byte, default:1375\n    --clear                               clear any iptables rules added by this program.overrides everything\n    --retry-on-error                      retry on error, allow to start udp2raw before network is initialized\n    -h,--help                             print this help message\n```\n\n### Iptables rules,`-a` and `-g`\nThis program sends packets via raw socket. In FakeTCP mode, Linux kernel TCP packet processing has to be blocked by a iptables rule on both sides, otherwise the kernel will automatically send RST for an unrecongized TCP packet and you will sustain from stability / peformance problems. You can use `-a` option to let the program automatically add / delete iptables rule on start / exit. You can also use the `-g` option to generate iptables rule and add it manually.\n\n### `--cipher-mode` and `--auth-mode`\nIt is suggested to use `aes128cbc` + `hmac_sha1` to obtain maximum security. If you want to run the program on a router, you can try `xor` + `simple`, which can fool packet inspection by firewalls the most of time, but it cannot protect you from serious attacks. Mode none is only for debugging purpose. It is not recommended to set the cipher-mode or auth-mode to none.\n\n### `--seq-mode`\nThe FakeTCP mode does not behave 100% like a real tcp connection. ISPs may be able to distinguish the simulated tcp traffic from the real TCP traffic (though it's costly). seq-mode can help you change the seq increase behavior slightly. If you experience connection problems, try to change the value.\n\n### `--lower-level`\n`--lower-level` allows you to send packet at OSI level 2(link level),so that you can bypass any local iptables rules. If you have a complicated iptables rules which conflicts with udp2raw and you cant(or too lazy to) edit the iptables rules,`--lower-level` can be very useful. Try `--lower-level auto` to auto detect the parameters,you can specify it manually if `auto` fails.\n\nManual format `if_name#dest_mac_adress`,ie:`eth0#00:23:45:67:89:b9`.\n\n### `--keep-rule`\nMonitor iptables and auto re-add iptables rules(for blocking kernel tcp processing) if necessary.Especially useful when iptables rules may be cleared by other programs(for example,if you are using openwrt,everytime you changed and commited a setting,iptables rule may be cleared and re-constructed).\n\n### `--conf-file`\n\nYou can also load options from a configuration file in order to keep secrets away from `ps` command.\n\nFor example, rewrite the options for the above `server` example (in Getting Started section) into configuration file:\n\n`server.conf`\n\n```\n-s\n# You can add comments like this\n# Comments MUST occupy an entire line\n# Or they will not work as expected\n# Listen address\n-l 0.0.0.0:4096\n# Remote address\n-r 127.0.0.1:7777\n-a\n-k passwd\n--raw-mode faketcp\n```\n\nPay attention to the `-k` parameter: In command line mode the quotes around the password will be removed by shell. In configuration files we do not remove quotes.\n\nThen start the server with\n\n```bash\n./udp2raw_amd64 --conf-file server.conf\n```\n\n### `--fifo`\nUse a fifo(named pipe) for sending commands to the running program. For example `--fifo fifo.file`.\n\nAt client side,you can use `echo reconnect >fifo.file` to force client to reconnect.Currently no command has been implemented for server.\n\n# Peformance Test\n#### Test method:\niperf3 TCP via OpenVPN + udp2raw\n(iperf3 UDP mode is not used because of a bug mentioned in this issue: https://github.com/esnet/iperf/issues/296 . Instead, we package the TCP traffic into UDP by OpenVPN to test the performance. Read [Application](https://github.com/wangyu-/udp2raw-tunnel#application) for details.\n\n#### iperf3 command:\n```\niperf3 -c 10.222.2.1 -P40\niperf3 -c 10.222.2.1 -P40 -R\n```\n#### Environments\n* **Client** Vultr $2.5/monthly plan (single core 2.4GHz cpu, 512MB RAM, Tokyo, Japan)\n* **Server** BandwagonHost $3.99/annually plan (single core 2.0GHz cpu, 128MB RAM, Los Angeles, USA)\n\n### Test1\nraw_mode: faketcp  cipher_mode: xor  auth_mode: simple\n\n![image4](images/image4.PNG)\n\n(reverse speed was simliar and not uploaded)\n\n### Test2\nraw_mode: faketcp  cipher_mode: aes128cbc  auth_mode: md5\n\n![image5](images/image5.PNG)\n\n(reverse speed was simliar and not uploaded)\n\n# wiki\n\nCheck wiki for more info:\n\nhttps://github.com/wangyu-/udp2raw-tunnel/wiki\n"
  },
  {
    "path": "client.cpp",
    "content": "#include \"common.h\"\n#include \"network.h\"\n#include \"connection.h\"\n#include \"misc.h\"\n#include \"log.h\"\n#include \"lib/md5.h\"\n#include \"encrypt.h\"\n#include \"fd_manager.h\"\n\n#ifdef UDP2RAW_MP\nu32_t detect_interval = 1500;\nu64_t laste_detect_time = 0;\n\nint use_udp_for_detection = 0;\nint use_tcp_for_detection = 1;\n\nextern pcap_t *pcap_handle;\n\nextern int pcap_captured_full_len;\n#endif\n\nint client_on_timer(conn_info_t &conn_info)  // for client. called when a timer is ready in epoll\n{\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n    raw_info_t &raw_info = conn_info.raw_info;\n    conn_info.blob->conv_manager.c.clear_inactive();\n    mylog(log_trace, \"timer!\\n\");\n\n    mylog(log_trace, \"roller my %d,oppsite %d,%lld\\n\", int(conn_info.my_roller), int(conn_info.oppsite_roller), conn_info.last_oppsite_roller_time);\n\n    mylog(log_trace, \"<client_on_timer,send_info.ts_ack= %u>\\n\", send_info.ts_ack);\n\n#ifdef UDP2RAW_MP\n    // mylog(log_debug,\"pcap cnt :%d\\n\",pcap_cnt);\n    if (send_with_pcap && !pcap_header_captured) {\n        if (get_current_time() - laste_detect_time > detect_interval) {\n            laste_detect_time = get_current_time();\n        } else {\n            return 0;\n        }\n        /*\n                        struct sockaddr_in remote_addr_in={0};\n\n                        socklen_t slen = sizeof(sockaddr_in);\n                        int port=get_true_random_number()%65534+1;\n                        remote_addr_in.sin_family = AF_INET;\n                        remote_addr_in.sin_port = htons(port);\n                        remote_addr_in.sin_addr.s_addr = remote_ip_uint32;*/\n        int port = get_true_random_number() % 65534 + 1;\n        address_t tmp_addr = remote_addr;\n        tmp_addr.set_port(port);\n\n        if (use_udp_for_detection) {\n            int new_udp_fd = socket(tmp_addr.get_type(), SOCK_DGRAM, IPPROTO_UDP);\n            if (new_udp_fd < 0) {\n                mylog(log_warn, \"create new_udp_fd error\\n\");\n                return -1;\n            }\n            setnonblocking(new_udp_fd);\n            u64_t tmp = get_true_random_number();\n\n            int ret = sendto(new_udp_fd, (char *)(&tmp), sizeof(tmp), 0, (struct sockaddr *)&tmp_addr.inner, tmp_addr.get_len());\n            if (ret == -1) {\n                mylog(log_warn, \"sendto() failed\\n\");\n            }\n            sock_close(new_udp_fd);\n        }\n\n        if (use_tcp_for_detection) {\n            static int last_tcp_fd = -1;\n\n            int new_tcp_fd = socket(tmp_addr.get_type(), SOCK_STREAM, IPPROTO_TCP);\n            if (new_tcp_fd < 0) {\n                mylog(log_warn, \"create new_tcp_fd error\\n\");\n                return -1;\n            }\n            setnonblocking(new_tcp_fd);\n            connect(new_tcp_fd, (struct sockaddr *)&tmp_addr.inner, tmp_addr.get_len());\n            if (last_tcp_fd != -1)\n                sock_close(last_tcp_fd);\n            last_tcp_fd = new_tcp_fd;\n            // close(new_tcp_fd);\n        }\n\n        mylog(log_info, \"waiting for a use-able packet to be captured\\n\");\n\n        return 0;\n    }\n#endif\n    if (raw_info.disabled) {\n        conn_info.state.client_current_state = client_idle;\n        conn_info.my_id = get_true_random_number_nz();\n\n        mylog(log_info, \"state back to client_idle\\n\");\n    }\n\n    if (conn_info.state.client_current_state == client_idle) {\n        raw_info.rst_received = 0;\n        raw_info.disabled = 0;\n\n        fail_time_counter++;\n        if (max_fail_time > 0 && fail_time_counter > max_fail_time) {\n            mylog(log_fatal, \"max_fail_time exceed\\n\");\n            myexit(-1);\n        }\n\n        conn_info.blob->anti_replay.re_init();\n        conn_info.my_id = get_true_random_number_nz();  /// todo no need to do this everytime\n\n        address_t tmp_addr;\n        // u32_t new_ip=0;\n        if (!force_source_ip) {\n            if (get_src_adress2(tmp_addr, remote_addr) != 0) {\n                mylog(log_warn, \"get_src_adress() failed\\n\");\n                return -1;\n            }\n            // source_addr=new_addr;\n            // source_addr.set_port(0);\n\n            mylog(log_info, \"source_addr is now %s\\n\", tmp_addr.get_ip());\n\n            /*\n            if(new_ip!=source_ip_uint32)\n            {\n                    mylog(log_info,\"source ip changed from %s to \",my_ntoa(source_ip_uint32));\n                    log_bare(log_info,\"%s\\n\",my_ntoa(new_ip));\n                    source_ip_uint32=new_ip;\n                    send_info.src_ip=new_ip;\n            }*/\n\n        } else {\n            tmp_addr = source_addr;\n        }\n\n        send_info.new_src_ip.from_address_t(tmp_addr);\n\n        if (force_source_port == 0) {\n            send_info.src_port = client_bind_to_a_new_port2(bind_fd, tmp_addr);\n        } else {\n            send_info.src_port = source_port;\n        }\n\n        if (raw_mode == mode_icmp) {\n            send_info.dst_port = send_info.src_port;\n        }\n\n        mylog(log_info, \"using port %d\\n\", send_info.src_port);\n        init_filter(send_info.src_port);\n\n        if (raw_mode == mode_icmp || raw_mode == mode_udp) {\n            conn_info.state.client_current_state = client_handshake1;\n\n            mylog(log_info, \"state changed from client_idle to client_pre_handshake\\n\");\n        }\n        if (raw_mode == mode_faketcp) {\n            if (use_tcp_dummy_socket) {\n                setnonblocking(bind_fd);\n                int ret = connect(bind_fd, (struct sockaddr *)&remote_addr.inner, remote_addr.get_len());\n                mylog(log_debug, \"ret=%d,errno=%s, %d %s\\n\", ret, get_sock_error(), bind_fd, remote_addr.get_str());\n                // mylog(log_info,\"ret=%d,errno=,%d %s\\n\",ret,bind_fd,remote_addr.get_str());\n                conn_info.state.client_current_state = client_tcp_handshake_dummy;\n                mylog(log_info, \"state changed from client_idle to client_tcp_handshake_dummy\\n\");\n            } else {\n                conn_info.state.client_current_state = client_tcp_handshake;\n                mylog(log_info, \"state changed from client_idle to client_tcp_handshake\\n\");\n            }\n        }\n        conn_info.last_state_time = get_current_time();\n        conn_info.last_hb_sent_time = 0;\n        // dont return;\n    }\n    if (conn_info.state.client_current_state == client_tcp_handshake)  // send and resend syn\n    {\n        assert(raw_mode == mode_faketcp);\n        if (get_current_time() - conn_info.last_state_time > client_handshake_timeout) {\n            conn_info.state.client_current_state = client_idle;\n            mylog(log_info, \"state back to client_idle from client_tcp_handshake\\n\");\n            return 0;\n\n        } else if (get_current_time() - conn_info.last_hb_sent_time > client_retry_interval) {\n            if (raw_mode == mode_faketcp) {\n                if (conn_info.last_hb_sent_time == 0) {\n                    send_info.psh = 0;\n                    send_info.syn = 1;\n                    send_info.ack = 0;\n                    send_info.ts_ack = 0;\n                    send_info.seq = get_true_random_number();\n                    send_info.ack_seq = get_true_random_number();\n                }\n            }\n\n            send_raw0(raw_info, 0, 0);\n\n            conn_info.last_hb_sent_time = get_current_time();\n            mylog(log_info, \"(re)sent tcp syn\\n\");\n            return 0;\n        } else {\n            return 0;\n        }\n        return 0;\n    } else if (conn_info.state.client_current_state == client_tcp_handshake_dummy) {\n        assert(raw_mode == mode_faketcp);\n        if (get_current_time() - conn_info.last_state_time > client_handshake_timeout) {\n            conn_info.state.client_current_state = client_idle;\n            mylog(log_info, \"state back to client_idle from client_tcp_handshake_dummy\\n\");\n            return 0;\n        }\n    } else if (conn_info.state.client_current_state == client_handshake1)  // send and resend handshake1\n    {\n        if (get_current_time() - conn_info.last_state_time > client_handshake_timeout) {\n            conn_info.state.client_current_state = client_idle;\n            mylog(log_info, \"state back to client_idle from client_handshake1\\n\");\n            return 0;\n\n        } else if (get_current_time() - conn_info.last_hb_sent_time > client_retry_interval) {\n            if (raw_mode == mode_faketcp) {\n                if (conn_info.last_hb_sent_time == 0) {\n                    send_info.seq++;\n                    send_info.ack_seq = recv_info.seq + 1;\n                    send_info.ts_ack = recv_info.ts;\n                    raw_info.reserved_send_seq = send_info.seq;\n                }\n                send_info.seq = raw_info.reserved_send_seq;\n                send_info.psh = 0;\n                send_info.syn = 0;\n                send_info.ack = 1;\n\n                if (!use_tcp_dummy_socket)\n                    send_raw0(raw_info, 0, 0);\n\n                send_handshake(raw_info, conn_info.my_id, 0, const_id);\n\n                send_info.seq += raw_info.send_info.data_len;\n            } else {\n                send_handshake(raw_info, conn_info.my_id, 0, const_id);\n                if (raw_mode == mode_icmp)\n                    send_info.my_icmp_seq++;\n            }\n\n            conn_info.last_hb_sent_time = get_current_time();\n            mylog(log_info, \"(re)sent handshake1\\n\");\n            return 0;\n        } else {\n            return 0;\n        }\n        return 0;\n    } else if (conn_info.state.client_current_state == client_handshake2) {\n        if (get_current_time() - conn_info.last_state_time > client_handshake_timeout) {\n            conn_info.state.client_current_state = client_idle;\n            mylog(log_info, \"state back to client_idle from client_handshake2\\n\");\n            return 0;\n        } else if (get_current_time() - conn_info.last_hb_sent_time > client_retry_interval) {\n            if (raw_mode == mode_faketcp) {\n                if (conn_info.last_hb_sent_time == 0) {\n                    send_info.ack_seq = recv_info.seq + raw_info.recv_info.data_len;\n                    send_info.ts_ack = recv_info.ts;\n                    raw_info.reserved_send_seq = send_info.seq;\n                }\n                send_info.seq = raw_info.reserved_send_seq;\n                send_handshake(raw_info, conn_info.my_id, conn_info.oppsite_id, const_id);\n                send_info.seq += raw_info.send_info.data_len;\n\n            } else {\n                send_handshake(raw_info, conn_info.my_id, conn_info.oppsite_id, const_id);\n                if (raw_mode == mode_icmp)\n                    send_info.my_icmp_seq++;\n            }\n            conn_info.last_hb_sent_time = get_current_time();\n            mylog(log_info, \"(re)sent handshake2\\n\");\n            return 0;\n\n        } else {\n            return 0;\n        }\n        return 0;\n    } else if (conn_info.state.client_current_state == client_ready) {\n        fail_time_counter = 0;\n        mylog(log_trace, \"time %llu,%llu\\n\", get_current_time(), conn_info.last_state_time);\n\n        if (get_current_time() - conn_info.last_hb_recv_time > client_conn_timeout) {\n            conn_info.state.client_current_state = client_idle;\n            conn_info.my_id = get_true_random_number_nz();\n            mylog(log_info, \"state back to client_idle from  client_ready bc of server-->client direction timeout\\n\");\n            return 0;\n        }\n\n        if (get_current_time() - conn_info.last_oppsite_roller_time > client_conn_uplink_timeout) {\n            conn_info.state.client_current_state = client_idle;\n            conn_info.my_id = get_true_random_number_nz();\n            mylog(log_info, \"state back to client_idle from  client_ready bc of client-->server direction timeout\\n\");\n        }\n\n        if (get_current_time() - conn_info.last_hb_sent_time < heartbeat_interval) {\n            return 0;\n        }\n\n        mylog(log_debug, \"heartbeat sent <%x,%x>\\n\", conn_info.oppsite_id, conn_info.my_id);\n\n        if (hb_mode == 0)\n            send_safer(conn_info, 'h', hb_buf, 0);  /////////////send\n        else\n            send_safer(conn_info, 'h', hb_buf, hb_len);\n        conn_info.last_hb_sent_time = get_current_time();\n        return 0;\n    } else {\n        mylog(log_fatal, \"unknown state,this shouldnt happen.\\n\");\n        myexit(-1);\n    }\n    return 0;\n}\nint client_on_raw_recv_hs2_or_ready(conn_info_t &conn_info, char type, char *data, int data_len) {\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n\n    if (!recv_info.new_src_ip.equal(send_info.new_dst_ip) || recv_info.src_port != send_info.dst_port) {\n        mylog(log_warn, \"unexpected adress %s %s %d %d,this shouldnt happen.\\n\", recv_info.new_src_ip.get_str1(), send_info.new_dst_ip.get_str2(), recv_info.src_port, send_info.dst_port);\n        return -1;\n    }\n\n    if (conn_info.state.client_current_state == client_handshake2) {\n        mylog(log_info, \"changed state from to client_handshake2 to client_ready\\n\");\n        conn_info.state.client_current_state = client_ready;\n        conn_info.last_hb_sent_time = 0;\n        conn_info.last_hb_recv_time = get_current_time();\n        conn_info.last_oppsite_roller_time = conn_info.last_hb_recv_time;\n        client_on_timer(conn_info);\n    }\n    if (data_len >= 0 && type == 'h') {\n        mylog(log_debug, \"[hb]heart beat received,oppsite_roller=%d\\n\", int(conn_info.oppsite_roller));\n        conn_info.last_hb_recv_time = get_current_time();\n        return 0;\n    } else if (data_len >= int(sizeof(u32_t)) && type == 'd') {\n        mylog(log_trace, \"received a data from fake tcp,len:%d\\n\", data_len);\n\n        if (hb_mode == 0)\n            conn_info.last_hb_recv_time = get_current_time();\n\n        u32_t tmp_conv_id;\n        memcpy(&tmp_conv_id, &data[0], sizeof(tmp_conv_id));\n        tmp_conv_id = ntohl(tmp_conv_id);\n\n        if (!conn_info.blob->conv_manager.c.is_conv_used(tmp_conv_id)) {\n            mylog(log_info, \"unknow conv %d,ignore\\n\", tmp_conv_id);\n            return 0;\n        }\n\n        conn_info.blob->conv_manager.c.update_active_time(tmp_conv_id);\n\n        // u64_t u64=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);\n        address_t tmp_addr = conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);\n\n        // sockaddr_in tmp_sockaddr={0};\n\n        // tmp_sockaddr.sin_family = AF_INET;\n        // tmp_sockaddr.sin_addr.s_addr=(u64>>32u);\n\n        // tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u));\n\n        int ret = sendto(udp_fd, data + sizeof(u32_t), data_len - (sizeof(u32_t)), 0, (struct sockaddr *)&tmp_addr.inner, tmp_addr.get_len());\n\n        if (ret < 0) {\n            mylog(log_warn, \"sento returned %d,%s,%02x,%s\\n\", ret, get_sock_error(), int(tmp_addr.get_type()), tmp_addr.get_str());\n            // perror(\"ret<0\");\n        }\n    } else {\n        mylog(log_warn, \"unknown packet,this shouldnt happen.\\n\");\n        return -1;\n    }\n    return 0;\n}\nint client_on_raw_recv(conn_info_t &conn_info)  // called when raw fd received a packet.\n{\n    char *data;\n    int data_len;\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n\n    raw_info_t &raw_info = conn_info.raw_info;\n\n    mylog(log_trace, \"<client_on_raw_recv,send_info.ts_ack= %u>\\n\", send_info.ts_ack);\n\n#ifdef UDP2RAW_LINUX\n    if (pre_recv_raw_packet() < 0) return -1;\n#endif\n\n    if (conn_info.state.client_current_state == client_idle) {\n        discard_raw_packet();\n        // recv(raw_recv_fd, 0,0, 0  );\n    } else if (conn_info.state.client_current_state == client_tcp_handshake || conn_info.state.client_current_state == client_tcp_handshake_dummy)  // received syn ack\n    {\n        assert(raw_mode == mode_faketcp);\n        if (recv_raw0(raw_info, data, data_len) < 0) {\n            return -1;\n        }\n        if (data_len >= max_data_len + 1) {\n            mylog(log_debug, \"data_len=%d >= max_data_len+1,ignored\", data_len);\n            return -1;\n        }\n        if (!recv_info.new_src_ip.equal(send_info.new_dst_ip) || recv_info.src_port != send_info.dst_port) {\n            mylog(log_debug, \"unexpected adress %s %s %d %d\\n\", recv_info.new_src_ip.get_str1(), send_info.new_dst_ip.get_str2(), recv_info.src_port, send_info.dst_port);\n            return -1;\n        }\n        if (data_len == 0 && raw_info.recv_info.syn == 1 && raw_info.recv_info.ack == 1) {\n            if (conn_info.state.client_current_state == client_tcp_handshake) {\n                if (recv_info.ack_seq != send_info.seq + 1) {\n                    mylog(log_debug, \"seq ack_seq mis match\\n\");\n                    return -1;\n                }\n                mylog(log_info, \"state changed from client_tcp_handshake to client_handshake1\\n\");\n            } else {\n                send_info.seq = recv_info.ack_seq - 1;\n                mylog(log_info, \"state changed from client_tcp_dummy to client_handshake1\\n\");\n                // send_info.ack_seq=recv_info.seq+1;\n            }\n            conn_info.state.client_current_state = client_handshake1;\n\n            conn_info.last_state_time = get_current_time();\n            conn_info.last_hb_sent_time = 0;\n            client_on_timer(conn_info);\n            return 0;\n        } else {\n            mylog(log_debug, \"unexpected packet type,expected:syn ack\\n\");\n            return -1;\n        }\n    } else if (conn_info.state.client_current_state == client_handshake1)  // recevied respond of handshake1\n    {\n        if (recv_bare(raw_info, data, data_len) != 0) {\n            mylog(log_debug, \"recv_bare failed!\\n\");\n            return -1;\n        }\n        if (!recv_info.new_src_ip.equal(send_info.new_dst_ip) || recv_info.src_port != send_info.dst_port) {\n            mylog(log_debug, \"unexpected adress %s %s %d %d\\n\", recv_info.new_src_ip.get_str1(), send_info.new_dst_ip.get_str2(), recv_info.src_port, send_info.dst_port);\n            return -1;\n        }\n        if (data_len < int(3 * sizeof(my_id_t))) {\n            mylog(log_debug, \"too short to be a handshake\\n\");\n            return -1;\n        }\n        my_id_t tmp_oppsite_id;\n        memcpy(&tmp_oppsite_id, &data[0], sizeof(tmp_oppsite_id));\n        tmp_oppsite_id = ntohl(tmp_oppsite_id);\n\n        my_id_t tmp_my_id;\n        memcpy(&tmp_my_id, &data[sizeof(my_id_t)], sizeof(tmp_my_id));\n        tmp_my_id = ntohl(tmp_my_id);\n\n        my_id_t tmp_oppsite_const_id;\n        memcpy(&tmp_oppsite_const_id, &data[sizeof(my_id_t) * 2], sizeof(tmp_oppsite_const_id));\n        tmp_oppsite_const_id = ntohl(tmp_oppsite_const_id);\n\n        if (tmp_my_id != conn_info.my_id) {\n            mylog(log_debug, \"tmp_my_id doesnt match\\n\");\n            return -1;\n        }\n\n        if (raw_mode == mode_faketcp) {\n            if (recv_info.ack_seq != send_info.seq) {\n                mylog(log_debug, \"seq ack_seq mis match\\n\");\n                return -1;\n            }\n            if (recv_info.seq != send_info.ack_seq) {\n                mylog(log_debug, \"seq ack_seq mis match\\n\");\n                return -1;\n            }\n        }\n        conn_info.oppsite_id = tmp_oppsite_id;\n\n        mylog(log_info, \"changed state from to client_handshake1 to client_handshake2,my_id is %x,oppsite id is %x\\n\", conn_info.my_id, conn_info.oppsite_id);\n\n        conn_info.state.client_current_state = client_handshake2;\n        conn_info.last_state_time = get_current_time();\n        conn_info.last_hb_sent_time = 0;\n        client_on_timer(conn_info);\n\n        return 0;\n    } else if (conn_info.state.client_current_state == client_handshake2 || conn_info.state.client_current_state == client_ready)  // received heartbeat or data\n    {\n        vector<char> type_vec;\n        vector<string> data_vec;\n        recv_safer_multi(conn_info, type_vec, data_vec);\n        if (data_vec.empty()) {\n            mylog(log_debug, \"recv_safer failed!\\n\");\n            return -1;\n        }\n\n        for (int i = 0; i < (int)type_vec.size(); i++) {\n            char type = type_vec[i];\n            char *data = (char *)data_vec[i].c_str();  // be careful, do not append data to it\n            int data_len = data_vec[i].length();\n            client_on_raw_recv_hs2_or_ready(conn_info, type, data, data_len);\n        }\n\n        return 0;\n    } else {\n        mylog(log_fatal, \"unknown state,this shouldnt happen.\\n\");\n        myexit(-1);\n    }\n    return 0;\n}\nint client_on_udp_recv(conn_info_t &conn_info) {\n    int recv_len;\n    char buf[buf_len];\n    address_t::storage_t udp_new_addr_in = {{0}};\n    socklen_t udp_new_addr_len = sizeof(address_t::storage_t);\n    if ((recv_len = recvfrom(udp_fd, buf, max_data_len + 1, 0,\n                             (struct sockaddr *)&udp_new_addr_in, &udp_new_addr_len)) == -1) {\n        mylog(log_debug, \"recv_from error,%s\\n\", get_sock_error());\n        return -1;\n        // myexit(1);\n    };\n\n    if (recv_len == max_data_len + 1) {\n        mylog(log_warn, \"huge packet, data_len > %d,dropped\\n\", max_data_len);\n        return -1;\n    }\n\n    if (recv_len >= mtu_warn) {\n        mylog(log_warn, \"huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\\n \", recv_len, mtu_warn);\n    }\n\n    address_t tmp_addr;\n    tmp_addr.from_sockaddr((sockaddr *)&udp_new_addr_in, udp_new_addr_len);\n    u32_t conv;\n\n    if (!conn_info.blob->conv_manager.c.is_data_used(tmp_addr)) {\n        if (conn_info.blob->conv_manager.c.get_size() >= max_conv_num) {\n            mylog(log_warn, \"ignored new udp connect bc max_conv_num exceed\\n\");\n            return -1;\n        }\n        conv = conn_info.blob->conv_manager.c.get_new_conv();\n        conn_info.blob->conv_manager.c.insert_conv(conv, tmp_addr);\n        mylog(log_info, \"new packet from %s,conv_id=%x\\n\", tmp_addr.get_str(), conv);\n    } else {\n        conv = conn_info.blob->conv_manager.c.find_conv_by_data(tmp_addr);\n    }\n\n    conn_info.blob->conv_manager.c.update_active_time(conv);\n\n    if (conn_info.state.client_current_state == client_ready) {\n        send_data_safer(conn_info, buf, recv_len, conv);\n    }\n    return 0;\n}\nvoid udp_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {\n    conn_info_t &conn_info = *((conn_info_t *)watcher->data);\n    client_on_udp_recv(conn_info);\n}\nvoid raw_recv_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {\n    if (is_udp2raw_mp) assert(0 == 1);\n    conn_info_t &conn_info = *((conn_info_t *)watcher->data);\n    client_on_raw_recv(conn_info);\n}\n#ifdef UDP2RAW_MP\nvoid async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents) {\n    conn_info_t &conn_info = *((conn_info_t *)watcher->data);\n\n    if (send_with_pcap && !pcap_header_captured) {\n        int empty = 0;\n        char *p;\n        int len;\n        pthread_mutex_lock(&queue_mutex);\n        empty = my_queue.empty();\n        if (!empty) {\n            my_queue.peek_front(p, len);\n            my_queue.pop_front();\n        }\n        pthread_mutex_unlock(&queue_mutex);\n        if (empty) return;\n\n        pcap_header_captured = 1;\n        assert(pcap_link_header_len != -1);\n        memcpy(pcap_header_buf, p, max_data_len);\n\n        log_bare(log_info, \"link level header captured:\\n\");\n        unsigned char *tmp = (unsigned char *)pcap_header_buf;\n        pcap_captured_full_len = len;\n        for (int i = 0; i < pcap_link_header_len; i++)\n            log_bare(log_info, \"<%x>\", (u32_t)tmp[i]);\n\n        log_bare(log_info, \"\\n\");\n        return;\n    }\n\n    // mylog(log_info,\"async_cb called\\n\");\n    while (1) {\n        int empty = 0;\n        char *p;\n        int len;\n        pthread_mutex_lock(&queue_mutex);\n        empty = my_queue.empty();\n        if (!empty) {\n            my_queue.peek_front(p, len);\n            my_queue.pop_front();\n        }\n        pthread_mutex_unlock(&queue_mutex);\n\n        if (empty) break;\n        if (g_fix_gro == 0 && len > max_data_len) {\n            mylog(log_warn, \"huge packet %d > %d, dropped. maybe you need to turn down mtu at upper level, or maybe you need the --fix-gro option\\n\", len, max_data_len);\n            break;\n        }\n\n        int new_len = len - pcap_link_header_len;\n        memcpy(g_packet_buf, p + pcap_link_header_len, new_len);\n        g_packet_buf_len = new_len;\n        assert(g_packet_buf_cnt == 0);\n        g_packet_buf_cnt++;\n        client_on_raw_recv(conn_info);\n    }\n}\n#endif\nvoid clear_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {\n    conn_info_t &conn_info = *((conn_info_t *)watcher->data);\n    client_on_timer(conn_info);\n}\nvoid fifo_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {\n    conn_info_t &conn_info = *((conn_info_t *)watcher->data);\n\n    char buf[buf_len];\n    int fifo_fd = watcher->fd;\n\n    int len = read(fifo_fd, buf, sizeof(buf));\n    if (len < 0) {\n        mylog(log_warn, \"fifo read failed len=%d,errno=%s\\n\", len, get_sock_error());\n        return;\n    }\n    buf[len] = 0;\n    while (len >= 1 && buf[len - 1] == '\\n')\n        buf[len - 1] = 0;\n    mylog(log_info, \"got data from fifo,len=%d,s=[%s]\\n\", len, buf);\n    if (strcmp(buf, \"reconnect\") == 0) {\n        mylog(log_info, \"received command: reconnect\\n\");\n        conn_info.state.client_current_state = client_idle;\n        conn_info.my_id = get_true_random_number_nz();\n    } else {\n        mylog(log_info, \"unknown command\\n\");\n    }\n}\nint client_event_loop() {\n    char buf[buf_len];\n\n    conn_info_t conn_info;\n    conn_info.my_id = get_true_random_number_nz();\n\n    conn_info.prepare();\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n\n#ifdef UDP2RAW_LINUX\n    if (lower_level) {\n        if (lower_level_manual) {\n            int index;\n            init_ifindex(if_name, raw_send_fd, index);\n            // init_ifindex(if_name);\n            memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));\n            send_info.addr_ll.sll_family = AF_PACKET;\n            send_info.addr_ll.sll_ifindex = index;\n            send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;\n            send_info.addr_ll.sll_protocol = htons(ETH_P_IP);\n            memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);\n            mylog(log_info, \"we are running at lower-level (manual) mode\\n\");\n        } else {\n            u32_t dest_ip;\n            string if_name_string;\n            string hw_string;\n            assert(remote_addr.get_type() == AF_INET);\n\n            if (retry_on_error == 0) {\n                if (find_lower_level_info(remote_addr.inner.ipv4.sin_addr.s_addr, dest_ip, if_name_string, hw_string) != 0) {\n                    mylog(log_fatal, \"auto detect lower-level info failed for %s,specific it manually\\n\", remote_addr.get_ip());\n                    myexit(-1);\n                }\n            } else {\n                int ok = 0;\n                while (!ok) {\n                    if (find_lower_level_info(remote_addr.inner.ipv4.sin_addr.s_addr, dest_ip, if_name_string, hw_string) != 0) {\n                        mylog(log_warn, \"auto detect lower-level info failed for %s,retry in %d seconds\\n\", remote_addr.get_ip(), retry_on_error_interval);\n                        sleep(retry_on_error_interval);\n                    } else {\n                        ok = 1;\n                    }\n                }\n            }\n            mylog(log_info, \"we are running at lower-level (auto) mode,%s %s %s\\n\", my_ntoa(dest_ip), if_name_string.c_str(), hw_string.c_str());\n\n            u32_t hw[6];\n            memset(hw, 0, sizeof(hw));\n            sscanf(hw_string.c_str(), \"%x:%x:%x:%x:%x:%x\", &hw[0], &hw[1], &hw[2],\n                   &hw[3], &hw[4], &hw[5]);\n\n            mylog(log_warn,\n                  \"make sure this is correct:   if_name=<%s>  dest_mac_adress=<%02x:%02x:%02x:%02x:%02x:%02x>  \\n\",\n                  if_name_string.c_str(), hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);\n            for (int i = 0; i < 6; i++) {\n                dest_hw_addr[i] = uint8_t(hw[i]);\n            }\n\n            // mylog(log_fatal,\"--lower-level auto for client hasnt been implemented\\n\");\n            int index;\n            init_ifindex(if_name_string.c_str(), raw_send_fd, index);\n\n            memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));\n            send_info.addr_ll.sll_family = AF_PACKET;\n            send_info.addr_ll.sll_ifindex = index;\n            send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;\n            send_info.addr_ll.sll_protocol = htons(ETH_P_IP);\n            memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);\n            // mylog(log_info,\"we are running at lower-level (manual) mode\\n\");\n        }\n    }\n#endif\n\n#ifdef UDP2RAW_MP\n\n    address_t tmp_addr;\n    if (get_src_adress2(tmp_addr, remote_addr) != 0) {\n        mylog(log_error, \"get_src_adress() failed\\n\");\n        myexit(-1);\n    }\n    if (strcmp(dev, \"\") == 0) {\n        mylog(log_info, \"--dev have not been set, trying to detect automatically, available devices:\\n\");\n\n        mylog(log_info, \"available device(device name: ip address ; description):\\n\");\n\n        char errbuf[PCAP_ERRBUF_SIZE];\n\n        int found = 0;\n\n        pcap_if_t *interfaces, *d;\n        if (pcap_findalldevs(&interfaces, errbuf) == -1) {\n            mylog(log_fatal, \"error in pcap_findalldevs(),%s\\n\", errbuf);\n            myexit(-1);\n        }\n\n        for (pcap_if_t *d = interfaces; d != NULL; d = d->next) {\n            log_bare(log_warn, \"%s:\", d->name);\n            int cnt = 0;\n            for (pcap_addr_t *a = d->addresses; a != NULL; a = a->next) {\n                if (a->addr == NULL) {\n                    log_bare(log_debug, \" [a->addr==NULL]\");\n                    continue;\n                }\n                if (a->addr->sa_family == AF_INET || a->addr->sa_family == AF_INET6) {\n                    cnt++;\n\n                    if (a->addr->sa_family == AF_INET) {\n                        char s[max_addr_len];\n                        inet_ntop(AF_INET, &((struct sockaddr_in *)a->addr)->sin_addr, s, max_addr_len);\n                        log_bare(log_warn, \" [%s]\", s);\n\n                        if (a->addr->sa_family == raw_ip_version) {\n                            if (((struct sockaddr_in *)a->addr)->sin_addr.s_addr == tmp_addr.inner.ipv4.sin_addr.s_addr) {\n                                found++;\n                                strcpy(dev, d->name);\n                            }\n                        }\n                    } else {\n                        assert(a->addr->sa_family == AF_INET6);\n\n                        char s[max_addr_len];\n                        inet_ntop(AF_INET6, &((struct sockaddr_in6 *)a->addr)->sin6_addr, s, max_addr_len);\n                        log_bare(log_warn, \" [%s]\", s);\n\n                        if (a->addr->sa_family == raw_ip_version) {\n                            if (memcmp(&((struct sockaddr_in6 *)a->addr)->sin6_addr, &tmp_addr.inner.ipv6.sin6_addr, sizeof(struct in6_addr)) == 0) {\n                                found++;\n                                strcpy(dev, d->name);\n                            }\n                        }\n                    }\n                } else {\n                    log_bare(log_debug, \" [unknow:%d]\", int(a->addr->sa_family));\n                }\n            }\n            if (cnt == 0) log_bare(log_warn, \" [no ip found]\");\n            if (d->description == 0) {\n                log_bare(log_warn, \"; (no description available)\");\n            } else {\n                log_bare(log_warn, \"; %s\", d->description);\n            }\n            log_bare(log_warn, \"\\n\");\n        }\n\n        if (found == 0) {\n            mylog(log_fatal, \"no matched device found for ip: [%s]\\n\", tmp_addr.get_ip());\n            myexit(-1);\n        } else if (found == 1) {\n            mylog(log_info, \"using device:[%s], ip: [%s]\\n\", dev, tmp_addr.get_ip());\n        } else {\n            mylog(log_fatal, \"more than one devices found for ip: [%s] , you need to use --dev manually\\n\", tmp_addr.get_ip());\n            myexit(-1);\n        }\n    } else {\n        mylog(log_info, \"--dev has been manually set, using device:[%s]\\n\", dev);\n    }\n#endif\n\n    send_info.src_port = 0;\n    memset(&send_info.new_src_ip, 0, sizeof(send_info.new_src_ip));\n\n    int i, j, k;\n    int ret;\n\n    send_info.new_dst_ip.from_address_t(remote_addr);\n    send_info.dst_port = remote_addr.get_port();\n\n    udp_fd = socket(local_addr.get_type(), SOCK_DGRAM, IPPROTO_UDP);\n    set_buf_size(udp_fd, socket_buf_size);\n\n    if (::bind(udp_fd, (struct sockaddr *)&local_addr.inner, local_addr.get_len()) == -1) {\n        mylog(log_fatal, \"socket bind error\\n\");\n        // perror(\"socket bind error\");\n        myexit(1);\n    }\n    setnonblocking(udp_fd);\n\n    // epollfd = epoll_create1(0);\n\n    // const int max_events = 4096;\n    // struct epoll_event ev, events[max_events];\n    // if (epollfd < 0) {\n    //\tmylog(log_fatal,\"epoll return %d\\n\", epollfd);\n    //\tmyexit(-1);\n    // }\n\n    struct ev_loop *loop = ev_default_loop(0);\n    assert(loop != NULL);\n\n    // ev.events = EPOLLIN;\n    // ev.data.u64 = udp_fd;\n    // ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, udp_fd, &ev);\n    // if (ret!=0) {\n    //\tmylog(log_fatal,\"add  udp_listen_fd error\\n\");\n    //\tmyexit(-1);\n    // }\n\n    struct ev_io udp_accept_watcher;\n\n    udp_accept_watcher.data = &conn_info;\n    ev_io_init(&udp_accept_watcher, udp_accept_cb, udp_fd, EV_READ);\n    ev_io_start(loop, &udp_accept_watcher);\n\n    // ev.events = EPOLLIN;\n    // ev.data.u64 = raw_recv_fd;\n\n    // ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, raw_recv_fd, &ev);\n    // if (ret!= 0) {\n    //\tmylog(log_fatal,\"add raw_fd error\\n\");\n    //\tmyexit(-1);\n    // }\n\n#ifdef UDP2RAW_LINUX\n    struct ev_io raw_recv_watcher;\n\n    raw_recv_watcher.data = &conn_info;\n    ev_io_init(&raw_recv_watcher, raw_recv_cb, raw_recv_fd, EV_READ);\n    ev_io_start(loop, &raw_recv_watcher);\n#endif\n\n#ifdef UDP2RAW_MP\n    g_default_loop = loop;\n    async_watcher.data = &conn_info;\n    ev_async_init(&async_watcher, async_cb);\n    ev_async_start(loop, &async_watcher);\n\n    init_raw_socket();  // must be put after dev detection\n#endif\n\n    // set_timer(epollfd,timer_fd);\n    struct ev_timer clear_timer;\n\n    clear_timer.data = &conn_info;\n    ev_timer_init(&clear_timer, clear_timer_cb, 0, timer_interval / 1000.0);\n    ev_timer_start(loop, &clear_timer);\n\n    mylog(log_debug, \"send_raw : from %s %d  to %s %d\\n\", send_info.new_src_ip.get_str1(), send_info.src_port, send_info.new_dst_ip.get_str2(), send_info.dst_port);\n\n    int fifo_fd = -1;\n\n    struct ev_io fifo_watcher;\n    fifo_watcher.data = &conn_info;\n\n    if (fifo_file[0] != 0) {\n        fifo_fd = create_fifo(fifo_file);\n\n        ev_io_init(&fifo_watcher, fifo_cb, fifo_fd, EV_READ);\n        ev_io_start(loop, &fifo_watcher);\n\n        mylog(log_info, \"fifo_file=%s\\n\", fifo_file);\n    }\n\n    ev_run(loop, 0);\n    return 0;\n}\n"
  },
  {
    "path": "common.cpp",
    "content": "/*\n * comm.cpp\n *\n *  Created on: Jul 29, 2017\n *      Author: wangyu\n */\n\n#include \"common.h\"\n#include \"log.h\"\n#include \"misc.h\"\n\n#include <random>\n#include <cmath>\n\n// static int random_number_fd=-1;\nint force_socket_buf = 0;\n\nint address_t::from_str(char *str) {\n    clear();\n\n    char ip_addr_str[100];\n    u32_t port;\n    mylog(log_info, \"parsing address: %s\\n\", str);\n    int is_ipv6 = 0;\n    if (sscanf(str, \"[%[^]]]:%u\", ip_addr_str, &port) == 2) {\n        mylog(log_info, \"its an ipv6 adress\\n\");\n        inner.ipv6.sin6_family = AF_INET6;\n        is_ipv6 = 1;\n    } else if (sscanf(str, \"%[^:]:%u\", ip_addr_str, &port) == 2) {\n        mylog(log_info, \"its an ipv4 adress\\n\");\n        inner.ipv4.sin_family = AF_INET;\n    } else {\n        mylog(log_error, \"failed to parse\\n\");\n        myexit(-1);\n    }\n\n    mylog(log_info, \"ip_address is {%s}, port is {%u}\\n\", ip_addr_str, port);\n\n    if (port > 65535) {\n        mylog(log_error, \"invalid port: %d\\n\", port);\n        myexit(-1);\n    }\n\n    int ret = -100;\n    if (is_ipv6) {\n        ret = inet_pton(AF_INET6, ip_addr_str, &(inner.ipv6.sin6_addr));\n        inner.ipv6.sin6_port = htons(port);\n        if (ret == 0)  // 0 if address type doesnt match\n        {\n            mylog(log_error, \"ip_addr %s is not an ipv6 address, %d\\n\", ip_addr_str, ret);\n            myexit(-1);\n        } else if (ret == 1)  // inet_pton returns 1 on success\n        {\n            // okay\n        } else {\n            mylog(log_error, \"ip_addr %s is invalid, %d\\n\", ip_addr_str, ret);\n            myexit(-1);\n        }\n    } else {\n        ret = inet_pton(AF_INET, ip_addr_str, &(inner.ipv4.sin_addr));\n        inner.ipv4.sin_port = htons(port);\n\n        if (ret == 0) {\n            mylog(log_error, \"ip_addr %s is not an ipv4 address, %d\\n\", ip_addr_str, ret);\n            myexit(-1);\n        } else if (ret == 1) {\n            // okay\n        } else {\n            mylog(log_error, \"ip_addr %s is invalid, %d\\n\", ip_addr_str, ret);\n            myexit(-1);\n        }\n    }\n\n    return 0;\n}\n\nint address_t::from_str_ip_only(char *str) {\n    clear();\n\n    u32_t type;\n\n    if (strchr(str, ':') == NULL)\n        type = AF_INET;\n    else\n        type = AF_INET6;\n\n    ((sockaddr *)&inner)->sa_family = type;\n\n    int ret;\n    if (type == AF_INET) {\n        ret = inet_pton(type, str, &inner.ipv4.sin_addr);\n    } else {\n        ret = inet_pton(type, str, &inner.ipv6.sin6_addr);\n    }\n\n    if (ret == 0)  // 0 if address type doesnt match\n    {\n        mylog(log_error, \"confusion in parsing %s, %d\\n\", str, ret);\n        myexit(-1);\n    } else if (ret == 1)  // inet_pton returns 1 on success\n    {\n        // okay\n    } else {\n        mylog(log_error, \"ip_addr %s is invalid, %d\\n\", str, ret);\n        myexit(-1);\n    }\n    return 0;\n}\n\nchar *address_t::get_str() {\n    static char res[max_addr_len];\n    to_str(res);\n    return res;\n}\nvoid address_t::to_str(char *s) {\n    // static char res[max_addr_len];\n    char ip_addr[max_addr_len];\n    u32_t port;\n    const char *ret = 0;\n    if (get_type() == AF_INET6) {\n        ret = inet_ntop(AF_INET6, &inner.ipv6.sin6_addr, ip_addr, max_addr_len);\n        port = inner.ipv6.sin6_port;\n    } else if (get_type() == AF_INET) {\n        ret = inet_ntop(AF_INET, &inner.ipv4.sin_addr, ip_addr, max_addr_len);\n        port = inner.ipv4.sin_port;\n    } else {\n        assert(0 == 1);\n    }\n\n    if (ret == 0)  // NULL on failure\n    {\n        mylog(log_error, \"inet_ntop failed\\n\");\n        myexit(-1);\n    }\n\n    port = ntohs(port);\n\n    ip_addr[max_addr_len - 1] = 0;\n    if (get_type() == AF_INET6) {\n        sprintf(s, \"[%s]:%u\", ip_addr, (u32_t)port);\n    } else {\n        sprintf(s, \"%s:%u\", ip_addr, (u32_t)port);\n    }\n\n    // return res;\n}\n\nchar *address_t::get_ip() {\n    char ip_addr[max_addr_len];\n    static char s[max_addr_len];\n    const char *ret = 0;\n    if (get_type() == AF_INET6) {\n        ret = inet_ntop(AF_INET6, &inner.ipv6.sin6_addr, ip_addr, max_addr_len);\n    } else if (get_type() == AF_INET) {\n        ret = inet_ntop(AF_INET, &inner.ipv4.sin_addr, ip_addr, max_addr_len);\n    } else {\n        assert(0 == 1);\n    }\n\n    if (ret == 0)  // NULL on failure\n    {\n        mylog(log_error, \"inet_ntop failed\\n\");\n        myexit(-1);\n    }\n\n    ip_addr[max_addr_len - 1] = 0;\n    if (get_type() == AF_INET6) {\n        sprintf(s, \"%s\", ip_addr);\n    } else {\n        sprintf(s, \"%s\", ip_addr);\n    }\n\n    return s;\n}\n\nint address_t::from_sockaddr(sockaddr *addr, socklen_t slen) {\n    clear();\n    // memset(&inner,0,sizeof(inner));\n    if (addr->sa_family == AF_INET6) {\n        assert(slen == sizeof(sockaddr_in6));\n        // inner.ipv6= *( (sockaddr_in6*) addr );\n        memcpy(&inner, addr, slen);\n    } else if (addr->sa_family == AF_INET) {\n        assert(slen == sizeof(sockaddr_in));\n        // inner.ipv4= *( (sockaddr_in*) addr );\n        memcpy(&inner, addr, slen);\n    } else {\n        assert(0 == 1);\n    }\n    return 0;\n}\n\nint address_t::new_connected_udp_fd() {\n    int new_udp_fd;\n    new_udp_fd = socket(get_type(), SOCK_DGRAM, IPPROTO_UDP);\n    if (new_udp_fd < 0) {\n        mylog(log_warn, \"create udp_fd error\\n\");\n        return -1;\n    }\n    setnonblocking(new_udp_fd);\n    set_buf_size(new_udp_fd, socket_buf_size);\n\n    mylog(log_debug, \"created new udp_fd %d\\n\", new_udp_fd);\n    int ret = connect(new_udp_fd, (struct sockaddr *)&inner, get_len());\n    if (ret != 0) {\n        mylog(log_warn, \"udp fd connect fail %d %s\\n\", ret, strerror(errno));\n        // sock_close(new_udp_fd);\n        close(new_udp_fd);\n        return -1;\n    }\n\n    return new_udp_fd;\n}\n\nbool my_ip_t::equal(const my_ip_t &b) const {\n    // extern int raw_ip_version;\n    if (raw_ip_version == AF_INET) {\n        return v4 == b.v4;\n    } else if (raw_ip_version == AF_INET6) {\n        return memcmp(&v6, &b.v6, sizeof(v6)) == 0;\n    }\n    assert(0 == 1);\n    return 0;\n}\nchar *my_ip_t::get_str1() const {\n    static char res[max_addr_len];\n    if (raw_ip_version == AF_INET6) {\n        assert(inet_ntop(AF_INET6, &v6, res, max_addr_len) != 0);\n    } else {\n        assert(raw_ip_version == AF_INET);\n        assert(inet_ntop(AF_INET, &v4, res, max_addr_len) != 0);\n    }\n    return res;\n}\nchar *my_ip_t::get_str2() const {\n    static char res[max_addr_len];\n    if (raw_ip_version == AF_INET6) {\n        assert(inet_ntop(AF_INET6, &v6, res, max_addr_len) != 0);\n    } else {\n        assert(raw_ip_version == AF_INET);\n        assert(inet_ntop(AF_INET, &v4, res, max_addr_len) != 0);\n    }\n    return res;\n}\n\nint my_ip_t::from_address_t(address_t tmp_addr) {\n    if (tmp_addr.get_type() == raw_ip_version && raw_ip_version == AF_INET) {\n        v4 = tmp_addr.inner.ipv4.sin_addr.s_addr;\n    } else if (tmp_addr.get_type() == raw_ip_version && raw_ip_version == AF_INET6) {\n        v6 = tmp_addr.inner.ipv6.sin6_addr;\n    } else {\n        assert(0 == 1);\n    }\n    return 0;\n}\n/*\nint my_ip_t::from_str(char * str)\n{\n        u32_t type;\n        if(strchr(str,':')==NULL)\n                type=AF_INET;\n        else\n                type=AF_INET6;\n        int ret;\n        ret=inet_pton(type, str,this);\n        if(ret==0)  // 0 if address type doesnt match\n        {\n                mylog(log_error,\"confusion in parsing %s, %d\\n\",str,ret);\n                myexit(-1);\n        }\n        else if(ret==1) // inet_pton returns 1 on success\n        {\n                //okay\n        }\n        else\n        {\n                mylog(log_error,\"ip_addr %s is invalid, %d\\n\",str,ret);\n                myexit(-1);\n        }\n        return 0;\n}*/\n#ifdef UDP2RAW_MP\n\nint init_ws() {\n#if defined(__MINGW32__)\n    WORD wVersionRequested;\n    WSADATA wsaData;\n    int err;\n\n    /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */\n    wVersionRequested = MAKEWORD(2, 2);\n\n    err = WSAStartup(wVersionRequested, &wsaData);\n    if (err != 0) {\n        /* Tell the user that we could not find a usable */\n        /* Winsock DLL.                                  */\n        printf(\"WSAStartup failed with error: %d\\n\", err);\n        exit(-1);\n    }\n\n    /* Confirm that the WinSock DLL supports 2.2.*/\n    /* Note that if the DLL supports versions greater    */\n    /* than 2.2 in addition to 2.2, it will still return */\n    /* 2.2 in wVersion since that is the version we      */\n    /* requested.                                        */\n\n    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {\n        /* Tell the user that we could not find a usable */\n        /* WinSock DLL.                                  */\n        printf(\"Could not find a usable version of Winsock.dll\\n\");\n        WSACleanup();\n        exit(-1);\n    } else {\n        printf(\"The Winsock 2.2 dll was found okay\");\n    }\n\n    int tmp[] = {0, 100, 200, 300, 500, 800, 1000, 2000, 3000, 4000, -1};\n    int succ = 0;\n    for (int i = 1; tmp[i] != -1; i++) {\n        if (_setmaxstdio(100) == -1)\n            break;\n        else\n            succ = i;\n    }\n    printf(\", _setmaxstdio() was set to %d\\n\", tmp[succ]);\n#endif\n    return 0;\n}\n\n#endif\n\n#if defined(__MINGW32__)\nint inet_pton(int af, const char *src, void *dst) {\n    struct sockaddr_storage ss;\n    int size = sizeof(ss);\n    char src_copy[max_addr_len + 1];\n\n    ZeroMemory(&ss, sizeof(ss));\n    /* stupid non-const API */\n    strncpy(src_copy, src, max_addr_len + 1);\n    src_copy[max_addr_len] = 0;\n\n    if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) {\n        switch (af) {\n            case AF_INET:\n                *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;\n                return 1;\n            case AF_INET6:\n                *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;\n                return 1;\n        }\n    }\n    return 0;\n}\n\nconst char *inet_ntop(int af, const void *src, char *dst, socklen_t size) {\n    struct sockaddr_storage ss;\n    unsigned long s = size;\n\n    ZeroMemory(&ss, sizeof(ss));\n    ss.ss_family = af;\n\n    switch (af) {\n        case AF_INET:\n            ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;\n            break;\n        case AF_INET6:\n            ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;\n            break;\n        default:\n            return NULL;\n    }\n    /* cannot direclty use &size because of strict aliasing rules */\n    return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0) ? dst : NULL;\n}\nchar *get_sock_error() {\n    static char buf[1000];\n    int e = WSAGetLastError();\n    wchar_t *s = NULL;\n    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n                   NULL, e,\n                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n                   (LPWSTR)&s, 0, NULL);\n    sprintf(buf, \"%d:%S\", e, s);\n    int len = strlen(buf);\n    while (len > 0 && (buf[len - 1] == '\\r' || buf[len - 1] == '\\n')) {\n        len--;\n        buf[len] = 0;\n    }\n    LocalFree(s);\n    return buf;\n}\nint get_sock_errno() {\n    return WSAGetLastError();\n}\n#else\nchar *get_sock_error() {\n    static char buf[1000];\n    sprintf(buf, \"%d:%s\", errno, strerror(errno));\n    return buf;\n}\nint get_sock_errno() {\n    return errno;\n}\n#endif\n\nu64_t get_current_time_us() {\n    static u64_t value_fix = 0;\n    static u64_t largest_value = 0;\n\n    u64_t raw_value = (u64_t)(ev_time() * 1000 * 1000);\n\n    u64_t fixed_value = raw_value + value_fix;\n\n    if (fixed_value < largest_value) {\n        value_fix += largest_value - fixed_value;\n    } else {\n        largest_value = fixed_value;\n    }\n\n    // printf(\"<%lld,%lld,%lld>\\n\",raw_value,value_fix,raw_value + value_fix);\n    return raw_value + value_fix;  // new fixed value\n}\n\nu64_t get_current_time() {\n    return get_current_time_us() / 1000;\n}\n\nu64_t pack_u64(u32_t a, u32_t b) {\n    u64_t ret = a;\n    ret <<= 32u;\n    ret += b;\n    return ret;\n}\nu32_t get_u64_h(u64_t a) {\n    return a >> 32u;\n}\nu32_t get_u64_l(u64_t a) {\n    return (a << 32u) >> 32u;\n}\n\nchar *my_ntoa(u32_t ip) {\n    in_addr a;\n    a.s_addr = ip;\n    return inet_ntoa(a);\n}\n/*\nvoid init_random_number_fd()\n{\n\n        random_number_fd=open(\"/dev/urandom\",O_RDONLY);\n\n        if(random_number_fd==-1)\n        {\n                mylog(log_fatal,\"error open /dev/urandom\\n\");\n                myexit(-1);\n        }\n        setnonblocking(random_number_fd);\n}*/\n\n#if !defined(__MINGW32__)\nstruct random_fd_t {\n    int random_number_fd;\n    random_fd_t() {\n        random_number_fd = open(\"/dev/urandom\", O_RDONLY);\n\n        if (random_number_fd == -1) {\n            mylog(log_fatal, \"error open /dev/urandom\\n\");\n            myexit(-1);\n        }\n        setnonblocking(random_number_fd);\n    }\n    int get_fd() {\n        return random_number_fd;\n    }\n} random_fd;\n#else\nstruct my_random_t {\n    std::random_device rd;\n    std::mt19937 gen;\n    std::uniform_int_distribution<u64_t> dis64;\n    std::uniform_int_distribution<u32_t> dis32;\n\n    std::uniform_int_distribution<unsigned char> dis8;\n\n    my_random_t() {\n        // std::mt19937 gen_tmp(rd());  //random device is broken on mingw\n        timespec tmp_time;\n        clock_gettime(CLOCK_MONOTONIC, &tmp_time);\n        long long a = ((u64_t)tmp_time.tv_sec) * 1000000000llu + ((u64_t)tmp_time.tv_nsec);\n        std::mt19937 gen_tmp(a);\n        gen = gen_tmp;\n        gen.discard(700000);  // magic\n    }\n    u64_t gen64() {\n        return dis64(gen);\n    }\n    u32_t gen32() {\n        return dis32(gen);\n    }\n\n    unsigned char gen8() {\n        return dis8(gen);\n    }\n    /*int random_number_fd;\n    random_fd_t()\n    {\n                    random_number_fd=open(\"/dev/urandom\",O_RDONLY);\n                    if(random_number_fd==-1)\n                    {\n                            mylog(log_fatal,\"error open /dev/urandom\\n\");\n                            myexit(-1);\n                    }\n                    setnonblocking(random_number_fd);\n    }\n    int get_fd()\n    {\n            return random_number_fd;\n    }*/\n} my_random;\n#endif\n\nu64_t get_true_random_number_64() {\n#if !defined(__MINGW32__)\n    u64_t ret;\n    int size = read(random_fd.get_fd(), &ret, sizeof(ret));\n    if (size != sizeof(ret)) {\n        mylog(log_fatal, \"get random number failed %d\\n\", size);\n        myexit(-1);\n    }\n    return ret;\n#else\n    return my_random.gen64();  // fake random number\n#endif\n}\nu32_t get_true_random_number() {\n#if !defined(__MINGW32__)\n    u32_t ret;\n    int size = read(random_fd.get_fd(), &ret, sizeof(ret));\n    if (size != sizeof(ret)) {\n        mylog(log_fatal, \"get random number failed %d\\n\", size);\n        myexit(-1);\n    }\n    return ret;\n#else\n    return my_random.gen32();  // fake random number\n#endif\n}\nu32_t get_true_random_number_nz()  // nz for non-zero\n{\n    u32_t ret = 0;\n    while (ret == 0) {\n        ret = get_true_random_number();\n    }\n    return ret;\n}\n\ninline int is_big_endian() {\n    int i = 1;\n    return !*((char *)&i);\n}\nu64_t ntoh64(u64_t a) {\n#ifdef UDP2RAW_LITTLE_ENDIAN\n    u32_t h = get_u64_h(a);\n    u32_t l = get_u64_l(a);\n    return pack_u64(ntohl(l), ntohl(h));\n    // return bswap_64( a);\n#else\n    return a;\n#endif\n}\nu64_t hton64(u64_t a) {\n    return ntoh64(a);\n}\n\nvoid write_u16(char *p, u16_t w) {\n    *(unsigned char *)(p + 1) = (w & 0xff);\n    *(unsigned char *)(p + 0) = (w >> 8);\n}\nu16_t read_u16(char *p) {\n    u16_t res;\n    res = *(const unsigned char *)(p + 0);\n    res = *(const unsigned char *)(p + 1) + (res << 8);\n    return res;\n}\n\nvoid write_u32(char *p, u32_t l) {\n    *(unsigned char *)(p + 3) = (unsigned char)((l >> 0) & 0xff);\n    *(unsigned char *)(p + 2) = (unsigned char)((l >> 8) & 0xff);\n    *(unsigned char *)(p + 1) = (unsigned char)((l >> 16) & 0xff);\n    *(unsigned char *)(p + 0) = (unsigned char)((l >> 24) & 0xff);\n}\nu32_t read_u32(char *p) {\n    u32_t res;\n    res = *(const unsigned char *)(p + 0);\n    res = *(const unsigned char *)(p + 1) + (res << 8);\n    res = *(const unsigned char *)(p + 2) + (res << 8);\n    res = *(const unsigned char *)(p + 3) + (res << 8);\n    return res;\n}\n\nvoid write_u64(char *s, u64_t a) {\n    assert(0 == 1);\n}\nu64_t read_u64(char *s) {\n    assert(0 == 1);\n    return 0;\n}\n\nvoid setnonblocking(int sock) {\n#if !defined(__MINGW32__)\n    int opts;\n    opts = fcntl(sock, F_GETFL);\n\n    if (opts < 0) {\n        mylog(log_fatal, \"fcntl(sock,GETFL)\\n\");\n        // perror(\"fcntl(sock,GETFL)\");\n        myexit(1);\n    }\n    opts = opts | O_NONBLOCK;\n    if (fcntl(sock, F_SETFL, opts) < 0) {\n        mylog(log_fatal, \"fcntl(sock,SETFL,opts)\\n\");\n        // perror(\"fcntl(sock,SETFL,opts)\");\n        myexit(1);\n    }\n#else\n    int iResult;\n    u_long iMode = 1;\n    iResult = ioctlsocket(sock, FIONBIO, &iMode);\n    if (iResult != NO_ERROR)\n        printf(\"ioctlsocket failed with error: %d\\n\", iResult);\n\n#endif\n}\n\n/*\n    Generic checksum calculation function\n*/\nunsigned short csum(const unsigned short *ptr, int nbytes) {  // works both for big and little endian\n    long sum;\n    unsigned short oddbyte;\n    short answer;\n\n    sum = 0;\n    while (nbytes > 1) {\n        sum += *ptr++;\n        nbytes -= 2;\n    }\n    if (nbytes == 1) {\n        oddbyte = 0;\n        *((u_char *)&oddbyte) = *(u_char *)ptr;\n        sum += oddbyte;\n    }\n\n    sum = (sum >> 16) + (sum & 0xffff);\n    sum = sum + (sum >> 16);\n    answer = (short)~sum;\n\n    return (answer);\n}\n\nunsigned short csum_with_header(char *header, int hlen, const unsigned short *ptr, int nbytes) {  // works both for big and little endian\n\n    long sum;\n    unsigned short oddbyte;\n    short answer;\n\n    assert(hlen % 2 == 0);\n\n    sum = 0;\n    unsigned short *tmp = (unsigned short *)header;\n    for (int i = 0; i < hlen / 2; i++) {\n        sum += *tmp++;\n    }\n\n    while (nbytes > 1) {\n        sum += *ptr++;\n        nbytes -= 2;\n    }\n    if (nbytes == 1) {\n        oddbyte = 0;\n        *((u_char *)&oddbyte) = *(u_char *)ptr;\n        sum += oddbyte;\n    }\n\n    sum = (sum >> 16) + (sum & 0xffff);\n    sum = sum + (sum >> 16);\n    answer = (short)~sum;\n\n    return (answer);\n}\n\nint set_buf_size(int fd, int socket_buf_size) {\n    if (force_socket_buf) {\n        if (is_udp2raw_mp) {\n            mylog(log_fatal, \"force_socket_buf not supported in this verion\\n\");\n            myexit(-1);\n        }\n        // assert(0==1);\n#ifdef UDP2RAW_LINUX\n        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &socket_buf_size, sizeof(socket_buf_size)) < 0) {\n            mylog(log_fatal, \"SO_SNDBUFFORCE fail  socket_buf_size=%d  errno=%s\\n\", socket_buf_size, strerror(errno));\n            myexit(1);\n        }\n        if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &socket_buf_size, sizeof(socket_buf_size)) < 0) {\n            mylog(log_fatal, \"SO_RCVBUFFORCE fail  socket_buf_size=%d  errno=%s\\n\", socket_buf_size, strerror(errno));\n            myexit(1);\n        }\n#endif\n\n    } else {\n        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &socket_buf_size, sizeof(socket_buf_size)) < 0) {\n            mylog(log_fatal, \"SO_SNDBUF fail  socket_buf_size=%d  errno=%s\\n\", socket_buf_size, get_sock_error());\n            myexit(1);\n        }\n        if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &socket_buf_size, sizeof(socket_buf_size)) < 0) {\n            mylog(log_fatal, \"SO_RCVBUF fail  socket_buf_size=%d  errno=%s\\n\", socket_buf_size, get_sock_error());\n            myexit(1);\n        }\n    }\n    return 0;\n}\n\nint numbers_to_char(my_id_t id1, my_id_t id2, my_id_t id3, char *&data, int &len) {\n    static char buf[buf_len];\n    data = buf;\n    my_id_t tmp = htonl(id1);\n    memcpy(buf, &tmp, sizeof(tmp));\n\n    tmp = htonl(id2);\n    memcpy(buf + sizeof(tmp), &tmp, sizeof(tmp));\n\n    tmp = htonl(id3);\n    memcpy(buf + sizeof(tmp) * 2, &tmp, sizeof(tmp));\n\n    len = sizeof(my_id_t) * 3;\n    return 0;\n}\n\nint char_to_numbers(const char *data, int len, my_id_t &id1, my_id_t &id2, my_id_t &id3) {\n    if (len < int(sizeof(my_id_t) * 3)) return -1;\n    // id1=ntohl(  *((id_t*)(data+0)) );\n    memcpy(&id1, data + 0, sizeof(id1));\n    id1 = ntohl(id1);\n    // id2=ntohl(  *((id_t*)(data+sizeof(id_t))) );\n    memcpy(&id2, data + sizeof(my_id_t), sizeof(id2));\n    id2 = ntohl(id2);\n    // id3=ntohl(  *((id_t*)(data+sizeof(id_t)*2)) );\n    memcpy(&id3, data + sizeof(my_id_t) * 2, sizeof(id3));\n    id3 = ntohl(id3);\n    return 0;\n}\nint hex_to_u32(const string &a, u32_t &output) {\n    // string b=\"0x\";\n    // b+=a;\n    if (sscanf(a.c_str(), \"%x\", &output) == 1) {\n        // printf(\"%s %x\\n\",a.c_str(),output);\n        return 0;\n    }\n    mylog(log_error, \"<%s> doesnt contain a hex\\n\", a.c_str());\n    return -1;\n}\nint hex_to_u32_with_endian(const string &a, u32_t &output) {\n    // string b=\"0x\";\n    // b+=a;\n    if (sscanf(a.c_str(), \"%x\", &output) == 1) {\n        output = htonl(output);\n        // printf(\"%s %x\\n\",a.c_str(),output);\n        return 0;\n    }\n    mylog(log_error, \"<%s> doesnt contain a hex\\n\", a.c_str());\n    return -1;\n}\nbool larger_than_u32(u32_t a, u32_t b) {\n    return ((i32_t(a - b)) > 0);\n    /*\n            u32_t smaller,bigger;\n            smaller=min(a,b);//smaller in normal sense\n            bigger=max(a,b);\n            u32_t distance=min(bigger-smaller,smaller+(0xffffffff-bigger+1));\n            if(distance==bigger-smaller)\n            {\n                    if(bigger==a)\n                    {\n                            return 1;\n                    }\n                    else\n                    {\n                            return 0;\n                    }\n            }\n            else\n            {\n                    if(smaller==b)\n                    {\n                            return 0;\n                    }\n                    else\n                    {\n                            return 1;\n                    }\n            }\n    */\n}\n\nbool larger_than_u16(uint16_t a, uint16_t b) {\n    return ((i16_t(a - b)) > 0);\n    /*\n            uint16_t smaller,bigger;\n            smaller=min(a,b);//smaller in normal sense\n            bigger=max(a,b);\n            uint16_t distance=min(bigger-smaller,smaller+(0xffff-bigger+1));\n            if(distance==bigger-smaller)\n            {\n                    if(bigger==a)\n                    {\n                            return 1;\n                    }\n                    else\n                    {\n                            return 0;\n                    }\n            }\n            else\n            {\n                    if(smaller==b)\n                    {\n                            return 0;\n                    }\n                    else\n                    {\n                            return 1;\n                    }\n            }*/\n}\n\nvoid myexit(int a) {\n    if (enable_log_color)\n        printf(\"%s\\n\", RESET);\n#ifdef UDP2RAW_LINUX\n    if (keep_thread_running) {\n        if (pthread_cancel(keep_thread)) {\n            mylog(log_warn, \"pthread_cancel failed\\n\");\n        } else {\n            mylog(log_info, \"pthread_cancel success\\n\");\n        }\n    }\n    clear_iptables_rule();\n#endif\n    exit(a);\n}\n\nvector<string> string_to_vec(const char *s, const char *sp) {\n    vector<string> res;\n    string str = s;\n    char *p = strtok((char *)str.c_str(), sp);\n    while (p != NULL) {\n        res.push_back(p);\n        // printf (\"%s\\n\",p);\n        p = strtok(NULL, sp);\n    }\n\n    /* for(int i=0;i<(int)res.size();i++)\n     {\n             printf(\"<<%s>>\\n\",res[i].c_str());\n     }*/\n    return res;\n}\n\nvector<vector<string> > string_to_vec2(const char *s) {\n    vector<vector<string> > res;\n    vector<string> lines = string_to_vec(s, \"\\n\");\n    for (int i = 0; i < int(lines.size()); i++) {\n        vector<string> tmp;\n        tmp = string_to_vec(lines[i].c_str(), \"\\t \");\n        res.push_back(tmp);\n    }\n    return res;\n}\nint read_file(const char *file, string &output) {\n    const int max_len = 3 * 1024 * 1024;\n    // static char buf[max_len+100];\n    string buf0;\n    buf0.reserve(max_len + 200);\n    char *buf = (char *)buf0.c_str();\n    buf[max_len] = 0;\n    // buf[sizeof(buf)-1]=0;\n    int fd = open(file, O_RDONLY);\n    if (fd == -1) {\n        mylog(log_error, \"read_file %s fail\\n\", file);\n        return -1;\n    }\n    int len = read(fd, buf, max_len);\n    if (len == max_len) {\n        buf[0] = 0;\n        mylog(log_error, \"%s too long,buf not large enough\\n\", file);\n        return -2;\n    } else if (len < 0) {\n        buf[0] = 0;\n        mylog(log_error, \"%s read fail %d\\n\", file, len);\n        return -3;\n    } else {\n        buf[len] = 0;\n        output = buf;\n    }\n    return 0;\n}\nint run_command(string command0, char *&output, int flag) {\n    if (is_udp2raw_mp) {\n        mylog(log_fatal, \"run_command not supported in this version\\n\");\n        myexit(-1);\n    }\n#ifdef UDP2RAW_LINUX\n    FILE *in;\n\n    if ((flag & show_log) == 0) command0 += \" 2>&1 \";\n\n    const char *command = command0.c_str();\n\n    int level = (flag & show_log) ? log_warn : log_debug;\n\n    if (flag & show_command) {\n        mylog(log_info, \"run_command %s\\n\", command);\n    } else {\n        mylog(log_debug, \"run_command %s\\n\", command);\n    }\n    static __thread char buf[1024 * 1024 + 100];\n    buf[sizeof(buf) - 1] = 0;\n    if (!(in = popen(command, \"r\"))) {\n        mylog(level, \"command %s popen failed,errno %s\\n\", command, strerror(errno));\n        return -1;\n    }\n\n    int len = fread(buf, 1024 * 1024, 1, in);\n    if (len == 1024 * 1024) {\n        buf[0] = 0;\n        mylog(level, \"too long,buf not larger enough\\n\");\n        return -2;\n    } else {\n        buf[len] = 0;\n    }\n    int ret;\n    if ((ret = ferror(in))) {\n        mylog(level, \"command %s fread failed,ferror return value %d \\n\", command, ret);\n        return -3;\n    }\n    // if(output!=0)\n    output = buf;\n    ret = pclose(in);\n\n    int ret2 = WEXITSTATUS(ret);\n\n    if (ret != 0 || ret2 != 0) {\n        mylog(level, \"commnad %s ,pclose returned %d ,WEXITSTATUS %d,errnor :%s \\n\", command, ret, ret2, strerror(errno));\n        return -4;\n    }\n\n#endif\n    return 0;\n}\n/*\nint run_command_no_log(string command0,char * &output) {\n    FILE *in;\n    command0+=\" 2>&1 \";\n    const char * command=command0.c_str();\n    mylog(log_debug,\"run_command_no_log %s\\n\",command);\n    static char buf[1024*1024+100];\n    buf[sizeof(buf)-1]=0;\n    if(!(in = popen(command, \"r\"))){\n        mylog(log_debug,\"command %s popen failed,errno %s\\n\",command,strerror(errno));\n        return -1;\n    }\n\n    int len =fread(buf, 1024*1024, 1, in);\n    if(len==1024*1024)\n    {\n        buf[0]=0;\n        mylog(log_debug,\"too long,buf not larger enough\\n\");\n        return -2;\n    }\n    else\n    {\n        buf[len]=0;\n    }\n    int ret;\n    if(( ret=ferror(in) ))\n    {\n        mylog(log_debug,\"command %s fread failed,ferror return value %d \\n\",command,ret);\n        return -3;\n    }\n    //if(output!=0)\n    output=buf;\n    ret= pclose(in);\n\n    int ret2=WEXITSTATUS(ret);\n\n    if(ret!=0||ret2!=0)\n    {\n        mylog(log_debug,\"commnad %s ,pclose returned %d ,WEXITSTATUS %d,errnor :%s \\n\",command,ret,ret2,strerror(errno));\n        return -4;\n    }\n\n    return 0;\n\n}*/\n\n// Remove preceding and trailing characters\nstring trim(const string &str, char c) {\n    size_t first = str.find_first_not_of(c);\n    if (string::npos == first) {\n        return \"\";\n    }\n    size_t last = str.find_last_not_of(c);\n    return str.substr(first, (last - first + 1));\n}\n\nvector<string> parse_conf_line(const string &s0) {\n    string s = s0;\n    s.reserve(s.length() + 200);\n    char *buf = (char *)s.c_str();\n    // char buf[s.length()+200];\n    char *p = buf;\n    int i = int(s.length()) - 1;\n    int j;\n    vector<string> res;\n    // strcpy(buf,(char *)s.c_str());\n    while (i >= 0) {\n        if (buf[i] == ' ' || buf[i] == '\\t')\n            buf[i] = 0;\n        else\n            break;\n        i--;\n    }\n    while (*p != 0) {\n        if (*p == ' ' || *p == '\\t') {\n            p++;\n        } else\n            break;\n    }\n    int new_len = strlen(p);\n    if (new_len == 0) return res;\n    if (p[0] == '#') return res;\n    if (p[0] != '-') {\n        mylog(log_fatal, \"line :<%s> not begin with '-' \", s.c_str());\n        myexit(-1);\n    }\n\n    for (i = 0; i < new_len; i++) {\n        if (p[i] == ' ' || p[i] == '\\t') {\n            break;\n        }\n    }\n    if (i == new_len) {\n        res.push_back(p);\n        return res;\n    }\n\n    j = i;\n    while (p[j] == ' ' || p[j] == '\\t')\n        j++;\n    p[i] = 0;\n    res.push_back(p);\n    res.push_back(p + j);\n    return res;\n}\n\nint create_fifo(char *file) {\n#if !defined(__MINGW32__)\n    if (mkfifo(file, 0666) != 0) {\n        if (errno == EEXIST) {\n            mylog(log_warn, \"warning fifo file %s exist\\n\", file);\n        } else {\n            mylog(log_fatal, \"create fifo file %s failed\\n\", file);\n            myexit(-1);\n        }\n    }\n    int fifo_fd = open(file, O_RDWR);\n    if (fifo_fd < 0) {\n        mylog(log_fatal, \"create fifo file %s failed\\n\", file);\n        myexit(-1);\n    }\n    struct stat st;\n    if (fstat(fifo_fd, &st) != 0) {\n        mylog(log_fatal, \"fstat failed for fifo file %s\\n\", file);\n        myexit(-1);\n    }\n\n    if (!S_ISFIFO(st.st_mode)) {\n        mylog(log_fatal, \"%s is not a fifo\\n\", file);\n        myexit(-1);\n    }\n\n    setnonblocking(fifo_fd);\n    return fifo_fd;\n#else\n    mylog(log_fatal, \"--fifo not supported in this version\\n\");\n    myexit(-1);\n    return 0;\n#endif\n}\n\n/*\nvoid ip_port_t::from_u64(u64_t u64)\n{\n        ip=get_u64_h(u64);\n        port=get_u64_l(u64);\n}\nu64_t ip_port_t::to_u64()\n{\n        return pack_u64(ip,port);\n}\nchar * ip_port_t::to_s()\n{\n        static char res[40];\n        sprintf(res,\"%s:%d\",my_ntoa(ip),port);\n        return res;\n}*/\n\nvoid print_binary_chars(const char *a, int len) {\n    for (int i = 0; i < len; i++) {\n        unsigned char b = a[i];\n        log_bare(log_debug, \"<%02x>\", (int)b);\n    }\n    log_bare(log_debug, \"\\n\");\n}\n\nu32_t djb2(unsigned char *str, int len) {\n    u32_t hash = 5381;\n    int c;\n    for (int i=0; i<len ;i++) {\n        c = *(str++);\n        hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */\n    }\n\n    hash = htonl(hash);\n    return hash;\n}\n\nu32_t sdbm(unsigned char *str, int len) {\n    u32_t hash = 0;\n    int c;\n    for (int i=0; i<len ;i++) {\n        c = *(str++);\n        hash = c + (hash << 6) + (hash << 16) - hash;\n    }\n    // hash=htonl(hash);\n    return hash;\n}\n"
  },
  {
    "path": "common.h",
    "content": "/*\n * common.h\n *\n *  Created on: Jul 29, 2017\n *      Author: wangyu\n */\n\n#ifndef UDP2RAW_COMMON_H_\n#define UDP2RAW_COMMON_H_\n#define __STDC_FORMAT_MACROS 1\n#include <inttypes.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <getopt.h>\n\n#include <unistd.h>\n#include <errno.h>\n#include <sys/stat.h>\n#include <stdlib.h>  //for exit(0);\n#include <errno.h>   //For errno - the error number\n#include <fcntl.h>\n#include <sys/time.h>\n#include <time.h>\n#include <stdarg.h>\n#include <assert.h>\n#include <pthread.h>\n\n#ifndef USE_LIBNET\n#define NO_LIBNET\n#endif\n\n#if defined(UDP2RAW_MP)\nconst int is_udp2raw_mp = 1;\n#if !defined(__CYGWIN__) && !defined(__MINGW32__)\n#include <pcap.h>\n#else\n#include <pcap_wrapper.h>\n#define NO_LIBNET\n#endif\n\n#ifndef NO_LIBNET\n#include <libnet.h>\n#endif\n\n#else\n#define UDP2RAW_LINUX\nconst int is_udp2raw_mp = 0;\n//#include <linux/if_ether.h>\n#include <linux/filter.h>\n#include <linux/if_packet.h>\n#include <sys/epoll.h>\n//#include <sys/wait.h> //signal\n#include <netinet/if_ether.h>\n#include <net/if.h>\n#include <sys/timerfd.h>\n\n#endif\n\n#if !defined(NO_LIBEV_EMBED)\n#include <my_ev.h>\n#else\n#include \"ev.h\"\n#endif\n\n#if defined(__MINGW32__)\n#include <winsock2.h>\n#include <ws2ipdef.h>\ntypedef unsigned char u_int8_t;\ntypedef unsigned short u_int16_t;\ntypedef unsigned int u_int32_t;\ntypedef int socklen_t;\n#else\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <sys/ioctl.h>\n#include <arpa/inet.h>\n#include <netinet/in.h>\n#endif\n\n#include <unordered_map>\n#include <fstream>\n#include <string>\n#include <vector>\n#include <map>\n#include <set>\n#include <list>\nusing namespace std;\n\n#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN ||             \\\n    defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \\\n    defined(__BIG_ENDIAN__) ||                                           \\\n    defined(__ARMEB__) ||                                                \\\n    defined(__THUMBEB__) ||                                              \\\n    defined(__AARCH64EB__) ||                                            \\\n    defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)\n#define UDP2RAW_BIG_ENDIAN 1\n#endif\n\n#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN ||             \\\n    defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \\\n    defined(__LITTLE_ENDIAN__) ||                                           \\\n    defined(__ARMEL__) ||                                                   \\\n    defined(__THUMBEL__) ||                                                 \\\n    defined(__AARCH64EL__) ||                                               \\\n    defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)\n#define UDP2RAW_LITTLE_ENDIAN 1\n#endif\n\n#if defined(UDP2RAW_BIG_ENDIAN) && defined(UDP2RAW_LITTLE_ENDIAN)\n#error \"endian detection conflicts\"\n#endif\n\n#if !defined(UDP2RAW_BIG_ENDIAN) && !defined(UDP2RAW_LITTLE_ENDIAN)\n#error \"endian detection failed\"\n#endif\n\n#if defined(__MINGW32__)\nint inet_pton(int af, const char *src, void *dst);\nconst char *inet_ntop(int af, const void *src, char *dst, socklen_t size);\n#define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (const char *)(d), e)\n#endif\n\nchar *get_sock_error();\nint get_sock_errno();\n\n#if defined(__MINGW32__)\ntypedef SOCKET my_fd_t;\ninline int sock_close(my_fd_t fd) {\n    return closesocket(fd);\n}\n#else\ntypedef int my_fd_t;\ninline int sock_close(my_fd_t fd) {\n    return close(fd);\n}\n\n#endif\n\ntypedef unsigned long long u64_t;  // this works on most platform,avoid using the PRId64\ntypedef long long i64_t;\n\ntypedef unsigned int u32_t;\ntypedef int i32_t;\n\ntypedef unsigned short u16_t;\ntypedef short i16_t;\n\ntypedef u32_t my_id_t;\n\ntypedef u64_t iv_t;\n\ntypedef u64_t padding_t;\n\ntypedef u64_t anti_replay_seq_t;\n\ntypedef u64_t my_time_t;\n\nconst int max_addr_len = 100;\n\nextern int force_socket_buf;\n\nextern int g_fix_gro;\n\n/*\nstruct ip_port_t\n{\n        u32_t ip;\n        int port;\n        void from_u64(u64_t u64);\n        u64_t to_u64();\n        char * to_s();\n};*/\n\ntypedef u64_t fd64_t;\n\nu32_t djb2(unsigned char *str, int len);\nu32_t sdbm(unsigned char *str, int len);\n\nstruct address_t  // TODO scope id\n{\n    struct hash_function {\n        u32_t operator()(const address_t &key) const {\n            return sdbm((unsigned char *)&key.inner, sizeof(key.inner));\n        }\n    };\n\n    union storage_t  // sockaddr_storage is too huge, we dont use it.\n    {\n        sockaddr_in ipv4;\n        sockaddr_in6 ipv6;\n    };\n    storage_t inner;\n\n    address_t() {\n        clear();\n    }\n    void clear() {\n        memset(&inner, 0, sizeof(inner));\n    }\n    int from_ip_port(u32_t ip, int port) {\n        clear();\n        inner.ipv4.sin_family = AF_INET;\n        inner.ipv4.sin_port = htons(port);\n        inner.ipv4.sin_addr.s_addr = ip;\n        return 0;\n    }\n\n    int from_ip_port_new(int type, void *ip, int port) {\n        clear();\n        if (type == AF_INET) {\n            inner.ipv4.sin_family = AF_INET;\n            inner.ipv4.sin_port = htons(port);\n            inner.ipv4.sin_addr.s_addr = *((u32_t *)ip);\n        } else if (type == AF_INET6) {\n            inner.ipv6.sin6_family = AF_INET6;\n            inner.ipv6.sin6_port = htons(port);\n            inner.ipv6.sin6_addr = *((in6_addr *)ip);\n        }\n        return 0;\n    }\n\n    int from_str(char *str);\n\n    int from_str_ip_only(char *str);\n\n    int from_sockaddr(sockaddr *, socklen_t);\n\n    char *get_str();\n    void to_str(char *);\n\n    inline u32_t get_type() {\n        u32_t ret = ((sockaddr *)&inner)->sa_family;\n        assert(ret == AF_INET || ret == AF_INET6);\n        return ret;\n    }\n\n    inline u32_t get_len() {\n        u32_t type = get_type();\n        switch (type) {\n            case AF_INET:\n                return sizeof(sockaddr_in);\n            case AF_INET6:\n                return sizeof(sockaddr_in6);\n            default:\n                assert(0 == 1);\n        }\n        return -1;\n    }\n\n    inline u32_t get_port() {\n        u32_t type = get_type();\n        switch (type) {\n            case AF_INET:\n                return ntohs(inner.ipv4.sin_port);\n            case AF_INET6:\n                return ntohs(inner.ipv6.sin6_port);\n            default:\n                assert(0 == 1);\n        }\n        return -1;\n    }\n\n    inline void set_port(int port) {\n        u32_t type = get_type();\n        switch (type) {\n            case AF_INET:\n                inner.ipv4.sin_port = htons(port);\n                break;\n            case AF_INET6:\n                inner.ipv6.sin6_port = htons(port);\n                break;\n            default:\n                assert(0 == 1);\n        }\n        return;\n    }\n\n    bool operator==(const address_t &b) const {\n        // return this->data==b.data;\n        return memcmp(&this->inner, &b.inner, sizeof(this->inner)) == 0;\n    }\n\n    int new_connected_udp_fd();\n\n    char *get_ip();\n};\n\nnamespace std {\ntemplate <>\nstruct hash<address_t> {\n    std::size_t operator()(const address_t &key) const {\n        // return address_t::hash_function(k);\n        return sdbm((unsigned char *)&key.inner, sizeof(key.inner));\n    }\n};\n}  // namespace std\n\nunion my_ip_t  // just a simple version of address_t,stores ip only\n{\n    u32_t v4;\n    in6_addr v6;\n\n    bool equal(const my_ip_t &b) const;\n\n    // int from_str(char * str);\n    char *get_str1() const;\n    char *get_str2() const;\n\n    int from_address_t(address_t a);\n};\n\nstruct not_copy_able_t {\n    not_copy_able_t() {\n    }\n    not_copy_able_t(const not_copy_able_t &other) {\n        assert(0 == 1);\n    }\n    const not_copy_able_t &operator=(const not_copy_able_t &other) {\n        assert(0 == 1);\n        return other;\n    }\n};\n\nconst int huge_data_len = 65535 + 100;  // a packet with link level header might be larger than 65535\nconst int huge_buf_len = huge_data_len + 100;\n\nconst int max_data_len = 1800;\nconst int buf_len = max_data_len + 400;\n\n// const int max_address_len=512;\n\n#ifdef UDP2RAW_MP\nconst int queue_len = 200;\n\nstruct queue_t {\n    char data[queue_len][huge_buf_len];\n    int data_len[queue_len];\n\n    int head = 0;\n    int tail = 0;\n    void clear() {\n        head = tail = 0;\n    }\n    int empty() {\n        if (head == tail)\n            return 1;\n        else\n            return 0;\n    }\n    int full() {\n        if ((tail + 1) % queue_len == head)\n            return 1;\n        else\n            return 0;\n    }\n    void peek_front(char *&p, int &len) {\n        assert(!empty());\n        p = data[head];\n        len = data_len[head];\n    }\n    void pop_front() {\n        assert(!empty());\n        head++;\n        head %= queue_len;\n    }\n    void push_back(char *p, int len) {\n        assert(!full());\n        memcpy(data[tail], p, len);\n        data_len[tail] = len;\n        tail++;\n        tail %= queue_len;\n    }\n};\n\nint init_ws();\n#endif\nu64_t get_current_time();\nu64_t pack_u64(u32_t a, u32_t b);\n\nu32_t get_u64_h(u64_t a);\n\nu32_t get_u64_l(u64_t a);\n\nchar *my_ntoa(u32_t ip);\n\nvoid init_random_number_fd();\nu64_t get_true_random_number_64();\nu32_t get_true_random_number();\nu32_t get_true_random_number_nz();\nu64_t ntoh64(u64_t a);\nu64_t hton64(u64_t a);\n\nvoid write_u16(char *, u16_t a);  // network order\nu16_t read_u16(char *);\nvoid write_u32(char *, u32_t a);  // network order\nu32_t read_u32(char *);\nvoid write_u64(char *, u64_t a);\nu64_t read_u64(char *);\n\nbool larger_than_u16(uint16_t a, uint16_t b);\nbool larger_than_u32(u32_t a, u32_t b);\nvoid setnonblocking(int sock);\nint set_buf_size(int fd, int socket_buf_size);\n\nvoid myexit(int a);\n\nunsigned short csum(const unsigned short *ptr, int nbytes);\nunsigned short csum_with_header(char *header, int hlen, const unsigned short *ptr, int nbytes);\n\nint numbers_to_char(my_id_t id1, my_id_t id2, my_id_t id3, char *&data, int &len);\nint char_to_numbers(const char *data, int len, my_id_t &id1, my_id_t &id2, my_id_t &id3);\n\nconst int show_none = 0;\nconst int show_command = 0x1;\nconst int show_log = 0x2;\nconst int show_all = show_command | show_log;\n\nint run_command(string command, char *&output, int flag = show_all);\n// int run_command_no_log(string command,char * &output);\nint read_file(const char *file, string &output);\n\nvector<string> string_to_vec(const char *s, const char *sp);\nvector<vector<string> > string_to_vec2(const char *s);\n\nstring trim(const string &str, char c);\n\nstring trim_conf_line(const string &str);\n\nvector<string> parse_conf_line(const string &s);\n\nint hex_to_u32_with_endian(const string &a, u32_t &output);\nint hex_to_u32(const string &a, u32_t &output);\n// extern string iptables_pattern;\n\nint create_fifo(char *file);\n\nvoid print_binary_chars(const char *a, int len);\n\ntemplate <class key_t>\nstruct lru_collector_t : not_copy_able_t {\n    // typedef void* key_t;\n    //#define key_t void*\n    struct lru_pair_t {\n        key_t key;\n        my_time_t ts;\n    };\n\n    unordered_map<key_t, typename list<lru_pair_t>::iterator> mp;\n\n    list<lru_pair_t> q;\n    int update(key_t key) {\n        assert(mp.find(key) != mp.end());\n        auto it = mp[key];\n        q.erase(it);\n\n        my_time_t value = get_current_time();\n        if (!q.empty()) {\n            assert(value >= q.front().ts);\n        }\n        lru_pair_t tmp;\n        tmp.key = key;\n        tmp.ts = value;\n        q.push_front(tmp);\n        mp[key] = q.begin();\n\n        return 0;\n    }\n    int new_key(key_t key) {\n        assert(mp.find(key) == mp.end());\n\n        my_time_t value = get_current_time();\n        if (!q.empty()) {\n            assert(value >= q.front().ts);\n        }\n        lru_pair_t tmp;\n        tmp.key = key;\n        tmp.ts = value;\n        q.push_front(tmp);\n        mp[key] = q.begin();\n\n        return 0;\n    }\n    int size() {\n        return q.size();\n    }\n    int empty() {\n        return q.empty();\n    }\n    void clear() {\n        mp.clear();\n        q.clear();\n    }\n    my_time_t ts_of(key_t key) {\n        assert(mp.find(key) != mp.end());\n        return mp[key]->ts;\n    }\n\n    my_time_t peek_back(key_t &key) {\n        assert(!q.empty());\n        auto it = q.end();\n        it--;\n        key = it->key;\n        return it->ts;\n    }\n    void erase(key_t key) {\n        assert(mp.find(key) != mp.end());\n        q.erase(mp[key]);\n        mp.erase(key);\n    }\n    /*\n    void erase_back()\n    {\n            assert(!q.empty());\n            auto it=q.end(); it--;\n            key_t key=it->key;\n            erase(key);\n    }*/\n};\n\n#endif /* COMMON_H_ */\n"
  },
  {
    "path": "connection.cpp",
    "content": "/*\n * connection.cpp\n *\n *  Created on: Sep 23, 2017\n *      Author: root\n */\n\n#include \"connection.h\"\n#include \"encrypt.h\"\n#include \"fd_manager.h\"\n\nint disable_anti_replay = 0;  // if anti_replay windows is diabled\n\nconst int disable_conn_clear = 0;  // a raw connection is called conn.\n\nconn_manager_t conn_manager;\n\nanti_replay_seq_t anti_replay_t::get_new_seq_for_send() {\n    return anti_replay_seq++;\n}\nanti_replay_t::anti_replay_t() {\n    max_packet_received = 0;\n    anti_replay_seq = get_true_random_number_64() / 10;  // random first seq\n    // memset(window,0,sizeof(window)); //not necessary\n}\nvoid anti_replay_t::re_init() {\n    max_packet_received = 0;\n    // memset(window,0,sizeof(window));\n}\n\nint anti_replay_t::is_vaild(u64_t seq) {\n    if (disable_anti_replay) return 1;\n    // if(disabled) return 0;\n\n    if (seq == max_packet_received)\n        return 0;\n    else if (seq > max_packet_received) {\n        if (seq - max_packet_received >= anti_replay_window_size) {\n            memset(window, 0, sizeof(window));\n            window[seq % anti_replay_window_size] = 1;\n        } else {\n            for (u64_t i = max_packet_received + 1; i < seq; i++)\n                window[i % anti_replay_window_size] = 0;\n            window[seq % anti_replay_window_size] = 1;\n        }\n        max_packet_received = seq;\n        return 1;\n    } else if (seq < max_packet_received) {\n        if (max_packet_received - seq >= anti_replay_window_size)\n            return 0;\n        else {\n            if (window[seq % anti_replay_window_size] == 1)\n                return 0;\n            else {\n                window[seq % anti_replay_window_size] = 1;\n                return 1;\n            }\n        }\n    }\n\n    return 0;  // for complier check\n}\n\nvoid conn_info_t::recover(const conn_info_t &conn_info) {\n    raw_info = conn_info.raw_info;\n\n    raw_info.rst_received = 0;\n    raw_info.disabled = 0;\n\n    last_state_time = conn_info.last_state_time;\n    last_hb_recv_time = conn_info.last_hb_recv_time;\n    last_hb_sent_time = conn_info.last_hb_sent_time;\n    my_id = conn_info.my_id;\n    oppsite_id = conn_info.oppsite_id;\n    blob->anti_replay.re_init();\n\n    my_roller = 0;       // no need to set,but for easier debug,set it to zero\n    oppsite_roller = 0;  // same as above\n    last_oppsite_roller_time = 0;\n}\n\nvoid conn_info_t::re_init() {\n    // send_packet_info.protocol=g_packet_info_send.protocol;\n    if (program_mode == server_mode)\n        state.server_current_state = server_idle;\n    else\n        state.client_current_state = client_idle;\n    last_state_time = 0;\n    oppsite_const_id = 0;\n\n    timer_fd64 = 0;\n\n    my_roller = 0;\n    oppsite_roller = 0;\n    last_oppsite_roller_time = 0;\n}\nconn_info_t::conn_info_t() {\n    blob = 0;\n    re_init();\n}\nvoid conn_info_t::prepare() {\n    assert(blob == 0);\n    blob = new blob_t;\n    if (program_mode == server_mode) {\n        blob->conv_manager.s.additional_clear_function = server_clear_function;\n    } else {\n        assert(program_mode == client_mode);\n    }\n}\n\nconn_info_t::conn_info_t(const conn_info_t &b) {\n    assert(0 == 1);\n    // mylog(log_error,\"called!!!!!!!!!!!!!\\n\");\n}\n\nconn_info_t &conn_info_t::operator=(const conn_info_t &b) {\n    mylog(log_fatal, \"not allowed\\n\");\n    myexit(-1);\n    return *this;\n}\nconn_info_t::~conn_info_t() {\n    if (program_mode == server_mode) {\n        if (state.server_current_state == server_ready) {\n            assert(blob != 0);\n            assert(oppsite_const_id != 0);\n            // assert(conn_manager.const_id_mp.find(oppsite_const_id)!=conn_manager.const_id_mp.end()); // conn_manager 's deconstuction function  erases it\n        } else {\n            assert(blob == 0);\n            assert(oppsite_const_id == 0);\n        }\n    }\n    assert(timer_fd64 == 0);\n    // if(oppsite_const_id!=0)     //do this at conn_manager 's deconstuction function\n    // conn_manager.const_id_mp.erase(oppsite_const_id);\n    if (blob != 0)\n        delete blob;\n\n    // send_packet_info.protocol=g_packet_info_send.protocol;\n}\n\nconn_manager_t::conn_manager_t() {\n    ready_num = 0;\n    mp.reserve(10007);\n    // clear_it=mp.begin();\n    // timer_fd_mp.reserve(10007);\n    const_id_mp.reserve(10007);\n    // udp_fd_mp.reserve(100007);\n    last_clear_time = 0;\n    // current_ready_ip=0;\n    // current_ready_port=0;\n}\nint conn_manager_t::exist(address_t addr) {\n    // u64_t u64=0;\n    // u64=ip;\n    // u64<<=32u;\n    // u64|=port;\n    if (mp.find(addr) != mp.end()) {\n        return 1;\n    }\n    return 0;\n}\n/*\nint insert(uint32_t ip,uint16_t port)\n{\n        uint64_t u64=0;\n        u64=ip;\n        u64<<=32u;\n        u64|=port;\n        mp[u64];\n        return 0;\n}*/\nconn_info_t *&conn_manager_t::find_insert_p(address_t addr)  // be aware,the adress may change after rehash\n{\n    // u64_t u64=0;\n    // u64=ip;\n    // u64<<=32u;\n    // u64|=port;\n    unordered_map<address_t, conn_info_t *>::iterator it = mp.find(addr);\n    if (it == mp.end()) {\n        mp[addr] = new conn_info_t;\n        // lru.new_key(addr);\n    } else {\n        // lru.update(addr);\n    }\n    return mp[addr];\n}\nconn_info_t &conn_manager_t::find_insert(address_t addr)  // be aware,the adress may change after rehash\n{\n    // u64_t u64=0;\n    // u64=ip;\n    // u64<<=32u;\n    // u64|=port;\n    unordered_map<address_t, conn_info_t *>::iterator it = mp.find(addr);\n    if (it == mp.end()) {\n        mp[addr] = new conn_info_t;\n        // lru.new_key(addr);\n    } else {\n        // lru.update(addr);\n    }\n    return *mp[addr];\n}\nint conn_manager_t::erase(unordered_map<address_t, conn_info_t *>::iterator erase_it) {\n    if (erase_it->second->state.server_current_state == server_ready) {\n        ready_num--;\n        assert(i32_t(ready_num) != -1);\n        assert(erase_it->second != 0);\n\n        assert(erase_it->second->timer_fd64 != 0);\n\n        assert(fd_manager.exist(erase_it->second->timer_fd64));\n\n        assert(erase_it->second->oppsite_const_id != 0);\n        assert(const_id_mp.find(erase_it->second->oppsite_const_id) != const_id_mp.end());\n\n        // assert(timer_fd_mp.find(erase_it->second->timer_fd)!=timer_fd_mp.end());\n\n        const_id_mp.erase(erase_it->second->oppsite_const_id);\n\n        fd_manager.fd64_close(erase_it->second->timer_fd64);\n\n        erase_it->second->timer_fd64 = 0;\n        // timer_fd_mp.erase(erase_it->second->timer_fd);\n        // close(erase_it->second->timer_fd);// close will auto delte it from epoll\n        delete (erase_it->second);\n        mp.erase(erase_it->first);\n    } else {\n        assert(erase_it->second->blob == 0);\n        assert(erase_it->second->timer_fd64 == 0);\n\n        assert(erase_it->second->oppsite_const_id == 0);\n        delete (erase_it->second);\n        mp.erase(erase_it->first);\n    }\n    return 0;\n}\nint conn_manager_t::clear_inactive() {\n    if (get_current_time() - last_clear_time > conn_clear_interval) {\n        last_clear_time = get_current_time();\n        return clear_inactive0();\n    }\n    return 0;\n}\nint conn_manager_t::clear_inactive0() {\n    unordered_map<address_t, conn_info_t *>::iterator it;\n    unordered_map<address_t, conn_info_t *>::iterator old_it;\n\n    if (disable_conn_clear) return 0;\n\n    // map<uint32_t,uint64_t>::iterator it;\n    int cnt = 0;\n    it = clear_it;\n    int size = mp.size();\n    int num_to_clean = size / conn_clear_ratio + conn_clear_min;  // clear 1/10 each time,to avoid latency glitch\n\n    mylog(log_trace, \"mp.size() %d\\n\", size);\n\n    num_to_clean = min(num_to_clean, (int)mp.size());\n    u64_t current_time = get_current_time();\n\n    for (;;) {\n        if (cnt >= num_to_clean) break;\n        if (mp.begin() == mp.end()) break;\n\n        if (it == mp.end()) {\n            it = mp.begin();\n        }\n\n        if (it->second->state.server_current_state == server_ready && current_time - it->second->last_hb_recv_time <= server_conn_timeout) {\n            it++;\n        } else if (it->second->state.server_current_state != server_ready && current_time - it->second->last_state_time <= server_handshake_timeout) {\n            it++;\n        } else if (it->second->blob != 0 && it->second->blob->conv_manager.s.get_size() > 0) {\n            assert(it->second->state.server_current_state == server_ready);\n            it++;\n        } else {\n            mylog(log_info, \"[%s:%d]inactive conn cleared \\n\", it->second->raw_info.recv_info.new_src_ip.get_str1(), it->second->raw_info.recv_info.src_port);\n            old_it = it;\n            it++;\n            erase(old_it);\n        }\n        cnt++;\n    }\n    clear_it = it;\n\n    return 0;\n}\n\nint send_bare(raw_info_t &raw_info, const char *data, int len)  // send function with encryption but no anti replay,this is used when client and server verifys each other\n// you have to design the protocol carefully, so that you wont be affect by relay attack\n{\n    if (len < 0) {\n        mylog(log_debug, \"input_len <0\\n\");\n        return -1;\n    }\n    packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    char send_data_buf[buf_len];  // buf for send data and send hb\n    char send_data_buf2[buf_len];\n\n    // static send_bare[buf_len];\n    iv_t iv = get_true_random_number_64();\n    padding_t padding = get_true_random_number_64();\n\n    memcpy(send_data_buf, &iv, sizeof(iv));\n    memcpy(send_data_buf + sizeof(iv), &padding, sizeof(padding));\n\n    send_data_buf[sizeof(iv) + sizeof(padding)] = 'b';\n    memcpy(send_data_buf + sizeof(iv) + sizeof(padding) + 1, data, len);\n    int new_len = len + sizeof(iv) + sizeof(padding) + 1;\n\n    if (my_encrypt(send_data_buf, send_data_buf2, new_len) != 0) {\n        return -1;\n    }\n    send_raw0(raw_info, send_data_buf2, new_len);\n    return 0;\n}\nint reserved_parse_bare(const char *input, int input_len, char *&data, int &len)  // a sub function used in recv_bare\n{\n    static char recv_data_buf[buf_len];\n\n    if (input_len < 0) {\n        mylog(log_debug, \"input_len <0\\n\");\n        return -1;\n    }\n    if (my_decrypt(input, recv_data_buf, input_len) != 0) {\n        mylog(log_debug, \"decrypt_fail in recv bare\\n\");\n        return -1;\n    }\n    if (recv_data_buf[sizeof(iv_t) + sizeof(padding_t)] != 'b') {\n        mylog(log_debug, \"not a bare packet\\n\");\n        return -1;\n    }\n    len = input_len;\n    data = recv_data_buf + sizeof(iv_t) + sizeof(padding_t) + 1;\n    len -= sizeof(iv_t) + sizeof(padding_t) + 1;\n    if (len < 0) {\n        mylog(log_debug, \"len <0\\n\");\n        return -1;\n    }\n    return 0;\n}\nint recv_bare(raw_info_t &raw_info, char *&data, int &len)  // recv function with encryption but no anti replay,this is used when client and server verifys each other\n// you have to design the protocol carefully, so that you wont be affect by relay attack\n{\n    packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    if (recv_raw0(raw_info, data, len) < 0) {\n        // printf(\"recv_raw_fail in recv bare\\n\");\n        return -1;\n    }\n\n    if (len >= max_data_len + 1) {\n        mylog(log_debug, \"data_len=%d >= max_data_len+1,ignored\", len);\n        return -1;\n    }\n\n    mylog(log_trace, \"data len=%d\\n\", len);\n    if ((raw_mode == mode_faketcp && (recv_info.syn == 1 || recv_info.ack != 1))) {\n        mylog(log_debug, \"unexpect packet type recv_info.syn=%d recv_info.ack=%d \\n\", recv_info.syn, recv_info.ack);\n        return -1;\n    }\n    return reserved_parse_bare(data, len, data, len);\n}\n\nint send_handshake(raw_info_t &raw_info, my_id_t id1, my_id_t id2, my_id_t id3)  // a warp for send_bare for sending handshake(this is not tcp handshake) easily\n{\n    packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    char *data;\n    int len;\n    // len=sizeof(id_t)*3;\n    if (numbers_to_char(id1, id2, id3, data, len) != 0) return -1;\n    if (send_bare(raw_info, data, len) != 0) {\n        mylog(log_warn, \"send bare fail\\n\");\n        return -1;\n    }\n    return 0;\n}\n/*\nint recv_handshake(packet_info_t &info,id_t &id1,id_t &id2,id_t &id3)\n{\n        char * data;int len;\n        if(recv_bare(info,data,len)!=0) return -1;\n\n        if(char_to_numbers(data,len,id1,id2,id3)!=0) return -1;\n\n        return 0;\n}*/\n\nint send_safer(conn_info_t &conn_info, char type, const char *data, int len)  // safer transfer function with anti-replay,when mutually verification is done.\n{\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n\n    if (type != 'h' && type != 'd') {\n        mylog(log_warn, \"first byte is not h or d  ,%x\\n\", type);\n        return -1;\n    }\n\n    char send_data_buf[buf_len];  // buf for send data and send hb\n    char send_data_buf2[buf_len];\n\n    my_id_t n_tmp_id = htonl(conn_info.my_id);\n\n    memcpy(send_data_buf, &n_tmp_id, sizeof(n_tmp_id));\n\n    n_tmp_id = htonl(conn_info.oppsite_id);\n\n    memcpy(send_data_buf + sizeof(n_tmp_id), &n_tmp_id, sizeof(n_tmp_id));\n\n    anti_replay_seq_t n_seq = hton64(conn_info.blob->anti_replay.get_new_seq_for_send());\n\n    memcpy(send_data_buf + sizeof(n_tmp_id) * 2, &n_seq, sizeof(n_seq));\n\n    send_data_buf[sizeof(n_tmp_id) * 2 + sizeof(n_seq)] = type;\n    send_data_buf[sizeof(n_tmp_id) * 2 + sizeof(n_seq) + 1] = conn_info.my_roller;\n\n    memcpy(send_data_buf + 2 + sizeof(n_tmp_id) * 2 + sizeof(n_seq), data, len);  // data;\n\n    int new_len = len + sizeof(n_seq) + sizeof(n_tmp_id) * 2 + 2;\n\n    if (g_fix_gro == 0) {\n        if (my_encrypt(send_data_buf, send_data_buf2, new_len) != 0) {\n            return -1;\n        }\n    } else {\n        if (my_encrypt(send_data_buf, send_data_buf2 + 2, new_len) != 0) {\n            return -1;\n        }\n        write_u16(send_data_buf2, new_len);\n        new_len += 2;\n        if (cipher_mode == cipher_xor) {\n            send_data_buf2[0] ^= gro_xor[0];\n            send_data_buf2[1] ^= gro_xor[1];\n        } else if (cipher_mode == cipher_aes128cbc || cipher_mode == cipher_aes128cfb) {\n            aes_ecb_encrypt1(send_data_buf2);\n        }\n    }\n\n    if (send_raw0(conn_info.raw_info, send_data_buf2, new_len) != 0) return -1;\n\n    if (after_send_raw0(conn_info.raw_info) != 0) return -1;\n\n    return 0;\n}\nint send_data_safer(conn_info_t &conn_info, const char *data, int len, u32_t conv_num)  // a wrap for  send_safer for transfer data.\n{\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n\n    char send_data_buf[buf_len];\n    // send_data_buf[0]='d';\n    u32_t n_conv_num = htonl(conv_num);\n    memcpy(send_data_buf, &n_conv_num, sizeof(n_conv_num));\n\n    memcpy(send_data_buf + sizeof(n_conv_num), data, len);\n    int new_len = len + sizeof(n_conv_num);\n    send_safer(conn_info, 'd', send_data_buf, new_len);\n    return 0;\n}\nint reserved_parse_safer(conn_info_t &conn_info, const char *input, int input_len, char &type, char *&data, int &len)  // subfunction for recv_safer,allow overlap\n{\n    static char recv_data_buf[buf_len];\n\n    // char *recv_data_buf=recv_data_buf0; //fix strict alias warning\n    if (my_decrypt(input, recv_data_buf, input_len) != 0) {\n        // printf(\"decrypt fail\\n\");\n        return -1;\n    }\n\n    // char *a=recv_data_buf;\n    // id_t h_oppiste_id= ntohl (  *((id_t * )(recv_data_buf)) );\n    my_id_t h_oppsite_id;\n    memcpy(&h_oppsite_id, recv_data_buf, sizeof(h_oppsite_id));\n    h_oppsite_id = ntohl(h_oppsite_id);\n\n    // id_t h_my_id= ntohl (  *((id_t * )(recv_data_buf+sizeof(id_t)))    );\n    my_id_t h_my_id;\n    memcpy(&h_my_id, recv_data_buf + sizeof(my_id_t), sizeof(h_my_id));\n    h_my_id = ntohl(h_my_id);\n\n    // anti_replay_seq_t h_seq= ntoh64 (  *((anti_replay_seq_t * )(recv_data_buf  +sizeof(id_t) *2 ))   );\n    anti_replay_seq_t h_seq;\n    memcpy(&h_seq, recv_data_buf + sizeof(my_id_t) * 2, sizeof(h_seq));\n    h_seq = ntoh64(h_seq);\n\n    if (h_oppsite_id != conn_info.oppsite_id || h_my_id != conn_info.my_id) {\n        mylog(log_debug, \"id and oppsite_id verification failed %x %x %x %x \\n\", h_oppsite_id, conn_info.oppsite_id, h_my_id, conn_info.my_id);\n        return -1;\n    }\n\n    if (conn_info.blob->anti_replay.is_vaild(h_seq) != 1) {\n        mylog(log_debug, \"dropped replay packet\\n\");\n        return -1;\n    }\n\n    // printf(\"recv _len %d\\n \",recv_len);\n    data = recv_data_buf + sizeof(anti_replay_seq_t) + sizeof(my_id_t) * 2;\n    len = input_len - (sizeof(anti_replay_seq_t) + sizeof(my_id_t) * 2);\n\n    if (data[0] != 'h' && data[0] != 'd') {\n        mylog(log_debug, \"first byte is not h or d  ,%x\\n\", data[0]);\n        return -1;\n    }\n\n    uint8_t roller = data[1];\n\n    type = data[0];\n    data += 2;\n    len -= 2;\n\n    if (len < 0) {\n        mylog(log_debug, \"len <0 ,%d\\n\", len);\n        return -1;\n    }\n\n    if (roller != conn_info.oppsite_roller) {\n        conn_info.oppsite_roller = roller;\n        conn_info.last_oppsite_roller_time = get_current_time();\n    }\n    if (hb_mode == 0)\n        conn_info.my_roller++;  // increase on a successful recv\n    else if (hb_mode == 1) {\n        if (type == 'h')\n            conn_info.my_roller++;\n    } else {\n        mylog(log_fatal, \"unknow hb_mode\\n\");\n        myexit(-1);\n    }\n\n    if (after_recv_raw0(conn_info.raw_info) != 0) return -1;  // TODO might need to move this function to somewhere else after --fix-gro is introduced\n\n    return 0;\n}\nint recv_safer_notused(conn_info_t &conn_info, char &type, char *&data, int &len)  /// safer transfer function with anti-replay,when mutually verification is done.\n{\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n\n    char *recv_data;\n    int recv_len;\n    // static char recv_data_buf[buf_len];\n\n    if (recv_raw0(conn_info.raw_info, recv_data, recv_len) != 0) return -1;\n\n    return reserved_parse_safer(conn_info, recv_data, recv_len, type, data, len);\n}\n\nint recv_safer_multi(conn_info_t &conn_info, vector<char> &type_arr, vector<string> &data_arr)  /// safer transfer function with anti-replay,when mutually verification is done.\n{\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n\n    char *recv_data;\n    int recv_len;\n    assert(type_arr.empty());\n    assert(data_arr.empty());\n\n    if (recv_raw0(conn_info.raw_info, recv_data, recv_len) != 0) return -1;\n\n    char type;\n    char *data;\n    int len;\n\n    if (g_fix_gro == 0) {\n        int ret = reserved_parse_safer(conn_info, recv_data, recv_len, type, data, len);\n        if (ret == 0) {\n            type_arr.push_back(type);\n            data_arr.emplace_back(data, data + len);\n            // std::copy(data,data+len,data_arr[0]);\n        }\n        return 0;\n    } else {\n        char *ori_recv_data = recv_data;\n        int ori_recv_len = recv_len;\n        // mylog(log_debug,\"recv_len:%d\\n\",recv_len);\n        int cnt = 0;\n        while (recv_len >= 16) {\n            cnt++;\n            int single_len_no_xor;\n            single_len_no_xor = read_u16(recv_data);\n            int single_len;\n            if (cipher_mode == cipher_xor) {\n                recv_data[0] ^= gro_xor[0];\n                recv_data[1] ^= gro_xor[1];\n            } else if (cipher_mode == cipher_aes128cbc || cipher_mode == cipher_aes128cfb) {\n                aes_ecb_decrypt1(recv_data);\n            }\n            single_len = read_u16(recv_data);\n            recv_len -= 2;\n            recv_data += 2;\n            if (single_len > recv_len) {\n                mylog(log_debug, \"illegal single_len %d(%d), recv_len %d left,dropped\\n\", single_len, single_len_no_xor, recv_len);\n                break;\n            }\n            if (single_len > max_data_len) {\n                mylog(log_warn, \"single_len %d(%d) > %d, maybe you need to turn down mtu at upper level\\n\", single_len, single_len_no_xor, max_data_len);\n                break;\n            }\n\n            int ret = reserved_parse_safer(conn_info, recv_data, single_len, type, data, len);\n\n            if (ret != 0) {\n                mylog(log_debug, \"parse failed, offset= %d,single_len=%d(%d)\\n\", (int)(recv_data - ori_recv_data), single_len, single_len_no_xor);\n            } else {\n                type_arr.push_back(type);\n                data_arr.emplace_back(data, data + len);\n                // std::copy(data,data+len,data_arr[data_arr.size()-1]);\n            }\n            recv_data += single_len;\n            recv_len -= single_len;\n        }\n        if (cnt > 1) {\n            mylog(log_debug, \"got a suspected gro packet, %d packets recovered, recv_len=%d, loop_cnt=%d\\n\", (int)data_arr.size(), ori_recv_len, cnt);\n        }\n        return 0;\n    }\n}\n\nvoid server_clear_function(u64_t u64)  // used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),\n// so we have to close the fd when conv expires\n{\n    // int fd=int(u64);\n    //\tint ret;\n    // assert(fd!=0);\n    /*\n    epoll_event ev;\n\n    ev.events = EPOLLIN;\n    ev.data.u64 = u64;\n\n    ret = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);\n    if (ret!=0)\n    {\n            mylog(log_fatal,\"fd:%d epoll delete failed!!!!\\n\",fd);\n            myexit(-1);   //this shouldnt happen\n    }*/\n    // no need\n\n    /*ret= close(fd);  //closed fd should be auto removed from epoll\n\n    if (ret!=0)\n    {\n            mylog(log_fatal,\"close fd %d failed !!!!\\n\",fd);\n            myexit(-1);  //this shouldnt happen\n    }*/\n    // mylog(log_fatal,\"size:%d !!!!\\n\",conn_manager.udp_fd_mp.size());\n    fd64_t fd64 = u64;\n    assert(fd_manager.exist(fd64));\n    fd_manager.fd64_close(fd64);\n\n    // assert(conn_manager.udp_fd_mp.find(fd)!=conn_manager.udp_fd_mp.end());\n    // conn_manager.udp_fd_mp.erase(fd);\n}\n"
  },
  {
    "path": "connection.h",
    "content": "/*\n * connection.h\n *\n *  Created on: Sep 23, 2017\n *      Author: root\n */\n\n#ifndef CONNECTION_H_\n#define CONNECTION_H_\n\nextern int disable_anti_replay;\n\n#include \"connection.h\"\n#include \"common.h\"\n#include \"log.h\"\n#include \"network.h\"\n#include \"misc.h\"\n\nconst int disable_conv_clear = 0;  // a udp connection in the multiplexer is called conversation in this program,conv for short.\n\nstruct anti_replay_t  // its for anti replay attack,similar to openvpn/ipsec 's anti replay window\n{\n    u64_t max_packet_received;\n    char window[anti_replay_window_size];\n    anti_replay_seq_t anti_replay_seq;\n    anti_replay_seq_t get_new_seq_for_send();\n    anti_replay_t();\n    void re_init();\n\n    int is_vaild(u64_t seq);\n};  // anti_replay;\n\nvoid server_clear_function(u64_t u64);\n\n#include <type_traits>\n\ntemplate <class T>\nstruct conv_manager_t  // manage the udp connections\n{\n    // typedef hash_map map;\n    unordered_map<T, u32_t> data_to_conv;  // conv and u64 are both supposed to be uniq\n    unordered_map<u32_t, T> conv_to_data;\n\n    lru_collector_t<u32_t> lru;\n    // unordered_map<u32_t,u64_t> conv_last_active_time;\n\n    // unordered_map<u32_t,u64_t>::iterator clear_it;\n\n    void (*additional_clear_function)(T data) = 0;\n\n    long long last_clear_time;\n\n    conv_manager_t() {\n        // clear_it=conv_last_active_time.begin();\n        long long last_clear_time = 0;\n        additional_clear_function = 0;\n    }\n    ~conv_manager_t() {\n        clear();\n    }\n    int get_size() {\n        return conv_to_data.size();\n    }\n    void reserve() {\n        data_to_conv.reserve(10007);\n        conv_to_data.reserve(10007);\n        // conv_last_active_time.reserve(10007);\n\n        lru.mp.reserve(10007);\n    }\n    void clear() {\n        if (disable_conv_clear) return;\n\n        if (additional_clear_function != 0) {\n            for (auto it = conv_to_data.begin(); it != conv_to_data.end(); it++) {\n                // int fd=int((it->second<<32u)>>32u);\n                additional_clear_function(it->second);\n            }\n        }\n        data_to_conv.clear();\n        conv_to_data.clear();\n\n        lru.clear();\n        // conv_last_active_time.clear();\n\n        // clear_it=conv_last_active_time.begin();\n    }\n    u32_t get_new_conv() {\n        u32_t conv = get_true_random_number_nz();\n        while (conv_to_data.find(conv) != conv_to_data.end()) {\n            conv = get_true_random_number_nz();\n        }\n        return conv;\n    }\n    int is_conv_used(u32_t conv) {\n        return conv_to_data.find(conv) != conv_to_data.end();\n    }\n    int is_data_used(T data) {\n        return data_to_conv.find(data) != data_to_conv.end();\n    }\n    u32_t find_conv_by_data(T data) {\n        return data_to_conv[data];\n    }\n    T find_data_by_conv(u32_t conv) {\n        return conv_to_data[conv];\n    }\n    int update_active_time(u32_t conv) {\n        // return conv_last_active_time[conv]=get_current_time();\n        lru.update(conv);\n        return 0;\n    }\n    int insert_conv(u32_t conv, T data) {\n        data_to_conv[data] = conv;\n        conv_to_data[conv] = data;\n        // conv_last_active_time[conv]=get_current_time();\n        lru.new_key(conv);\n        return 0;\n    }\n    int erase_conv(u32_t conv) {\n        if (disable_conv_clear) return 0;\n        T data = conv_to_data[conv];\n        if (additional_clear_function != 0) {\n            additional_clear_function(data);\n        }\n        conv_to_data.erase(conv);\n        data_to_conv.erase(data);\n        // conv_last_active_time.erase(conv);\n        lru.erase(conv);\n        return 0;\n    }\n    int clear_inactive(char *info = 0) {\n        if (get_current_time() - last_clear_time > conv_clear_interval) {\n            last_clear_time = get_current_time();\n            return clear_inactive0(info);\n        }\n        return 0;\n    }\n    int clear_inactive0(char *info) {\n        if (disable_conv_clear) return 0;\n\n        unordered_map<u32_t, u64_t>::iterator it;\n        unordered_map<u32_t, u64_t>::iterator old_it;\n\n        // map<uint32_t,uint64_t>::iterator it;\n        int cnt = 0;\n        // it=clear_it;\n        int size = lru.size();\n        int num_to_clean = size / conv_clear_ratio + conv_clear_min;  // clear 1/10 each time,to avoid latency glitch\n\n        num_to_clean = min(num_to_clean, size);\n\n        my_time_t current_time = get_current_time();\n        for (;;) {\n            if (cnt >= num_to_clean) break;\n            if (lru.empty()) break;\n\n            u32_t conv;\n            my_time_t ts = lru.peek_back(conv);\n\n            if (current_time - ts < conv_timeout) break;\n\n            erase_conv(conv);\n            if (info == 0) {\n                mylog(log_info, \"conv %x cleared\\n\", conv);\n            } else {\n                mylog(log_info, \"[%s]conv %x cleared\\n\", info, conv);\n            }\n            cnt++;\n        }\n        return 0;\n    }\n\n    /*\nconv_manager_t();\n~conv_manager_t();\nint get_size();\nvoid reserve();\nvoid clear();\nu32_t get_new_conv();\nint is_conv_used(u32_t conv);\nint is_u64_used(T u64);\nu32_t find_conv_by_u64(T u64);\nT find_u64_by_conv(u32_t conv);\nint update_active_time(u32_t conv);\nint insert_conv(u32_t conv,T u64);\nint erase_conv(u32_t conv);\nint clear_inactive(char * ip_port=0);\nint clear_inactive0(char * ip_port);*/\n};  // g_conv_manager;\n\nstruct blob_t : not_copy_able_t  // used in conn_info_t.\n{\n    union tmp_union_t  // conv_manager_t is here to avoid copying when a connection is recovered\n    {\n        conv_manager_t<address_t> c;\n        conv_manager_t<u64_t> s;\n        // avoid templates here and there, avoid pointer and type cast\n        tmp_union_t() {\n            if (program_mode == client_mode) {\n                new (&c) conv_manager_t<address_t>();\n            } else {\n                assert(program_mode == server_mode);\n                new (&s) conv_manager_t<u64_t>();\n            }\n        }\n        ~tmp_union_t() {\n            if (program_mode == client_mode) {\n                c.~conv_manager_t<address_t>();\n            } else {\n                assert(program_mode == server_mode);\n                s.~conv_manager_t<u64_t>();\n            }\n        }\n    } conv_manager;\n\n    anti_replay_t anti_replay;  // anti_replay_t is here bc its huge,its allocation is delayed.\n};\nstruct conn_info_t  // stores info for a raw connection.for client ,there is only one connection,for server there can be thousand of connection since server can\n// handle multiple clients\n{\n    current_state_t state;\n\n    raw_info_t raw_info;\n    u64_t last_state_time;\n    u64_t last_hb_sent_time;  // client re-use this for retry\n    u64_t last_hb_recv_time;\n    // long long last_resent_time;\n\n    my_id_t my_id;\n    my_id_t oppsite_id;\n\n    fd64_t timer_fd64;\n    fd64_t udp_fd64;\n\n    my_id_t oppsite_const_id;\n\n    blob_t *blob;\n\n    uint8_t my_roller;\n    uint8_t oppsite_roller;\n    u64_t last_oppsite_roller_time;\n\n    //\tip_port_t ip_port;\n\n    /*\n            const uint32_t &ip=raw_info.recv_info.src_ip;\n            const uint16_t &port=raw_info.recv_info.src_port;\n\n    */\n    void recover(const conn_info_t &conn_info);\n    void re_init();\n    conn_info_t();\n    void prepare();\n    conn_info_t(const conn_info_t &b);\n    conn_info_t &operator=(const conn_info_t &b);\n    ~conn_info_t();\n};  // g_conn_info;\n\nstruct conn_manager_t  // manager for connections. for client,we dont need conn_manager since there is only one connection.for server we use one conn_manager for all connections\n{\n    u32_t ready_num;\n\n    // unordered_map<int,conn_info_t *> udp_fd_mp;  //a bit dirty to used pointer,but can void unordered_map search\n    // unordered_map<int,conn_info_t *> timer_fd_mp;//we can use pointer here since unordered_map.rehash() uses shallow copy\n\n    unordered_map<my_id_t, conn_info_t *> const_id_mp;\n\n    unordered_map<address_t, conn_info_t *> mp;  // put it at end so that it de-consturcts first\n\n    // lru_collector_t<address_t> lru;\n\n    unordered_map<address_t, conn_info_t *>::iterator clear_it;\n\n    long long last_clear_time;\n\n    conn_manager_t();\n    int exist(address_t addr);\n    /*\n    int insert(uint32_t ip,uint16_t port)\n    {\n            uint64_t u64=0;\n            u64=ip;\n            u64<<=32u;\n            u64|=port;\n            mp[u64];\n            return 0;\n    }*/\n    conn_info_t *&find_insert_p(address_t addr);  // be aware,the adress may change after rehash //not true?\n    conn_info_t &find_insert(address_t addr);     // be aware,the adress may change after rehash\n\n    int erase(unordered_map<address_t, conn_info_t *>::iterator erase_it);\n    int clear_inactive();\n    int clear_inactive0();\n};\n\nextern conn_manager_t conn_manager;\n\nvoid server_clear_function(u64_t u64);\n\nint send_bare(raw_info_t &raw_info, const char *data, int len);  // send function with encryption but no anti replay,this is used when client and server verifys each other\n// you have to design the protocol carefully, so that you wont be affect by relay attack\n// int reserved_parse_bare(const char *input,int input_len,char* & data,int & len); // a sub function used in recv_bare\nint recv_bare(raw_info_t &raw_info, char *&data, int &len);  // recv function with encryption but no anti replay,this is used when client and server verifys each other\n// you have to design the protocol carefully, so that you wont be affect by relay attack\nint send_handshake(raw_info_t &raw_info, my_id_t id1, my_id_t id2, my_id_t id3);         // a warp for send_bare for sending handshake(this is not tcp handshake) easily\nint send_safer(conn_info_t &conn_info, char type, const char *data, int len);            // safer transfer function with anti-replay,when mutually verification is done.\nint send_data_safer(conn_info_t &conn_info, const char *data, int len, u32_t conv_num);  // a wrap for  send_safer for transfer data.\n// int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap\n\n// int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.\n\nint recv_safer_multi(conn_info_t &conn_info, vector<char> &type_arr, vector<string> &data_arr);  // new api for handle gro\n#endif                                                                                           /* CONNECTION_H_ */\n"
  },
  {
    "path": "doc/README.zh-cn.md",
    "content": "# Udp2raw-tunnel \r\n![image2](/images/image0.PNG)\r\nudp2raw tunnel，通过raw socket给UDP包加上TCP或ICMP header，进而绕过UDP屏蔽或QoS，或在UDP不稳定的环境下提升稳定性。可以有效防止在使用kcptun或者finalspeed的情况下udp端口被运营商限速。\r\n\r\n支持心跳保活、自动重连，重连后会恢复上次连接，在底层掉线的情况下可以保持上层不掉线。同时有加密、防重放攻击、信道复用的功能。\r\n\r\n[English](/README.md)\r\n\r\n[udp2raw+kcptun step_by_step教程](kcptun_step_by_step.md)\r\n\r\n[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)\r\n\r\n[udp2raw wiki](https://github.com/wangyu-/udp2raw-tunnel/wiki)\r\n\r\n**提示：**\r\n\r\nudp2raw不是加速器，只是一个帮助你绕过UDP限制的工具。如果你需要UDP“加速器” (改善UDP丢包)，请看UDPspeeder。\r\n\r\nUDPspeeder的repo:\r\n\r\nhttps://github.com/wangyu-/UDPspeeder\r\n# 支持的平台\r\nLinux主机，有root权限或cap_net_raw capability.。可以是PC、android手机/平板、openwrt路由器、树莓派。主机上最好安装了iptables命令(apt/yum很容易安装)。\r\n\r\nRelease中提供了`amd64`、`x86`、`arm`、`mips_be`、`mips_le`的预编译binary.\r\n\r\n##### 对于windows和mac用户：\r\n\r\n可以用[这个repo](https://github.com/wangyu-/udp2raw-multiplatform)里的udp2raw。\r\n\r\n##### 对于ios和游戏主机用户：\r\n\r\n可以把udp2raw运行在局域网的其他机器/虚拟机上。最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器，把udp2raw运行在路由器上。\r\n\r\n# 功能特性\r\n### 把udp流量伪装成tcp /icmp\r\n用raw socket给udp包加上tcp/icmp包头，可以突破udp流量限制或Udp QOS。或者在udp nat有问题的环境下，提升稳定性。  另外也支持用raw 发udp包，这样流量不会被伪装，只会被加密。\r\n\r\n### 模拟TCP3次握手\r\n模拟TCP3次握手，模拟seq ack过程。另外还模拟了一些tcp option：MSS,sackOk,TS,TS_ack,wscale，用来使流量看起来更像是由普通的linux tcp协议栈发送的。\r\n\r\n### 心跳保活、自动重连，连接恢复\r\n心跳保活、自动重连，udp2raw重连可以恢复上次的连接，重连后上层连接继续有效，底层掉线上层不掉线。有效解决上层连接断开的问题。 （功能借鉴自[kcptun-raw](https://github.com/Chion82/kcptun-raw)）（**就算你拔掉网线重插，或者重新拨号获得新ip，上层应用也不会断线**）\r\n\r\n### 加密、防重放攻击\r\n用aes128cbc加密(或更弱的xor)，hmac-sha1(或更弱的md5/crc32/simple)做数据完整校验。用类似ipsec/openvpn的replay window机制来防止重放攻击。\r\n\r\n[Notes on encryption](https://github.com/wangyu-/udp2raw-tunnel/wiki/Notes-on-encryption)\r\n\r\n### 其他特性\r\n信道复用，client的udp端支持多个连接。\r\n\r\nserver支持多个client，也能正确处理多个连接的重连和连接恢复。\r\n\r\nNAT 穿透 ，tcp icmp udp模式都支持nat穿透。\r\n\r\n支持Openvz，配合finalspeed使用，可以在openvz上用tcp模式的finalspeed.\r\n\r\n支持Openwrt，没有编译依赖，容易编译到任何平台上。\r\n\r\n### 关键词\r\n突破udp qos,突破udp屏蔽，openvpn tcp over tcp problem,openvpn over icmp,udp to icmp tunnel,udp to tcp tunnel,udp via icmp,udp via tcp\r\n\r\n# 简明操作说明\r\n\r\n### 安装\r\n下载编译好的二进制文件，解压到任意目录。\r\n\r\nhttps://github.com/wangyu-/udp2raw-tunnel/releases\r\n\r\n### 运行\r\n假设你有一个server，ip为44.55.66.77，有一个服务监听在udp 7777端口。 假设你本地的主机到44.55.66.77的UDP流量被屏蔽了，或者被qos了\r\n\r\n```\r\n在server端运行:\r\n./udp2raw_amd64 -s -l0.0.0.0:4096  -r127.0.0.1:7777   -k \"passwd\" --raw-mode faketcp   --cipher-mode xor  -a\r\n\r\n在client端运行:\r\n./udp2raw_amd64 -c -l0.0.0.0:3333  -r44.55.66.77:4096 -k \"passwd\" --raw-mode faketcp   --cipher-mode xor  -a\r\n```\r\n(以上例子需要用root账号运行。 用非root运行udp2raw需要一些额外的步骤，具体方法请看 [这个](https://github.com/wangyu-/udp2raw-tunnel/wiki/run-udp2raw-as-non-root) 链接。用非root运行更安全)\r\n\r\n###### Server端输出:\r\n![](/images/output_server.PNG)\r\n###### Client端输出:\r\n![](/images/output_client.PNG)\r\n\r\n现在client和server之间建立起了，tunnel。想要在本地连接44.55.66.77:7777，只需要连接 127.0.0.1:3333。来回的所有的udp流量会被经过tunneling发送。在外界看起来是tcp流量，不会有udp流量暴露到公网。\r\n\r\n### MTU设置(重要)\r\n\r\n不论你用udp2raw来加速kcptun还是vpn,为了稳定使用,都需要设置合理的MTU（在kcptun/vpn里设置，而不是在udp2raw里），建议把MTU设置成1200。client和server端都要设置。\r\n\r\n### 提醒\r\n`--cipher-mode xor`表示仅使用简单的XOR加密，这样可以节省CPU占用，以免CPU成为速度瓶颈。如果你需要更强的加密，可以去掉此选项，使用默认的AES加密。加密相关的选项见后文的`--cipher-mode`和`--auth-mode`。\r\n\r\n如果要在anroid上运行，请看[Android简明教程](/doc/android_guide.md)\r\n\r\n`-a`选项会自动添加一条/几条iptables规则，udp2raw必须和相应的iptables规则配合才能稳定工作，一定要注意不要忘了`-a`(这是个常见错误)。 如果你不想让udp2raw自动添加iptables规则，可以自己手动添加相应的iptables规则(看一下`-g`选项)，然后以不带`-a`的方式运行udp2raw。\r\n\r\n# 进阶操作说明\r\n\r\n### 命令选项\r\n```\r\nudp2raw-tunnel\r\ngit version:4623f878e0    build date:Nov  3 2024 23:15:46\r\nrepository: https://github.com/wangyu-/udp2raw-tunnel\r\n\r\nusage:\r\n    run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port  [options]\r\n    run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port  [options]\r\n\r\ncommon options,these options must be same on both side:\r\n    --raw-mode            <string>        available values:faketcp(default),udp,icmp and easy-faketcp\r\n    -k,--key              <string>        password to gen symetric key,default:\"secret key\"\r\n    --cipher-mode         <string>        available values:aes128cfb,aes128cbc(default),xor,none\r\n    --auth-mode           <string>        available values:hmac_sha1,md5(default),crc32,simple,none\r\n    -a,--auto-rule                        auto add (and delete) iptables rule\r\n    -g,--gen-rule                         generate iptables rule then exit,so that you can copy and\r\n                                          add it manually.overrides -a\r\n    --disable-anti-replay                 disable anti-replay,not suggested\r\n    --fix-gro                             try to fix huge packet caused by GRO. this option is at an early stage.\r\n                                          make sure client and server are at same version.\r\nclient options:\r\n    --source-ip           <ip>            force source-ip for raw socket\r\n    --source-port         <port>          force source-port for raw socket,tcp/udp only\r\n                                          this option disables port changing while re-connecting\r\nother options:\r\n    --conf-file           <string>        read options from a configuration file instead of command line.\r\n                                          check example.conf in repo for format\r\n    --fifo                <string>        use a fifo(named pipe) for sending commands to the running program,\r\n                                          check readme.md in repository for supported commands.\r\n    --log-level           <number>        0:never    1:fatal   2:error   3:warn\r\n                                          4:info (default)     5:debug   6:trace\r\n    --log-position                        enable file name,function name,line number in log\r\n    --disable-color                       disable log color\r\n    --disable-bpf                         disable the kernel space filter,most time its not necessary\r\n                                          unless you suspect there is a bug\r\n    --dev                 <string>        bind raw socket to a device, not necessary but improves performance\r\n    --sock-buf            <number>        buf size for socket,>=10 and <=10240,unit:kbyte,default:1024\r\n    --force-sock-buf                      bypass system limitation while setting sock-buf\r\n    --seq-mode            <number>        seq increase mode for faketcp:\r\n                                          0:static header,do not increase seq and ack_seq\r\n                                          1:increase seq for every packet,simply ack last seq\r\n                                          2:increase seq randomly, about every 3 packets,simply ack last seq\r\n                                          3:simulate an almost real seq/ack procedure(default)\r\n                                          4:similiar to 3,but do not consider TCP Option Window_Scale,\r\n                                          maybe useful when firewall doesnt support TCP Option\r\n    --lower-level         <string>        send packets at OSI level 2, format:'if_name#dest_mac_adress'\r\n                                          ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain\r\n                                          the parameter automatically,specify it manually if 'auto' failed\r\n    --wait-lock                           wait for xtables lock while invoking iptables, need iptables v1.4.20+\r\n    --gen-add                             generate iptables rule and add it permanently,then exit.overrides -g\r\n    --keep-rule                           monitor iptables and auto re-add if necessary.implys -a\r\n    --hb-len              <number>        length of heart-beat packet, >=0 and <=1500\r\n    --mtu-warn            <number>        mtu warning threshold, unit:byte, default:1375\r\n    --clear                               clear any iptables rules added by this program.overrides everything\r\n    --retry-on-error                      retry on error, allow to start udp2raw before network is initialized\r\n    -h,--help                             print this help message\r\n```\r\n\r\n### iptables 规则,`-a`和`-g`\r\n用raw收发tcp包本质上绕过了linux内核的tcp协议栈。linux碰到raw socket发来的包会不认识，如果一直收到不认识的包，会回复大量RST，造成不稳定或性能问题。所以强烈建议添加iptables规则屏蔽Linux内核的对指定端口的处理。用-a选项，udp2raw会在启动的时候自动帮你加上Iptables规则，退出的时候再自动删掉。如果长期使用，可以用-g选项来生成相应的Iptables规则再自己手动添加，这样规则不会在udp2raw退出时被删掉，可以避免停掉udp2raw后内核向对端回复RST。\r\n\r\n用raw收发udp包也类似，只是内核回复的是icmp unreachable。而用raw 收发icmp，内核会自动回复icmp echo。都需要相应的iptables规则。\r\n### `--cipher-mode` 和 `--auth-mode` \r\n如果要最大的安全性建议用aes128cbc+hmac_sha1。如果要运行在路由器上，建议用xor+simple，可以节省CPU。但是注意xor+simple只能骗过防火墙的包检测，不能防止真正的攻击者。\r\n\r\n### `--seq-mode`\r\nfaketcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和真正的tcp流量区分开来（虽然大部分ISP不太可能做这种程度的包检测）。seq-mode可以改变一些seq ack的行为。如果遇到了连接问题，可以尝试更改。在我这边的移动线路用3种模式都没问题。\r\n\r\n### `--keep-rule`\r\n定期主动检查iptables，如果udp2raw添加的iptables规则丢了，就重新添加。在一些iptables可能会被其他程序清空的情况下(比如梅林固件和openwrt的路由器)格外有用。\r\n\r\n### `--fifo`\r\n指定一个fifo(named pipe)来向运行中的程序发送命令，例如`--fifo fifo.file`：\r\n\r\n在client端,可以用`echo reconnect >fifo.file`来强制client换端口重连（上层不断线）.对Server，目前没有效果。\r\n\r\n### `--lower-level`\r\n大部分udp2raw不能连通的情况都是设置了不兼容的iptables造成的。--lower-level选项允许绕过本地iptables。在一些iptables不好改动的情况下尤其有效（比如你用的是梅林固件，iptables全是固件自己生成的）。\r\n\r\n##### 格式\r\n`if_name#dest_mac_adress`,例如 `eth0#00:23:45:67:89:b9` 。`eth0`换成你的出口网卡名。`00:23:45:67:89:b9`换成网关的mac地址（如果client和server在同一个局域网内，可能不需要网关，这时候直接用对方主机的mac地址，这个属于罕见的应用场景，可以忽略）。\r\n\r\n可以用`--lower-level auto`自动获取参数，如果获取参数失败，再手动填写。\r\n\r\n##### client端获得--lower-level参数的办法\r\n在client 端，运行`traceroute <server_ip>`，记下第一跳的地址，这个就是`网关ip`。再运行`arp -s <网关ip>`，可以同时查到出口网卡名和mac。\r\n\r\n![](/images/lower_level.PNG)\r\n\r\n如果traceroute第一跳结果是`* * *`，说明网关屏蔽了对traceroute的应答。需要用`ip route`或`route`查询网关：\r\n\r\n![](/images/route.PNG)\r\n##### server端获得--lower-level参数的办法\r\n如果client有公网ip，就`traceroute <client_ip>`。下一步和client端的方法一样。\r\n\r\n如果client没有公网ip，就`traceroute google.com` 或`traceroute baidu.com`。下一步和client端的方法一样。\r\n\r\nserver端也可以用`--lower-level auto` 来尝试自动获得参数，如果无法连接再手动填写。\r\n\r\n##### 注意\r\n如果用了`--lower-level`选项。server虽然还可以bind在0.0.0.0，但是因为你显式指定了网络接口，就只能工作在这一个网络接口了。\r\n\r\n如果`arps -s`命令查询不到，首先再试几次。如果还是查询不到，那么可能是因为你用的是pppoe方式的拨号宽带，查询不到是正常的。这种情况下`if_name`填pppoe产生的虚拟interface，通常名字叫`pppXXXX`，从`ifconfig`命令的输出里找一下；`des_mac_adress`填`00:00:00:00:00:00`,例如`ppp0#00:00:00:00:00:00`\r\n\r\n### `--conf-file`\r\n\r\n为了避免将密码等私密信息暴露给`ps`命令，你也可以使用 `配置文件` 来存储参数。\r\n\r\n比如，将以上服务端参数改写成配置文件\r\n\r\n`server.conf`:\r\n\r\n```\r\n-s\r\n# 你可以像这样添加注释\r\n# 注意，只有整行注释才能在配置文件里使用\r\n# 注释必须独占一行\r\n-l 0.0.0.0:4096\r\n-r 127.0.0.1:7777\r\n-a\r\n-k passwd\r\n--raw-mode faketcp\r\n```\r\n\r\n注意，当写入配置文件的时候，密码等参数两边的引号必须去除。\r\n\r\n然后就可以使用下面的方式启动服务端\r\n\r\n```bash\r\n./udp2raw_amd64 --conf-file server.conf\r\n```\r\n\r\n# 性能测试\r\niperf3 的UDP模式有BUG，所以，这里用iperf3的tcp模式，配合Openvpn，测试udp2raw的性能。（iperf3 udp issue ,https://github.com/esnet/iperf/issues/296 ）\r\n\r\nopenvpn关掉了自带的加密。\r\n#### iperf3 命令: \r\n```\r\niperf3 -c 10.222.2.1 -P40 \r\niperf3 -c 10.222.2.1 -P40 -R\r\n```\r\n#### client主机\r\nvultr 2.5美元每月套餐(single core 2.4ghz cpu,512m ram,日本东京机房),\r\n#### server主机\r\nbandwagonhost 3.99美元每年套餐(single core 2.0ghz cpu,128m ram,美国洛杉矶机房)\r\n### 测试1\r\nraw_mode: faketcp  cipher_mode: xor  auth_mode: simple\r\n\r\n![image4](/images/image4.PNG)\r\n\r\n（反向的速度几乎一样，所以只发正向测试的图)\r\n\r\n测试中cpu被打满。其中有30%的cpu是被openvpn占的。 如果不用Openvpn中转，实际达到100+Mb/S 应该没问题。\r\n\r\n### 测试2\r\nraw_mode: faketcp  cipher_mode: aes128cbc  auth_mode: md5\r\n\r\n![image5](/images/image5.PNG)\r\n\r\n（反向的速度几乎一样，所以只发正向测试的图)\r\n\r\n测试中cpu被打满。绝大多数cpu都是被udp2raw占用的（主要消耗在aes加密）。即使不用Openvpn，速度也不会快很多了。\r\n# 应用\r\n### 中转 kcptun\r\n[udp2raw+kcptun step_by_step教程](kcptun_step_by_step.md)\r\n### 中转 finalspeed\r\n[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)\r\n\r\n# wiki\r\n\r\n更多内容请看 wiki:\r\n\r\nhttps://github.com/wangyu-/udp2raw-tunnel/wiki\r\n\r\n\r\n"
  },
  {
    "path": "doc/android_guide.md",
    "content": "# How to run udp2raw on a rooted android device(arm cpu)\n\nThere is currently no GUI for udp2raw on android.Make sure you have installed Terminal to run it.Your device has to be rooted,otherwise you cant use raw socket.\n\nDownload udp2raw_arm from https://github.com/wangyu-/udp2raw-tunnel/releases.\n\nCopy udp2raw_arm to any dir of your **internal storage** .Copying it to **SD card wont work**.\n\n# Steps\n1.  run udp2raw_arm  as usual, except you must change the -a option to -g\n```\n./udp2raw_arm -c -r 44.55.66.77:9966 -l 0.0.0.0:4000 -k1234 --cipher xor -g\n```\n\n2. find the generated iptables rule from udp2raw's output,add it manually by running:\n```\niptables -I INPUT -s 44.55.66.77/32 -p tcp -m tcp --sport 9966 -j DROP\n```\n\n3. run udp2raw_ram without -g command\n\n```\n./udp2raw_arm -c -r 44.55.66.77:9966 -l 0.0.0.0:4000 -k1234 --cipher xor \n```\n\n# ScreenShot \nzoom-in if not large enough\n\n![](/images/android.png)\n"
  },
  {
    "path": "doc/build_guide.md",
    "content": "# udp2raw build guide\n\nthe guide on how to build udp2raw\n\n## Build udp2raw for a specific platform\n\n### linux platform which supports local compile\nsuch as PC,raspberry pi\n\n##### install git\nrun on debian/ubuntun：\n```\nsudo apt-get install git\n```\nrun on redhat/centos:\n```\nsudo yum install git\n```\n##### clone git code\n\nrun in any dir：\n\n```\ngit clone https://github.com/wangyu-/udp2raw-tunnel.git\ncd udp2raw-tunnel\n```\n\n##### install compile tool\nrun on debian/ubuntun：\n```\nsudo apt-get install build-essential\n```\n\nrun on redhat/centos:\n```\nsudo yum groupinstall 'Development Tools'\n```\n\nrun 'make'，compilation done. the udp2raw file is the just compiled binary\n\n### platform which needs cross-compile\nsuch as openwrt router,run following instructions on your PC\n\n##### install git\nrun on debian/ubuntun：\n```\nsudo apt-get install git\n```\nrun on redhat/centos:\n```\nsudo yum install git\n```\n\n##### download cross compile tool chain\n\nfind it on downloads.openwrt.org according to your openwrt version and cpu model.\n\nfor example, my tplink wdr4310 runs chaos_calmer 15.05,its with ar71xx cpu，download the following package.\n\n```\nhttp://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2\n```\nunzip it to any dir,such as ：/home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2\n\ncd into staging_dir ，toolchain-xxxxx ，bin .find the soft link with g++ suffix. in my case ,its mips-openwrt-linux-g++ ,check for its full path:\n\n```\n/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++\n```\n##### compile\nmodify first line of makefile to:\n```\ncc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++\n```\n\nrun `make cross`，the just generated `udp2raw_cross` is the binary,compile done. copy it to your router to run.\n\n`make cross` generates non-static binary. If you have any problem on running it,try to compile a static binary by using `make cross2` or `make cross3`.If your toolchain supports static compiling, usually one of them will succeed. The generated file is still named `udp2raw_cross`.\n\n\n\n## Build a full release (include all binaries supported in the makefile)\n\n1. make sure your linux is amd64 version\n\n2. clone the repo\n\n3. make sure you have g++ , make sure your g++ support the `-m32` option; make your your have installed libraries for `-m32` option\n\n4. download https://github.com/wangyu-/files/releases/download/files/toolchains.tar.gz , and extract it to the right position (according to the makefile)\n\n5. run `make release` inside udp2raw's directory\n"
  },
  {
    "path": "doc/build_guide.zh-cn.md",
    "content": "# udp2raw编译方法\n本文演示怎么把udp2raw编译到自己所需的平台。\n\n## 可以本地编译的linux平台\n比如电脑、树莓派\n\n##### 首先安装git\ndebian/ubuntun执行：\n```\nsudo apt-get install git\n```\nredhat/centos执行:\n```\nsudo yum install git\n```\n##### 用git把源码clone至本地\n\n在任意目录执行：\n\n```\ngit clone https://github.com/wangyu-/udp2raw-tunnel.git\ncd udp2raw-tunnel\n```\n\n##### 安装g++ make 等工具\ndebian/ubuntun执行：\n```\nsudo apt-get install build-essential\n```\n\nredhat/centos执行:\n```\nsudo yum groupinstall 'Development Tools'\n```\n\n然后运行make，编译完成。 生成的udp2raw就是编译好的bianry。\n\n## 需要交叉编译的平台\n比如各种openwrt路由器\n\n##### 首先安装git\ndebian/ubuntun执行：\n```\nsudo apt-get install git\n```\nredhat/centos执行:\n```\nsudo yum install git\n```\n\n##### 下载安装交叉编译工具包\n去downloads.openwrt.org上找到自己的openwrt版本和cpu型号对应的SDK。通常openwrt版本号不一样也问题不大，最主要是cpu型号。\n\n比如我的tplink wdr4310运行的是chaos_calmer 15.05,ar71xx cpu，应该下载这个包：\n\n```\nhttp://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2\n```\n解压到本地任意目录，比如：/home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2\n\n让后依次进入，staging_dir ，toolchain-xxxxx ，bin 目录，找到后缀是g++的软链,比如我的是mips-openwrt-linux-g++ ，记下这个文件的完整路径：\n\n```\n/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++\n```\n##### 编译\n把makefile的第一行 cross_cc=后面的内容改成你刚才记下的完整路径：\n```\ncc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++\n```\n\n执行`make cross`，目录下生成udp2raw_cross文件。编译完成。\n\n`make cross`编译出的binary是非静态的。如果运行有问题，可以尝试用`make cross2`或`make cross3`编译静态的binary,你的工具链必须带静态库才能成功编译,生成的文件仍然叫udp2raw_cross.\n"
  },
  {
    "path": "doc/finalspeed_step_by_step/11",
    "content": "11\n"
  },
  {
    "path": "doc/finalspeed_step_by_step.md",
    "content": "# udp2raw+finalspeed 加速tcp流量 Step by Step 教程\n![image](finalspeed_step_by_step/Capture0.PNG)\n\n##### 背景\n国内有些ISP会对UDP做QOS或屏蔽，这时候加速协议对TCP发包模式的支持就很重要。finalspeed虽然本身支持在底层用TCP发包，但是其依赖的libpcap不支持openvz架构，即使不是openvz架构的主机，也存在不稳定的问题。\n\n\n##### 摘要\nudp2raw是一个把udp流量通过raw socket包装成tcp流量的工具。通过用udp2raw配合udp模式的 finalspeed一样可以达到在底层发tcp包，绕过QOS的效果。支持openvz,稳定性也好很多。原理上相当于在finalspeed外面再包了一层tunnel。\n\n本教程会一步一步演示用udp2raw+finalspeed加速http流量的过程。加速任何其他tcp流量也一样，包括$\\*\\*\\*。本文避免讨论科学上网，所以只演示加速http流量。\n\nudp2raw也支持把udp流量包装成Icmp发送，本教程不做演示。\n\n### 环境要求\n服务器主机是linux，有root权限。  可以是openvz架构的vps。 也可以是openwrt路由器。\n\n本地主机是windows,本地有openwrt路由器或树莓派或安装了linux虚拟机（网卡设置为桥接模式）。\n\n(如果嫌给虚拟机安装linux麻烦，可以用release里发布的预装了udp2raw的openwrt_x86虚拟机镜像，容量4.4mb)\n\n下面的教程按虚拟机演示，如果你有openwrt路由器或树莓派，可以直接运行再路由器或树莓派上，就不需要虚拟机了。\n\n### 安装\n下载好udp2raw的压缩包，解压分别解压到服务器和本地的虚拟机。\n\nhttps://github.com/wangyu-/udp2raw-tunnel/releases\n\n在服务器端安装好finalspeed服务端，在本地windows安装好finalspeed的客户端。服务端我以前是用91yun的一键安装脚本安装的，没装过的可以去网上搜一键安装脚本。\n\n### 运行\n1.先在服务器主机运行如下命令，确定finalspeed服务端已经正常启动了。\n\n```\nnetstat -nlp|grep java\n```\n![image](finalspeed_step_by_step/Capture5.PNG)\n\n如果显示了150端口，就表示服务端启动好了。\n\n2.在服务器启动udp2raw server\n```\n ./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:150  -a -k \"passwd\" --raw-mode faketcp\n```\n![image](finalspeed_step_by_step/Capture2.PNG)\n\n3.在本地的虚拟机上启动udp2raw client  ,假设服务器ip是45.66.77.88\n```\n./udp2raw_amd64 -c -r45.66.77.88:8855 -l0.0.0.0:150 --raw-mode faketcp -a -k\"passwd\"\n```\n如果一切正常，client端会显示client_ready:\n\n![image](finalspeed_step_by_step/Capture3.PNG)\n\n记下红框中的ip,这是虚拟机的网卡ip\n\n在server端也会显示server_ready\n![image](finalspeed_step_by_step/Capture4.PNG)\n\n4.在本地windows,按图配置好finalspeed的客户端。注意，192.168.205.8改成你刚才记下来的IP，带宽也要按实际的填。传输协议要选UDP.\n![image](finalspeed_step_by_step/Capture.PNG)\n\n5.所有准备工作已经完成了，在本地访问本地的8012端口，相当于访问服务器的80端口。\n\n来试一下通过http://127.0.0.1:8012/ 下载文件 ，1.5M/s：\n![image](finalspeed_step_by_step/Capture6.PNG)\n\n再试一下直接通过服务器的ip访问，http://45.66.77.88:80/ ，速度只有600K/s\n![image](finalspeed_step_by_step/Capture7.PNG)\n\n教程就到这里了，用来加速其他的tcp服务也是一样的，只要再第三步那里设置其他的端口。\n"
  },
  {
    "path": "doc/kcptun_step_by_step.md",
    "content": "# udp2raw+kcptun 加速tcp流量 Step by Step 教程\n![image](kcptun_step_by_step/Capture00.PNG)\n\n本教程会一步一步演示用udp2raw+kcptun加速SSH流量的过程。加速任何其他tcp流量也一样，包括$\\*\\*\\*；本文避免涉及科学上网，所以演示ssh。\n\n### 环境要求\n两边的主机都是linux，有root权限。 可以是openwrt路由器或树莓派，也可以是root了的android。\n\n在windows/mac上运行udp2raw可以参考这个教程：\n\nhttps://github.com/wangyu-/udp2raw-tunnel/wiki/在windows-mac上运行udp2raw客户端，带图形界面\n\n\n### 安装\n下载好kcptun和udp2raw的压缩包，解压分别解压到client端和server端。\n\nhttps://github.com/xtaci/kcptun/releases\nhttps://github.com/wangyu-/udp2raw-tunnel/releases\n\n解压好后，如图：\n![image](kcptun_step_by_step/Capture0.PNG)\n\n### 运行\n1.在远程服务器运行 udp2raw_amd64 server模式：\n```\n./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:4000 -k \"passwd\" --raw-mode faketcp -a\n```\n![image](kcptun_step_by_step/Capture.PNG)\n\n2.在本地运行udp2raw_amd64 client模式，假设server ip是45.66.77.88：\n```\n./udp2raw_amd64 -c -r45.66.77.88:8855 -l0.0.0.0:4000 --raw-mode faketcp -a -k\"passwd\"\n```\n如果一切正常client端输出如下，显示client_ready：\n![image](kcptun_step_by_step/Capture2.PNG)\n\nserver端也会有类似输出,显示server_ready：\n![image](kcptun_step_by_step/Capture3.PNG)\n\n3.在远程服务器运行 kcp server\n\n\n```\n./server_linux_amd64 -t \"127.0.0.1:22\" -l \":4000\" -mode fast2 -mtu 1300\n```\n-mtu 1300很重要，或者设置成更小。\n![image](kcptun_step_by_step/Capture6.PNG)\n\n4.在本地运行 \n\n\n```\n ./client_linux_amd64 -r \"127.0.0.1:4000\" -l \":3322\" -mode fast2 -mtu 1300\n```\n-mtu 1300很重要，或者设置成更小。\n![image](kcptun_step_by_step/Capture7.PNG)\n\n5.所有准备工作已经做好，在本地运行\n```\nssh -p 3322 root@127.0.0.1\n```\n已经连进去了，而且是经过kcptun加速的：\n![image](kcptun_step_by_step/Capture8.PNG)\n"
  },
  {
    "path": "doc/openvpn_guide.md",
    "content": "# udp2raw+openvpn config guide\n![image_vpn](/images/openvpn.PNG)\n\n![image4](/images/image4.PNG)\n\n# udp2raw command\n#### run at server side\n```\n./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:7777 -k \"passwd\" --raw-mode faketcp -a\n```\n#### run at client side\nassume server ip is 45.66.77.88\n```\n./udp2raw_amd64 -c -l0.0.0.0:3333 -r 45.66.77.88:8855 -k \"passwd\" --raw-mode faketcp -a\n```\n\n#### hint\nYou can add `--cipher-mode xor` `--auth-mode simple` to **both** sides to obtain maximum performance(but poor security).\n\n# openvpn config\n\n#### client side config\n```\nclient\ndev tun100\nproto udp\n\nremote 127.0.0.1 3333\nresolv-retry infinite \nnobind \npersist-key \npersist-tun  \n\nca /root/add-on/openvpn/ca.crt\ncert /root/add-on/openvpn/client.crt\nkey /root/add-on/openvpn/client.key\n\nkeepalive 3 20\nverb 3\nmute 20\n\ncomp-lzo no\ncipher none      ##### disable openvpn 's cipher and auth for maxmized peformance. \nauth none        ##### you can enable openvpn's cipher and auth,if you dont care about peformance,or you dont trust udp2raw 's encryption\n\nfragment 1200       ##### very important    you can turn it up a bit. but,the lower the safer\nmssfix 1200         ##### very important\n\nsndbuf 2000000      ##### important\nrcvbuf 2000000      ##### important\ntxqueuelen 4000     ##### suggested\n```\n\n\n#### server side config\n```\nlocal 0.0.0.0\nport 7777 \nproto udp\ndev tun \n\nca /etc/openvpn/easy-rsa/2.0/keys/ca.crt\ncert /etc/openvpn/easy-rsa/2.0/keys/server.crt\nkey /etc/openvpn/easy-rsa/2.0/keys/server.key\ndh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem\n\nserver 10.222.2.0 255.255.255.0 \nifconfig 10.222.2.1 10.222.2.6\n\nclient-to-client\nduplicate-cn \nkeepalive 10 60 \n\nmax-clients 50\n\npersist-key\npersist-tun\n\nstatus /etc/openvpn/openvpn-status.log\n\nverb 3\nmute 20  \n\ncomp-lzo no\ncipher none      ##### disable openvpn 's cipher and auth for maxmized peformance. \nauth none        ##### you can enable openvpn's cipher and auth,if you dont care about peformance,or you dont trust udp2raw 's encryption\n\nfragment 1200       ##### very important    you can turn it up a bit. but,the lower the safer\nmssfix 1200         ##### very important\n\nsndbuf 2000000      ##### important\nrcvbuf 2000000      ##### important\ntxqueuelen 4000     ##### suggested\n```\n"
  },
  {
    "path": "encrypt.cpp",
    "content": "#include \"lib/aes-common.h\"\n#include \"lib/md5.h\"\n#include \"lib/pbkdf2-sha1.h\"\n#include \"lib/pbkdf2-sha256.h\"\n#include <string.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include \"encrypt.h\"\n#include \"common.h\"\n#include \"log.h\"\n\n// static uint64_t seq=1;\n\nstatic int8_t zero_iv[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // this prog use zero iv,you should make sure first block of data contains a random/nonce data\n/****\n * security of zero_iv + nonce first data block\n * https://crypto.stackexchange.com/questions/5421/using-cbc-with-a-fixed-iv-and-a-random-first-plaintext-block\n ****/\n\nchar normal_key[16 + 100];    // generated from key_string by md5. reserved for compatiblity\nconst int hmac_key_len = 64;  // generate 512bit long keys, use first n chars when needed\nconst int cipher_key_len = 64;\nunsigned char hmac_key_encrypt[hmac_key_len + 100];      // key for hmac\nunsigned char hmac_key_decrypt[hmac_key_len + 100];      // key for hmac\nunsigned char cipher_key_encrypt[cipher_key_len + 100];  // key for aes etc.\nunsigned char cipher_key_decrypt[cipher_key_len + 100];  // key for aes etc.\n\nchar gro_xor[256 + 100];  // dirty fix for gro\n\nunordered_map<int, const char *> auth_mode_tostring = {\n    {auth_none, \"none\"},\n    {auth_md5, \"md5\"},\n    {auth_crc32, \"crc32\"},\n    {auth_simple, \"simple\"},\n    {auth_hmac_sha1, \"hmac_sha1\"},\n};\n\nunordered_map<int, const char *> cipher_mode_tostring = {\n    {cipher_none, \"none\"},\n    {cipher_aes128cfb, \"aes128cfb\"},\n    {cipher_aes128cbc, \"aes128cbc\"},\n    {cipher_xor, \"xor\"},\n};\n// TODO aes-gcm\n\nauth_mode_t auth_mode = auth_md5;\ncipher_mode_t cipher_mode = cipher_aes128cbc;\nint is_hmac_used = 0;\n\nint aes128cfb_old = 0;\n\n// TODO key negotiation and forward secrecy\n\nint my_init_keys(const char *user_passwd, int is_client) {\n    char tmp[1000] = \"\";\n    int len = strlen(user_passwd);\n\n    strcat(tmp, user_passwd);\n\n    strcat(tmp, \"key1\");\n\n    md5((uint8_t *)tmp, strlen(tmp), (uint8_t *)normal_key);\n\n    if (auth_mode == auth_hmac_sha1)\n        is_hmac_used = 1;\n    if (is_hmac_used || g_fix_gro || 1) {\n        unsigned char salt[400] = \"\";\n        char salt_text[400] = \"udp2raw_salt1\";\n        md5((uint8_t *)(salt_text), strlen(salt_text), salt);  // TODO different salt per session\n\n        unsigned char pbkdf2_output1[400] = \"\";\n        PKCS5_PBKDF2_HMAC_SHA256((uint8_t *)user_passwd, len, salt, 16, 10000, 32, pbkdf2_output1);  // TODO argon2 ?\n\n        // unsigned char pbkdf2_output2[400]=\"\";\n        // PKCS5_PBKDF2_HMAC_SHA256(pbkdf2_output1,32,0,0,1, hmac_key_len*2+cipher_key_len*2,pbkdf2_output2);  //stretch it\n\n        const char *info_hmac_encrypt = \"hmac_key server-->client\";\n        const char *info_hmac_decrypt = \"hmac_key client-->server\";\n        const char *info_cipher_encrypt = \"cipher_key server-->client\";\n        const char *info_cipher_decrypt = \"cipher_key client-->server\";\n\n        if (is_client) {\n            const char *tmp;\n            tmp = info_hmac_encrypt;\n            info_hmac_encrypt = info_hmac_decrypt;\n            info_hmac_decrypt = tmp;\n            tmp = info_cipher_encrypt;\n            info_cipher_encrypt = info_cipher_decrypt;\n            info_cipher_decrypt = tmp;\n        } else {\n            // nop\n        }\n\n        assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)info_cipher_encrypt, strlen(info_cipher_encrypt), cipher_key_encrypt, cipher_key_len) == 0);\n        assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)info_cipher_decrypt, strlen(info_cipher_decrypt), cipher_key_decrypt, cipher_key_len) == 0);\n        assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)info_hmac_encrypt, strlen(info_hmac_encrypt), hmac_key_encrypt, hmac_key_len) == 0);\n        assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)info_hmac_decrypt, strlen(info_hmac_decrypt), hmac_key_decrypt, hmac_key_len) == 0);\n\n        const char *gro_info = \"gro\";\n        assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)gro_info, strlen(gro_info), (unsigned char *)gro_xor, 256) == 0);\n    }\n\n    print_binary_chars(normal_key, 16);\n    print_binary_chars((char *)hmac_key_encrypt, hmac_key_len);\n    print_binary_chars((char *)hmac_key_decrypt, hmac_key_len);\n    print_binary_chars((char *)cipher_key_encrypt, cipher_key_len);\n    print_binary_chars((char *)cipher_key_decrypt, cipher_key_len);\n\n    return 0;\n}\n/*\n *  this function comes from  http://www.hackersdelight.org/hdcodetxt/crc.c.txt\n */\nunsigned int crc32h(unsigned char *message, int len) {\n    int i, crc;\n    unsigned int byte, c;\n    const unsigned int g0 = 0xEDB88320, g1 = g0 >> 1,\n                       g2 = g0 >> 2, g3 = g0 >> 3, g4 = g0 >> 4, g5 = g0 >> 5,\n                       g6 = (g0 >> 6) ^ g0, g7 = ((g0 >> 6) ^ g0) >> 1;\n\n    i = 0;\n    crc = 0xFFFFFFFF;\n    while (i != len) {  // Get next byte.\n        byte = message[i];\n        crc = crc ^ byte;\n        c = ((crc << 31 >> 31) & g7) ^ ((crc << 30 >> 31) & g6) ^\n            ((crc << 29 >> 31) & g5) ^ ((crc << 28 >> 31) & g4) ^\n            ((crc << 27 >> 31) & g3) ^ ((crc << 26 >> 31) & g2) ^\n            ((crc << 25 >> 31) & g1) ^ ((crc << 24 >> 31) & g0);\n        crc = ((unsigned)crc >> 8) ^ c;\n        i = i + 1;\n    }\n    return ~crc;\n}\n\n/*\n void sum(const unsigned  char *data,int len,unsigned char*  res) {\n   memset(res,0,sizeof(int));\n   for(int i=0,j=0;i<len;i++,j++)\n   {\n           if(j==4) j=0;\n           res[j]+=data[i];\n   }\n\n   return ;\n}*/\n\nvoid simple_hash(unsigned char *str, int len, unsigned char res[8])  // djb2+ sdbm\n{\n    u32_t hash = 5381;\n    u32_t hash2 = 0;\n    int c;\n    int i = 0;\n    while (c = *str++, i++ != len) {\n        // hash = ((hash << 5) + hash) + c; /* hash * 33 + c */\n        hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */\n        hash2 = c + (hash2 << 6) + (hash2 << 16) - hash2;\n    }\n\n    hash = htonl(hash);\n    hash2 = htonl(hash2);\n    memcpy(res, &hash, sizeof(hash));\n    memcpy(res + sizeof(hash), &hash2, sizeof(hash2));\n}\n\nint auth_md5_cal(const char *data, char *output, int &len) {\n    memcpy(output, data, len);  // TODO inefficient code\n    md5((unsigned char *)output, len, (unsigned char *)(output + len));\n    len += 16;\n    return 0;\n}\n\nint auth_hmac_sha1_cal(const char *data, char *output, int &len) {\n    mylog(log_trace, \"auth_hmac_sha1_cal() is called\\n\");\n    memcpy(output, data, len);  // TODO inefficient code\n    sha1_hmac(hmac_key_encrypt, 20, (const unsigned char *)data, len, (unsigned char *)(output + len));\n    // use key len of 20 instead of hmac_key_len, \"extra length would not significantly increase the function strength\" (rfc2104)\n    len += 20;\n    return 0;\n}\n\nint auth_hmac_sha1_verify(const char *data, int &len) {\n    mylog(log_trace, \"auth_hmac_sha1_verify() is called\\n\");\n    if (len < 20) {\n        mylog(log_trace, \"auth_hmac_sha1_verify len<20\\n\");\n        return -1;\n    }\n    char res[20];\n\n    sha1_hmac(hmac_key_decrypt, 20, (const unsigned char *)data, len - 20, (unsigned char *)(res));\n\n    if (memcmp(res, data + len - 20, 20) != 0) {\n        mylog(log_trace, \"auth_hmac_sha1 check failed\\n\");\n        return -2;\n    }\n    len -= 20;\n    return 0;\n}\n\nint auth_crc32_cal(const char *data, char *output, int &len) {\n    memcpy(output, data, len);  // TODO inefficient code\n    unsigned int ret = crc32h((unsigned char *)output, len);\n    unsigned int ret_n = htonl(ret);\n    memcpy(output + len, &ret_n, sizeof(unsigned int));\n    len += sizeof(unsigned int);\n    return 0;\n}\n\nint auth_simple_cal(const char *data, char *output, int &len) {\n    // char res[4];\n    memcpy(output, data, len);  // TODO inefficient code\n    simple_hash((unsigned char *)output, len, (unsigned char *)(output + len));\n    len += 8;\n    return 0;\n}\nint auth_simple_verify(const char *data, int &len) {\n    if (len < 8) return -1;\n    unsigned char res[8];\n    len -= 8;\n    simple_hash((unsigned char *)data, len, res);\n    if (memcmp(res, data + len, 8) != 0)\n        return -1;\n    return 0;\n}\n\nint auth_none_cal(const char *data, char *output, int &len) {\n    memcpy(output, data, len);\n    return 0;\n}\nint auth_md5_verify(const char *data, int &len) {\n    if (len < 16) {\n        mylog(log_trace, \"auth_md5_verify len<16\\n\");\n        return -1;\n    }\n    char md5_res[16];\n\n    md5((unsigned char *)data, len - 16, (unsigned char *)md5_res);\n\n    if (memcmp(md5_res, data + len - 16, 16) != 0) {\n        mylog(log_trace, \"auth_md5_verify md5 check failed\\n\");\n        return -2;\n    }\n    len -= 16;\n    return 0;\n}\nint auth_none_verify(const char *data, int &len) {\n    return 0;\n}\n\nint cipher_xor_encrypt(const char *data, char *output, int &len, char *key) {\n    int i, j;\n    for (i = 0, j = 0; i < len; i++, j++) {\n        if (j == 16) j = 0;\n        output[i] = data[i] ^ key[j];\n    }\n    return 0;\n}\nint cipher_xor_decrypt(const char *data, char *output, int &len, char *key) {\n    int i, j;\n    // char tmp[buf_len];\n    // len=len/16*16+1;\n    // AES128_CBC_decrypt_buffer((uint8_t *)tmp, (uint8_t *)input, len, (uint8_t *)key, (uint8_t *)iv);\n    // for(i=0;i<len;i++)\n    // input[i]=tmp[i];\n    for (i = 0, j = 0; i < len; i++, j++) {\n        if (j == 16) j = 0;\n        output[i] = data[i] ^ key[j];\n    }\n    return 0;\n}\n\nint padding(char *data, int &data_len, int padding_num) {\n    int old_len = data_len;\n    data_len += 1;\n    if (data_len % padding_num != 0) {\n        data_len = (data_len / padding_num) * padding_num + padding_num;\n    }\n    unsigned char *p = (unsigned char *)&data[data_len - 1];\n    *p = (data_len - old_len);\n    return 0;\n}\n\nint de_padding(const char *data, int &data_len, int padding_num) {\n    if (data_len == 0) return -1;\n    if ((uint8_t)data[data_len - 1] > padding_num) return -1;\n    data_len -= (uint8_t)data[data_len - 1];\n    if (data_len < 0) {\n        return -1;\n    }\n    return 0;\n}\nvoid aes_ecb_encrypt(const char *data, char *output) {\n    static int first_time = 1;\n    char *key = (char *)cipher_key_encrypt;\n    if (aes_key_optimize) {\n        if (first_time == 0)\n            key = 0;\n        else\n            first_time = 0;\n    }\n    AES_ECB_encrypt_buffer((uint8_t *)data, (uint8_t *)key, (uint8_t *)output);\n}\nvoid aes_ecb_encrypt1(char *data) {\n    char buf[16];\n    memcpy(buf, data, 16);\n    aes_ecb_encrypt(buf, data);\n}\nvoid aes_ecb_decrypt(const char *data, char *output) {\n    static int first_time = 1;\n    char *key = (char *)cipher_key_decrypt;\n    if (aes_key_optimize) {\n        if (first_time == 0)\n            key = 0;\n        else\n            first_time = 0;\n    }\n    AES_ECB_decrypt_buffer((uint8_t *)data, (uint8_t *)key, (uint8_t *)output);\n}\nvoid aes_ecb_decrypt1(char *data) {\n    char buf[16];\n    memcpy(buf, data, 16);\n    aes_ecb_decrypt(buf, data);\n}\nint cipher_aes128cbc_encrypt(const char *data, char *output, int &len, char *key) {\n    static int first_time = 1;\n\n    char buf[buf_len];\n    memcpy(buf, data, len);  // TODO inefficient code\n\n    if (padding(buf, len, 16) < 0) return -1;\n\n    if (aes_key_optimize) {\n        if (first_time == 0)\n            key = 0;\n        else\n            first_time = 0;\n    }\n\n    AES_CBC_encrypt_buffer((unsigned char *)output, (unsigned char *)buf, len, (unsigned char *)key, (unsigned char *)zero_iv);\n    return 0;\n}\nint cipher_aes128cfb_encrypt(const char *data, char *output, int &len, char *key) {\n    static int first_time = 1;\n    assert(len >= 16);\n\n    char buf[buf_len];\n    memcpy(buf, data, len);  // TODO inefficient code\n    if (aes_key_optimize) {\n        if (first_time == 0)\n            key = 0;\n        else\n            first_time = 0;\n    }\n    if (!aes128cfb_old) {\n        aes_ecb_encrypt(data, buf);  // encrypt the first block\n    }\n\n    AES_CFB_encrypt_buffer((unsigned char *)output, (unsigned char *)buf, len, (unsigned char *)key, (unsigned char *)zero_iv);\n    return 0;\n}\nint auth_crc32_verify(const char *data, int &len) {\n    if (len < int(sizeof(unsigned int))) {\n        mylog(log_debug, \"auth_crc32_verify len<%d\\n\", int(sizeof(unsigned int)));\n        return -1;\n    }\n    unsigned int ret = crc32h((unsigned char *)data, len - sizeof(unsigned int));\n    unsigned int ret_n = htonl(ret);\n\n    if (memcmp(data + len - sizeof(unsigned int), &ret_n, sizeof(unsigned int)) != 0) {\n        mylog(log_debug, \"auth_crc32_verify memcmp fail\\n\");\n        return -1;\n    }\n    len -= sizeof(unsigned int);\n    return 0;\n}\nint cipher_none_encrypt(const char *data, char *output, int &len, char *key) {\n    memcpy(output, data, len);\n    return 0;\n}\nint cipher_aes128cbc_decrypt(const char *data, char *output, int &len, char *key) {\n    static int first_time = 1;\n    if (len % 16 != 0) {\n        mylog(log_debug, \"len%%16!=0\\n\");\n        return -1;\n    }\n    if (aes_key_optimize) {\n        if (first_time == 0)\n            key = 0;\n        else\n            first_time = 0;\n    }\n    AES_CBC_decrypt_buffer((unsigned char *)output, (unsigned char *)data, len, (unsigned char *)key, (unsigned char *)zero_iv);\n    if (de_padding(output, len, 16) < 0) return -1;\n    return 0;\n}\nint cipher_aes128cfb_decrypt(const char *data, char *output, int &len, char *key) {\n    static int first_time = 1;\n    if (len < 16) return -1;\n\n    if (aes_key_optimize) {\n        if (first_time == 0)\n            key = 0;\n        else\n            first_time = 0;\n    }\n\n    AES_CFB_decrypt_buffer((unsigned char *)output, (unsigned char *)data, len, (unsigned char *)key, (unsigned char *)zero_iv);\n\n    if (!aes128cfb_old)\n        aes_ecb_decrypt1(output);  // decrypt the first block\n    // if(de_padding(output,len,16)<0) return -1;\n    return 0;\n}\n\nint cipher_none_decrypt(const char *data, char *output, int &len, char *key) {\n    memcpy(output, data, len);\n    return 0;\n}\n\nint auth_cal(const char *data, char *output, int &len) {\n    mylog(log_trace, \"auth:%d\\n\", auth_mode);\n    switch (auth_mode) {\n        case auth_crc32:\n            return auth_crc32_cal(data, output, len);\n        case auth_md5:\n            return auth_md5_cal(data, output, len);\n        case auth_simple:\n            return auth_simple_cal(data, output, len);\n        case auth_none:\n            return auth_none_cal(data, output, len);\n        case auth_hmac_sha1:\n            return auth_hmac_sha1_cal(data, output, len);\n        // default:\treturn auth_md5_cal(data,output,len);//default;\n        default:\n            assert(0 == 1);\n    }\n    return -1;\n}\nint auth_verify(const char *data, int &len) {\n    mylog(log_trace, \"auth:%d\\n\", auth_mode);\n    switch (auth_mode) {\n        case auth_crc32:\n            return auth_crc32_verify(data, len);\n        case auth_md5:\n            return auth_md5_verify(data, len);\n        case auth_simple:\n            return auth_simple_verify(data, len);\n        case auth_none:\n            return auth_none_verify(data, len);\n        case auth_hmac_sha1:\n            return auth_hmac_sha1_verify(data, len);\n        // default:\treturn auth_md5_verify(data,len);//default\n        default:\n            assert(0 == 1);\n    }\n    return -1;\n}\nint cipher_encrypt(const char *data, char *output, int &len, char *key) {\n    mylog(log_trace, \"cipher:%d\\n\", cipher_mode);\n    switch (cipher_mode) {\n        case cipher_aes128cbc:\n            return cipher_aes128cbc_encrypt(data, output, len, key);\n        case cipher_aes128cfb:\n            return cipher_aes128cfb_encrypt(data, output, len, key);\n        case cipher_xor:\n            return cipher_xor_encrypt(data, output, len, key);\n        case cipher_none:\n            return cipher_none_encrypt(data, output, len, key);\n        // default:return cipher_aes128cbc_encrypt(data,output,len, key);\n        default:\n            assert(0 == 1);\n    }\n    return -1;\n}\nint cipher_decrypt(const char *data, char *output, int &len, char *key) {\n    mylog(log_trace, \"cipher:%d\\n\", cipher_mode);\n    switch (cipher_mode) {\n        case cipher_aes128cbc:\n            return cipher_aes128cbc_decrypt(data, output, len, key);\n        case cipher_aes128cfb:\n            return cipher_aes128cfb_decrypt(data, output, len, key);\n        case cipher_xor:\n            return cipher_xor_decrypt(data, output, len, key);\n        case cipher_none:\n            return cipher_none_decrypt(data, output, len, key);\n        //\tdefault:\treturn cipher_aes128cbc_decrypt(data,output,len,key);\n        default:\n            assert(0 == 1);\n    }\n    return -1;\n}\n\nint encrypt_AE(const char *data, char *output, int &len /*,char * key*/) {\n    mylog(log_trace, \"encrypt_AE is called\\n\");\n    char buf[buf_len];\n    char buf2[buf_len];\n    memcpy(buf, data, len);\n    if (cipher_encrypt(buf, buf2, len, (char *)cipher_key_encrypt) != 0) {\n        mylog(log_debug, \"cipher_encrypt failed \");\n        return -1;\n    }\n    if (auth_cal(buf2, output, len) != 0) {\n        mylog(log_debug, \"auth_cal failed \");\n        return -1;\n    }\n\n    // printf(\"%d %x %x\\n\",len,(int)(output[0]),(int)(output[1]));\n    // print_binary_chars(output,len);\n\n    // use encrypt-then-MAC scheme\n    return 0;\n}\n\nint decrypt_AE(const char *data, char *output, int &len /*,char * key*/) {\n    mylog(log_trace, \"decrypt_AE is called\\n\");\n    // printf(\"%d %x %x\\n\",len,(int)(data[0]),(int)(data[1]));\n    // print_binary_chars(data,len);\n\n    if (auth_verify(data, len) != 0) {\n        mylog(log_debug, \"auth_verify failed\\n\");\n        return -1;\n    }\n    if (cipher_decrypt(data, output, len, (char *)cipher_key_decrypt) != 0) {\n        mylog(log_debug, \"cipher_decrypt failed \\n\");\n        return -1;\n    }\n    return 0;\n}\n\nint my_encrypt(const char *data, char *output, int &len /*,char * key*/) {\n    if (len < 0) {\n        mylog(log_trace, \"len<0\");\n        return -1;\n    }\n    if (len > max_data_len) {\n        mylog(log_warn, \"len>max_data_len\");\n        return -1;\n    }\n\n    if (is_hmac_used)\n        return encrypt_AE(data, output, len);\n\n    char buf[buf_len];\n    char buf2[buf_len];\n    memcpy(buf, data, len);\n    if (auth_cal(buf, buf2, len) != 0) {\n        mylog(log_debug, \"auth_cal failed \");\n        return -1;\n    }\n    if (cipher_encrypt(buf2, output, len, normal_key) != 0) {\n        mylog(log_debug, \"cipher_encrypt failed \");\n        return -1;\n    }\n    return 0;\n}\n\nint my_decrypt(const char *data, char *output, int &len /*,char * key*/) {\n    if (len < 0) return -1;\n    if (len > max_data_len) {\n        mylog(log_warn, \"len>max_data_len\");\n        return -1;\n    }\n\n    if (is_hmac_used)\n        return decrypt_AE(data, output, len);\n\n    if (cipher_decrypt(data, output, len, normal_key) != 0) {\n        mylog(log_debug, \"cipher_decrypt failed \\n\");\n        return -1;\n    }\n    if (auth_verify(output, len) != 0) {\n        mylog(log_debug, \"auth_verify failed\\n\");\n        return -1;\n    }\n\n    return 0;\n}\n\nint encrypt_AEAD(uint8_t *data, uint8_t *output, int &len, uint8_t *key, uint8_t *header, int hlen) {\n    // TODO\n    return -1;\n}\n\nint decrypt_AEAD(uint8_t *data, uint8_t *output, int &len, uint8_t *key, uint8_t *header, int hlen) {\n    // TODO\n    return -1;\n}\n"
  },
  {
    "path": "encrypt.h",
    "content": "#ifndef UDP2RAW_ENCRYPTION_H_\n#define UDP2RAW_ENCRYPTION_H_\n\n//#include \"aes.h\"\n//#include \"md5.h\"\n#include \"common.h\"\n\n// using namespace std;\n// extern char key[16];\n\nconst int aes_key_optimize = 1;  // if enabled,once you used a key for aes,you cant change it anymore\nextern int aes128cfb_old;\n\nint my_init_keys(const char *, int);\n\nint my_encrypt(const char *data, char *output, int &len);\nint my_decrypt(const char *data, char *output, int &len);\n\nunsigned short csum(const unsigned short *ptr, int nbytes);\n\nenum auth_mode_t { auth_none = 0,\n                   auth_md5,\n                   auth_crc32,\n                   auth_simple,\n                   auth_hmac_sha1,\n                   auth_end };\n\nenum cipher_mode_t { cipher_none = 0,\n                     cipher_aes128cbc,\n                     cipher_xor,\n                     cipher_aes128cfb,\n                     cipher_end };\n\nextern auth_mode_t auth_mode;\nextern cipher_mode_t cipher_mode;\n\nextern unordered_map<int, const char *> auth_mode_tostring;\nextern unordered_map<int, const char *> cipher_mode_tostring;\n\nextern char gro_xor[256 + 100];\n\nint cipher_decrypt(const char *data, char *output, int &len, char *key);  // internal interface ,exposed for test only\nint cipher_encrypt(const char *data, char *output, int &len, char *key);  // internal interface ,exposed for test only\n\nvoid aes_ecb_encrypt(const char *data, char *output);\nvoid aes_ecb_decrypt(const char *data, char *output);\n\nvoid aes_ecb_encrypt1(char *data);\nvoid aes_ecb_decrypt1(char *data);\n\n#endif\n"
  },
  {
    "path": "example.conf",
    "content": "# Basically this file is the equivalent to splitting the command line options into multiple lines\n# Each line should contain an option\n\n# This is client\n-c\n# Or use -s if you use it on server side\n# Define local address\n-l 127.0.0.1:56789\n# Define remote address\n-r 45.66.77.88:45678\n# Password\n-k my_awesome_password\n# Mode\n--raw-mode faketcp\n# Log Level\n--log-level 4\n"
  },
  {
    "path": "fd_manager.cpp",
    "content": "/*\n * fd_manager.cpp\n *\n *  Created on: Sep 25, 2017\n *      Author: root\n */\n\n#include \"fd_manager.h\"\nint fd_manager_t::fd_exist(int fd) {\n    return fd_to_fd64_mp.find(fd) != fd_to_fd64_mp.end();\n}\nint fd_manager_t::exist(fd64_t fd64) {\n    return fd64_to_fd_mp.find(fd64) != fd64_to_fd_mp.end();\n}\nint fd_manager_t::to_fd(fd64_t fd64) {\n    assert(exist(fd64));\n    return fd64_to_fd_mp[fd64];\n}\nvoid fd_manager_t::fd64_close(fd64_t fd64) {\n    assert(exist(fd64));\n    int fd = fd64_to_fd_mp[fd64];\n    fd64_to_fd_mp.erase(fd64);\n    fd_to_fd64_mp.erase(fd);\n    if (exist_info(fd64)) {\n        fd_info_mp.erase(fd64);\n    }\n    // assert(close(fd)==0);\n    sock_close(fd);\n}\nvoid fd_manager_t::reserve(int n) {\n    fd_to_fd64_mp.reserve(n);\n    fd64_to_fd_mp.reserve(n);\n    fd_info_mp.reserve(n);\n}\nu64_t fd_manager_t::create(int fd) {\n    assert(!fd_exist(fd));\n    fd64_t fd64 = counter++;\n    fd_to_fd64_mp[fd] = fd64;\n    fd64_to_fd_mp[fd64] = fd;\n    return fd64;\n}\nfd_manager_t::fd_manager_t() {\n    counter = u32_t(-1);\n    counter += 100;\n    reserve(10007);\n}\nfd_info_t& fd_manager_t::get_info(fd64_t fd64) {\n    assert(exist(fd64));\n    return fd_info_mp[fd64];\n}\nint fd_manager_t::exist_info(fd64_t fd64) {\n    return fd_info_mp.find(fd64) != fd_info_mp.end();\n}\n"
  },
  {
    "path": "fd_manager.h",
    "content": "/*\n * fd_manager.h\n *\n *  Created on: Sep 25, 2017\n *      Author: root\n */\n\n#ifndef FD_MANAGER_H_\n#define FD_MANAGER_H_\n\n#include \"common.h\"\n//#include \"packet.h\"\n#include \"connection.h\"\n\nstruct fd_info_t {\n    // ip_port_t ip_port;\n    conn_info_t *p_conn_info;\n};\n\nstruct fd_manager_t  // conver fd to a uniq 64bit number,avoid fd value conflict caused by close and re-create\n// this class is not strictly necessary,it just makes epoll fd handling easier\n{\n    fd_info_t &get_info(fd64_t fd64);\n    int exist_info(fd64_t);\n    int exist(fd64_t fd64);\n    int to_fd(fd64_t);\n    void fd64_close(fd64_t fd64);\n    void reserve(int n);\n    u64_t create(int fd);\n    fd_manager_t();\n\n   private:\n    u64_t counter;\n    unordered_map<int, fd64_t> fd_to_fd64_mp;\n    unordered_map<fd64_t, int> fd64_to_fd_mp;\n    unordered_map<fd64_t, fd_info_t> fd_info_mp;\n    int fd_exist(int fd);\n    // void remove_fd(int fd);\n    // fd64_t fd_to_fd64(int fd);\n};\n\nextern fd_manager_t fd_manager;\n#endif /* FD_MANAGER_H_ */\n"
  },
  {
    "path": "images/speedtest/111",
    "content": "\n"
  },
  {
    "path": "images/wiki/111",
    "content": "\n"
  },
  {
    "path": "lib/aes-common.h",
    "content": "/*\n *  this file comes from https://github.com/kokke/tiny-AES128-C\n */\n\n#pragma once\n\n#include <stdint.h>\n\n\nvoid AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output);\nvoid AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output);\n\nvoid AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);\nvoid AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);\n\n\nvoid AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);\nvoid AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);\n"
  },
  {
    "path": "lib/aes_acc/aesacc.c",
    "content": "/*\n * This file is adapted from PolarSSL 1.3.19 (GPL)\n */\n\n#include \"aesni.h\"\n#include \"aesarm.h\"\n#include <stdint.h>\n#include <string.h>\n#include <assert.h>\n\n#if defined(AES256) && (AES256 == 1)\n#define AES_KEYSIZE 256\n#ifdef HAVE_AMD64\n  #define aeshw_setkey_enc aesni_setkey_enc_256\n#endif\n#elif defined(AES192) && (AES192 == 1)\n#define AES_KEYSIZE 192\n#ifdef HAVE_AMD64\n  #define aeshw_setkey_enc aesni_setkey_enc_192\n#endif\n#else\n#define AES_KEYSIZE 128\n#ifdef HAVE_AMD64\n  #define aeshw_setkey_enc aesni_setkey_enc_128\n#endif\n#endif\n\n#define AES_NR ((AES_KEYSIZE >> 5) + 6)\n#define AES_RKSIZE      272\n\n#ifdef HAVE_AMD64\n#define HAVE_HARDAES 1\n#define aeshw_supported aesni_supported\n#define aeshw_crypt_ecb aesni_crypt_ecb\n#define aeshw_inverse_key(a,b) aesni_inverse_key(a,b,AES_NR)\n#endif /* HAVE_AMD64 */\n\n#ifdef HAVE_ARM64\n#define HAVE_HARDAES 1\n#define aeshw_supported aesarm_supported\n#define aeshw_crypt_ecb aesarm_crypt_ecb\n\n#include \"aesarm_table.h\"\n\n#ifndef GET_UINT32_LE\n#define GET_UINT32_LE(n,b,i)                            \\\n{                                                       \\\n    (n) = ( (uint32_t) (b)[(i)    ]       )             \\\n        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \\\n        | ( (uint32_t) (b)[(i) + 2] << 16 )             \\\n        | ( (uint32_t) (b)[(i) + 3] << 24 );            \\\n}\n#endif\n\nstatic void aeshw_setkey_enc(uint8_t *rk, const uint8_t *key)\n{\n    unsigned int i;\n    uint32_t *RK;\n\n    RK = (uint32_t *) rk;\n\n    for( i = 0; i < ( AES_KEYSIZE >> 5 ); i++ )\n    {\n        GET_UINT32_LE( RK[i], key, i << 2 );\n    }\n\n    switch( AES_NR )\n    {\n        case 10:\n\n            for( i = 0; i < 10; i++, RK += 4 )\n            {\n                RK[4]  = RK[0] ^ RCON[i] ^\n                ( (uint32_t) FSb[ ( RK[3] >>  8 ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( RK[3]       ) & 0xFF ] << 24 );\n\n                RK[5]  = RK[1] ^ RK[4];\n                RK[6]  = RK[2] ^ RK[5];\n                RK[7]  = RK[3] ^ RK[6];\n            }\n            break;\n\n        case 12:\n\n            for( i = 0; i < 8; i++, RK += 6 )\n            {\n                RK[6]  = RK[0] ^ RCON[i] ^\n                ( (uint32_t) FSb[ ( RK[5] >>  8 ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( RK[5]       ) & 0xFF ] << 24 );\n\n                RK[7]  = RK[1] ^ RK[6];\n                RK[8]  = RK[2] ^ RK[7];\n                RK[9]  = RK[3] ^ RK[8];\n                RK[10] = RK[4] ^ RK[9];\n                RK[11] = RK[5] ^ RK[10];\n            }\n            break;\n\n        case 14:\n\n            for( i = 0; i < 7; i++, RK += 8 )\n            {\n                RK[8]  = RK[0] ^ RCON[i] ^\n                ( (uint32_t) FSb[ ( RK[7] >>  8 ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( RK[7]       ) & 0xFF ] << 24 );\n\n                RK[9]  = RK[1] ^ RK[8];\n                RK[10] = RK[2] ^ RK[9];\n                RK[11] = RK[3] ^ RK[10];\n\n                RK[12] = RK[4] ^\n                ( (uint32_t) FSb[ ( RK[11]       ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( RK[11] >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );\n\n                RK[13] = RK[5] ^ RK[12];\n                RK[14] = RK[6] ^ RK[13];\n                RK[15] = RK[7] ^ RK[14];\n            }\n            break;\n    }\n}\n\nstatic void aeshw_inverse_key(uint8_t *invkey, const uint8_t *fwdkey)\n{\n  int i, j;\n  uint32_t *RK;\n  uint32_t *SK;\n\n  RK = (uint32_t *) invkey;\n  SK = ((uint32_t *) fwdkey) + AES_NR * 4;\n\n  *RK++ = *SK++;\n  *RK++ = *SK++;\n  *RK++ = *SK++;\n  *RK++ = *SK++;\n\n  for( i = AES_NR - 1, SK -= 8; i > 0; i--, SK -= 8 )\n  {\n      for( j = 0; j < 4; j++, SK++ )\n      {\n          *RK++ = RT0[ FSb[ ( *SK       ) & 0xFF ] ] ^\n                  RT1[ FSb[ ( *SK >>  8 ) & 0xFF ] ] ^\n                  RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^\n                  RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];\n      }\n  }\n\n  *RK++ = *SK++;\n  *RK++ = *SK++;\n  *RK++ = *SK++;\n  *RK++ = *SK++;\n}\n#endif /* HAVE_ARM64 */\n\n#ifdef HAVE_HARDAES\nstatic void aeshw_setkey_dec(uint8_t *rk, const uint8_t *key)\n{\n  uint8_t rk_tmp[AES_RKSIZE];\n  aeshw_setkey_enc(rk_tmp, key);\n  aeshw_inverse_key(rk, rk_tmp);\n}\n\nstatic void aeshw_encrypt_ecb( int nr,\n                               unsigned char *rk,\n                               const unsigned char input[16],\n                               unsigned char output[16] )\n{\n  aeshw_crypt_ecb(nr, rk, AES_ENCRYPT, input, output);\n}\n\nstatic void aeshw_decrypt_ecb( int nr,\n                               unsigned char *rk,\n                               const unsigned char input[16],\n                               unsigned char output[16] )\n{\n  aeshw_crypt_ecb(nr, rk, AES_DECRYPT, input, output);\n}\n#endif /* HAVE_HARDAES */\n\n/* OpenSSL assembly functions */\n#define AES_MAXNR 14\ntypedef struct {\n  uint32_t rd_key[4 * (AES_MAXNR + 1)];\n  uint32_t rounds;\n} AES_KEY;\n\n#if defined(__amd64__) || defined(__x86_64__) || \\\n    defined(__aarch64__)\n#define AES_set_encrypt_key vpaes_set_encrypt_key\n#define AES_set_decrypt_key vpaes_set_decrypt_key\n#define AES_encrypt vpaes_encrypt\n#define AES_decrypt vpaes_decrypt\n#endif /* VPAES for 64-bit Intel and ARM */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint AES_set_encrypt_key(const unsigned char *userKey, const int bits,\n                        AES_KEY *key);\nint AES_set_decrypt_key(const unsigned char *userKey, const int bits,\n                        AES_KEY *key);\n\nvoid AES_encrypt(const unsigned char *in, unsigned char *out,\n                 const AES_KEY *key);\nvoid AES_decrypt(const unsigned char *in, unsigned char *out,\n                 const AES_KEY *key);\n\n#ifdef __cplusplus\n}\n#endif\n\nstatic void aes_encrypt_ecb( int nr,\n                             unsigned char *rk,\n                             const unsigned char input[16],\n                             unsigned char output[16] )\n{\n  AES_encrypt(input, output, (AES_KEY *) rk);\n}\n\nstatic void aes_decrypt_ecb( int nr,\n                             unsigned char *rk,\n                             const unsigned char input[16],\n                             unsigned char output[16] )\n{\n  AES_decrypt(input, output, (AES_KEY *) rk);\n}\n\nstatic void aes_setkey_enc(uint8_t *rk, const uint8_t *key)\n{\n  AES_set_encrypt_key(key, AES_KEYSIZE, (AES_KEY *) rk);\n}\n\nstatic void aes_setkey_dec(uint8_t *rk, const uint8_t *key)\n{\n  AES_set_decrypt_key(key, AES_KEYSIZE, (AES_KEY *) rk);\n}\n\nstatic void (*encrypt_ecb) ( int nr,\n                             unsigned char *rk,\n                             const unsigned char input[16],\n                             unsigned char output[16] )\n  = aes_encrypt_ecb;\n\nstatic void (*decrypt_ecb) ( int nr,\n                             unsigned char *rk,\n                             const unsigned char input[16],\n                             unsigned char output[16] )\n  = aes_decrypt_ecb;\n\nstatic void (*setkey_enc) (uint8_t *rk, const uint8_t *key)\n  = aes_setkey_enc;\n\nstatic void (*setkey_dec) (uint8_t *rk, const uint8_t *key)\n  = aes_setkey_dec;\n\n/*\n * AESNI-CBC buffer encryption/decryption\n */\nstatic void encrypt_cbc( uint8_t* rk,\n                         uint32_t length,\n                         uint8_t iv[16],\n                         const uint8_t *input,\n                         uint8_t *output )\n{\n    int i;\n    uint8_t temp[16];\n\n    while( length > 0 )\n    {\n        for( i = 0; i < 16; i++ )\n            output[i] = (uint8_t)( input[i] ^ iv[i] );\n\n        encrypt_ecb( AES_NR, rk, output, output );\n        memcpy( iv, output, 16 );\n\n        input  += 16;\n        output += 16;\n        length -= 16;\n    }\n}\n\nstatic void decrypt_cbc( uint8_t* rk,\n                         uint32_t length,\n                         uint8_t iv[16],\n                         const uint8_t *input,\n                         uint8_t *output )\n{\n    int i;\n    uint8_t temp[16];\n\n    while( length > 0 )\n    {\n        memcpy( temp, input, 16 );\n        decrypt_ecb( AES_NR, rk, input, output );\n\n        for( i = 0; i < 16; i++ )\n            output[i] = (uint8_t)( output[i] ^ iv[i] );\n\n        memcpy( iv, temp, 16 );\n\n        input  += 16;\n        output += 16;\n        length -= 16;\n    }\n}\n\nstatic void aeshw_init(void)\n{\n#ifdef HAVE_HARDAES\n  static int done = 0;\n  if (!done) {\n    if (aeshw_supported()) {\n      encrypt_ecb = aeshw_encrypt_ecb;\n      decrypt_ecb = aeshw_decrypt_ecb;\n      setkey_enc = aeshw_setkey_enc;\n      setkey_dec = aeshw_setkey_dec;\n    }\n    done = 1;\n  }\n#endif\n}\n\nint AES_support_hwaccel(void)\n{\n#ifdef HAVE_HARDAES\n  return aeshw_supported();\n#else\n  return 0;\n#endif\n}\n\nvoid AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)\n{\n  uint8_t iv_tmp[16];\n  static uint8_t rk[AES_RKSIZE];\n\n  assert(iv!=NULL);\n  aeshw_init();\n  memcpy(iv_tmp, iv, 16);\n  if(key!= NULL)\n\t  setkey_enc(rk, key);\n  encrypt_cbc(rk, length, iv_tmp, input, output);\n}\n\nvoid AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)\n{\n  uint8_t iv_tmp[16];\n  static uint8_t rk[AES_RKSIZE];\n\n  assert(iv!=NULL);\n  aeshw_init();\n  memcpy(iv_tmp, iv, 16);\n  if(key!= NULL)\n  {\n\t  setkey_dec(rk, key);\n  }\n  decrypt_cbc(rk, length, iv_tmp, input, output);\n}\n\nvoid AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t* output)\n{\n  static uint8_t rk[AES_RKSIZE];\n\n  aeshw_init();\n  if(key!=NULL)\n    setkey_enc(rk, key);\n  encrypt_ecb(AES_NR, rk, input, output);\n}\n\nvoid AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)\n{\n  static uint8_t rk[AES_RKSIZE];\n\n  aeshw_init();\n  if(key!=NULL)\n    setkey_dec(rk, key);\n  decrypt_ecb(AES_NR, rk, input, output);\n}\n\nstatic void encrypt_cfb( uint8_t* rk,\n                         uint32_t length,size_t *iv_off,\n                         uint8_t iv[16],\n                         const uint8_t *input,\n                         uint8_t *output )\n{\n    int c;\n    size_t n = *iv_off;\n    while( length-- )\n    {\n        if( n == 0 )\n        \tencrypt_ecb( AES_NR, rk, iv, iv );\n\n        iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );\n\n        n = ( n + 1 ) & 0x0F;\n    }\n\n    *iv_off = n;\n}\n\nstatic void decrypt_cfb( uint8_t* rk,\n                         uint32_t length,size_t *iv_off,\n                         uint8_t iv[16],\n                         const uint8_t *input,\n                         uint8_t *output )\n{\n    int c;\n    size_t n = *iv_off;\n    while( length-- )\n    {\n        if( n == 0 )\n        \tencrypt_ecb( AES_NR, rk, iv, iv );\n\n        c = *input++;\n        *output++ = (unsigned char)( c ^ iv[n] );\n        iv[n] = (unsigned char) c;\n\n        n = ( n + 1 ) & 0x0F;\n    }\n\n    *iv_off = n;\n}\n\nvoid AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)\n{\n  uint8_t iv_tmp[16];\n  static uint8_t rk[AES_RKSIZE];\n\n  assert(iv!=NULL);\n  aeshw_init();\n  memcpy(iv_tmp, iv, 16);\n  if(key!= NULL)\n\t  setkey_enc(rk, key);\n  size_t offset=0;\n  encrypt_cfb(rk, length,&offset, iv_tmp, input, output);\n}\n\nvoid AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)\n{\n  uint8_t iv_tmp[16];\n  static uint8_t rk[AES_RKSIZE];\n\n  assert(iv!=NULL);\n  aeshw_init();\n  memcpy(iv_tmp, iv, 16);\n  if(key!= NULL)\n  {\n\t  setkey_enc(rk, key);//its enc again,not typo\n  }\n  size_t offset=0;\n  decrypt_cfb(rk, length,&offset, iv_tmp, input, output);\n}\n\n"
  },
  {
    "path": "lib/aes_acc/aesarm.c",
    "content": "/*\n * This file is adapted from https://github.com/CriticalBlue/mbedtls\n */\n\n/*\n *  ARMv8-A Cryptography Extension AES support functions\n *\n *  Copyright (C) 2016, CriticalBlue Limited, All Rights Reserved\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of mbed TLS (https://tls.mbed.org)\n */\n\n#include \"aesarm.h\"\n\n#if defined(HAVE_ARM64)\n\n#include <sys/auxv.h>\n#include <asm/hwcap.h>\n#include <arm_neon.h>\n\n/*\n * ARMv8a Crypto Extension support detection routine\n */\nint aesarm_supported( void )\n{\n    static int done = 0;\n    static unsigned int c = 0;\n\n    if ( ! done )\n    {\n        c = getauxval(AT_HWCAP);\n        done = 1;\n    }\n\n    return ( c & HWCAP_AES ) != 0;\n}\n\n/*\n * ARMv8a AES-ECB block en(de)cryption\n */\nvoid aesarm_crypt_ecb( int nr,\n                       unsigned char *rk,\n                       int mode,\n                       const unsigned char input[16],\n                       unsigned char output[16] )\n{\n    int i;\n    uint8x16_t state_vec, roundkey_vec;\n    uint8_t *RK = (uint8_t *) rk;\n\n    // Load input and round key into into their vectors\n    state_vec = vld1q_u8( input );\n\n    if ( mode == AES_ENCRYPT )\n    {\n        // Initial AddRoundKey is in the loop due to AES instruction always doing AddRoundKey first\n        for( i = 0; i < nr - 1; i++ )\n        {\n            // Load Round Key\n            roundkey_vec = vld1q_u8( RK );\n            // Forward (AESE) round (AddRoundKey, SubBytes and ShiftRows)\n            state_vec = vaeseq_u8( state_vec, roundkey_vec );\n            // Mix Columns (AESMC)\n            state_vec = vaesmcq_u8( state_vec );\n            // Move pointer ready to load next round key\n            RK += 16;\n        }\n\n        // Final Forward (AESE) round (AddRoundKey, SubBytes and ShiftRows). No Mix columns\n        roundkey_vec = vld1q_u8( RK ); /* RK already moved in loop */\n        state_vec = vaeseq_u8( state_vec, roundkey_vec );\n    }\n    else\n    {\n        // Initial AddRoundKey is in the loop due to AES instruction always doing AddRoundKey first\n        for( i = 0; i < nr - 1; i++ )\n        {\n            // Load Round Key\n            roundkey_vec = vld1q_u8( RK );\n            // Reverse (AESD) round (AddRoundKey, SubBytes and ShiftRows)\n            state_vec = vaesdq_u8( state_vec, roundkey_vec );\n            // Inverse Mix Columns (AESIMC)\n            state_vec = vaesimcq_u8( state_vec );\n            // Move pointer ready to load next round key\n            RK += 16;\n        }\n\n        // Final Reverse (AESD) round (AddRoundKey, SubBytes and ShiftRows). No Mix columns\n        roundkey_vec = vld1q_u8( RK ); /* RK already moved in loop */\n        state_vec = vaesdq_u8( state_vec, roundkey_vec );\n    }\n\n    // Manually apply final Add RoundKey step (EOR)\n    RK += 16;\n    roundkey_vec = vld1q_u8( RK );\n    state_vec = veorq_u8( state_vec, roundkey_vec );\n\n    // Write results back to output array\n    vst1q_u8( output, state_vec );\n}\n\n#endif /* HAVE_ARM64 */\n"
  },
  {
    "path": "lib/aes_acc/aesarm.h",
    "content": "/*\n * This file is adapted from https://github.com/CriticalBlue/mbedtls\n */\n\n/**\n * \\file aes_armv8a_ce.h\n *\n * \\brief AES support functions using the ARMv8-A Cryptography Extension for\n * hardware acceleration on some ARM processors.\n *\n *  Copyright (C) 2016, CriticalBlue Limited, All Rights Reserved\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of mbed TLS (https://tls.mbed.org)\n */\n\n#ifndef UDP2RAW_AESARM_H_\n#define UDP2RAW_AESARM_H_\n\n#ifndef AES_ENCRYPT\n#define AES_ENCRYPT     1\n#endif\n\n#ifndef AES_DECRYPT\n#define AES_DECRYPT     0\n#endif\n\n#if defined(__GNUC__) && \\\n    __ARM_ARCH >= 8 && \\\n    __ARM_ARCH_PROFILE == 'A' && \\\n    defined(__aarch64__) &&  \\\n    defined(__ARM_FEATURE_CRYPTO) && \\\n    defined(__linux__) && \\\n    !defined(NO_AESACC)\n#define HAVE_ARM64\n#endif\n\n#if defined(HAVE_ARM64)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          ARMv8-A features detection routine\n *\n * \\return         1 if the CPU has support for the feature, 0 otherwise\n */\nint aesarm_supported( void );\n\n/**\n * \\brief          AES ARMv8-A Cryptography Extension AES-ECB block en(de)cryption\n *\n * \\param nr       number of rounds\n * \\param rk       AES round keys\n * \\param mode     AESARM_ENCRYPT or AESARM_DECRYPT\n * \\param input    16-byte input block\n * \\param output   16-byte output block\n */\nvoid aesarm_crypt_ecb( int nr,\n                       unsigned char *rk,\n                       int mode,\n                       const unsigned char input[16],\n                       unsigned char output[16] );\n\n#ifdef __cplusplus\n}\n#endif \n\n#endif /* HAVE_ARM64 */\n\n#endif /* _AESARM_H_ */\n"
  },
  {
    "path": "lib/aes_acc/aesarm_table.h",
    "content": "/*\n * This file is adapted from PolarSSL 1.3.19 (GPL)\n */\n\n/*\n * Forward S-box\n */\nstatic const unsigned char FSb[256] =\n{\n    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,\n    0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,\n    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,\n    0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,\n    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,\n    0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,\n    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,\n    0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,\n    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,\n    0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,\n    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,\n    0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,\n    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,\n    0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,\n    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,\n    0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,\n    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,\n    0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,\n    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,\n    0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,\n    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,\n    0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,\n    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,\n    0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,\n    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,\n    0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,\n    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,\n    0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,\n    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,\n    0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,\n    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,\n    0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16\n};\n\n/*\n * Round constants\n */\nstatic const uint32_t RCON[10] =\n{\n    0x00000001, 0x00000002, 0x00000004, 0x00000008,\n    0x00000010, 0x00000020, 0x00000040, 0x00000080,\n    0x0000001B, 0x00000036\n};\n\n/*\n * Reverse tables\n */\n#define RT \\\n\\\n    V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \\\n    V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \\\n    V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \\\n    V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \\\n    V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \\\n    V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \\\n    V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \\\n    V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \\\n    V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \\\n    V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \\\n    V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \\\n    V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \\\n    V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \\\n    V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \\\n    V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \\\n    V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \\\n    V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \\\n    V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \\\n    V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \\\n    V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \\\n    V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \\\n    V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \\\n    V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \\\n    V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \\\n    V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \\\n    V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \\\n    V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \\\n    V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \\\n    V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \\\n    V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \\\n    V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \\\n    V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \\\n    V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \\\n    V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \\\n    V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \\\n    V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \\\n    V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \\\n    V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \\\n    V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \\\n    V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \\\n    V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \\\n    V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \\\n    V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \\\n    V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \\\n    V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \\\n    V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \\\n    V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \\\n    V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \\\n    V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \\\n    V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \\\n    V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \\\n    V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \\\n    V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \\\n    V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \\\n    V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \\\n    V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \\\n    V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \\\n    V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \\\n    V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \\\n    V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \\\n    V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \\\n    V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \\\n    V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \\\n    V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)\n\n#define V(a,b,c,d) 0x##a##b##c##d\nstatic const uint32_t RT0[256] = { RT };\n#undef V\n\n#define V(a,b,c,d) 0x##b##c##d##a\nstatic const uint32_t RT1[256] = { RT };\n#undef V\n\n#define V(a,b,c,d) 0x##c##d##a##b\nstatic const uint32_t RT2[256] = { RT };\n#undef V\n\n#define V(a,b,c,d) 0x##d##a##b##c\nstatic const uint32_t RT3[256] = { RT };\n#undef V\n\n#undef RT\n"
  },
  {
    "path": "lib/aes_acc/aesni.c",
    "content": "/*\n * This file is adapted from PolarSSL 1.3.19 (GPL)\n */\n\n/*\n *  AES-NI support functions\n *\n *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved\n *\n *  This file is part of mbed TLS (https://tls.mbed.org)\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License along\n *  with this program; if not, write to the Free Software Foundation, Inc.,\n *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n */\n\n/*\n * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set\n * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/\n */\n\n#include <string.h>\n#include \"aesni.h\"\n\n#if defined(HAVE_AMD64)\n\n/*\n * AES-NI support detection routine\n */\n#define AESNI_AES 0x02000000u\n\nint aesni_supported( void )\n{\n    static int done = 0;\n    static unsigned int c = 0;\n\n    if( ! done )\n    {\n        asm( \"movl  $1, %%eax   \\n\\t\"\n             \"cpuid             \\n\\t\"\n             : \"=c\" (c)\n             :\n             : \"eax\", \"ebx\", \"edx\" );\n        done = 1;\n    }\n\n    return( ( c & AESNI_AES ) != 0 );\n}\n\n/*\n * Binutils needs to be at least 2.19 to support AES-NI instructions.\n * Unfortunately, a lot of users have a lower version now (2014-04).\n * Emit bytecode directly in order to support \"old\" version of gas.\n *\n * Opcodes from the Intel architecture reference manual, vol. 3.\n * We always use registers, so we don't need prefixes for memory operands.\n * Operand macros are in gas order (src, dst) as opposed to Intel order\n * (dst, src) in order to blend better into the surrounding assembly code.\n */\n#define AESDEC      \".byte 0x66,0x0F,0x38,0xDE,\"\n#define AESDECLAST  \".byte 0x66,0x0F,0x38,0xDF,\"\n#define AESENC      \".byte 0x66,0x0F,0x38,0xDC,\"\n#define AESENCLAST  \".byte 0x66,0x0F,0x38,0xDD,\"\n#define AESIMC      \".byte 0x66,0x0F,0x38,0xDB,\"\n#define AESKEYGENA  \".byte 0x66,0x0F,0x3A,0xDF,\"\n#define PCLMULQDQ   \".byte 0x66,0x0F,0x3A,0x44,\"\n\n#define xmm0_xmm0   \"0xC0\"\n#define xmm0_xmm1   \"0xC8\"\n#define xmm0_xmm2   \"0xD0\"\n#define xmm0_xmm3   \"0xD8\"\n#define xmm0_xmm4   \"0xE0\"\n#define xmm1_xmm0   \"0xC1\"\n#define xmm1_xmm2   \"0xD1\"\n\n/*\n * AES-NI AES-ECB block en(de)cryption\n */\nvoid aesni_crypt_ecb( int nr,\n                      unsigned char *rk,\n                      int mode,\n                      const unsigned char input[16],\n                      unsigned char output[16] )\n{\n    asm( \"movdqu    (%3), %%xmm0    \\n\\t\" // load input\n         \"movdqu    (%1), %%xmm1    \\n\\t\" // load round key 0\n         \"pxor      %%xmm1, %%xmm0  \\n\\t\" // round 0\n         \"addq      $16, %1         \\n\\t\" // point to next round key\n         \"subl      $1, %0          \\n\\t\" // normal rounds = nr - 1\n         \"test      %2, %2          \\n\\t\" // mode?\n         \"jz        2f              \\n\\t\" // 0 = decrypt\n\n         \"1:                        \\n\\t\" // encryption loop\n         \"movdqu    (%1), %%xmm1    \\n\\t\" // load round key\n         AESENC     xmm1_xmm0      \"\\n\\t\" // do round\n         \"addq      $16, %1         \\n\\t\" // point to next round key\n         \"subl      $1, %0          \\n\\t\" // loop\n         \"jnz       1b              \\n\\t\"\n         \"movdqu    (%1), %%xmm1    \\n\\t\" // load round key\n         AESENCLAST xmm1_xmm0      \"\\n\\t\" // last round\n         \"jmp       3f              \\n\\t\"\n\n         \"2:                        \\n\\t\" // decryption loop\n         \"movdqu    (%1), %%xmm1    \\n\\t\"\n         AESDEC     xmm1_xmm0      \"\\n\\t\" // do round\n         \"addq      $16, %1         \\n\\t\"\n         \"subl      $1, %0          \\n\\t\"\n         \"jnz       2b              \\n\\t\"\n         \"movdqu    (%1), %%xmm1    \\n\\t\" // load round key\n         AESDECLAST xmm1_xmm0      \"\\n\\t\" // last round\n\n         \"3:                        \\n\\t\"\n         \"movdqu    %%xmm0, (%4)    \\n\\t\" // export output\n         :\n         : \"r\" (nr), \"r\" (rk), \"r\" (mode), \"r\" (input), \"r\" (output)\n         : \"memory\", \"cc\", \"xmm0\", \"xmm1\" );\n}\n\n/*\n * Compute decryption round keys from encryption round keys\n */\nvoid aesni_inverse_key( unsigned char *invkey,\n                        const unsigned char *fwdkey, int nr )\n{\n    unsigned char *ik = invkey;\n    const unsigned char *fk = fwdkey + 16 * nr;\n\n    memcpy( ik, fk, 16 );\n\n    for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 )\n        asm( \"movdqu (%0), %%xmm0       \\n\\t\"\n             AESIMC  xmm0_xmm0         \"\\n\\t\"\n             \"movdqu %%xmm0, (%1)       \\n\\t\"\n             :\n             : \"r\" (fk), \"r\" (ik)\n             : \"memory\", \"xmm0\" );\n\n    memcpy( ik, fk, 16 );\n}\n\n/*\n * Key expansion, 128-bit case\n */\nvoid aesni_setkey_enc_128( unsigned char *rk,\n                           const unsigned char *key )\n{\n    asm( \"movdqu (%1), %%xmm0               \\n\\t\" // copy the original key\n         \"movdqu %%xmm0, (%0)               \\n\\t\" // as round key 0\n         \"jmp 2f                            \\n\\t\" // skip auxiliary routine\n\n         /*\n          * Finish generating the next round key.\n          *\n          * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff\n          * with X = rot( sub( r3 ) ) ^ RCON.\n          *\n          * On exit, xmm0 is r7:r6:r5:r4\n          * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3\n          * and those are written to the round key buffer.\n          */\n         \"1:                                \\n\\t\"\n         \"pshufd $0xff, %%xmm1, %%xmm1      \\n\\t\" // X:X:X:X\n         \"pxor %%xmm0, %%xmm1               \\n\\t\" // X+r3:X+r2:X+r1:r4\n         \"pslldq $4, %%xmm0                 \\n\\t\" // r2:r1:r0:0\n         \"pxor %%xmm0, %%xmm1               \\n\\t\" // X+r3+r2:X+r2+r1:r5:r4\n         \"pslldq $4, %%xmm0                 \\n\\t\" // etc\n         \"pxor %%xmm0, %%xmm1               \\n\\t\"\n         \"pslldq $4, %%xmm0                 \\n\\t\"\n         \"pxor %%xmm1, %%xmm0               \\n\\t\" // update xmm0 for next time!\n         \"add $16, %0                       \\n\\t\" // point to next round key\n         \"movdqu %%xmm0, (%0)               \\n\\t\" // write it\n         \"ret                               \\n\\t\"\n\n         /* Main \"loop\" */\n         \"2:                                \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x01        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x02        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x04        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x08        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x10        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x20        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x40        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x80        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x1B        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm0_xmm1 \",0x36        \\n\\tcall 1b \\n\\t\"\n         :\n         : \"r\" (rk), \"r\" (key)\n         : \"memory\", \"cc\", \"0\" );\n}\n\n/*\n * Key expansion, 192-bit case\n */\nvoid aesni_setkey_enc_192( unsigned char *rk,\n                           const unsigned char *key )\n{\n    asm( \"movdqu (%1), %%xmm0   \\n\\t\" // copy original round key\n         \"movdqu %%xmm0, (%0)   \\n\\t\"\n         \"add $16, %0           \\n\\t\"\n         \"movq 16(%1), %%xmm1   \\n\\t\"\n         \"movq %%xmm1, (%0)     \\n\\t\"\n         \"add $8, %0            \\n\\t\"\n         \"jmp 2f                \\n\\t\" // skip auxiliary routine\n\n         /*\n          * Finish generating the next 6 quarter-keys.\n          *\n          * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4\n          * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.\n          *\n          * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10\n          * and those are written to the round key buffer.\n          */\n         \"1:                            \\n\\t\"\n         \"pshufd $0x55, %%xmm2, %%xmm2  \\n\\t\" // X:X:X:X\n         \"pxor %%xmm0, %%xmm2           \\n\\t\" // X+r3:X+r2:X+r1:r4\n         \"pslldq $4, %%xmm0             \\n\\t\" // etc\n         \"pxor %%xmm0, %%xmm2           \\n\\t\"\n         \"pslldq $4, %%xmm0             \\n\\t\"\n         \"pxor %%xmm0, %%xmm2           \\n\\t\"\n         \"pslldq $4, %%xmm0             \\n\\t\"\n         \"pxor %%xmm2, %%xmm0           \\n\\t\" // update xmm0 = r9:r8:r7:r6\n         \"movdqu %%xmm0, (%0)           \\n\\t\"\n         \"add $16, %0                   \\n\\t\"\n         \"pshufd $0xff, %%xmm0, %%xmm2  \\n\\t\" // r9:r9:r9:r9\n         \"pxor %%xmm1, %%xmm2           \\n\\t\" // stuff:stuff:r9+r5:r10\n         \"pslldq $4, %%xmm1             \\n\\t\" // r2:r1:r0:0\n         \"pxor %%xmm2, %%xmm1           \\n\\t\" // xmm1 = stuff:stuff:r11:r10\n         \"movq %%xmm1, (%0)             \\n\\t\"\n         \"add $8, %0                    \\n\\t\"\n         \"ret                           \\n\\t\"\n\n         \"2:                            \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x01    \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x02    \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x04    \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x08    \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x10    \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x20    \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x40    \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x80    \\n\\tcall 1b \\n\\t\"\n\n         :\n         : \"r\" (rk), \"r\" (key)\n         : \"memory\", \"cc\", \"0\" );\n}\n\n/*\n * Key expansion, 256-bit case\n */\nvoid aesni_setkey_enc_256( unsigned char *rk,\n                           const unsigned char *key )\n{\n    asm( \"movdqu (%1), %%xmm0           \\n\\t\"\n         \"movdqu %%xmm0, (%0)           \\n\\t\"\n         \"add $16, %0                   \\n\\t\"\n         \"movdqu 16(%1), %%xmm1         \\n\\t\"\n         \"movdqu %%xmm1, (%0)           \\n\\t\"\n         \"jmp 2f                        \\n\\t\" // skip auxiliary routine\n\n         /*\n          * Finish generating the next two round keys.\n          *\n          * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and\n          * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON\n          *\n          * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12\n          * and those have been written to the output buffer.\n          */\n         \"1:                                \\n\\t\"\n         \"pshufd $0xff, %%xmm2, %%xmm2      \\n\\t\"\n         \"pxor %%xmm0, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm0                 \\n\\t\"\n         \"pxor %%xmm0, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm0                 \\n\\t\"\n         \"pxor %%xmm0, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm0                 \\n\\t\"\n         \"pxor %%xmm2, %%xmm0               \\n\\t\"\n         \"add $16, %0                       \\n\\t\"\n         \"movdqu %%xmm0, (%0)               \\n\\t\"\n\n         /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )\n          * and proceed to generate next round key from there */\n         AESKEYGENA xmm0_xmm2 \",0x00        \\n\\t\"\n         \"pshufd $0xaa, %%xmm2, %%xmm2      \\n\\t\"\n         \"pxor %%xmm1, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm1                 \\n\\t\"\n         \"pxor %%xmm1, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm1                 \\n\\t\"\n         \"pxor %%xmm1, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm1                 \\n\\t\"\n         \"pxor %%xmm2, %%xmm1               \\n\\t\"\n         \"add $16, %0                       \\n\\t\"\n         \"movdqu %%xmm1, (%0)               \\n\\t\"\n         \"ret                               \\n\\t\"\n\n         /*\n          * Main \"loop\" - Generating one more key than necessary,\n          * see definition of aes_context.buf\n          */\n         \"2:                                \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x01        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x02        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x04        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x08        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x10        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x20        \\n\\tcall 1b \\n\\t\"\n         AESKEYGENA xmm1_xmm2 \",0x40        \\n\\tcall 1b \\n\\t\"\n         :\n         : \"r\" (rk), \"r\" (key)\n         : \"memory\", \"cc\", \"0\" );\n}\n\n#endif /* HAVE_AMD64 */\n"
  },
  {
    "path": "lib/aes_acc/aesni.h",
    "content": "/*\n * This file is adapted from PolarSSL 1.3.19 (GPL)\n */\n\n/**\n * \\file aesni.h\n *\n * \\brief AES-NI for hardware AES acceleration on some Intel processors\n *\n *  Copyright (C) 2013, ARM Limited, All Rights Reserved\n *\n *  This file is part of mbed TLS (https://tls.mbed.org)\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License along\n *  with this program; if not, write to the Free Software Foundation, Inc.,\n *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n */\n\n#ifndef UDP2RAW_AESNI_H_\n#define UDP2RAW_AESNI_H_\n\n#ifndef AES_ENCRYPT\n#define AES_ENCRYPT     1\n#endif\n\n#ifndef AES_DECRYPT\n#define AES_DECRYPT     0\n#endif\n\n#if defined(__GNUC__) &&  \\\n    ( defined(__amd64__) || defined(__x86_64__) ) && \\\n    !defined(NO_AESACC)\n#define HAVE_AMD64\n#endif\n\n#if defined(HAVE_AMD64)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          AES-NI features detection routine\n *\n * \\return         1 if CPU has support for AES-NI, 0 otherwise\n */\nint aesni_supported( void );\n\n/**\n * \\brief          AES-NI AES-ECB block en(de)cryption\n *\n * \\param nr       number of rounds\n * \\param rk       AES round keys\n * \\param mode     AES_ENCRYPT or AES_DECRYPT\n * \\param input    16-byte input block\n * \\param output   16-byte output block\n */\nvoid aesni_crypt_ecb( int nr,\n                      unsigned char *rk,\n                      int mode,\n                      const unsigned char input[16],\n                      unsigned char output[16] );\n\n/**\n * \\brief           Compute decryption round keys from encryption round keys\n *\n * \\param invkey    Round keys for the equivalent inverse cipher\n * \\param fwdkey    Original round keys (for encryption)\n * \\param nr        Number of rounds (that is, number of round keys minus one)\n */\nvoid aesni_inverse_key( unsigned char *invkey,\n                        const unsigned char *fwdkey, int nr );\n\n/**\n * \\brief           Perform 128-bit key expansion (for encryption)\n *\n * \\param rk        Destination buffer where the round keys are written\n * \\param key       Encryption key\n */\nvoid aesni_setkey_enc_128( unsigned char *rk,\n                           const unsigned char *key );\n\n/**\n * \\brief           Perform 192-bit key expansion (for encryption)\n *\n * \\param rk        Destination buffer where the round keys are written\n * \\param key       Encryption key\n */\nvoid aesni_setkey_enc_192( unsigned char *rk,\n                           const unsigned char *key );\n\n/**\n * \\brief           Perform 256-bit key expansion (for encryption)\n *\n * \\param rk        Destination buffer where the round keys are written\n * \\param key       Encryption key\n */\nvoid aesni_setkey_enc_256( unsigned char *rk,\n                           const unsigned char *key );\n\n#ifdef __cplusplus\n}\n#endif \n\n#endif /* HAVE_AMD64 */\n\n#endif /* _AESNI_H_ */\n"
  },
  {
    "path": "lib/aes_acc/asm/arm.S",
    "content": "@ Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.\n@\n@ Licensed under the OpenSSL license (the \"License\").  You may not use\n@ this file except in compliance with the License.  You can obtain a copy\n@ in the file LICENSE in the source distribution or at\n@ https://www.openssl.org/source/license.html\n\n\n@ ====================================================================\n@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL\n@ project. The module is, however, dual licensed under OpenSSL and\n@ CRYPTOGAMS licenses depending on where you obtain it. For further\n@ details see http://www.openssl.org/~appro/cryptogams/.\n@ ====================================================================\n\n@ AES for ARMv4\n\n@ January 2007.\n@\n@ Code uses single 1K S-box and is >2 times faster than code generated\n@ by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which\n@ allows to merge logical or arithmetic operation with shift or rotate\n@ in one instruction and emit combined result every cycle. The module\n@ is endian-neutral. The performance is ~42 cycles/byte for 128-bit\n@ key [on single-issue Xscale PXA250 core].\n\n@ May 2007.\n@\n@ AES_set_[en|de]crypt_key is added.\n\n@ July 2010.\n@\n@ Rescheduling for dual-issue pipeline resulted in 12% improvement on\n@ Cortex A8 core and ~25 cycles per byte processed with 128-bit key.\n\n@ February 2011.\n@\n@ Profiler-assisted and platform-specific optimization resulted in 16%\n@ improvement on Cortex A8 core and ~21.5 cycles per byte.\n\n#ifndef __KERNEL__\n# include \"arm_arch.h\"\n#else\n# define __ARM_ARCH__ __LINUX_ARM_ARCH__\n#endif\n\n.text\n#if defined(__thumb2__) && !defined(__APPLE__)\n.syntax\tunified\n.thumb\n#else\n.code\t32\n#undef __thumb2__\n#endif\n\n\n.align\t5\nAES_Te:\n.word\t0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d\n.word\t0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554\n.word\t0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d\n.word\t0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a\n.word\t0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87\n.word\t0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b\n.word\t0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea\n.word\t0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b\n.word\t0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a\n.word\t0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f\n.word\t0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108\n.word\t0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f\n.word\t0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e\n.word\t0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5\n.word\t0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d\n.word\t0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f\n.word\t0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e\n.word\t0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb\n.word\t0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce\n.word\t0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497\n.word\t0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c\n.word\t0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed\n.word\t0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b\n.word\t0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a\n.word\t0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16\n.word\t0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594\n.word\t0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81\n.word\t0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3\n.word\t0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a\n.word\t0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504\n.word\t0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163\n.word\t0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d\n.word\t0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f\n.word\t0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739\n.word\t0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47\n.word\t0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395\n.word\t0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f\n.word\t0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883\n.word\t0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c\n.word\t0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76\n.word\t0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e\n.word\t0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4\n.word\t0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6\n.word\t0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b\n.word\t0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7\n.word\t0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0\n.word\t0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25\n.word\t0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818\n.word\t0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72\n.word\t0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651\n.word\t0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21\n.word\t0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85\n.word\t0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa\n.word\t0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12\n.word\t0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0\n.word\t0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9\n.word\t0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133\n.word\t0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7\n.word\t0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920\n.word\t0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a\n.word\t0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17\n.word\t0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8\n.word\t0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11\n.word\t0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a\n@ Te4[256]\n.byte\t0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5\n.byte\t0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76\n.byte\t0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0\n.byte\t0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0\n.byte\t0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc\n.byte\t0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15\n.byte\t0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a\n.byte\t0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75\n.byte\t0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0\n.byte\t0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84\n.byte\t0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b\n.byte\t0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf\n.byte\t0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85\n.byte\t0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8\n.byte\t0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5\n.byte\t0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2\n.byte\t0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17\n.byte\t0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73\n.byte\t0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88\n.byte\t0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb\n.byte\t0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c\n.byte\t0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79\n.byte\t0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9\n.byte\t0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08\n.byte\t0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6\n.byte\t0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a\n.byte\t0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e\n.byte\t0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e\n.byte\t0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94\n.byte\t0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf\n.byte\t0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68\n.byte\t0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16\n@ rcon[]\n.word\t0x01000000, 0x02000000, 0x04000000, 0x08000000\n.word\t0x10000000, 0x20000000, 0x40000000, 0x80000000\n.word\t0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0\n\n\n@ void AES_encrypt(const unsigned char *in, unsigned char *out,\n@ \t\t const AES_KEY *key) {\n.globl\tAES_encrypt\n\n.align\t5\nAES_encrypt:\n#ifndef\t__thumb2__\n\tsub\tr3,pc,#8\t\t@ AES_encrypt\n#else\n\tadr\tr3,AES_encrypt\n#endif\n\tstmdb\tsp!,{r1,r4-r12,lr}\n#ifdef\t__APPLE__\n\tadr\tr10,AES_Te\n#else\n\tsub\tr10,r3,#AES_encrypt-AES_Te\t@ Te\n#endif\n\tmov\tr12,r0\t\t@ inp\n\tmov\tr11,r2\n#if __ARM_ARCH__<7\n\tldrb\tr0,[r12,#3]\t@ load input data in endian-neutral\n\tldrb\tr4,[r12,#2]\t@ manner...\n\tldrb\tr5,[r12,#1]\n\tldrb\tr6,[r12,#0]\n\torr\tr0,r0,r4,lsl#8\n\tldrb\tr1,[r12,#7]\n\torr\tr0,r0,r5,lsl#16\n\tldrb\tr4,[r12,#6]\n\torr\tr0,r0,r6,lsl#24\n\tldrb\tr5,[r12,#5]\n\tldrb\tr6,[r12,#4]\n\torr\tr1,r1,r4,lsl#8\n\tldrb\tr2,[r12,#11]\n\torr\tr1,r1,r5,lsl#16\n\tldrb\tr4,[r12,#10]\n\torr\tr1,r1,r6,lsl#24\n\tldrb\tr5,[r12,#9]\n\tldrb\tr6,[r12,#8]\n\torr\tr2,r2,r4,lsl#8\n\tldrb\tr3,[r12,#15]\n\torr\tr2,r2,r5,lsl#16\n\tldrb\tr4,[r12,#14]\n\torr\tr2,r2,r6,lsl#24\n\tldrb\tr5,[r12,#13]\n\tldrb\tr6,[r12,#12]\n\torr\tr3,r3,r4,lsl#8\n\torr\tr3,r3,r5,lsl#16\n\torr\tr3,r3,r6,lsl#24\n#else\n\tldr\tr0,[r12,#0]\n\tldr\tr1,[r12,#4]\n\tldr\tr2,[r12,#8]\n\tldr\tr3,[r12,#12]\n#ifdef __ARMEL__\n\trev\tr0,r0\n\trev\tr1,r1\n\trev\tr2,r2\n\trev\tr3,r3\n#endif\n#endif\n\tbl\t_armv4_AES_encrypt\n\n\tldr\tr12,[sp],#4\t\t@ pop out\n#if __ARM_ARCH__>=7\n#ifdef __ARMEL__\n\trev\tr0,r0\n\trev\tr1,r1\n\trev\tr2,r2\n\trev\tr3,r3\n#endif\n\tstr\tr0,[r12,#0]\n\tstr\tr1,[r12,#4]\n\tstr\tr2,[r12,#8]\n\tstr\tr3,[r12,#12]\n#else\n\tmov\tr4,r0,lsr#24\t\t@ write output in endian-neutral\n\tmov\tr5,r0,lsr#16\t\t@ manner...\n\tmov\tr6,r0,lsr#8\n\tstrb\tr4,[r12,#0]\n\tstrb\tr5,[r12,#1]\n\tmov\tr4,r1,lsr#24\n\tstrb\tr6,[r12,#2]\n\tmov\tr5,r1,lsr#16\n\tstrb\tr0,[r12,#3]\n\tmov\tr6,r1,lsr#8\n\tstrb\tr4,[r12,#4]\n\tstrb\tr5,[r12,#5]\n\tmov\tr4,r2,lsr#24\n\tstrb\tr6,[r12,#6]\n\tmov\tr5,r2,lsr#16\n\tstrb\tr1,[r12,#7]\n\tmov\tr6,r2,lsr#8\n\tstrb\tr4,[r12,#8]\n\tstrb\tr5,[r12,#9]\n\tmov\tr4,r3,lsr#24\n\tstrb\tr6,[r12,#10]\n\tmov\tr5,r3,lsr#16\n\tstrb\tr2,[r12,#11]\n\tmov\tr6,r3,lsr#8\n\tstrb\tr4,[r12,#12]\n\tstrb\tr5,[r12,#13]\n\tstrb\tr6,[r12,#14]\n\tstrb\tr3,[r12,#15]\n#endif\n#if __ARM_ARCH__>=5\n\tldmia\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}\n#else\n\tldmia\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}\n\ttst\tlr,#1\n\tmoveq\tpc,lr\t\t\t@ be binary compatible with V4, yet\n.word\t0xe12fff1e\t\t\t@ interoperable with Thumb ISA:-)\n#endif\n\n\n\n.align\t2\n_armv4_AES_encrypt:\n\tstr\tlr,[sp,#-4]!\t\t@ push lr\n\tldmia\tr11!,{r4,r5,r6,r7}\n\teor\tr0,r0,r4\n\tldr\tr12,[r11,#240-16]\n\teor\tr1,r1,r5\n\teor\tr2,r2,r6\n\teor\tr3,r3,r7\n\tsub\tr12,r12,#1\n\tmov\tlr,#255\n\n\tand\tr7,lr,r0\n\tand\tr8,lr,r0,lsr#8\n\tand\tr9,lr,r0,lsr#16\n\tmov\tr0,r0,lsr#24\nLenc_loop:\n\tldr\tr4,[r10,r7,lsl#2]\t@ Te3[s0>>0]\n\tand\tr7,lr,r1,lsr#16\t@ i0\n\tldr\tr5,[r10,r8,lsl#2]\t@ Te2[s0>>8]\n\tand\tr8,lr,r1\n\tldr\tr6,[r10,r9,lsl#2]\t@ Te1[s0>>16]\n\tand\tr9,lr,r1,lsr#8\n\tldr\tr0,[r10,r0,lsl#2]\t@ Te0[s0>>24]\n\tmov\tr1,r1,lsr#24\n\n\tldr\tr7,[r10,r7,lsl#2]\t@ Te1[s1>>16]\n\tldr\tr8,[r10,r8,lsl#2]\t@ Te3[s1>>0]\n\tldr\tr9,[r10,r9,lsl#2]\t@ Te2[s1>>8]\n\teor\tr0,r0,r7,ror#8\n\tldr\tr1,[r10,r1,lsl#2]\t@ Te0[s1>>24]\n\tand\tr7,lr,r2,lsr#8\t@ i0\n\teor\tr5,r5,r8,ror#8\n\tand\tr8,lr,r2,lsr#16\t@ i1\n\teor\tr6,r6,r9,ror#8\n\tand\tr9,lr,r2\n\tldr\tr7,[r10,r7,lsl#2]\t@ Te2[s2>>8]\n\teor\tr1,r1,r4,ror#24\n\tldr\tr8,[r10,r8,lsl#2]\t@ Te1[s2>>16]\n\tmov\tr2,r2,lsr#24\n\n\tldr\tr9,[r10,r9,lsl#2]\t@ Te3[s2>>0]\n\teor\tr0,r0,r7,ror#16\n\tldr\tr2,[r10,r2,lsl#2]\t@ Te0[s2>>24]\n\tand\tr7,lr,r3\t\t@ i0\n\teor\tr1,r1,r8,ror#8\n\tand\tr8,lr,r3,lsr#8\t@ i1\n\teor\tr6,r6,r9,ror#16\n\tand\tr9,lr,r3,lsr#16\t@ i2\n\tldr\tr7,[r10,r7,lsl#2]\t@ Te3[s3>>0]\n\teor\tr2,r2,r5,ror#16\n\tldr\tr8,[r10,r8,lsl#2]\t@ Te2[s3>>8]\n\tmov\tr3,r3,lsr#24\n\n\tldr\tr9,[r10,r9,lsl#2]\t@ Te1[s3>>16]\n\teor\tr0,r0,r7,ror#24\n\tldr\tr7,[r11],#16\n\teor\tr1,r1,r8,ror#16\n\tldr\tr3,[r10,r3,lsl#2]\t@ Te0[s3>>24]\n\teor\tr2,r2,r9,ror#8\n\tldr\tr4,[r11,#-12]\n\teor\tr3,r3,r6,ror#8\n\n\tldr\tr5,[r11,#-8]\n\teor\tr0,r0,r7\n\tldr\tr6,[r11,#-4]\n\tand\tr7,lr,r0\n\teor\tr1,r1,r4\n\tand\tr8,lr,r0,lsr#8\n\teor\tr2,r2,r5\n\tand\tr9,lr,r0,lsr#16\n\teor\tr3,r3,r6\n\tmov\tr0,r0,lsr#24\n\n\tsubs\tr12,r12,#1\n\tbne\tLenc_loop\n\n\tadd\tr10,r10,#2\n\n\tldrb\tr4,[r10,r7,lsl#2]\t@ Te4[s0>>0]\n\tand\tr7,lr,r1,lsr#16\t@ i0\n\tldrb\tr5,[r10,r8,lsl#2]\t@ Te4[s0>>8]\n\tand\tr8,lr,r1\n\tldrb\tr6,[r10,r9,lsl#2]\t@ Te4[s0>>16]\n\tand\tr9,lr,r1,lsr#8\n\tldrb\tr0,[r10,r0,lsl#2]\t@ Te4[s0>>24]\n\tmov\tr1,r1,lsr#24\n\n\tldrb\tr7,[r10,r7,lsl#2]\t@ Te4[s1>>16]\n\tldrb\tr8,[r10,r8,lsl#2]\t@ Te4[s1>>0]\n\tldrb\tr9,[r10,r9,lsl#2]\t@ Te4[s1>>8]\n\teor\tr0,r7,r0,lsl#8\n\tldrb\tr1,[r10,r1,lsl#2]\t@ Te4[s1>>24]\n\tand\tr7,lr,r2,lsr#8\t@ i0\n\teor\tr5,r8,r5,lsl#8\n\tand\tr8,lr,r2,lsr#16\t@ i1\n\teor\tr6,r9,r6,lsl#8\n\tand\tr9,lr,r2\n\tldrb\tr7,[r10,r7,lsl#2]\t@ Te4[s2>>8]\n\teor\tr1,r4,r1,lsl#24\n\tldrb\tr8,[r10,r8,lsl#2]\t@ Te4[s2>>16]\n\tmov\tr2,r2,lsr#24\n\n\tldrb\tr9,[r10,r9,lsl#2]\t@ Te4[s2>>0]\n\teor\tr0,r7,r0,lsl#8\n\tldrb\tr2,[r10,r2,lsl#2]\t@ Te4[s2>>24]\n\tand\tr7,lr,r3\t\t@ i0\n\teor\tr1,r1,r8,lsl#16\n\tand\tr8,lr,r3,lsr#8\t@ i1\n\teor\tr6,r9,r6,lsl#8\n\tand\tr9,lr,r3,lsr#16\t@ i2\n\tldrb\tr7,[r10,r7,lsl#2]\t@ Te4[s3>>0]\n\teor\tr2,r5,r2,lsl#24\n\tldrb\tr8,[r10,r8,lsl#2]\t@ Te4[s3>>8]\n\tmov\tr3,r3,lsr#24\n\n\tldrb\tr9,[r10,r9,lsl#2]\t@ Te4[s3>>16]\n\teor\tr0,r7,r0,lsl#8\n\tldr\tr7,[r11,#0]\n\tldrb\tr3,[r10,r3,lsl#2]\t@ Te4[s3>>24]\n\teor\tr1,r1,r8,lsl#8\n\tldr\tr4,[r11,#4]\n\teor\tr2,r2,r9,lsl#16\n\tldr\tr5,[r11,#8]\n\teor\tr3,r6,r3,lsl#24\n\tldr\tr6,[r11,#12]\n\n\teor\tr0,r0,r7\n\teor\tr1,r1,r4\n\teor\tr2,r2,r5\n\teor\tr3,r3,r6\n\n\tsub\tr10,r10,#2\n\tldr\tpc,[sp],#4\t\t@ pop and return\n\n\n.globl\tAES_set_encrypt_key\n\n.align\t5\nAES_set_encrypt_key:\n_armv4_AES_set_encrypt_key:\n#ifndef\t__thumb2__\n\tsub\tr3,pc,#8\t\t@ AES_set_encrypt_key\n#else\n\tadr\tr3,AES_set_encrypt_key\n#endif\n\tteq\tr0,#0\n#ifdef\t__thumb2__\n\titt\teq\t\t\t@ Thumb2 thing, sanity check in ARM\n#endif\n\tmoveq\tr0,#-1\n\tbeq\tLabrt\n\tteq\tr2,#0\n#ifdef\t__thumb2__\n\titt\teq\t\t\t@ Thumb2 thing, sanity check in ARM\n#endif\n\tmoveq\tr0,#-1\n\tbeq\tLabrt\n\n\tteq\tr1,#128\n\tbeq\tLok\n\tteq\tr1,#192\n\tbeq\tLok\n\tteq\tr1,#256\n#ifdef\t__thumb2__\n\titt\tne\t\t\t@ Thumb2 thing, sanity check in ARM\n#endif\n\tmovne\tr0,#-1\n\tbne\tLabrt\n\nLok:\tstmdb\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}\n\tmov\tr12,r0\t\t@ inp\n\tmov\tlr,r1\t\t\t@ bits\n\tmov\tr11,r2\t\t\t@ key\n\n#ifdef\t__APPLE__\n\tadr\tr10,AES_Te+1024\t\t\t\t@ Te4\n#else\n\tsub\tr10,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024\t@ Te4\n#endif\n\n#if __ARM_ARCH__<7\n\tldrb\tr0,[r12,#3]\t@ load input data in endian-neutral\n\tldrb\tr4,[r12,#2]\t@ manner...\n\tldrb\tr5,[r12,#1]\n\tldrb\tr6,[r12,#0]\n\torr\tr0,r0,r4,lsl#8\n\tldrb\tr1,[r12,#7]\n\torr\tr0,r0,r5,lsl#16\n\tldrb\tr4,[r12,#6]\n\torr\tr0,r0,r6,lsl#24\n\tldrb\tr5,[r12,#5]\n\tldrb\tr6,[r12,#4]\n\torr\tr1,r1,r4,lsl#8\n\tldrb\tr2,[r12,#11]\n\torr\tr1,r1,r5,lsl#16\n\tldrb\tr4,[r12,#10]\n\torr\tr1,r1,r6,lsl#24\n\tldrb\tr5,[r12,#9]\n\tldrb\tr6,[r12,#8]\n\torr\tr2,r2,r4,lsl#8\n\tldrb\tr3,[r12,#15]\n\torr\tr2,r2,r5,lsl#16\n\tldrb\tr4,[r12,#14]\n\torr\tr2,r2,r6,lsl#24\n\tldrb\tr5,[r12,#13]\n\tldrb\tr6,[r12,#12]\n\torr\tr3,r3,r4,lsl#8\n\tstr\tr0,[r11],#16\n\torr\tr3,r3,r5,lsl#16\n\tstr\tr1,[r11,#-12]\n\torr\tr3,r3,r6,lsl#24\n\tstr\tr2,[r11,#-8]\n\tstr\tr3,[r11,#-4]\n#else\n\tldr\tr0,[r12,#0]\n\tldr\tr1,[r12,#4]\n\tldr\tr2,[r12,#8]\n\tldr\tr3,[r12,#12]\n#ifdef __ARMEL__\n\trev\tr0,r0\n\trev\tr1,r1\n\trev\tr2,r2\n\trev\tr3,r3\n#endif\n\tstr\tr0,[r11],#16\n\tstr\tr1,[r11,#-12]\n\tstr\tr2,[r11,#-8]\n\tstr\tr3,[r11,#-4]\n#endif\n\n\tteq\tlr,#128\n\tbne\tLnot128\n\tmov\tr12,#10\n\tstr\tr12,[r11,#240-16]\n\tadd\tr6,r10,#256\t\t\t@ rcon\n\tmov\tlr,#255\n\nL128_loop:\n\tand\tr5,lr,r3,lsr#24\n\tand\tr7,lr,r3,lsr#16\n\tldrb\tr5,[r10,r5]\n\tand\tr8,lr,r3,lsr#8\n\tldrb\tr7,[r10,r7]\n\tand\tr9,lr,r3\n\tldrb\tr8,[r10,r8]\n\torr\tr5,r5,r7,lsl#24\n\tldrb\tr9,[r10,r9]\n\torr\tr5,r5,r8,lsl#16\n\tldr\tr4,[r6],#4\t\t\t@ rcon[i++]\n\torr\tr5,r5,r9,lsl#8\n\teor\tr5,r5,r4\n\teor\tr0,r0,r5\t\t\t@ rk[4]=rk[0]^...\n\teor\tr1,r1,r0\t\t\t@ rk[5]=rk[1]^rk[4]\n\tstr\tr0,[r11],#16\n\teor\tr2,r2,r1\t\t\t@ rk[6]=rk[2]^rk[5]\n\tstr\tr1,[r11,#-12]\n\teor\tr3,r3,r2\t\t\t@ rk[7]=rk[3]^rk[6]\n\tstr\tr2,[r11,#-8]\n\tsubs\tr12,r12,#1\n\tstr\tr3,[r11,#-4]\n\tbne\tL128_loop\n\tsub\tr2,r11,#176\n\tb\tLdone\n\nLnot128:\n#if __ARM_ARCH__<7\n\tldrb\tr8,[r12,#19]\n\tldrb\tr4,[r12,#18]\n\tldrb\tr5,[r12,#17]\n\tldrb\tr6,[r12,#16]\n\torr\tr8,r8,r4,lsl#8\n\tldrb\tr9,[r12,#23]\n\torr\tr8,r8,r5,lsl#16\n\tldrb\tr4,[r12,#22]\n\torr\tr8,r8,r6,lsl#24\n\tldrb\tr5,[r12,#21]\n\tldrb\tr6,[r12,#20]\n\torr\tr9,r9,r4,lsl#8\n\torr\tr9,r9,r5,lsl#16\n\tstr\tr8,[r11],#8\n\torr\tr9,r9,r6,lsl#24\n\tstr\tr9,[r11,#-4]\n#else\n\tldr\tr8,[r12,#16]\n\tldr\tr9,[r12,#20]\n#ifdef __ARMEL__\n\trev\tr8,r8\n\trev\tr9,r9\n#endif\n\tstr\tr8,[r11],#8\n\tstr\tr9,[r11,#-4]\n#endif\n\n\tteq\tlr,#192\n\tbne\tLnot192\n\tmov\tr12,#12\n\tstr\tr12,[r11,#240-24]\n\tadd\tr6,r10,#256\t\t\t@ rcon\n\tmov\tlr,#255\n\tmov\tr12,#8\n\nL192_loop:\n\tand\tr5,lr,r9,lsr#24\n\tand\tr7,lr,r9,lsr#16\n\tldrb\tr5,[r10,r5]\n\tand\tr8,lr,r9,lsr#8\n\tldrb\tr7,[r10,r7]\n\tand\tr9,lr,r9\n\tldrb\tr8,[r10,r8]\n\torr\tr5,r5,r7,lsl#24\n\tldrb\tr9,[r10,r9]\n\torr\tr5,r5,r8,lsl#16\n\tldr\tr4,[r6],#4\t\t\t@ rcon[i++]\n\torr\tr5,r5,r9,lsl#8\n\teor\tr9,r5,r4\n\teor\tr0,r0,r9\t\t\t@ rk[6]=rk[0]^...\n\teor\tr1,r1,r0\t\t\t@ rk[7]=rk[1]^rk[6]\n\tstr\tr0,[r11],#24\n\teor\tr2,r2,r1\t\t\t@ rk[8]=rk[2]^rk[7]\n\tstr\tr1,[r11,#-20]\n\teor\tr3,r3,r2\t\t\t@ rk[9]=rk[3]^rk[8]\n\tstr\tr2,[r11,#-16]\n\tsubs\tr12,r12,#1\n\tstr\tr3,[r11,#-12]\n#ifdef\t__thumb2__\n\titt\teq\t\t\t\t@ Thumb2 thing, sanity check in ARM\n#endif\n\tsubeq\tr2,r11,#216\n\tbeq\tLdone\n\n\tldr\tr7,[r11,#-32]\n\tldr\tr8,[r11,#-28]\n\teor\tr7,r7,r3\t\t\t@ rk[10]=rk[4]^rk[9]\n\teor\tr9,r8,r7\t\t\t@ rk[11]=rk[5]^rk[10]\n\tstr\tr7,[r11,#-8]\n\tstr\tr9,[r11,#-4]\n\tb\tL192_loop\n\nLnot192:\n#if __ARM_ARCH__<7\n\tldrb\tr8,[r12,#27]\n\tldrb\tr4,[r12,#26]\n\tldrb\tr5,[r12,#25]\n\tldrb\tr6,[r12,#24]\n\torr\tr8,r8,r4,lsl#8\n\tldrb\tr9,[r12,#31]\n\torr\tr8,r8,r5,lsl#16\n\tldrb\tr4,[r12,#30]\n\torr\tr8,r8,r6,lsl#24\n\tldrb\tr5,[r12,#29]\n\tldrb\tr6,[r12,#28]\n\torr\tr9,r9,r4,lsl#8\n\torr\tr9,r9,r5,lsl#16\n\tstr\tr8,[r11],#8\n\torr\tr9,r9,r6,lsl#24\n\tstr\tr9,[r11,#-4]\n#else\n\tldr\tr8,[r12,#24]\n\tldr\tr9,[r12,#28]\n#ifdef __ARMEL__\n\trev\tr8,r8\n\trev\tr9,r9\n#endif\n\tstr\tr8,[r11],#8\n\tstr\tr9,[r11,#-4]\n#endif\n\n\tmov\tr12,#14\n\tstr\tr12,[r11,#240-32]\n\tadd\tr6,r10,#256\t\t\t@ rcon\n\tmov\tlr,#255\n\tmov\tr12,#7\n\nL256_loop:\n\tand\tr5,lr,r9,lsr#24\n\tand\tr7,lr,r9,lsr#16\n\tldrb\tr5,[r10,r5]\n\tand\tr8,lr,r9,lsr#8\n\tldrb\tr7,[r10,r7]\n\tand\tr9,lr,r9\n\tldrb\tr8,[r10,r8]\n\torr\tr5,r5,r7,lsl#24\n\tldrb\tr9,[r10,r9]\n\torr\tr5,r5,r8,lsl#16\n\tldr\tr4,[r6],#4\t\t\t@ rcon[i++]\n\torr\tr5,r5,r9,lsl#8\n\teor\tr9,r5,r4\n\teor\tr0,r0,r9\t\t\t@ rk[8]=rk[0]^...\n\teor\tr1,r1,r0\t\t\t@ rk[9]=rk[1]^rk[8]\n\tstr\tr0,[r11],#32\n\teor\tr2,r2,r1\t\t\t@ rk[10]=rk[2]^rk[9]\n\tstr\tr1,[r11,#-28]\n\teor\tr3,r3,r2\t\t\t@ rk[11]=rk[3]^rk[10]\n\tstr\tr2,[r11,#-24]\n\tsubs\tr12,r12,#1\n\tstr\tr3,[r11,#-20]\n#ifdef\t__thumb2__\n\titt\teq\t\t\t\t@ Thumb2 thing, sanity check in ARM\n#endif\n\tsubeq\tr2,r11,#256\n\tbeq\tLdone\n\n\tand\tr5,lr,r3\n\tand\tr7,lr,r3,lsr#8\n\tldrb\tr5,[r10,r5]\n\tand\tr8,lr,r3,lsr#16\n\tldrb\tr7,[r10,r7]\n\tand\tr9,lr,r3,lsr#24\n\tldrb\tr8,[r10,r8]\n\torr\tr5,r5,r7,lsl#8\n\tldrb\tr9,[r10,r9]\n\torr\tr5,r5,r8,lsl#16\n\tldr\tr4,[r11,#-48]\n\torr\tr5,r5,r9,lsl#24\n\n\tldr\tr7,[r11,#-44]\n\tldr\tr8,[r11,#-40]\n\teor\tr4,r4,r5\t\t\t@ rk[12]=rk[4]^...\n\tldr\tr9,[r11,#-36]\n\teor\tr7,r7,r4\t\t\t@ rk[13]=rk[5]^rk[12]\n\tstr\tr4,[r11,#-16]\n\teor\tr8,r8,r7\t\t\t@ rk[14]=rk[6]^rk[13]\n\tstr\tr7,[r11,#-12]\n\teor\tr9,r9,r8\t\t\t@ rk[15]=rk[7]^rk[14]\n\tstr\tr8,[r11,#-8]\n\tstr\tr9,[r11,#-4]\n\tb\tL256_loop\n\n.align\t2\nLdone:\tmov\tr0,#0\n\tldmia\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}\nLabrt:\n#if __ARM_ARCH__>=5\n\tbx\tlr\t\t\t\t@ .word\t0xe12fff1e\n#else\n\ttst\tlr,#1\n\tmoveq\tpc,lr\t\t\t@ be binary compatible with V4, yet\n.word\t0xe12fff1e\t\t\t@ interoperable with Thumb ISA:-)\n#endif\n\n\n.globl\tAES_set_decrypt_key\n\n.align\t5\nAES_set_decrypt_key:\n\tstr\tlr,[sp,#-4]!            @ push lr\n\tbl\t_armv4_AES_set_encrypt_key\n\tteq\tr0,#0\n\tldr\tlr,[sp],#4              @ pop lr\n\tbne\tLabrt\n\n\tmov\tr0,r2\t\t\t@ AES_set_encrypt_key preserves r2,\n\tmov\tr1,r2\t\t\t@ which is AES_KEY *key\n\tb\t_armv4_AES_set_enc2dec_key\n\n\n@ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out)\n.globl\tAES_set_enc2dec_key\n\n.align\t5\nAES_set_enc2dec_key:\n_armv4_AES_set_enc2dec_key:\n\tstmdb\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}\n\n\tldr\tr12,[r0,#240]\n\tmov\tr7,r0\t\t\t@ input\n\tadd\tr8,r0,r12,lsl#4\n\tmov\tr11,r1\t\t\t@ output\n\tadd\tr10,r1,r12,lsl#4\n\tstr\tr12,[r1,#240]\n\nLinv:\tldr\tr0,[r7],#16\n\tldr\tr1,[r7,#-12]\n\tldr\tr2,[r7,#-8]\n\tldr\tr3,[r7,#-4]\n\tldr\tr4,[r8],#-16\n\tldr\tr5,[r8,#16+4]\n\tldr\tr6,[r8,#16+8]\n\tldr\tr9,[r8,#16+12]\n\tstr\tr0,[r10],#-16\n\tstr\tr1,[r10,#16+4]\n\tstr\tr2,[r10,#16+8]\n\tstr\tr3,[r10,#16+12]\n\tstr\tr4,[r11],#16\n\tstr\tr5,[r11,#-12]\n\tstr\tr6,[r11,#-8]\n\tstr\tr9,[r11,#-4]\n\tteq\tr7,r8\n\tbne\tLinv\n\n\tldr\tr0,[r7]\n\tldr\tr1,[r7,#4]\n\tldr\tr2,[r7,#8]\n\tldr\tr3,[r7,#12]\n\tstr\tr0,[r11]\n\tstr\tr1,[r11,#4]\n\tstr\tr2,[r11,#8]\n\tstr\tr3,[r11,#12]\n\tsub\tr11,r11,r12,lsl#3\n\tldr\tr0,[r11,#16]!\t\t@ prefetch tp1\n\tmov\tr7,#0x80\n\tmov\tr8,#0x1b\n\torr\tr7,r7,#0x8000\n\torr\tr8,r8,#0x1b00\n\torr\tr7,r7,r7,lsl#16\n\torr\tr8,r8,r8,lsl#16\n\tsub\tr12,r12,#1\n\tmvn\tr9,r7\n\tmov\tr12,r12,lsl#2\t@ (rounds-1)*4\n\nLmix:\tand\tr4,r0,r7\n\tand\tr1,r0,r9\n\tsub\tr4,r4,r4,lsr#7\n\tand\tr4,r4,r8\n\teor\tr1,r4,r1,lsl#1\t@ tp2\n\n\tand\tr4,r1,r7\n\tand\tr2,r1,r9\n\tsub\tr4,r4,r4,lsr#7\n\tand\tr4,r4,r8\n\teor\tr2,r4,r2,lsl#1\t@ tp4\n\n\tand\tr4,r2,r7\n\tand\tr3,r2,r9\n\tsub\tr4,r4,r4,lsr#7\n\tand\tr4,r4,r8\n\teor\tr3,r4,r3,lsl#1\t@ tp8\n\n\teor\tr4,r1,r2\n\teor\tr5,r0,r3\t\t@ tp9\n\teor\tr4,r4,r3\t\t@ tpe\n\teor\tr4,r4,r1,ror#24\n\teor\tr4,r4,r5,ror#24\t@ ^= ROTATE(tpb=tp9^tp2,8)\n\teor\tr4,r4,r2,ror#16\n\teor\tr4,r4,r5,ror#16\t@ ^= ROTATE(tpd=tp9^tp4,16)\n\teor\tr4,r4,r5,ror#8\t@ ^= ROTATE(tp9,24)\n\n\tldr\tr0,[r11,#4]\t\t@ prefetch tp1\n\tstr\tr4,[r11],#4\n\tsubs\tr12,r12,#1\n\tbne\tLmix\n\n\tmov\tr0,#0\n#if __ARM_ARCH__>=5\n\tldmia\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}\n#else\n\tldmia\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}\n\ttst\tlr,#1\n\tmoveq\tpc,lr\t\t\t@ be binary compatible with V4, yet\n.word\t0xe12fff1e\t\t\t@ interoperable with Thumb ISA:-)\n#endif\n\n\n\n.align\t5\nAES_Td:\n.word\t0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96\n.word\t0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393\n.word\t0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25\n.word\t0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f\n.word\t0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1\n.word\t0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6\n.word\t0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da\n.word\t0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844\n.word\t0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd\n.word\t0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4\n.word\t0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45\n.word\t0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94\n.word\t0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7\n.word\t0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a\n.word\t0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5\n.word\t0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c\n.word\t0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1\n.word\t0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a\n.word\t0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75\n.word\t0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051\n.word\t0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46\n.word\t0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff\n.word\t0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77\n.word\t0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb\n.word\t0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000\n.word\t0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e\n.word\t0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927\n.word\t0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a\n.word\t0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e\n.word\t0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16\n.word\t0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d\n.word\t0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8\n.word\t0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd\n.word\t0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34\n.word\t0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163\n.word\t0xd731dcca, 0x42638510, 0x13972240, 0x84c61120\n.word\t0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d\n.word\t0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0\n.word\t0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422\n.word\t0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef\n.word\t0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36\n.word\t0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4\n.word\t0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662\n.word\t0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5\n.word\t0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3\n.word\t0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b\n.word\t0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8\n.word\t0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6\n.word\t0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6\n.word\t0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0\n.word\t0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815\n.word\t0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f\n.word\t0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df\n.word\t0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f\n.word\t0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e\n.word\t0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713\n.word\t0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89\n.word\t0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c\n.word\t0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf\n.word\t0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86\n.word\t0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f\n.word\t0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541\n.word\t0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190\n.word\t0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742\n@ Td4[256]\n.byte\t0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38\n.byte\t0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb\n.byte\t0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87\n.byte\t0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb\n.byte\t0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d\n.byte\t0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e\n.byte\t0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2\n.byte\t0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25\n.byte\t0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16\n.byte\t0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92\n.byte\t0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda\n.byte\t0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84\n.byte\t0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a\n.byte\t0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06\n.byte\t0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02\n.byte\t0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b\n.byte\t0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea\n.byte\t0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73\n.byte\t0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85\n.byte\t0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e\n.byte\t0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89\n.byte\t0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b\n.byte\t0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20\n.byte\t0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4\n.byte\t0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31\n.byte\t0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f\n.byte\t0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d\n.byte\t0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef\n.byte\t0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0\n.byte\t0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61\n.byte\t0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26\n.byte\t0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d\n\n\n@ void AES_decrypt(const unsigned char *in, unsigned char *out,\n@ \t\t const AES_KEY *key) {\n.globl\tAES_decrypt\n\n.align\t5\nAES_decrypt:\n#ifndef\t__thumb2__\n\tsub\tr3,pc,#8\t\t@ AES_decrypt\n#else\n\tadr\tr3,AES_decrypt\n#endif\n\tstmdb\tsp!,{r1,r4-r12,lr}\n#ifdef\t__APPLE__\n\tadr\tr10,AES_Td\n#else\n\tsub\tr10,r3,#AES_decrypt-AES_Td\t@ Td\n#endif\n\tmov\tr12,r0\t\t@ inp\n\tmov\tr11,r2\n#if __ARM_ARCH__<7\n\tldrb\tr0,[r12,#3]\t@ load input data in endian-neutral\n\tldrb\tr4,[r12,#2]\t@ manner...\n\tldrb\tr5,[r12,#1]\n\tldrb\tr6,[r12,#0]\n\torr\tr0,r0,r4,lsl#8\n\tldrb\tr1,[r12,#7]\n\torr\tr0,r0,r5,lsl#16\n\tldrb\tr4,[r12,#6]\n\torr\tr0,r0,r6,lsl#24\n\tldrb\tr5,[r12,#5]\n\tldrb\tr6,[r12,#4]\n\torr\tr1,r1,r4,lsl#8\n\tldrb\tr2,[r12,#11]\n\torr\tr1,r1,r5,lsl#16\n\tldrb\tr4,[r12,#10]\n\torr\tr1,r1,r6,lsl#24\n\tldrb\tr5,[r12,#9]\n\tldrb\tr6,[r12,#8]\n\torr\tr2,r2,r4,lsl#8\n\tldrb\tr3,[r12,#15]\n\torr\tr2,r2,r5,lsl#16\n\tldrb\tr4,[r12,#14]\n\torr\tr2,r2,r6,lsl#24\n\tldrb\tr5,[r12,#13]\n\tldrb\tr6,[r12,#12]\n\torr\tr3,r3,r4,lsl#8\n\torr\tr3,r3,r5,lsl#16\n\torr\tr3,r3,r6,lsl#24\n#else\n\tldr\tr0,[r12,#0]\n\tldr\tr1,[r12,#4]\n\tldr\tr2,[r12,#8]\n\tldr\tr3,[r12,#12]\n#ifdef __ARMEL__\n\trev\tr0,r0\n\trev\tr1,r1\n\trev\tr2,r2\n\trev\tr3,r3\n#endif\n#endif\n\tbl\t_armv4_AES_decrypt\n\n\tldr\tr12,[sp],#4\t\t@ pop out\n#if __ARM_ARCH__>=7\n#ifdef __ARMEL__\n\trev\tr0,r0\n\trev\tr1,r1\n\trev\tr2,r2\n\trev\tr3,r3\n#endif\n\tstr\tr0,[r12,#0]\n\tstr\tr1,[r12,#4]\n\tstr\tr2,[r12,#8]\n\tstr\tr3,[r12,#12]\n#else\n\tmov\tr4,r0,lsr#24\t\t@ write output in endian-neutral\n\tmov\tr5,r0,lsr#16\t\t@ manner...\n\tmov\tr6,r0,lsr#8\n\tstrb\tr4,[r12,#0]\n\tstrb\tr5,[r12,#1]\n\tmov\tr4,r1,lsr#24\n\tstrb\tr6,[r12,#2]\n\tmov\tr5,r1,lsr#16\n\tstrb\tr0,[r12,#3]\n\tmov\tr6,r1,lsr#8\n\tstrb\tr4,[r12,#4]\n\tstrb\tr5,[r12,#5]\n\tmov\tr4,r2,lsr#24\n\tstrb\tr6,[r12,#6]\n\tmov\tr5,r2,lsr#16\n\tstrb\tr1,[r12,#7]\n\tmov\tr6,r2,lsr#8\n\tstrb\tr4,[r12,#8]\n\tstrb\tr5,[r12,#9]\n\tmov\tr4,r3,lsr#24\n\tstrb\tr6,[r12,#10]\n\tmov\tr5,r3,lsr#16\n\tstrb\tr2,[r12,#11]\n\tmov\tr6,r3,lsr#8\n\tstrb\tr4,[r12,#12]\n\tstrb\tr5,[r12,#13]\n\tstrb\tr6,[r12,#14]\n\tstrb\tr3,[r12,#15]\n#endif\n#if __ARM_ARCH__>=5\n\tldmia\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}\n#else\n\tldmia\tsp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}\n\ttst\tlr,#1\n\tmoveq\tpc,lr\t\t\t@ be binary compatible with V4, yet\n.word\t0xe12fff1e\t\t\t@ interoperable with Thumb ISA:-)\n#endif\n\n\n\n.align\t2\n_armv4_AES_decrypt:\n\tstr\tlr,[sp,#-4]!\t\t@ push lr\n\tldmia\tr11!,{r4,r5,r6,r7}\n\teor\tr0,r0,r4\n\tldr\tr12,[r11,#240-16]\n\teor\tr1,r1,r5\n\teor\tr2,r2,r6\n\teor\tr3,r3,r7\n\tsub\tr12,r12,#1\n\tmov\tlr,#255\n\n\tand\tr7,lr,r0,lsr#16\n\tand\tr8,lr,r0,lsr#8\n\tand\tr9,lr,r0\n\tmov\tr0,r0,lsr#24\nLdec_loop:\n\tldr\tr4,[r10,r7,lsl#2]\t@ Td1[s0>>16]\n\tand\tr7,lr,r1\t\t@ i0\n\tldr\tr5,[r10,r8,lsl#2]\t@ Td2[s0>>8]\n\tand\tr8,lr,r1,lsr#16\n\tldr\tr6,[r10,r9,lsl#2]\t@ Td3[s0>>0]\n\tand\tr9,lr,r1,lsr#8\n\tldr\tr0,[r10,r0,lsl#2]\t@ Td0[s0>>24]\n\tmov\tr1,r1,lsr#24\n\n\tldr\tr7,[r10,r7,lsl#2]\t@ Td3[s1>>0]\n\tldr\tr8,[r10,r8,lsl#2]\t@ Td1[s1>>16]\n\tldr\tr9,[r10,r9,lsl#2]\t@ Td2[s1>>8]\n\teor\tr0,r0,r7,ror#24\n\tldr\tr1,[r10,r1,lsl#2]\t@ Td0[s1>>24]\n\tand\tr7,lr,r2,lsr#8\t@ i0\n\teor\tr5,r8,r5,ror#8\n\tand\tr8,lr,r2\t\t@ i1\n\teor\tr6,r9,r6,ror#8\n\tand\tr9,lr,r2,lsr#16\n\tldr\tr7,[r10,r7,lsl#2]\t@ Td2[s2>>8]\n\teor\tr1,r1,r4,ror#8\n\tldr\tr8,[r10,r8,lsl#2]\t@ Td3[s2>>0]\n\tmov\tr2,r2,lsr#24\n\n\tldr\tr9,[r10,r9,lsl#2]\t@ Td1[s2>>16]\n\teor\tr0,r0,r7,ror#16\n\tldr\tr2,[r10,r2,lsl#2]\t@ Td0[s2>>24]\n\tand\tr7,lr,r3,lsr#16\t@ i0\n\teor\tr1,r1,r8,ror#24\n\tand\tr8,lr,r3,lsr#8\t@ i1\n\teor\tr6,r9,r6,ror#8\n\tand\tr9,lr,r3\t\t@ i2\n\tldr\tr7,[r10,r7,lsl#2]\t@ Td1[s3>>16]\n\teor\tr2,r2,r5,ror#8\n\tldr\tr8,[r10,r8,lsl#2]\t@ Td2[s3>>8]\n\tmov\tr3,r3,lsr#24\n\n\tldr\tr9,[r10,r9,lsl#2]\t@ Td3[s3>>0]\n\teor\tr0,r0,r7,ror#8\n\tldr\tr7,[r11],#16\n\teor\tr1,r1,r8,ror#16\n\tldr\tr3,[r10,r3,lsl#2]\t@ Td0[s3>>24]\n\teor\tr2,r2,r9,ror#24\n\n\tldr\tr4,[r11,#-12]\n\teor\tr0,r0,r7\n\tldr\tr5,[r11,#-8]\n\teor\tr3,r3,r6,ror#8\n\tldr\tr6,[r11,#-4]\n\tand\tr7,lr,r0,lsr#16\n\teor\tr1,r1,r4\n\tand\tr8,lr,r0,lsr#8\n\teor\tr2,r2,r5\n\tand\tr9,lr,r0\n\teor\tr3,r3,r6\n\tmov\tr0,r0,lsr#24\n\n\tsubs\tr12,r12,#1\n\tbne\tLdec_loop\n\n\tadd\tr10,r10,#1024\n\n\tldr\tr5,[r10,#0]\t\t@ prefetch Td4\n\tldr\tr6,[r10,#32]\n\tldr\tr4,[r10,#64]\n\tldr\tr5,[r10,#96]\n\tldr\tr6,[r10,#128]\n\tldr\tr4,[r10,#160]\n\tldr\tr5,[r10,#192]\n\tldr\tr6,[r10,#224]\n\n\tldrb\tr0,[r10,r0]\t\t@ Td4[s0>>24]\n\tldrb\tr4,[r10,r7]\t\t@ Td4[s0>>16]\n\tand\tr7,lr,r1\t\t@ i0\n\tldrb\tr5,[r10,r8]\t\t@ Td4[s0>>8]\n\tand\tr8,lr,r1,lsr#16\n\tldrb\tr6,[r10,r9]\t\t@ Td4[s0>>0]\n\tand\tr9,lr,r1,lsr#8\n\n\tadd\tr1,r10,r1,lsr#24\n\tldrb\tr7,[r10,r7]\t\t@ Td4[s1>>0]\n\tldrb\tr1,[r1]\t\t@ Td4[s1>>24]\n\tldrb\tr8,[r10,r8]\t\t@ Td4[s1>>16]\n\teor\tr0,r7,r0,lsl#24\n\tldrb\tr9,[r10,r9]\t\t@ Td4[s1>>8]\n\teor\tr1,r4,r1,lsl#8\n\tand\tr7,lr,r2,lsr#8\t@ i0\n\teor\tr5,r5,r8,lsl#8\n\tand\tr8,lr,r2\t\t@ i1\n\tldrb\tr7,[r10,r7]\t\t@ Td4[s2>>8]\n\teor\tr6,r6,r9,lsl#8\n\tldrb\tr8,[r10,r8]\t\t@ Td4[s2>>0]\n\tand\tr9,lr,r2,lsr#16\n\n\tadd\tr2,r10,r2,lsr#24\n\tldrb\tr2,[r2]\t\t@ Td4[s2>>24]\n\teor\tr0,r0,r7,lsl#8\n\tldrb\tr9,[r10,r9]\t\t@ Td4[s2>>16]\n\teor\tr1,r8,r1,lsl#16\n\tand\tr7,lr,r3,lsr#16\t@ i0\n\teor\tr2,r5,r2,lsl#16\n\tand\tr8,lr,r3,lsr#8\t@ i1\n\tldrb\tr7,[r10,r7]\t\t@ Td4[s3>>16]\n\teor\tr6,r6,r9,lsl#16\n\tldrb\tr8,[r10,r8]\t\t@ Td4[s3>>8]\n\tand\tr9,lr,r3\t\t@ i2\n\n\tadd\tr3,r10,r3,lsr#24\n\tldrb\tr9,[r10,r9]\t\t@ Td4[s3>>0]\n\tldrb\tr3,[r3]\t\t@ Td4[s3>>24]\n\teor\tr0,r0,r7,lsl#16\n\tldr\tr7,[r11,#0]\n\teor\tr1,r1,r8,lsl#8\n\tldr\tr4,[r11,#4]\n\teor\tr2,r9,r2,lsl#8\n\tldr\tr5,[r11,#8]\n\teor\tr3,r6,r3,lsl#24\n\tldr\tr6,[r11,#12]\n\n\teor\tr0,r0,r7\n\teor\tr1,r1,r4\n\teor\tr2,r2,r5\n\teor\tr3,r3,r6\n\n\tsub\tr10,r10,#1024\n\tldr\tpc,[sp],#4\t\t@ pop and return\n\n.byte\t65,69,83,32,102,111,114,32,65,82,77,118,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0\n.align\t2\n.align\t2\n"
  },
  {
    "path": "lib/aes_acc/asm/arm64.S",
    "content": ".text\n\n.type\t_vpaes_consts,%object\n.align\t7\t// totally strategic alignment\n_vpaes_consts:\n.Lk_mc_forward:\t//\tmc_forward\n.quad\t0x0407060500030201, 0x0C0F0E0D080B0A09\n.quad\t0x080B0A0904070605, 0x000302010C0F0E0D\n.quad\t0x0C0F0E0D080B0A09, 0x0407060500030201\n.quad\t0x000302010C0F0E0D, 0x080B0A0904070605\n.Lk_mc_backward:\t//\tmc_backward\n.quad\t0x0605040702010003, 0x0E0D0C0F0A09080B\n.quad\t0x020100030E0D0C0F, 0x0A09080B06050407\n.quad\t0x0E0D0C0F0A09080B, 0x0605040702010003\n.quad\t0x0A09080B06050407, 0x020100030E0D0C0F\n.Lk_sr:\t//\tsr\n.quad\t0x0706050403020100, 0x0F0E0D0C0B0A0908\n.quad\t0x030E09040F0A0500, 0x0B06010C07020D08\n.quad\t0x0F060D040B020900, 0x070E050C030A0108\n.quad\t0x0B0E0104070A0D00, 0x0306090C0F020508\n\n//\n// \"Hot\" constants\n//\n.Lk_inv:\t//\tinv, inva\n.quad\t0x0E05060F0D080180, 0x040703090A0B0C02\n.quad\t0x01040A060F0B0780, 0x030D0E0C02050809\n.Lk_ipt:\t//\tinput transform (lo, hi)\n.quad\t0xC2B2E8985A2A7000, 0xCABAE09052227808\n.quad\t0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81\n.Lk_sbo:\t//\tsbou, sbot\n.quad\t0xD0D26D176FBDC700, 0x15AABF7AC502A878\n.quad\t0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA\n.Lk_sb1:\t//\tsb1u, sb1t\n.quad\t0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF\n.quad\t0xB19BE18FCB503E00, 0xA5DF7A6E142AF544\n.Lk_sb2:\t//\tsb2u, sb2t\n.quad\t0x69EB88400AE12900, 0xC2A163C8AB82234A\n.quad\t0xE27A93C60B712400, 0x5EB7E955BC982FCD\n\n//\n//  Decryption stuff\n//\n.Lk_dipt:\t//\tdecryption input transform\n.quad\t0x0F505B040B545F00, 0x154A411E114E451A\n.quad\t0x86E383E660056500, 0x12771772F491F194\n.Lk_dsbo:\t//\tdecryption sbox final output\n.quad\t0x1387EA537EF94000, 0xC7AA6DB9D4943E2D\n.quad\t0x12D7560F93441D00, 0xCA4B8159D8C58E9C\n.Lk_dsb9:\t//\tdecryption sbox output *9*u, *9*t\n.quad\t0x851C03539A86D600, 0xCAD51F504F994CC9\n.quad\t0xC03B1789ECD74900, 0x725E2C9EB2FBA565\n.Lk_dsbd:\t//\tdecryption sbox output *D*u, *D*t\n.quad\t0x7D57CCDFE6B1A200, 0xF56E9B13882A4439\n.quad\t0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3\n.Lk_dsbb:\t//\tdecryption sbox output *B*u, *B*t\n.quad\t0xD022649296B44200, 0x602646F6B0F2D404\n.quad\t0xC19498A6CD596700, 0xF3FF0C3E3255AA6B\n.Lk_dsbe:\t//\tdecryption sbox output *E*u, *E*t\n.quad\t0x46F2929626D4D000, 0x2242600464B4F6B0\n.quad\t0x0C55A6CDFFAAC100, 0x9467F36B98593E32\n\n//\n//  Key schedule constants\n//\n.Lk_dksd:\t//\tdecryption key schedule: invskew x*D\n.quad\t0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9\n.quad\t0x41C277F4B5368300, 0x5FDC69EAAB289D1E\n.Lk_dksb:\t//\tdecryption key schedule: invskew x*B\n.quad\t0x9A4FCA1F8550D500, 0x03D653861CC94C99\n.quad\t0x115BEDA7B6FC4A00, 0xD993256F7E3482C8\n.Lk_dkse:\t//\tdecryption key schedule: invskew x*E + 0x63\n.quad\t0xD5031CCA1FC9D600, 0x53859A4C994F5086\n.quad\t0xA23196054FDC7BE8, 0xCD5EF96A20B31487\n.Lk_dks9:\t//\tdecryption key schedule: invskew x*9\n.quad\t0xB6116FC87ED9A700, 0x4AED933482255BFC\n.quad\t0x4576516227143300, 0x8BB89FACE9DAFDCE\n\n.Lk_rcon:\t//\trcon\n.quad\t0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81\n\n.Lk_opt:\t//\toutput transform\n.quad\t0xFF9F4929D6B66000, 0xF7974121DEBE6808\n.quad\t0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0\n.Lk_deskew:\t//\tdeskew tables: inverts the sbox's \"skew\"\n.quad\t0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A\n.quad\t0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77\n\n.byte\t86,101,99,116,111,114,32,80,101,114,109,117,116,97,105,111,110,32,65,69,83,32,102,111,114,32,65,82,77,118,56,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0\n.align\t2\n.size\t_vpaes_consts,.-_vpaes_consts\n.align\t6\n##\n##  _aes_preheat\n##\n##  Fills register %r10 -> .aes_consts (so you can -fPIC)\n##  and %xmm9-%xmm15 as specified below.\n##\n.type\t_vpaes_encrypt_preheat,%function\n.align\t4\n_vpaes_encrypt_preheat:\n\tadr\tx10, .Lk_inv\n\tmovi\tv17.16b, #0x0f\n\tld1\t{v18.2d,v19.2d}, [x10],#32\t// .Lk_inv\n\tld1\t{v20.2d,v21.2d,v22.2d,v23.2d}, [x10],#64\t// .Lk_ipt, .Lk_sbo\n\tld1\t{v24.2d,v25.2d,v26.2d,v27.2d}, [x10]\t\t// .Lk_sb1, .Lk_sb2\n\tret\n.size\t_vpaes_encrypt_preheat,.-_vpaes_encrypt_preheat\n\n##\n##  _aes_encrypt_core\n##\n##  AES-encrypt %xmm0.\n##\n##  Inputs:\n##     %xmm0 = input\n##     %xmm9-%xmm15 as in _vpaes_preheat\n##    (%rdx) = scheduled keys\n##\n##  Output in %xmm0\n##  Clobbers  %xmm1-%xmm5, %r9, %r10, %r11, %rax\n##  Preserves %xmm6 - %xmm8 so you get some local vectors\n##\n##\n.type\t_vpaes_encrypt_core,%function\n.align\t4\n_vpaes_encrypt_core:\n\tmov\tx9, x2\n\tldr\tw8, [x2,#240]\t\t\t// pull rounds\n\tadr\tx11, .Lk_mc_forward+16\n\t\t\t\t\t\t// vmovdqa\t.Lk_ipt(%rip),\t%xmm2\t# iptlo\n\tld1\t{v16.2d}, [x9], #16\t\t// vmovdqu\t(%r9),\t%xmm5\t\t# round0 key\n\tand\tv1.16b, v7.16b, v17.16b\t\t// vpand\t%xmm9,\t%xmm0,\t%xmm1\n\tushr\tv0.16b, v7.16b, #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\n\ttbl\tv1.16b, {v20.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm2,\t%xmm1\n\t\t\t\t\t\t// vmovdqa\t.Lk_ipt+16(%rip), %xmm3\t# ipthi\n\ttbl\tv2.16b, {v21.16b}, v0.16b\t// vpshufb\t%xmm0,\t%xmm3,\t%xmm2\n\teor\tv0.16b, v1.16b, v16.16b\t\t// vpxor\t%xmm5,\t%xmm1,\t%xmm0\n\teor\tv0.16b, v0.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm0,\t%xmm0\n\tb\t.Lenc_entry\n\n.align\t4\n.Lenc_loop:\n\t// middle of middle round\n\tadd\tx10, x11, #0x40\n\ttbl\tv4.16b, {v25.16b}, v2.16b\t\t// vpshufb\t%xmm2,\t%xmm13,\t%xmm4\t# 4 = sb1u\n\tld1\t{v1.2d}, [x11], #16\t\t// vmovdqa\t-0x40(%r11,%r10), %xmm1\t# .Lk_mc_forward[]\n\ttbl\tv0.16b, {v24.16b}, v3.16b\t\t// vpshufb\t%xmm3,\t%xmm12,\t%xmm0\t# 0 = sb1t\n\teor\tv4.16b, v4.16b, v16.16b\t\t// vpxor\t%xmm5,\t%xmm4,\t%xmm4\t# 4 = sb1u + k\n\ttbl\tv5.16b,\t{v27.16b}, v2.16b\t\t// vpshufb\t%xmm2,\t%xmm15,\t%xmm5\t# 4 = sb2u\n\teor\tv0.16b, v0.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t# 0 = A\n\ttbl\tv2.16b, {v26.16b}, v3.16b\t\t// vpshufb\t%xmm3,\t%xmm14,\t%xmm2\t# 2 = sb2t\n\tld1\t{v4.2d}, [x10]\t\t\t// vmovdqa\t(%r11,%r10), %xmm4\t# .Lk_mc_backward[]\n\ttbl\tv3.16b, {v0.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm0,\t%xmm3\t# 0 = B\n\teor\tv2.16b, v2.16b, v5.16b\t\t// vpxor\t%xmm5,\t%xmm2,\t%xmm2\t# 2 = 2A\n\ttbl\tv0.16b, {v0.16b}, v4.16b\t// vpshufb\t%xmm4,\t%xmm0,\t%xmm0\t# 3 = D\n\teor\tv3.16b, v3.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm3,\t%xmm3\t# 0 = 2A+B\n\ttbl\tv4.16b, {v3.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm3,\t%xmm4\t# 0 = 2B+C\n\teor\tv0.16b, v0.16b, v3.16b\t\t// vpxor\t%xmm3,\t%xmm0,\t%xmm0\t# 3 = 2A+B+D\n\tand\tx11, x11, #~(1<<6)\t\t// and\t\t$0x30,\t%r11\t\t# ... mod 4\n\teor\tv0.16b, v0.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm0, %xmm0\t# 0 = 2A+3B+C+D\n\tsub\tw8, w8, #1\t\t\t// nr--\n\n.Lenc_entry:\n\t// top of round\n\tand\tv1.16b, v0.16b, v17.16b\t\t// vpand\t%xmm0,\t%xmm9,\t%xmm1   # 0 = k\n\tushr\tv0.16b, v0.16b, #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\t# 1 = i\n\ttbl\tv5.16b, {v19.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm11,\t%xmm5\t# 2 = a/k\n\teor\tv1.16b, v1.16b, v0.16b\t\t// vpxor\t%xmm0,\t%xmm1,\t%xmm1\t# 0 = j\n\ttbl\tv3.16b, {v18.16b}, v0.16b\t// vpshufb\t%xmm0, \t%xmm10,\t%xmm3  \t# 3 = 1/i\n\ttbl\tv4.16b, {v18.16b}, v1.16b\t// vpshufb\t%xmm1, \t%xmm10,\t%xmm4  \t# 4 = 1/j\n\teor\tv3.16b, v3.16b, v5.16b\t\t// vpxor\t%xmm5,\t%xmm3,\t%xmm3\t# 3 = iak = 1/i + a/k\n\teor\tv4.16b, v4.16b, v5.16b\t\t// vpxor\t%xmm5,\t%xmm4,\t%xmm4  \t# 4 = jak = 1/j + a/k\n\ttbl\tv2.16b, {v18.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm10,\t%xmm2  \t# 2 = 1/iak\n\ttbl\tv3.16b, {v18.16b}, v4.16b\t// vpshufb\t%xmm4,\t%xmm10,\t%xmm3\t# 3 = 1/jak\n\teor\tv2.16b, v2.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm2,\t%xmm2  \t# 2 = io\n\teor\tv3.16b, v3.16b, v0.16b\t\t// vpxor\t%xmm0,\t%xmm3,\t%xmm3\t# 3 = jo\n\tld1\t{v16.2d}, [x9],#16\t\t// vmovdqu\t(%r9),\t%xmm5\n\tcbnz\tw8, .Lenc_loop\n\n\t// middle of last round\n\tadd\tx10, x11, #0x80\n\t\t\t\t\t\t// vmovdqa\t-0x60(%r10), %xmm4\t# 3 : sbou\t.Lk_sbo\n\t\t\t\t\t\t// vmovdqa\t-0x50(%r10), %xmm0\t# 0 : sbot\t.Lk_sbo+16\n\ttbl\tv4.16b, {v22.16b}, v2.16b\t\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t# 4 = sbou\n\tld1\t{v1.2d}, [x10]\t\t\t// vmovdqa\t0x40(%r11,%r10), %xmm1\t# .Lk_sr[]\n\ttbl\tv0.16b, {v23.16b}, v3.16b\t\t// vpshufb\t%xmm3,\t%xmm0,\t%xmm0\t# 0 = sb1t\n\teor\tv4.16b, v4.16b, v16.16b\t\t// vpxor\t%xmm5,\t%xmm4,\t%xmm4\t# 4 = sb1u + k\n\teor\tv0.16b, v0.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t# 0 = A\n\ttbl\tv0.16b, {v0.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm0,\t%xmm0\n\tret\n.size\t_vpaes_encrypt_core,.-_vpaes_encrypt_core\n\n.globl\tvpaes_encrypt\n.type\tvpaes_encrypt,%function\n.align\t4\nvpaes_encrypt:\n\tstp\tx29,x30,[sp,#-16]!\n\tadd\tx29,sp,#0\n\n\tld1\t{v7.16b}, [x0]\n\tbl\t_vpaes_encrypt_preheat\n\tbl\t_vpaes_encrypt_core\n\tst1\t{v0.16b}, [x1]\n\n\tldp\tx29,x30,[sp],#16\n\tret\n.size\tvpaes_encrypt,.-vpaes_encrypt\n\n.type\t_vpaes_encrypt_2x,%function\n.align\t4\n_vpaes_encrypt_2x:\n\tmov\tx9, x2\n\tldr\tw8, [x2,#240]\t\t\t// pull rounds\n\tadr\tx11, .Lk_mc_forward+16\n\t\t\t\t\t\t// vmovdqa\t.Lk_ipt(%rip),\t%xmm2\t# iptlo\n\tld1\t{v16.2d}, [x9], #16\t\t// vmovdqu\t(%r9),\t%xmm5\t\t# round0 key\n\tand\tv1.16b,  v14.16b,  v17.16b\t// vpand\t%xmm9,\t%xmm0,\t%xmm1\n\tushr\tv0.16b,  v14.16b,  #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\n\tand\tv9.16b,  v15.16b,  v17.16b\n\tushr\tv8.16b,  v15.16b,  #4\n\ttbl\tv1.16b,  {v20.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm2,\t%xmm1\n\ttbl\tv9.16b,  {v20.16b}, v9.16b\n\t\t\t\t\t\t// vmovdqa\t.Lk_ipt+16(%rip), %xmm3\t# ipthi\n\ttbl\tv2.16b,  {v21.16b}, v0.16b\t// vpshufb\t%xmm0,\t%xmm3,\t%xmm2\n\ttbl\tv10.16b, {v21.16b}, v8.16b\n\teor\tv0.16b,  v1.16b,   v16.16b\t// vpxor\t%xmm5,\t%xmm1,\t%xmm0\n\teor\tv8.16b,  v9.16b,   v16.16b\n\teor\tv0.16b,  v0.16b,   v2.16b\t// vpxor\t%xmm2,\t%xmm0,\t%xmm0\n\teor\tv8.16b,  v8.16b,   v10.16b\n\tb\t.Lenc_2x_entry\n\n.align\t4\n.Lenc_2x_loop:\n\t// middle of middle round\n\tadd\tx10, x11, #0x40\n\ttbl\tv4.16b,  {v25.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm13,\t%xmm4\t# 4 = sb1u\n\ttbl\tv12.16b, {v25.16b}, v10.16b\n\tld1\t{v1.2d}, [x11], #16\t\t// vmovdqa\t-0x40(%r11,%r10), %xmm1\t# .Lk_mc_forward[]\n\ttbl\tv0.16b,  {v24.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm12,\t%xmm0\t# 0 = sb1t\n\ttbl\tv8.16b,  {v24.16b}, v11.16b\n\teor\tv4.16b,  v4.16b,  v16.16b\t// vpxor\t%xmm5,\t%xmm4,\t%xmm4\t# 4 = sb1u + k\n\teor\tv12.16b, v12.16b, v16.16b\n\ttbl\tv5.16b,\t {v27.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm15,\t%xmm5\t# 4 = sb2u\n\ttbl\tv13.16b, {v27.16b}, v10.16b\n\teor\tv0.16b,  v0.16b,  v4.16b\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t# 0 = A\n\teor\tv8.16b,  v8.16b,  v12.16b\n\ttbl\tv2.16b,  {v26.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm14,\t%xmm2\t# 2 = sb2t\n\ttbl\tv10.16b, {v26.16b}, v11.16b\n\tld1\t{v4.2d}, [x10]\t\t\t// vmovdqa\t(%r11,%r10), %xmm4\t# .Lk_mc_backward[]\n\ttbl\tv3.16b,  {v0.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm0,\t%xmm3\t# 0 = B\n\ttbl\tv11.16b, {v8.16b}, v1.16b\n\teor\tv2.16b,  v2.16b,  v5.16b\t// vpxor\t%xmm5,\t%xmm2,\t%xmm2\t# 2 = 2A\n\teor\tv10.16b, v10.16b, v13.16b\n\ttbl\tv0.16b,  {v0.16b}, v4.16b\t// vpshufb\t%xmm4,\t%xmm0,\t%xmm0\t# 3 = D\n\ttbl\tv8.16b,  {v8.16b}, v4.16b\n\teor\tv3.16b,  v3.16b,  v2.16b\t// vpxor\t%xmm2,\t%xmm3,\t%xmm3\t# 0 = 2A+B\n\teor\tv11.16b, v11.16b, v10.16b\n\ttbl\tv4.16b,  {v3.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm3,\t%xmm4\t# 0 = 2B+C\n\ttbl\tv12.16b, {v11.16b},v1.16b\n\teor\tv0.16b,  v0.16b,  v3.16b\t// vpxor\t%xmm3,\t%xmm0,\t%xmm0\t# 3 = 2A+B+D\n\teor\tv8.16b,  v8.16b,  v11.16b\n\tand\tx11, x11, #~(1<<6)\t\t// and\t\t$0x30,\t%r11\t\t# ... mod 4\n\teor\tv0.16b,  v0.16b,  v4.16b\t// vpxor\t%xmm4,\t%xmm0, %xmm0\t# 0 = 2A+3B+C+D\n\teor\tv8.16b,  v8.16b,  v12.16b\n\tsub\tw8, w8, #1\t\t\t// nr--\n\n.Lenc_2x_entry:\n\t// top of round\n\tand\tv1.16b,  v0.16b, v17.16b\t// vpand\t%xmm0,\t%xmm9,\t%xmm1   # 0 = k\n\tushr\tv0.16b,  v0.16b, #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\t# 1 = i\n\tand\tv9.16b,  v8.16b, v17.16b\n\tushr\tv8.16b,  v8.16b, #4\n\ttbl\tv5.16b,  {v19.16b},v1.16b\t// vpshufb\t%xmm1,\t%xmm11,\t%xmm5\t# 2 = a/k\n\ttbl\tv13.16b, {v19.16b},v9.16b\n\teor\tv1.16b,  v1.16b,  v0.16b\t// vpxor\t%xmm0,\t%xmm1,\t%xmm1\t# 0 = j\n\teor\tv9.16b,  v9.16b,  v8.16b\n\ttbl\tv3.16b,  {v18.16b},v0.16b\t// vpshufb\t%xmm0, \t%xmm10,\t%xmm3  \t# 3 = 1/i\n\ttbl\tv11.16b, {v18.16b},v8.16b\n\ttbl\tv4.16b,  {v18.16b},v1.16b\t// vpshufb\t%xmm1, \t%xmm10,\t%xmm4  \t# 4 = 1/j\n\ttbl\tv12.16b, {v18.16b},v9.16b\n\teor\tv3.16b,  v3.16b,  v5.16b\t// vpxor\t%xmm5,\t%xmm3,\t%xmm3\t# 3 = iak = 1/i + a/k\n\teor\tv11.16b, v11.16b, v13.16b\n\teor\tv4.16b,  v4.16b,  v5.16b\t// vpxor\t%xmm5,\t%xmm4,\t%xmm4  \t# 4 = jak = 1/j + a/k\n\teor\tv12.16b, v12.16b, v13.16b\n\ttbl\tv2.16b,  {v18.16b},v3.16b\t// vpshufb\t%xmm3,\t%xmm10,\t%xmm2  \t# 2 = 1/iak\n\ttbl\tv10.16b, {v18.16b},v11.16b\n\ttbl\tv3.16b,  {v18.16b},v4.16b\t// vpshufb\t%xmm4,\t%xmm10,\t%xmm3\t# 3 = 1/jak\n\ttbl\tv11.16b, {v18.16b},v12.16b\n\teor\tv2.16b,  v2.16b,  v1.16b\t// vpxor\t%xmm1,\t%xmm2,\t%xmm2  \t# 2 = io\n\teor\tv10.16b, v10.16b, v9.16b\n\teor\tv3.16b,  v3.16b,  v0.16b\t// vpxor\t%xmm0,\t%xmm3,\t%xmm3\t# 3 = jo\n\teor\tv11.16b, v11.16b, v8.16b\n\tld1\t{v16.2d}, [x9],#16\t\t// vmovdqu\t(%r9),\t%xmm5\n\tcbnz\tw8, .Lenc_2x_loop\n\n\t// middle of last round\n\tadd\tx10, x11, #0x80\n\t\t\t\t\t\t// vmovdqa\t-0x60(%r10), %xmm4\t# 3 : sbou\t.Lk_sbo\n\t\t\t\t\t\t// vmovdqa\t-0x50(%r10), %xmm0\t# 0 : sbot\t.Lk_sbo+16\n\ttbl\tv4.16b,  {v22.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t# 4 = sbou\n\ttbl\tv12.16b, {v22.16b}, v10.16b\n\tld1\t{v1.2d}, [x10]\t\t\t// vmovdqa\t0x40(%r11,%r10), %xmm1\t# .Lk_sr[]\n\ttbl\tv0.16b,  {v23.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm0,\t%xmm0\t# 0 = sb1t\n\ttbl\tv8.16b,  {v23.16b}, v11.16b\n\teor\tv4.16b,  v4.16b,  v16.16b\t// vpxor\t%xmm5,\t%xmm4,\t%xmm4\t# 4 = sb1u + k\n\teor\tv12.16b, v12.16b, v16.16b\n\teor\tv0.16b,  v0.16b,  v4.16b\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t# 0 = A\n\teor\tv8.16b,  v8.16b,  v12.16b\n\ttbl\tv0.16b,  {v0.16b},v1.16b\t// vpshufb\t%xmm1,\t%xmm0,\t%xmm0\n\ttbl\tv1.16b,  {v8.16b},v1.16b\n\tret\n.size\t_vpaes_encrypt_2x,.-_vpaes_encrypt_2x\n\n.type\t_vpaes_decrypt_preheat,%function\n.align\t4\n_vpaes_decrypt_preheat:\n\tadr\tx10, .Lk_inv\n\tmovi\tv17.16b, #0x0f\n\tadr\tx11, .Lk_dipt\n\tld1\t{v18.2d,v19.2d}, [x10],#32\t// .Lk_inv\n\tld1\t{v20.2d,v21.2d,v22.2d,v23.2d}, [x11],#64\t// .Lk_dipt, .Lk_dsbo\n\tld1\t{v24.2d,v25.2d,v26.2d,v27.2d}, [x11],#64\t// .Lk_dsb9, .Lk_dsbd\n\tld1\t{v28.2d,v29.2d,v30.2d,v31.2d}, [x11]\t\t// .Lk_dsbb, .Lk_dsbe\n\tret\n.size\t_vpaes_decrypt_preheat,.-_vpaes_decrypt_preheat\n\n##\n##  Decryption core\n##\n##  Same API as encryption core.\n##\n.type\t_vpaes_decrypt_core,%function\n.align\t4\n_vpaes_decrypt_core:\n\tmov\tx9, x2\n\tldr\tw8, [x2,#240]\t\t\t// pull rounds\n\n\t\t\t\t\t\t// vmovdqa\t.Lk_dipt(%rip), %xmm2\t# iptlo\n\tlsl\tx11, x8, #4\t\t\t// mov\t%rax,\t%r11;\tshl\t$4, %r11\n\teor\tx11, x11, #0x30\t\t\t// xor\t\t$0x30,\t%r11\n\tadr\tx10, .Lk_sr\n\tand\tx11, x11, #0x30\t\t\t// and\t\t$0x30,\t%r11\n\tadd\tx11, x11, x10\n\tadr\tx10, .Lk_mc_forward+48\n\n\tld1\t{v16.2d}, [x9],#16\t\t// vmovdqu\t(%r9),\t%xmm4\t\t# round0 key\n\tand\tv1.16b, v7.16b, v17.16b\t\t// vpand\t%xmm9,\t%xmm0,\t%xmm1\n\tushr\tv0.16b, v7.16b, #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\n\ttbl\tv2.16b, {v20.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm2,\t%xmm2\n\tld1\t{v5.2d}, [x10]\t\t\t// vmovdqa\t.Lk_mc_forward+48(%rip), %xmm5\n\t\t\t\t\t\t// vmovdqa\t.Lk_dipt+16(%rip), %xmm1 # ipthi\n\ttbl\tv0.16b, {v21.16b}, v0.16b\t// vpshufb\t%xmm0,\t%xmm1,\t%xmm0\n\teor\tv2.16b, v2.16b, v16.16b\t\t// vpxor\t%xmm4,\t%xmm2,\t%xmm2\n\teor\tv0.16b, v0.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm0,\t%xmm0\n\tb\t.Ldec_entry\n\n.align\t4\n.Ldec_loop:\n//\n//  Inverse mix columns\n//\n\t\t\t\t\t\t// vmovdqa\t-0x20(%r10),%xmm4\t\t# 4 : sb9u\n\t\t\t\t\t\t// vmovdqa\t-0x10(%r10),%xmm1\t\t# 0 : sb9t\n\ttbl\tv4.16b, {v24.16b}, v2.16b\t\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = sb9u\n\ttbl\tv1.16b, {v25.16b}, v3.16b\t\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t\t# 0 = sb9t\n\teor\tv0.16b, v4.16b, v16.16b\t\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\n\t\t\t\t\t\t// vmovdqa\t0x00(%r10),%xmm4\t\t# 4 : sbdu\n\teor\tv0.16b, v0.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\t\t\t\t\t\t// vmovdqa\t0x10(%r10),%xmm1\t\t# 0 : sbdt\n\n\ttbl\tv4.16b, {v26.16b}, v2.16b\t\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = sbdu\n\ttbl\tv0.16b, {v0.16b}, v5.16b\t// vpshufb\t%xmm5,\t%xmm0,\t%xmm0\t\t# MC ch\n\ttbl\tv1.16b, {v27.16b}, v3.16b\t\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t\t# 0 = sbdt\n\teor\tv0.16b, v0.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t\t# 4 = ch\n\t\t\t\t\t\t// vmovdqa\t0x20(%r10),\t%xmm4\t\t# 4 : sbbu\n\teor\tv0.16b, v0.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\t\t\t\t\t\t// vmovdqa\t0x30(%r10),\t%xmm1\t\t# 0 : sbbt\n\n\ttbl\tv4.16b, {v28.16b}, v2.16b\t\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = sbbu\n\ttbl\tv0.16b, {v0.16b}, v5.16b\t// vpshufb\t%xmm5,\t%xmm0,\t%xmm0\t\t# MC ch\n\ttbl\tv1.16b, {v29.16b}, v3.16b\t\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t\t# 0 = sbbt\n\teor\tv0.16b, v0.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t\t# 4 = ch\n\t\t\t\t\t\t// vmovdqa\t0x40(%r10),\t%xmm4\t\t# 4 : sbeu\n\teor\tv0.16b, v0.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\t\t\t\t\t\t// vmovdqa\t0x50(%r10),\t%xmm1\t\t# 0 : sbet\n\n\ttbl\tv4.16b, {v30.16b}, v2.16b\t\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = sbeu\n\ttbl\tv0.16b, {v0.16b}, v5.16b\t// vpshufb\t%xmm5,\t%xmm0,\t%xmm0\t\t# MC ch\n\ttbl\tv1.16b, {v31.16b}, v3.16b\t\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t\t# 0 = sbet\n\teor\tv0.16b, v0.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t\t# 4 = ch\n\text\tv5.16b, v5.16b, v5.16b, #12\t// vpalignr $12,\t%xmm5,\t%xmm5,\t%xmm5\n\teor\tv0.16b, v0.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\tsub\tw8, w8, #1\t\t\t// sub\t\t$1,%rax\t\t\t# nr--\n\n.Ldec_entry:\n\t// top of round\n\tand\tv1.16b, v0.16b, v17.16b\t\t// vpand\t%xmm9,\t%xmm0,\t%xmm1\t# 0 = k\n\tushr\tv0.16b, v0.16b, #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\t# 1 = i\n\ttbl\tv2.16b, {v19.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm11,\t%xmm2\t# 2 = a/k\n\teor\tv1.16b,\tv1.16b, v0.16b\t\t// vpxor\t%xmm0,\t%xmm1,\t%xmm1\t# 0 = j\n\ttbl\tv3.16b, {v18.16b}, v0.16b\t// vpshufb\t%xmm0, \t%xmm10,\t%xmm3\t# 3 = 1/i\n\ttbl\tv4.16b, {v18.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm10,\t%xmm4\t# 4 = 1/j\n\teor\tv3.16b, v3.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm3,\t%xmm3\t# 3 = iak = 1/i + a/k\n\teor\tv4.16b, v4.16b, v2.16b\t\t// vpxor\t%xmm2, \t%xmm4,\t%xmm4\t# 4 = jak = 1/j + a/k\n\ttbl\tv2.16b, {v18.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm10,\t%xmm2\t# 2 = 1/iak\n\ttbl\tv3.16b, {v18.16b}, v4.16b\t// vpshufb\t%xmm4,  %xmm10,\t%xmm3\t# 3 = 1/jak\n\teor\tv2.16b, v2.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm2,\t%xmm2\t# 2 = io\n\teor\tv3.16b, v3.16b, v0.16b\t\t// vpxor\t%xmm0,  %xmm3,\t%xmm3\t# 3 = jo\n\tld1\t{v16.2d}, [x9],#16\t\t// vmovdqu\t(%r9),\t%xmm0\n\tcbnz\tw8, .Ldec_loop\n\n\t// middle of last round\n\t\t\t\t\t\t// vmovdqa\t0x60(%r10),\t%xmm4\t# 3 : sbou\n\ttbl\tv4.16b, {v22.16b}, v2.16b\t\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t# 4 = sbou\n\t\t\t\t\t\t// vmovdqa\t0x70(%r10),\t%xmm1\t# 0 : sbot\n\tld1\t{v2.2d}, [x11]\t\t\t// vmovdqa\t-0x160(%r11),\t%xmm2\t# .Lk_sr-.Lk_dsbd=-0x160\n\ttbl\tv1.16b, {v23.16b}, v3.16b\t\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t# 0 = sb1t\n\teor\tv4.16b, v4.16b, v16.16b\t\t// vpxor\t%xmm0,\t%xmm4,\t%xmm4\t# 4 = sb1u + k\n\teor\tv0.16b, v1.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm1,\t%xmm0\t# 0 = A\n\ttbl\tv0.16b, {v0.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm0,\t%xmm0\n\tret\n.size\t_vpaes_decrypt_core,.-_vpaes_decrypt_core\n\n.globl\tvpaes_decrypt\n.type\tvpaes_decrypt,%function\n.align\t4\nvpaes_decrypt:\n\tstp\tx29,x30,[sp,#-16]!\n\tadd\tx29,sp,#0\n\n\tld1\t{v7.16b}, [x0]\n\tbl\t_vpaes_decrypt_preheat\n\tbl\t_vpaes_decrypt_core\n\tst1\t{v0.16b}, [x1]\n\n\tldp\tx29,x30,[sp],#16\n\tret\n.size\tvpaes_decrypt,.-vpaes_decrypt\n\n// v14-v15 input, v0-v1 output\n.type\t_vpaes_decrypt_2x,%function\n.align\t4\n_vpaes_decrypt_2x:\n\tmov\tx9, x2\n\tldr\tw8, [x2,#240]\t\t\t// pull rounds\n\n\t\t\t\t\t\t// vmovdqa\t.Lk_dipt(%rip), %xmm2\t# iptlo\n\tlsl\tx11, x8, #4\t\t\t// mov\t%rax,\t%r11;\tshl\t$4, %r11\n\teor\tx11, x11, #0x30\t\t\t// xor\t\t$0x30,\t%r11\n\tadr\tx10, .Lk_sr\n\tand\tx11, x11, #0x30\t\t\t// and\t\t$0x30,\t%r11\n\tadd\tx11, x11, x10\n\tadr\tx10, .Lk_mc_forward+48\n\n\tld1\t{v16.2d}, [x9],#16\t\t// vmovdqu\t(%r9),\t%xmm4\t\t# round0 key\n\tand\tv1.16b,  v14.16b, v17.16b\t// vpand\t%xmm9,\t%xmm0,\t%xmm1\n\tushr\tv0.16b,  v14.16b, #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\n\tand\tv9.16b,  v15.16b, v17.16b\n\tushr\tv8.16b,  v15.16b, #4\n\ttbl\tv2.16b,  {v20.16b},v1.16b\t// vpshufb\t%xmm1,\t%xmm2,\t%xmm2\n\ttbl\tv10.16b, {v20.16b},v9.16b\n\tld1\t{v5.2d}, [x10]\t\t\t// vmovdqa\t.Lk_mc_forward+48(%rip), %xmm5\n\t\t\t\t\t\t// vmovdqa\t.Lk_dipt+16(%rip), %xmm1 # ipthi\n\ttbl\tv0.16b,  {v21.16b},v0.16b\t// vpshufb\t%xmm0,\t%xmm1,\t%xmm0\n\ttbl\tv8.16b,  {v21.16b},v8.16b\n\teor\tv2.16b,  v2.16b,  v16.16b\t// vpxor\t%xmm4,\t%xmm2,\t%xmm2\n\teor\tv10.16b, v10.16b, v16.16b\n\teor\tv0.16b,  v0.16b,  v2.16b\t// vpxor\t%xmm2,\t%xmm0,\t%xmm0\n\teor\tv8.16b,  v8.16b,  v10.16b\n\tb\t.Ldec_2x_entry\n\n.align\t4\n.Ldec_2x_loop:\n//\n//  Inverse mix columns\n//\n\t\t\t\t\t\t// vmovdqa\t-0x20(%r10),%xmm4\t\t# 4 : sb9u\n\t\t\t\t\t\t// vmovdqa\t-0x10(%r10),%xmm1\t\t# 0 : sb9t\n\ttbl\tv4.16b,  {v24.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = sb9u\n\ttbl\tv12.16b, {v24.16b}, v10.16b\n\ttbl\tv1.16b,  {v25.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t\t# 0 = sb9t\n\ttbl\tv9.16b,  {v25.16b}, v11.16b\n\teor\tv0.16b,  v4.16b,  v16.16b\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\n\teor\tv8.16b,  v12.16b, v16.16b\n\t\t\t\t\t\t// vmovdqa\t0x00(%r10),%xmm4\t\t# 4 : sbdu\n\teor\tv0.16b,  v0.16b,  v1.16b\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\teor\tv8.16b,  v8.16b,  v9.16b\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\t\t\t\t\t\t// vmovdqa\t0x10(%r10),%xmm1\t\t# 0 : sbdt\n\n\ttbl\tv4.16b,  {v26.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = sbdu\n\ttbl\tv12.16b, {v26.16b}, v10.16b\n\ttbl\tv0.16b,  {v0.16b},v5.16b\t// vpshufb\t%xmm5,\t%xmm0,\t%xmm0\t\t# MC ch\n\ttbl\tv8.16b,  {v8.16b},v5.16b\n\ttbl\tv1.16b,  {v27.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t\t# 0 = sbdt\n\ttbl\tv9.16b,  {v27.16b}, v11.16b\n\teor\tv0.16b,  v0.16b,  v4.16b\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t\t# 4 = ch\n\teor\tv8.16b,  v8.16b,  v12.16b\n\t\t\t\t\t\t// vmovdqa\t0x20(%r10),\t%xmm4\t\t# 4 : sbbu\n\teor\tv0.16b,  v0.16b,  v1.16b\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\teor\tv8.16b,  v8.16b,  v9.16b\n\t\t\t\t\t\t// vmovdqa\t0x30(%r10),\t%xmm1\t\t# 0 : sbbt\n\n\ttbl\tv4.16b,  {v28.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = sbbu\n\ttbl\tv12.16b, {v28.16b}, v10.16b\n\ttbl\tv0.16b,  {v0.16b},v5.16b\t// vpshufb\t%xmm5,\t%xmm0,\t%xmm0\t\t# MC ch\n\ttbl\tv8.16b,  {v8.16b},v5.16b\n\ttbl\tv1.16b,  {v29.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t\t# 0 = sbbt\n\ttbl\tv9.16b,  {v29.16b}, v11.16b\n\teor\tv0.16b,  v0.16b,  v4.16b\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t\t# 4 = ch\n\teor\tv8.16b,  v8.16b,  v12.16b\n\t\t\t\t\t\t// vmovdqa\t0x40(%r10),\t%xmm4\t\t# 4 : sbeu\n\teor\tv0.16b,  v0.16b,  v1.16b\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\teor\tv8.16b,  v8.16b,  v9.16b\n\t\t\t\t\t\t// vmovdqa\t0x50(%r10),\t%xmm1\t\t# 0 : sbet\n\n\ttbl\tv4.16b,  {v30.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = sbeu\n\ttbl\tv12.16b, {v30.16b}, v10.16b\n\ttbl\tv0.16b,  {v0.16b},v5.16b\t// vpshufb\t%xmm5,\t%xmm0,\t%xmm0\t\t# MC ch\n\ttbl\tv8.16b,  {v8.16b},v5.16b\n\ttbl\tv1.16b,  {v31.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t\t# 0 = sbet\n\ttbl\tv9.16b,  {v31.16b}, v11.16b\n\teor\tv0.16b,  v0.16b,  v4.16b\t// vpxor\t%xmm4,\t%xmm0,\t%xmm0\t\t# 4 = ch\n\teor\tv8.16b,  v8.16b,  v12.16b\n\text\tv5.16b,  v5.16b,  v5.16b, #12\t// vpalignr $12,\t%xmm5,\t%xmm5,\t%xmm5\n\teor\tv0.16b,  v0.16b,  v1.16b\t// vpxor\t%xmm1,\t%xmm0,\t%xmm0\t\t# 0 = ch\n\teor\tv8.16b,  v8.16b,  v9.16b\n\tsub\tw8, w8, #1\t\t\t// sub\t\t$1,%rax\t\t\t# nr--\n\n.Ldec_2x_entry:\n\t// top of round\n\tand\tv1.16b,  v0.16b,  v17.16b\t// vpand\t%xmm9,\t%xmm0,\t%xmm1\t# 0 = k\n\tushr\tv0.16b,  v0.16b,  #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\t# 1 = i\n\tand\tv9.16b,  v8.16b,  v17.16b\n\tushr\tv8.16b,  v8.16b,  #4\n\ttbl\tv2.16b,  {v19.16b},v1.16b\t// vpshufb\t%xmm1,\t%xmm11,\t%xmm2\t# 2 = a/k\n\ttbl\tv10.16b, {v19.16b},v9.16b\n\teor\tv1.16b,\t v1.16b,  v0.16b\t// vpxor\t%xmm0,\t%xmm1,\t%xmm1\t# 0 = j\n\teor\tv9.16b,\t v9.16b,  v8.16b\n\ttbl\tv3.16b,  {v18.16b},v0.16b\t// vpshufb\t%xmm0, \t%xmm10,\t%xmm3\t# 3 = 1/i\n\ttbl\tv11.16b, {v18.16b},v8.16b\n\ttbl\tv4.16b,  {v18.16b},v1.16b\t// vpshufb\t%xmm1,\t%xmm10,\t%xmm4\t# 4 = 1/j\n\ttbl\tv12.16b, {v18.16b},v9.16b\n\teor\tv3.16b,  v3.16b,  v2.16b\t// vpxor\t%xmm2,\t%xmm3,\t%xmm3\t# 3 = iak = 1/i + a/k\n\teor\tv11.16b, v11.16b, v10.16b\n\teor\tv4.16b,  v4.16b,  v2.16b\t// vpxor\t%xmm2, \t%xmm4,\t%xmm4\t# 4 = jak = 1/j + a/k\n\teor\tv12.16b, v12.16b, v10.16b\n\ttbl\tv2.16b,  {v18.16b},v3.16b\t// vpshufb\t%xmm3,\t%xmm10,\t%xmm2\t# 2 = 1/iak\n\ttbl\tv10.16b, {v18.16b},v11.16b\n\ttbl\tv3.16b,  {v18.16b},v4.16b\t// vpshufb\t%xmm4,  %xmm10,\t%xmm3\t# 3 = 1/jak\n\ttbl\tv11.16b, {v18.16b},v12.16b\n\teor\tv2.16b,  v2.16b,  v1.16b\t// vpxor\t%xmm1,\t%xmm2,\t%xmm2\t# 2 = io\n\teor\tv10.16b, v10.16b, v9.16b\n\teor\tv3.16b,  v3.16b,  v0.16b\t// vpxor\t%xmm0,  %xmm3,\t%xmm3\t# 3 = jo\n\teor\tv11.16b, v11.16b, v8.16b\n\tld1\t{v16.2d}, [x9],#16\t\t// vmovdqu\t(%r9),\t%xmm0\n\tcbnz\tw8, .Ldec_2x_loop\n\n\t// middle of last round\n\t\t\t\t\t\t// vmovdqa\t0x60(%r10),\t%xmm4\t# 3 : sbou\n\ttbl\tv4.16b,  {v22.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm4,\t%xmm4\t# 4 = sbou\n\ttbl\tv12.16b, {v22.16b}, v10.16b\n\t\t\t\t\t\t// vmovdqa\t0x70(%r10),\t%xmm1\t# 0 : sbot\n\ttbl\tv1.16b,  {v23.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm1,\t%xmm1\t# 0 = sb1t\n\ttbl\tv9.16b,  {v23.16b}, v11.16b\n\tld1\t{v2.2d}, [x11]\t\t\t// vmovdqa\t-0x160(%r11),\t%xmm2\t# .Lk_sr-.Lk_dsbd=-0x160\n\teor\tv4.16b,  v4.16b,  v16.16b\t// vpxor\t%xmm0,\t%xmm4,\t%xmm4\t# 4 = sb1u + k\n\teor\tv12.16b, v12.16b, v16.16b\n\teor\tv0.16b,  v1.16b,  v4.16b\t// vpxor\t%xmm4,\t%xmm1,\t%xmm0\t# 0 = A\n\teor\tv8.16b,  v9.16b,  v12.16b\n\ttbl\tv0.16b,  {v0.16b},v2.16b\t// vpshufb\t%xmm2,\t%xmm0,\t%xmm0\n\ttbl\tv1.16b,  {v8.16b},v2.16b\n\tret\n.size\t_vpaes_decrypt_2x,.-_vpaes_decrypt_2x\n########################################################\n##                                                    ##\n##                  AES key schedule                  ##\n##                                                    ##\n########################################################\n.type\t_vpaes_key_preheat,%function\n.align\t4\n_vpaes_key_preheat:\n\tadr\tx10, .Lk_inv\n\tmovi\tv16.16b, #0x5b\t\t\t// .Lk_s63\n\tadr\tx11, .Lk_sb1\n\tmovi\tv17.16b, #0x0f\t\t\t// .Lk_s0F\n\tld1\t{v18.2d,v19.2d,v20.2d,v21.2d}, [x10]\t\t// .Lk_inv, .Lk_ipt\n\tadr\tx10, .Lk_dksd\n\tld1\t{v22.2d,v23.2d}, [x11]\t\t// .Lk_sb1\n\tadr\tx11, .Lk_mc_forward\n\tld1\t{v24.2d,v25.2d,v26.2d,v27.2d}, [x10],#64\t// .Lk_dksd, .Lk_dksb\n\tld1\t{v28.2d,v29.2d,v30.2d,v31.2d}, [x10],#64\t// .Lk_dkse, .Lk_dks9\n\tld1\t{v8.2d}, [x10]\t\t\t// .Lk_rcon\n\tld1\t{v9.2d}, [x11]\t\t\t// .Lk_mc_forward[0]\n\tret\n.size\t_vpaes_key_preheat,.-_vpaes_key_preheat\n\n.type\t_vpaes_schedule_core,%function\n.align\t4\n_vpaes_schedule_core:\n\tstp\tx29, x30, [sp,#-16]!\n\tadd\tx29,sp,#0\n\n\tbl\t_vpaes_key_preheat\t\t// load the tables\n\n\tld1\t{v0.16b}, [x0],#16\t\t// vmovdqu\t(%rdi),\t%xmm0\t\t# load key (unaligned)\n\n\t// input transform\n\tmov\tv3.16b, v0.16b\t\t\t// vmovdqa\t%xmm0,\t%xmm3\n\tbl\t_vpaes_schedule_transform\n\tmov\tv7.16b, v0.16b\t\t\t// vmovdqa\t%xmm0,\t%xmm7\n\n\tadr\tx10, .Lk_sr\t\t\t// lea\t.Lk_sr(%rip),%r10\n\tadd\tx8, x8, x10\n\tcbnz\tw3, .Lschedule_am_decrypting\n\n\t// encrypting, output zeroth round key after transform\n\tst1\t{v0.2d}, [x2]\t\t\t// vmovdqu\t%xmm0,\t(%rdx)\n\tb\t.Lschedule_go\n\n.Lschedule_am_decrypting:\n\t// decrypting, output zeroth round key after shiftrows\n\tld1\t{v1.2d}, [x8]\t\t\t// vmovdqa\t(%r8,%r10),\t%xmm1\n\ttbl\tv3.16b, {v3.16b}, v1.16b\t// vpshufb  %xmm1,\t%xmm3,\t%xmm3\n\tst1\t{v3.2d}, [x2]\t\t\t// vmovdqu\t%xmm3,\t(%rdx)\n\teor\tx8, x8, #0x30\t\t\t// xor\t$0x30, %r8\n\n.Lschedule_go:\n\tcmp\tw1, #192\t\t\t// cmp\t$192,\t%esi\n\tb.hi\t.Lschedule_256\n\tb.eq\t.Lschedule_192\n\t// 128: fall though\n\n##\n##  .schedule_128\n##\n##  128-bit specific part of key schedule.\n##\n##  This schedule is really simple, because all its parts\n##  are accomplished by the subroutines.\n##\n.Lschedule_128:\n\tmov\tx0, #10\t\t\t// mov\t$10, %esi\n\n.Loop_schedule_128:\n\tsub\tx0, x0, #1\t\t\t// dec\t%esi\n\tbl\t_vpaes_schedule_round\n\tcbz\tx0, .Lschedule_mangle_last\n\tbl\t_vpaes_schedule_mangle\t\t// write output\n\tb\t.Loop_schedule_128\n\n##\n##  .aes_schedule_192\n##\n##  192-bit specific part of key schedule.\n##\n##  The main body of this schedule is the same as the 128-bit\n##  schedule, but with more smearing.  The long, high side is\n##  stored in %xmm7 as before, and the short, low side is in\n##  the high bits of %xmm6.\n##\n##  This schedule is somewhat nastier, however, because each\n##  round produces 192 bits of key material, or 1.5 round keys.\n##  Therefore, on each cycle we do 2 rounds and produce 3 round\n##  keys.\n##\n.align\t4\n.Lschedule_192:\n\tsub\tx0, x0, #8\n\tld1\t{v0.16b}, [x0]\t\t// vmovdqu\t8(%rdi),%xmm0\t\t# load key part 2 (very unaligned)\n\tbl\t_vpaes_schedule_transform\t// input transform\n\tmov\tv6.16b, v0.16b\t\t\t// vmovdqa\t%xmm0,\t%xmm6\t\t# save short part\n\teor\tv4.16b, v4.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm4, %xmm4\t# clear 4\n\tins\tv6.d[0], v4.d[0]\t\t// vmovhlps\t%xmm4,\t%xmm6,\t%xmm6\t\t# clobber low side with zeros\n\tmov\tx0, #4\t\t\t// mov\t$4,\t%esi\n\n.Loop_schedule_192:\n\tsub\tx0, x0, #1\t\t\t// dec\t%esi\n\tbl\t_vpaes_schedule_round\n\text\tv0.16b, v6.16b, v0.16b, #8\t// vpalignr\t$8,%xmm6,%xmm0,%xmm0\n\tbl\t_vpaes_schedule_mangle\t\t// save key n\n\tbl\t_vpaes_schedule_192_smear\n\tbl\t_vpaes_schedule_mangle\t\t// save key n+1\n\tbl\t_vpaes_schedule_round\n\tcbz\tx0, .Lschedule_mangle_last\n\tbl\t_vpaes_schedule_mangle\t\t// save key n+2\n\tbl\t_vpaes_schedule_192_smear\n\tb\t.Loop_schedule_192\n\n##\n##  .aes_schedule_256\n##\n##  256-bit specific part of key schedule.\n##\n##  The structure here is very similar to the 128-bit\n##  schedule, but with an additional \"low side\" in\n##  %xmm6.  The low side's rounds are the same as the\n##  high side's, except no rcon and no rotation.\n##\n.align\t4\n.Lschedule_256:\n\tld1\t{v0.16b}, [x0]\t\t// vmovdqu\t16(%rdi),%xmm0\t\t# load key part 2 (unaligned)\n\tbl\t_vpaes_schedule_transform\t// input transform\n\tmov\tx0, #7\t\t\t// mov\t$7, %esi\n\n.Loop_schedule_256:\n\tsub\tx0, x0, #1\t\t\t// dec\t%esi\n\tbl\t_vpaes_schedule_mangle\t\t// output low result\n\tmov\tv6.16b, v0.16b\t\t\t// vmovdqa\t%xmm0,\t%xmm6\t\t# save cur_lo in xmm6\n\n\t// high round\n\tbl\t_vpaes_schedule_round\n\tcbz\tx0, .Lschedule_mangle_last\n\tbl\t_vpaes_schedule_mangle\n\n\t// low round. swap xmm7 and xmm6\n\tdup\tv0.4s, v0.s[3]\t\t\t// vpshufd\t$0xFF,\t%xmm0,\t%xmm0\n\tmovi\tv4.16b, #0\n\tmov\tv5.16b, v7.16b\t\t\t// vmovdqa\t%xmm7,\t%xmm5\n\tmov\tv7.16b, v6.16b\t\t\t// vmovdqa\t%xmm6,\t%xmm7\n\tbl\t_vpaes_schedule_low_round\n\tmov\tv7.16b, v5.16b\t\t\t// vmovdqa\t%xmm5,\t%xmm7\n\n\tb\t.Loop_schedule_256\n\n##\n##  .aes_schedule_mangle_last\n##\n##  Mangler for last round of key schedule\n##  Mangles %xmm0\n##    when encrypting, outputs out(%xmm0) ^ 63\n##    when decrypting, outputs unskew(%xmm0)\n##\n##  Always called right before return... jumps to cleanup and exits\n##\n.align\t4\n.Lschedule_mangle_last:\n\t// schedule last round key from xmm0\n\tadr\tx11, .Lk_deskew\t\t\t// lea\t.Lk_deskew(%rip),%r11\t# prepare to deskew\n\tcbnz\tw3, .Lschedule_mangle_last_dec\n\n\t// encrypting\n\tld1\t{v1.2d}, [x8]\t\t\t// vmovdqa\t(%r8,%r10),%xmm1\n\tadr\tx11, .Lk_opt\t\t\t// lea\t.Lk_opt(%rip),\t%r11\t\t# prepare to output transform\n\tadd\tx2, x2, #32\t\t\t// add\t$32,\t%rdx\n\ttbl\tv0.16b, {v0.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm0,\t%xmm0\t\t# output permute\n\n.Lschedule_mangle_last_dec:\n\tld1\t{v20.2d,v21.2d}, [x11]\t\t// reload constants\n\tsub\tx2, x2, #16\t\t\t// add\t$-16,\t%rdx\n\teor\tv0.16b, v0.16b, v16.16b\t\t// vpxor\t.Lk_s63(%rip),\t%xmm0,\t%xmm0\n\tbl\t_vpaes_schedule_transform\t// output transform\n\tst1\t{v0.2d}, [x2]\t\t\t// vmovdqu\t%xmm0,\t(%rdx)\t\t# save last key\n\n\t// cleanup\n\teor\tv0.16b, v0.16b, v0.16b\t\t// vpxor\t%xmm0,\t%xmm0,\t%xmm0\n\teor\tv1.16b, v1.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm1,\t%xmm1\n\teor\tv2.16b, v2.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm2,\t%xmm2\n\teor\tv3.16b, v3.16b, v3.16b\t\t// vpxor\t%xmm3,\t%xmm3,\t%xmm3\n\teor\tv4.16b, v4.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm4,\t%xmm4\n\teor\tv5.16b, v5.16b, v5.16b\t\t// vpxor\t%xmm5,\t%xmm5,\t%xmm5\n\teor\tv6.16b, v6.16b, v6.16b\t\t// vpxor\t%xmm6,\t%xmm6,\t%xmm6\n\teor\tv7.16b, v7.16b, v7.16b\t\t// vpxor\t%xmm7,\t%xmm7,\t%xmm7\n\tldp\tx29, x30, [sp],#16\n\tret\n.size\t_vpaes_schedule_core,.-_vpaes_schedule_core\n\n##\n##  .aes_schedule_192_smear\n##\n##  Smear the short, low side in the 192-bit key schedule.\n##\n##  Inputs:\n##    %xmm7: high side, b  a  x  y\n##    %xmm6:  low side, d  c  0  0\n##    %xmm13: 0\n##\n##  Outputs:\n##    %xmm6: b+c+d  b+c  0  0\n##    %xmm0: b+c+d  b+c  b  a\n##\n.type\t_vpaes_schedule_192_smear,%function\n.align\t4\n_vpaes_schedule_192_smear:\n\tmovi\tv1.16b, #0\n\tdup\tv0.4s, v7.s[3]\n\tins\tv1.s[3], v6.s[2]\t// vpshufd\t$0x80,\t%xmm6,\t%xmm1\t# d c 0 0 -> c 0 0 0\n\tins\tv0.s[0], v7.s[2]\t// vpshufd\t$0xFE,\t%xmm7,\t%xmm0\t# b a _ _ -> b b b a\n\teor\tv6.16b, v6.16b, v1.16b\t// vpxor\t%xmm1,\t%xmm6,\t%xmm6\t# -> c+d c 0 0\n\teor\tv1.16b, v1.16b, v1.16b\t// vpxor\t%xmm1,\t%xmm1,\t%xmm1\n\teor\tv6.16b, v6.16b, v0.16b\t// vpxor\t%xmm0,\t%xmm6,\t%xmm6\t# -> b+c+d b+c b a\n\tmov\tv0.16b, v6.16b\t\t// vmovdqa\t%xmm6,\t%xmm0\n\tins\tv6.d[0], v1.d[0]\t// vmovhlps\t%xmm1,\t%xmm6,\t%xmm6\t# clobber low side with zeros\n\tret\n.size\t_vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear\n\n##\n##  .aes_schedule_round\n##\n##  Runs one main round of the key schedule on %xmm0, %xmm7\n##\n##  Specifically, runs subbytes on the high dword of %xmm0\n##  then rotates it by one byte and xors into the low dword of\n##  %xmm7.\n##\n##  Adds rcon from low byte of %xmm8, then rotates %xmm8 for\n##  next rcon.\n##\n##  Smears the dwords of %xmm7 by xoring the low into the\n##  second low, result into third, result into highest.\n##\n##  Returns results in %xmm7 = %xmm0.\n##  Clobbers %xmm1-%xmm4, %r11.\n##\n.type\t_vpaes_schedule_round,%function\n.align\t4\n_vpaes_schedule_round:\n\t// extract rcon from xmm8\n\tmovi\tv4.16b, #0\t\t\t// vpxor\t%xmm4,\t%xmm4,\t%xmm4\n\text\tv1.16b, v8.16b, v4.16b, #15\t// vpalignr\t$15,\t%xmm8,\t%xmm4,\t%xmm1\n\text\tv8.16b, v8.16b, v8.16b, #15\t// vpalignr\t$15,\t%xmm8,\t%xmm8,\t%xmm8\n\teor\tv7.16b, v7.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm7,\t%xmm7\n\n\t// rotate\n\tdup\tv0.4s, v0.s[3]\t\t\t// vpshufd\t$0xFF,\t%xmm0,\t%xmm0\n\text\tv0.16b, v0.16b, v0.16b, #1\t// vpalignr\t$1,\t%xmm0,\t%xmm0,\t%xmm0\n\n\t// fall through...\n\n\t// low round: same as high round, but no rotation and no rcon.\n_vpaes_schedule_low_round:\n\t// smear xmm7\n\text\tv1.16b, v4.16b, v7.16b, #12\t// vpslldq\t$4,\t%xmm7,\t%xmm1\n\teor\tv7.16b, v7.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm7,\t%xmm7\n\text\tv4.16b, v4.16b, v7.16b, #8\t// vpslldq\t$8,\t%xmm7,\t%xmm4\n\n\t// subbytes\n\tand\tv1.16b, v0.16b, v17.16b\t\t// vpand\t%xmm9,\t%xmm0,\t%xmm1\t\t# 0 = k\n\tushr\tv0.16b, v0.16b, #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\t\t# 1 = i\n\teor\tv7.16b, v7.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm7,\t%xmm7\n\ttbl\tv2.16b, {v19.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm11,\t%xmm2\t\t# 2 = a/k\n\teor\tv1.16b, v1.16b, v0.16b\t\t// vpxor\t%xmm0,\t%xmm1,\t%xmm1\t\t# 0 = j\n\ttbl\tv3.16b, {v18.16b}, v0.16b\t// vpshufb\t%xmm0, \t%xmm10,\t%xmm3\t\t# 3 = 1/i\n\teor\tv3.16b, v3.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm3,\t%xmm3\t\t# 3 = iak = 1/i + a/k\n\ttbl\tv4.16b, {v18.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm10,\t%xmm4\t\t# 4 = 1/j\n\teor\tv7.16b, v7.16b, v16.16b\t\t// vpxor\t.Lk_s63(%rip),\t%xmm7,\t%xmm7\n\ttbl\tv3.16b, {v18.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm10,\t%xmm3\t\t# 2 = 1/iak\n\teor\tv4.16b, v4.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm4,\t%xmm4\t\t# 4 = jak = 1/j + a/k\n\ttbl\tv2.16b, {v18.16b}, v4.16b\t// vpshufb\t%xmm4,\t%xmm10,\t%xmm2\t\t# 3 = 1/jak\n\teor\tv3.16b, v3.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm3,\t%xmm3\t\t# 2 = io\n\teor\tv2.16b, v2.16b, v0.16b\t\t// vpxor\t%xmm0,\t%xmm2,\t%xmm2\t\t# 3 = jo\n\ttbl\tv4.16b, {v23.16b}, v3.16b\t// vpshufb\t%xmm3,\t%xmm13,\t%xmm4\t\t# 4 = sbou\n\ttbl\tv1.16b, {v22.16b}, v2.16b\t// vpshufb\t%xmm2,\t%xmm12,\t%xmm1\t\t# 0 = sb1t\n\teor\tv1.16b, v1.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm1,\t%xmm1\t\t# 0 = sbox output\n\n\t// add in smeared stuff\n\teor\tv0.16b, v1.16b, v7.16b\t\t// vpxor\t%xmm7,\t%xmm1,\t%xmm0\n\teor\tv7.16b, v1.16b, v7.16b\t\t// vmovdqa\t%xmm0,\t%xmm7\n\tret\n.size\t_vpaes_schedule_round,.-_vpaes_schedule_round\n\n##\n##  .aes_schedule_transform\n##\n##  Linear-transform %xmm0 according to tables at (%r11)\n##\n##  Requires that %xmm9 = 0x0F0F... as in preheat\n##  Output in %xmm0\n##  Clobbers %xmm1, %xmm2\n##\n.type\t_vpaes_schedule_transform,%function\n.align\t4\n_vpaes_schedule_transform:\n\tand\tv1.16b, v0.16b, v17.16b\t\t// vpand\t%xmm9,\t%xmm0,\t%xmm1\n\tushr\tv0.16b, v0.16b, #4\t\t// vpsrlb\t$4,\t%xmm0,\t%xmm0\n\t\t\t\t\t\t// vmovdqa\t(%r11),\t%xmm2 \t# lo\n\ttbl\tv2.16b, {v20.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm2,\t%xmm2\n\t\t\t\t\t\t// vmovdqa\t16(%r11),\t%xmm1 # hi\n\ttbl\tv0.16b, {v21.16b}, v0.16b\t// vpshufb\t%xmm0,\t%xmm1,\t%xmm0\n\teor\tv0.16b, v0.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm0,\t%xmm0\n\tret\n.size\t_vpaes_schedule_transform,.-_vpaes_schedule_transform\n\n##\n##  .aes_schedule_mangle\n##\n##  Mangle xmm0 from (basis-transformed) standard version\n##  to our version.\n##\n##  On encrypt,\n##    xor with 0x63\n##    multiply by circulant 0,1,1,1\n##    apply shiftrows transform\n##\n##  On decrypt,\n##    xor with 0x63\n##    multiply by \"inverse mixcolumns\" circulant E,B,D,9\n##    deskew\n##    apply shiftrows transform\n##\n##\n##  Writes out to (%rdx), and increments or decrements it\n##  Keeps track of round number mod 4 in %r8\n##  Preserves xmm0\n##  Clobbers xmm1-xmm5\n##\n.type\t_vpaes_schedule_mangle,%function\n.align\t4\n_vpaes_schedule_mangle:\n\tmov\tv4.16b, v0.16b\t\t\t// vmovdqa\t%xmm0,\t%xmm4\t# save xmm0 for later\n\t\t\t\t\t\t// vmovdqa\t.Lk_mc_forward(%rip),%xmm5\n\tcbnz\tw3, .Lschedule_mangle_dec\n\n\t// encrypting\n\teor\tv4.16b, v0.16b, v16.16b\t\t// vpxor\t.Lk_s63(%rip),\t%xmm0,\t%xmm4\n\tadd\tx2, x2, #16\t\t\t// add\t$16,\t%rdx\n\ttbl\tv4.16b, {v4.16b}, v9.16b\t// vpshufb\t%xmm5,\t%xmm4,\t%xmm4\n\ttbl\tv1.16b, {v4.16b}, v9.16b\t// vpshufb\t%xmm5,\t%xmm4,\t%xmm1\n\ttbl\tv3.16b, {v1.16b}, v9.16b\t// vpshufb\t%xmm5,\t%xmm1,\t%xmm3\n\teor\tv4.16b, v4.16b, v1.16b\t\t// vpxor\t%xmm1,\t%xmm4,\t%xmm4\n\tld1\t{v1.2d}, [x8]\t\t\t// vmovdqa\t(%r8,%r10),\t%xmm1\n\teor\tv3.16b, v3.16b, v4.16b\t\t// vpxor\t%xmm4,\t%xmm3,\t%xmm3\n\n\tb\t.Lschedule_mangle_both\n.align\t4\n.Lschedule_mangle_dec:\n\t// inverse mix columns\n\t\t\t\t\t\t// lea\t.Lk_dksd(%rip),%r11\n\tushr\tv1.16b, v4.16b, #4\t\t// vpsrlb\t$4,\t%xmm4,\t%xmm1\t# 1 = hi\n\tand\tv4.16b, v4.16b, v17.16b\t\t// vpand\t%xmm9,\t%xmm4,\t%xmm4\t# 4 = lo\n\n\t\t\t\t\t\t// vmovdqa\t0x00(%r11),\t%xmm2\n\ttbl\tv2.16b, {v24.16b}, v4.16b\t// vpshufb\t%xmm4,\t%xmm2,\t%xmm2\n\t\t\t\t\t\t// vmovdqa\t0x10(%r11),\t%xmm3\n\ttbl\tv3.16b,\t{v25.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm3,\t%xmm3\n\teor\tv3.16b, v3.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm3,\t%xmm3\n\ttbl\tv3.16b, {v3.16b}, v9.16b\t// vpshufb\t%xmm5,\t%xmm3,\t%xmm3\n\n\t\t\t\t\t\t// vmovdqa\t0x20(%r11),\t%xmm2\n\ttbl\tv2.16b, {v26.16b}, v4.16b\t// vpshufb\t%xmm4,\t%xmm2,\t%xmm2\n\teor\tv2.16b, v2.16b, v3.16b\t\t// vpxor\t%xmm3,\t%xmm2,\t%xmm2\n\t\t\t\t\t\t// vmovdqa\t0x30(%r11),\t%xmm3\n\ttbl\tv3.16b, {v27.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm3,\t%xmm3\n\teor\tv3.16b, v3.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm3,\t%xmm3\n\ttbl\tv3.16b, {v3.16b}, v9.16b\t// vpshufb\t%xmm5,\t%xmm3,\t%xmm3\n\n\t\t\t\t\t\t// vmovdqa\t0x40(%r11),\t%xmm2\n\ttbl\tv2.16b, {v28.16b}, v4.16b\t// vpshufb\t%xmm4,\t%xmm2,\t%xmm2\n\teor\tv2.16b, v2.16b, v3.16b\t\t// vpxor\t%xmm3,\t%xmm2,\t%xmm2\n\t\t\t\t\t\t// vmovdqa\t0x50(%r11),\t%xmm3\n\ttbl\tv3.16b, {v29.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm3,\t%xmm3\n\teor\tv3.16b, v3.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm3,\t%xmm3\n\n\t\t\t\t\t\t// vmovdqa\t0x60(%r11),\t%xmm2\n\ttbl\tv2.16b, {v30.16b}, v4.16b\t// vpshufb\t%xmm4,\t%xmm2,\t%xmm2\n\ttbl\tv3.16b, {v3.16b}, v9.16b\t// vpshufb\t%xmm5,\t%xmm3,\t%xmm3\n\t\t\t\t\t\t// vmovdqa\t0x70(%r11),\t%xmm4\n\ttbl\tv4.16b, {v31.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm4,\t%xmm4\n\tld1\t{v1.2d}, [x8]\t\t\t// vmovdqa\t(%r8,%r10),\t%xmm1\n\teor\tv2.16b, v2.16b, v3.16b\t\t// vpxor\t%xmm3,\t%xmm2,\t%xmm2\n\teor\tv3.16b, v4.16b, v2.16b\t\t// vpxor\t%xmm2,\t%xmm4,\t%xmm3\n\n\tsub\tx2, x2, #16\t\t\t// add\t$-16,\t%rdx\n\n.Lschedule_mangle_both:\n\ttbl\tv3.16b, {v3.16b}, v1.16b\t// vpshufb\t%xmm1,\t%xmm3,\t%xmm3\n\tadd\tx8, x8, #64-16\t\t\t// add\t$-16,\t%r8\n\tand\tx8, x8, #~(1<<6)\t\t// and\t$0x30,\t%r8\n\tst1\t{v3.2d}, [x2]\t\t\t// vmovdqu\t%xmm3,\t(%rdx)\n\tret\n.size\t_vpaes_schedule_mangle,.-_vpaes_schedule_mangle\n\n.globl\tvpaes_set_encrypt_key\n.type\tvpaes_set_encrypt_key,%function\n.align\t4\nvpaes_set_encrypt_key:\n\tstp\tx29,x30,[sp,#-16]!\n\tadd\tx29,sp,#0\n\tstp\td8,d9,[sp,#-16]!\t// ABI spec says so\n\n\tlsr\tw9, w1, #5\t\t// shr\t$5,%eax\n\tadd\tw9, w9, #5\t\t// $5,%eax\n\tstr\tw9, [x2,#240]\t\t// mov\t%eax,240(%rdx)\t# AES_KEY->rounds = nbits/32+5;\n\n\tmov\tw3, #0\t\t// mov\t$0,%ecx\n\tmov\tx8, #0x30\t\t// mov\t$0x30,%r8d\n\tbl\t_vpaes_schedule_core\n\teor\tx0, x0, x0\n\n\tldp\td8,d9,[sp],#16\n\tldp\tx29,x30,[sp],#16\n\tret\n.size\tvpaes_set_encrypt_key,.-vpaes_set_encrypt_key\n\n.globl\tvpaes_set_decrypt_key\n.type\tvpaes_set_decrypt_key,%function\n.align\t4\nvpaes_set_decrypt_key:\n\tstp\tx29,x30,[sp,#-16]!\n\tadd\tx29,sp,#0\n\tstp\td8,d9,[sp,#-16]!\t// ABI spec says so\n\n\tlsr\tw9, w1, #5\t\t// shr\t$5,%eax\n\tadd\tw9, w9, #5\t\t// $5,%eax\n\tstr\tw9, [x2,#240]\t\t// mov\t%eax,240(%rdx)\t# AES_KEY->rounds = nbits/32+5;\n\tlsl\tw9, w9, #4\t\t// shl\t$4,%eax\n\tadd\tx2, x2, #16\t\t// lea\t16(%rdx,%rax),%rdx\n\tadd\tx2, x2, x9\n\n\tmov\tw3, #1\t\t// mov\t$1,%ecx\n\tlsr\tw8, w1, #1\t\t// shr\t$1,%r8d\n\tand\tx8, x8, #32\t\t// and\t$32,%r8d\n\teor\tx8, x8, #32\t\t// xor\t$32,%r8d\t# nbits==192?0:32\n\tbl\t_vpaes_schedule_core\n\n\tldp\td8,d9,[sp],#16\n\tldp\tx29,x30,[sp],#16\n\tret\n.size\tvpaes_set_decrypt_key,.-vpaes_set_decrypt_key\n.globl\tvpaes_cbc_encrypt\n.type\tvpaes_cbc_encrypt,%function\n.align\t4\nvpaes_cbc_encrypt:\n\tcbz\tx2, .Lcbc_abort\n\tcmp\tw5, #0\t\t\t// check direction\n\tb.eq\tvpaes_cbc_decrypt\n\n\tstp\tx29,x30,[sp,#-16]!\n\tadd\tx29,sp,#0\n\n\tmov\tx17, x2\t\t// reassign\n\tmov\tx2,  x3\t\t// reassign\n\n\tld1\t{v0.16b}, [x4]\t// load ivec\n\tbl\t_vpaes_encrypt_preheat\n\tb\t.Lcbc_enc_loop\n\n.align\t4\n.Lcbc_enc_loop:\n\tld1\t{v7.16b}, [x0],#16\t// load input\n\teor\tv7.16b, v7.16b, v0.16b\t// xor with ivec\n\tbl\t_vpaes_encrypt_core\n\tst1\t{v0.16b}, [x1],#16\t// save output\n\tsubs\tx17, x17, #16\n\tb.hi\t.Lcbc_enc_loop\n\n\tst1\t{v0.16b}, [x4]\t// write ivec\n\n\tldp\tx29,x30,[sp],#16\n.Lcbc_abort:\n\tret\n.size\tvpaes_cbc_encrypt,.-vpaes_cbc_encrypt\n\n.type\tvpaes_cbc_decrypt,%function\n.align\t4\nvpaes_cbc_decrypt:\n\tstp\tx29,x30,[sp,#-16]!\n\tadd\tx29,sp,#0\n\tstp\td8,d9,[sp,#-16]!\t// ABI spec says so\n\tstp\td10,d11,[sp,#-16]!\n\tstp\td12,d13,[sp,#-16]!\n\tstp\td14,d15,[sp,#-16]!\n\n\tmov\tx17, x2\t\t// reassign\n\tmov\tx2,  x3\t\t// reassign\n\tld1\t{v6.16b}, [x4]\t// load ivec\n\tbl\t_vpaes_decrypt_preheat\n\ttst\tx17, #16\n\tb.eq\t.Lcbc_dec_loop2x\n\n\tld1\t{v7.16b}, [x0], #16\t// load input\n\tbl\t_vpaes_decrypt_core\n\teor\tv0.16b, v0.16b, v6.16b\t// xor with ivec\n\torr\tv6.16b, v7.16b, v7.16b\t// next ivec value\n\tst1\t{v0.16b}, [x1], #16\n\tsubs\tx17, x17, #16\n\tb.ls\t.Lcbc_dec_done\n\n.align\t4\n.Lcbc_dec_loop2x:\n\tld1\t{v14.16b,v15.16b}, [x0], #32\n\tbl\t_vpaes_decrypt_2x\n\teor\tv0.16b, v0.16b, v6.16b\t// xor with ivec\n\teor\tv1.16b, v1.16b, v14.16b\n\torr\tv6.16b, v15.16b, v15.16b\n\tst1\t{v0.16b,v1.16b}, [x1], #32\n\tsubs\tx17, x17, #32\n\tb.hi\t.Lcbc_dec_loop2x\n\n.Lcbc_dec_done:\n\tst1\t{v6.16b}, [x4]\n\n\tldp\td14,d15,[sp],#16\n\tldp\td12,d13,[sp],#16\n\tldp\td10,d11,[sp],#16\n\tldp\td8,d9,[sp],#16\n\tldp\tx29,x30,[sp],#16\n\tret\n.size\tvpaes_cbc_decrypt,.-vpaes_cbc_decrypt\n.globl\tvpaes_ecb_encrypt\n.type\tvpaes_ecb_encrypt,%function\n.align\t4\nvpaes_ecb_encrypt:\n\tstp\tx29,x30,[sp,#-16]!\n\tadd\tx29,sp,#0\n\tstp\td8,d9,[sp,#-16]!\t// ABI spec says so\n\tstp\td10,d11,[sp,#-16]!\n\tstp\td12,d13,[sp,#-16]!\n\tstp\td14,d15,[sp,#-16]!\n\n\tmov\tx17, x2\n\tmov\tx2,  x3\n\tbl\t_vpaes_encrypt_preheat\n\ttst\tx17, #16\n\tb.eq\t.Lecb_enc_loop\n\n\tld1\t{v7.16b}, [x0],#16\n\tbl\t_vpaes_encrypt_core\n\tst1\t{v0.16b}, [x1],#16\n\tsubs\tx17, x17, #16\n\tb.ls\t.Lecb_enc_done\n\n.align\t4\n.Lecb_enc_loop:\n\tld1\t{v14.16b,v15.16b}, [x0], #32\n\tbl\t_vpaes_encrypt_2x\n\tst1\t{v0.16b,v1.16b}, [x1], #32\n\tsubs\tx17, x17, #32\n\tb.hi\t.Lecb_enc_loop\n\n.Lecb_enc_done:\n\tldp\td14,d15,[sp],#16\n\tldp\td12,d13,[sp],#16\n\tldp\td10,d11,[sp],#16\n\tldp\td8,d9,[sp],#16\n\tldp\tx29,x30,[sp],#16\n\tret\n.size\tvpaes_ecb_encrypt,.-vpaes_ecb_encrypt\n\n.globl\tvpaes_ecb_decrypt\n.type\tvpaes_ecb_decrypt,%function\n.align\t4\nvpaes_ecb_decrypt:\n\tstp\tx29,x30,[sp,#-16]!\n\tadd\tx29,sp,#0\n\tstp\td8,d9,[sp,#-16]!\t// ABI spec says so\n\tstp\td10,d11,[sp,#-16]!\n\tstp\td12,d13,[sp,#-16]!\n\tstp\td14,d15,[sp,#-16]!\n\n\tmov\tx17, x2\n\tmov\tx2,  x3\n\tbl\t_vpaes_decrypt_preheat\n\ttst\tx17, #16\n\tb.eq\t.Lecb_dec_loop\n\n\tld1\t{v7.16b}, [x0],#16\n\tbl\t_vpaes_encrypt_core\n\tst1\t{v0.16b}, [x1],#16\n\tsubs\tx17, x17, #16\n\tb.ls\t.Lecb_dec_done\n\n.align\t4\n.Lecb_dec_loop:\n\tld1\t{v14.16b,v15.16b}, [x0], #32\n\tbl\t_vpaes_decrypt_2x\n\tst1\t{v0.16b,v1.16b}, [x1], #32\n\tsubs\tx17, x17, #32\n\tb.hi\t.Lecb_dec_loop\n\n.Lecb_dec_done:\n\tldp\td14,d15,[sp],#16\n\tldp\td12,d13,[sp],#16\n\tldp\td10,d11,[sp],#16\n\tldp\td8,d9,[sp],#16\n\tldp\tx29,x30,[sp],#16\n\tret\n.size\tvpaes_ecb_decrypt,.-vpaes_ecb_decrypt\n"
  },
  {
    "path": "lib/aes_acc/asm/arm_arch.h",
    "content": "/*\n * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.\n *\n * Licensed under the OpenSSL license (the \"License\").  You may not use\n * this file except in compliance with the License.  You can obtain a copy\n * in the file LICENSE in the source distribution or at\n * https://www.openssl.org/source/license.html\n */\n\n#ifndef UDP2RAW_ARM_ARCH_H_\n# define UDP2RAW_ARM_ARCH_H_\n\n# if !defined(__ARM_ARCH__)\n#  if defined(__CC_ARM)\n#   define __ARM_ARCH__ __TARGET_ARCH_ARM\n#   if defined(__BIG_ENDIAN)\n#    define __ARMEB__\n#   else\n#    define __ARMEL__\n#   endif\n#  elif defined(__GNUC__)\n#   if   defined(__aarch64__)\n#    define __ARM_ARCH__ 8\n#    if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__\n#     define __ARMEB__\n#    else\n#     define __ARMEL__\n#    endif\n  /*\n   * Why doesn't gcc define __ARM_ARCH__? Instead it defines\n   * bunch of below macros. See all_architectires[] table in\n   * gcc/config/arm/arm.c. On a side note it defines\n   * __ARMEL__/__ARMEB__ for little-/big-endian.\n   */\n#   elif defined(__ARM_ARCH)\n#    define __ARM_ARCH__ __ARM_ARCH\n#   elif defined(__ARM_ARCH_8A__)\n#    define __ARM_ARCH__ 8\n#   elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)     || \\\n        defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__)     || \\\n        defined(__ARM_ARCH_7EM__)\n#    define __ARM_ARCH__ 7\n#   elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__)     || \\\n        defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__)     || \\\n        defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__)    || \\\n        defined(__ARM_ARCH_6T2__)\n#    define __ARM_ARCH__ 6\n#   elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__)     || \\\n        defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__)    || \\\n        defined(__ARM_ARCH_5TEJ__)\n#    define __ARM_ARCH__ 5\n#   elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)\n#    define __ARM_ARCH__ 4\n#   else\n#    error \"unsupported ARM architecture\"\n#   endif\n#  endif\n# endif\n\n# if !defined(__ARM_MAX_ARCH__)\n#  define __ARM_MAX_ARCH__ __ARM_ARCH__\n# endif\n\n# if __ARM_MAX_ARCH__<__ARM_ARCH__\n#  error \"__ARM_MAX_ARCH__ can't be less than __ARM_ARCH__\"\n# elif __ARM_MAX_ARCH__!=__ARM_ARCH__\n#  if __ARM_ARCH__<7 && __ARM_MAX_ARCH__>=7 && defined(__ARMEB__)\n#   error \"can't build universal big-endian binary\"\n#  endif\n# endif\n\n# if !__ASSEMBLER__\nextern unsigned int OPENSSL_armcap_P;\n# endif\n\n# define ARMV7_NEON      (1<<0)\n# define ARMV7_TICK      (1<<1)\n# define ARMV8_AES       (1<<2)\n# define ARMV8_SHA1      (1<<3)\n# define ARMV8_SHA256    (1<<4)\n# define ARMV8_PMULL     (1<<5)\n\n#endif\n"
  },
  {
    "path": "lib/aes_acc/asm/mips.S",
    "content": ".text\n#ifdef OPENSSL_FIPSCANISTER\n# include <openssl/fipssyms.h>\n#endif\n\n#if defined(__mips_smartmips) && !defined(_MIPS_ARCH_MIPS32R2)\n#define _MIPS_ARCH_MIPS32R2\n#endif\n\n#if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__))\n.option\tpic2\n#endif\n.set\tnoat\n.align\t5\n.ent\t_mips_AES_encrypt\n_mips_AES_encrypt:\n\t.frame\t$29,0,$31\n\t.set\treorder\n\tlw\t$12,0($6)\n\tlw\t$13,4($6)\n\tlw\t$14,8($6)\n\tlw\t$15,12($6)\n\tlw\t$30,240($6)\n\tadd $3,$6,16\n\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\n\tsub\t$30,1\n#if defined(__mips_smartmips)\n\text\t$1,$9,8,8\n.Loop_enc:\n\text\t$2,$10,8,8\n\text\t$24,$11,8,8\n\text\t$25,$8,8,8\n\tlwxs\t$12,$1($7)\t\t# Te1[s1>>16]\n\text\t$1,$10,16,8\n\tlwxs\t$13,$2($7)\t\t# Te1[s2>>16]\n\text\t$2,$11,16,8\n\tlwxs\t$14,$24($7)\t\t# Te1[s3>>16]\n\text\t$24,$8,16,8\n\tlwxs\t$15,$25($7)\t\t# Te1[s0>>16]\n\text\t$25,$9,16,8\n\n\tlwxs\t$16,$1($7)\t\t# Te2[s2>>8]\n\text\t$1,$11,24,8\n\tlwxs\t$17,$2($7)\t\t# Te2[s3>>8]\n\text\t$2,$8,24,8\n\tlwxs\t$18,$24($7)\t\t# Te2[s0>>8]\n\text\t$24,$9,24,8\n\tlwxs\t$19,$25($7)\t\t# Te2[s1>>8]\n\text\t$25,$10,24,8\n\n\tlwxs\t$20,$1($7)\t\t# Te3[s3]\n\text\t$1,$8,0,8\n\tlwxs\t$21,$2($7)\t\t# Te3[s0]\n\text\t$2,$9,0,8\n\tlwxs\t$22,$24($7)\t\t# Te3[s1]\n\text\t$24,$10,0,8\n\tlwxs\t$23,$25($7)\t\t# Te3[s2]\n\text\t$25,$11,0,8\n\n\trotr\t$12,$12,24\n\trotr\t$13,$13,24\n\trotr\t$14,$14,24\n\trotr\t$15,$15,24\n\n\trotr\t$16,$16,16\n\trotr\t$17,$17,16\n\trotr\t$18,$18,16\n\trotr\t$19,$19,16\n\n\txor\t$12,$16\n\tlwxs\t$16,$1($7)\t\t# Te0[s0>>24]\n\txor\t$13,$17\n\tlwxs\t$17,$2($7)\t\t# Te0[s1>>24]\n\txor\t$14,$18\n\tlwxs\t$18,$24($7)\t\t# Te0[s2>>24]\n\txor\t$15,$19\n\tlwxs\t$19,$25($7)\t\t# Te0[s3>>24]\n\n\trotr\t$20,$20,8\n\tlw\t$8,0($3)\n\trotr\t$21,$21,8\n\tlw\t$9,4($3)\n\trotr\t$22,$22,8\n\tlw\t$10,8($3)\n\trotr\t$23,$23,8\n\tlw\t$11,12($3)\n\n\txor\t$12,$20\n\txor\t$13,$21\n\txor\t$14,$22\n\txor\t$15,$23\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n\n\tsub\t$30,1\n\tadd $3,16\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\t.set\tnoreorder\n\tbnez\t$30,.Loop_enc\n\text\t$1,$9,8,8\n\n\tsrl\t$1,$9,6\n#else\n\tsrl\t$1,$9,6\n.Loop_enc:\n\tsrl\t$2,$10,6\n\tsrl\t$24,$11,6\n\tsrl\t$25,$8,6\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\tlw\t$12,0($1)\t\t# Te1[s1>>16]\n\tsrl\t$1,$10,14\n\tlw\t$13,0($2)\t\t# Te1[s2>>16]\n\tsrl\t$2,$11,14\n\tlw\t$14,0($24)\t\t# Te1[s3>>16]\n\tsrl\t$24,$8,14\n\tlw\t$15,0($25)\t\t# Te1[s0>>16]\n\tsrl\t$25,$9,14\n#else\n\tlwl\t$12,2($1)\t\t# Te1[s1>>16]\n\tlwl\t$13,2($2)\t\t# Te1[s2>>16]\n\tlwl\t$14,2($24)\t\t# Te1[s3>>16]\n\tlwl\t$15,2($25)\t\t# Te1[s0>>16]\n\tlwr\t$12,3($1)\t\t# Te1[s1>>16]\n\tsrl\t$1,$10,14\n\tlwr\t$13,3($2)\t\t# Te1[s2>>16]\n\tsrl\t$2,$11,14\n\tlwr\t$14,3($24)\t\t# Te1[s3>>16]\n\tsrl\t$24,$8,14\n\tlwr\t$15,3($25)\t\t# Te1[s0>>16]\n\tsrl\t$25,$9,14\n#endif\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\trotr\t$12,$12,24\n\trotr\t$13,$13,24\n\trotr\t$14,$14,24\n\trotr\t$15,$15,24\n# if defined(_MIPSEL)\n\tlw\t$16,0($1)\t\t# Te2[s2>>8]\n\tsrl\t$1,$11,22\n\tlw\t$17,0($2)\t\t# Te2[s3>>8]\n\tsrl\t$2,$8,22\n\tlw\t$18,0($24)\t\t# Te2[s0>>8]\n\tsrl\t$24,$9,22\n\tlw\t$19,0($25)\t\t# Te2[s1>>8]\n\tsrl\t$25,$10,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlw\t$20,0($1)\t\t# Te3[s3]\n\tins $1,$8,2,8\n\tlw\t$21,0($2)\t\t# Te3[s0]\n\tins $2,$9,2,8\n\tlw\t$22,0($24)\t\t# Te3[s1]\n\tins $24,$10,2,8\n\tlw\t$23,0($25)\t\t# Te3[s2]\n\tins $25,$11,2,8\n# else\n\tlw\t$16,0($1)\t\t# Te2[s2>>8]\n\tins $1,$11,2,8\n\tlw\t$17,0($2)\t\t# Te2[s3>>8]\n\tins $2,$8,2,8\n\tlw\t$18,0($24)\t\t# Te2[s0>>8]\n\tins $24,$9,2,8\n\tlw\t$19,0($25)\t\t# Te2[s1>>8]\n\tins $25,$10,2,8\n\n\tlw\t$20,0($1)\t\t# Te3[s3]\n\tsll\t$1,$8,2\n\tlw\t$21,0($2)\t\t# Te3[s0]\n\tsll\t$2,$9,2\n\tlw\t$22,0($24)\t\t# Te3[s1]\n\tsll\t$24,$10,2\n\tlw\t$23,0($25)\t\t# Te3[s2]\n\tsll\t$25,$11,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n# endif\n\trotr\t$16,$16,16\n\trotr\t$17,$17,16\n\trotr\t$18,$18,16\n\trotr\t$19,$19,16\n\n\trotr\t$20,$20,8\n\trotr\t$21,$21,8\n\trotr\t$22,$22,8\n\trotr\t$23,$23,8\n#else\n\tlwl\t$16,1($1)\t\t# Te2[s2>>8]\n\tlwl\t$17,1($2)\t\t# Te2[s3>>8]\n\tlwl\t$18,1($24)\t\t# Te2[s0>>8]\n\tlwl\t$19,1($25)\t\t# Te2[s1>>8]\n\tlwr\t$16,2($1)\t\t# Te2[s2>>8]\n\tsrl\t$1,$11,22\n\tlwr\t$17,2($2)\t\t# Te2[s3>>8]\n\tsrl\t$2,$8,22\n\tlwr\t$18,2($24)\t\t# Te2[s0>>8]\n\tsrl\t$24,$9,22\n\tlwr\t$19,2($25)\t\t# Te2[s1>>8]\n\tsrl\t$25,$10,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlwl\t$20,0($1)\t\t# Te3[s3]\n\tlwl\t$21,0($2)\t\t# Te3[s0]\n\tlwl\t$22,0($24)\t\t# Te3[s1]\n\tlwl\t$23,0($25)\t\t# Te3[s2]\n\tlwr\t$20,1($1)\t\t# Te3[s3]\n\tsll\t$1,$8,2\n\tlwr\t$21,1($2)\t\t# Te3[s0]\n\tsll\t$2,$9,2\n\tlwr\t$22,1($24)\t\t# Te3[s1]\n\tsll\t$24,$10,2\n\tlwr\t$23,1($25)\t\t# Te3[s2]\n\tsll\t$25,$11,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#endif\n\txor\t$12,$16\n\tlw\t$16,0($1)\t\t# Te0[s0>>24]\n\txor\t$13,$17\n\tlw\t$17,0($2)\t\t# Te0[s1>>24]\n\txor\t$14,$18\n\tlw\t$18,0($24)\t\t# Te0[s2>>24]\n\txor\t$15,$19\n\tlw\t$19,0($25)\t\t# Te0[s3>>24]\n\n\txor\t$12,$20\n\tlw\t$8,0($3)\n\txor\t$13,$21\n\tlw\t$9,4($3)\n\txor\t$14,$22\n\tlw\t$10,8($3)\n\txor\t$15,$23\n\tlw\t$11,12($3)\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n\n\tsub\t$30,1\n\tadd $3,16\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\t.set\tnoreorder\n\tbnez\t$30,.Loop_enc\n\tsrl\t$1,$9,6\n#endif\n\n\t.set\treorder\n\tsrl\t$2,$10,6\n\tsrl\t$24,$11,6\n\tsrl\t$25,$8,6\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$12,2($1)\t\t# Te4[s1>>16]\n\tsrl\t$1,$10,14\n\tlbu\t$13,2($2)\t\t# Te4[s2>>16]\n\tsrl\t$2,$11,14\n\tlbu\t$14,2($24)\t\t# Te4[s3>>16]\n\tsrl\t$24,$8,14\n\tlbu\t$15,2($25)\t\t# Te4[s0>>16]\n\tsrl\t$25,$9,14\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n# if defined(_MIPSEL)\n\tlbu\t$16,2($1)\t\t# Te4[s2>>8]\n\tins $1,$8,2,8\n\tlbu\t$17,2($2)\t\t# Te4[s3>>8]\n\tins $2,$9,2,8\n\tlbu\t$18,2($24)\t\t# Te4[s0>>8]\n\tins $24,$10,2,8\n\tlbu\t$19,2($25)\t\t# Te4[s1>>8]\n\tins $25,$11,2,8\n\n\tlbu\t$20,2($1)\t\t# Te4[s0>>24]\n\tsrl\t$1,$11,22\n\tlbu\t$21,2($2)\t\t# Te4[s1>>24]\n\tsrl\t$2,$8,22\n\tlbu\t$22,2($24)\t\t# Te4[s2>>24]\n\tsrl\t$24,$9,22\n\tlbu\t$23,2($25)\t\t# Te4[s3>>24]\n\tsrl\t$25,$10,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n# else\n\tlbu\t$16,2($1)\t\t# Te4[s2>>8]\n\tsll\t$1,$8,2\n\tlbu\t$17,2($2)\t\t# Te4[s3>>8]\n\tsll\t$2,$9,2\n\tlbu\t$18,2($24)\t\t# Te4[s0>>8]\n\tsll\t$24,$10,2\n\tlbu\t$19,2($25)\t\t# Te4[s1>>8]\n\tsll\t$25,$11,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$20,2($1)\t\t# Te4[s0>>24]\n\tins $1,$11,2,8\n\tlbu\t$21,2($2)\t\t# Te4[s1>>24]\n\tins $2,$8,2,8\n\tlbu\t$22,2($24)\t\t# Te4[s2>>24]\n\tins $24,$9,2,8\n\tlbu\t$23,2($25)\t\t# Te4[s3>>24]\n\tins $25,$10,2,8\n# endif\n\tsll\t$12,$12,8\n\tsll\t$13,$13,8\n\tsll\t$14,$14,8\n\tsll\t$15,$15,8\n\n\tins\t$12,$16,16,8\n\tlbu\t$16,2($1)\t\t# Te4[s3]\n\tins\t$13,$17,16,8\n\tlbu\t$17,2($2)\t\t# Te4[s0]\n\tins\t$14,$18,16,8\n\tlbu\t$18,2($24)\t\t# Te4[s1]\n\tins\t$15,$19,16,8\n\tlbu\t$19,2($25)\t\t# Te4[s2]\n\n\tins\t$12,$20,0,8\n\tlw\t$8,0($3)\n\tins\t$13,$21,0,8\n\tlw\t$9,4($3)\n\tins\t$14,$22,0,8\n\tlw\t$10,8($3)\n\tins\t$15,$23,0,8\n\tlw\t$11,12($3)\n\n\tins\t$12,$16,24,8\n\tins\t$13,$17,24,8\n\tins\t$14,$18,24,8\n\tins\t$15,$19,24,8\n#else\n\tlbu\t$16,2($1)\t\t# Te4[s2>>8]\n\tsll\t$1,$8,2\n\tlbu\t$17,2($2)\t\t# Te4[s3>>8]\n\tsll\t$2,$9,2\n\tlbu\t$18,2($24)\t\t# Te4[s0>>8]\n\tsll\t$24,$10,2\n\tlbu\t$19,2($25)\t\t# Te4[s1>>8]\n\tsll\t$25,$11,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$20,2($1)\t\t# Te4[s0>>24]\n\tsrl\t$1,$11,22\n\tlbu\t$21,2($2)\t\t# Te4[s1>>24]\n\tsrl\t$2,$8,22\n\tlbu\t$22,2($24)\t\t# Te4[s2>>24]\n\tsrl\t$24,$9,22\n\tlbu\t$23,2($25)\t\t# Te4[s3>>24]\n\tsrl\t$25,$10,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\n\tsll\t$12,$12,8\n\tsll\t$13,$13,8\n\tsll\t$14,$14,8\n\tsll\t$15,$15,8\n\n\tsll\t$16,$16,16\n\tsll\t$17,$17,16\n\tsll\t$18,$18,16\n\tsll\t$19,$19,16\n\n\txor\t$12,$16\n\tlbu\t$16,2($1)\t\t# Te4[s3]\n\txor\t$13,$17\n\tlbu\t$17,2($2)\t\t# Te4[s0]\n\txor\t$14,$18\n\tlbu\t$18,2($24)\t\t# Te4[s1]\n\txor\t$15,$19\n\tlbu\t$19,2($25)\t\t# Te4[s2]\n\n\t#sll\t$20,$20,0\n\tlw\t$8,0($3)\n\t#sll\t$21,$21,0\n\tlw\t$9,4($3)\n\t#sll\t$22,$22,0\n\tlw\t$10,8($3)\n\t#sll\t$23,$23,0\n\tlw\t$11,12($3)\n\n\txor\t$12,$20\n\txor\t$13,$21\n\txor\t$14,$22\n\txor\t$15,$23\n\n\tsll\t$16,$16,24\n\tsll\t$17,$17,24\n\tsll\t$18,$18,24\n\tsll\t$19,$19,24\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n#endif\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\n\tjr\t$31\n.end\t_mips_AES_encrypt\n\n.align\t5\n.globl\tAES_encrypt\n.ent\tAES_encrypt\nAES_encrypt:\n\t.frame\t$29,64,$31\n\t.mask\t0xc0ff0000,-4\n\t.set\tnoreorder\n\t.cpload\t$25\n\tsub $29,64\n\tsw\t$31,64-1*4($29)\n\tsw\t$30,64-2*4($29)\n\tsw\t$23,64-3*4($29)\n\tsw\t$22,64-4*4($29)\n\tsw\t$21,64-5*4($29)\n\tsw\t$20,64-6*4($29)\n\tsw\t$19,64-7*4($29)\n\tsw\t$18,64-8*4($29)\n\tsw\t$17,64-9*4($29)\n\tsw\t$16,64-10*4($29)\n\t.set\treorder\n\tla\t$7,AES_Te\t\t# PIC-ified 'load address'\n\n\tlwl\t$8,0+3($4)\n\tlwl\t$9,4+3($4)\n\tlwl\t$10,8+3($4)\n\tlwl\t$11,12+3($4)\n\tlwr\t$8,0+0($4)\n\tlwr\t$9,4+0($4)\n\tlwr\t$10,8+0($4)\n\tlwr\t$11,12+0($4)\n\n\tbal\t_mips_AES_encrypt\n\n\tswr\t$8,0+0($5)\n\tswr\t$9,4+0($5)\n\tswr\t$10,8+0($5)\n\tswr\t$11,12+0($5)\n\tswl\t$8,0+3($5)\n\tswl\t$9,4+3($5)\n\tswl\t$10,8+3($5)\n\tswl\t$11,12+3($5)\n\n\t.set\tnoreorder\n\tlw\t$31,64-1*4($29)\n\tlw\t$30,64-2*4($29)\n\tlw\t$23,64-3*4($29)\n\tlw\t$22,64-4*4($29)\n\tlw\t$21,64-5*4($29)\n\tlw\t$20,64-6*4($29)\n\tlw\t$19,64-7*4($29)\n\tlw\t$18,64-8*4($29)\n\tlw\t$17,64-9*4($29)\n\tlw\t$16,64-10*4($29)\n\tjr\t$31\n\tadd $29,64\n.end\tAES_encrypt\n.align\t5\n.ent\t_mips_AES_decrypt\n_mips_AES_decrypt:\n\t.frame\t$29,0,$31\n\t.set\treorder\n\tlw\t$12,0($6)\n\tlw\t$13,4($6)\n\tlw\t$14,8($6)\n\tlw\t$15,12($6)\n\tlw\t$30,240($6)\n\tadd $3,$6,16\n\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\n\tsub\t$30,1\n#if defined(__mips_smartmips)\n\text\t$1,$11,8,8\n.Loop_dec:\n\text\t$2,$8,8,8\n\text\t$24,$9,8,8\n\text\t$25,$10,8,8\n\tlwxs\t$12,$1($7)\t\t# Td1[s3>>16]\n\text\t$1,$10,16,8\n\tlwxs\t$13,$2($7)\t\t# Td1[s0>>16]\n\text\t$2,$11,16,8\n\tlwxs\t$14,$24($7)\t\t# Td1[s1>>16]\n\text\t$24,$8,16,8\n\tlwxs\t$15,$25($7)\t\t# Td1[s2>>16]\n\text\t$25,$9,16,8\n\n\tlwxs\t$16,$1($7)\t\t# Td2[s2>>8]\n\text\t$1,$9,24,8\n\tlwxs\t$17,$2($7)\t\t# Td2[s3>>8]\n\text\t$2,$10,24,8\n\tlwxs\t$18,$24($7)\t\t# Td2[s0>>8]\n\text\t$24,$11,24,8\n\tlwxs\t$19,$25($7)\t\t# Td2[s1>>8]\n\text\t$25,$8,24,8\n\n\tlwxs\t$20,$1($7)\t\t# Td3[s1]\n\text\t$1,$8,0,8\n\tlwxs\t$21,$2($7)\t\t# Td3[s2]\n\text\t$2,$9,0,8\n\tlwxs\t$22,$24($7)\t\t# Td3[s3]\n\text\t$24,$10,0,8\n\tlwxs\t$23,$25($7)\t\t# Td3[s0]\n\text\t$25,$11,0,8\n\n\trotr\t$12,$12,24\n\trotr\t$13,$13,24\n\trotr\t$14,$14,24\n\trotr\t$15,$15,24\n\n\trotr\t$16,$16,16\n\trotr\t$17,$17,16\n\trotr\t$18,$18,16\n\trotr\t$19,$19,16\n\n\txor\t$12,$16\n\tlwxs\t$16,$1($7)\t\t# Td0[s0>>24]\n\txor\t$13,$17\n\tlwxs\t$17,$2($7)\t\t# Td0[s1>>24]\n\txor\t$14,$18\n\tlwxs\t$18,$24($7)\t\t# Td0[s2>>24]\n\txor\t$15,$19\n\tlwxs\t$19,$25($7)\t\t# Td0[s3>>24]\n\n\trotr\t$20,$20,8\n\tlw\t$8,0($3)\n\trotr\t$21,$21,8\n\tlw\t$9,4($3)\n\trotr\t$22,$22,8\n\tlw\t$10,8($3)\n\trotr\t$23,$23,8\n\tlw\t$11,12($3)\n\n\txor\t$12,$20\n\txor\t$13,$21\n\txor\t$14,$22\n\txor\t$15,$23\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n\n\tsub\t$30,1\n\tadd $3,16\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\t.set\tnoreorder\n\tbnez\t$30,.Loop_dec\n\text\t$1,$11,8,8\n\n\tsrl\t$1,$11,6\n#else\n\tsrl\t$1,$11,6\n.Loop_dec:\n\tsrl\t$2,$8,6\n\tsrl\t$24,$9,6\n\tsrl\t$25,$10,6\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\tlw\t$12,0($1)\t\t# Td1[s3>>16]\n\tsrl\t$1,$10,14\n\tlw\t$13,0($2)\t\t# Td1[s0>>16]\n\tsrl\t$2,$11,14\n\tlw\t$14,0($24)\t\t# Td1[s1>>16]\n\tsrl\t$24,$8,14\n\tlw\t$15,0($25)\t\t# Td1[s2>>16]\n\tsrl\t$25,$9,14\n#else\n\tlwl\t$12,2($1)\t\t# Td1[s3>>16]\n\tlwl\t$13,2($2)\t\t# Td1[s0>>16]\n\tlwl\t$14,2($24)\t\t# Td1[s1>>16]\n\tlwl\t$15,2($25)\t\t# Td1[s2>>16]\n\tlwr\t$12,3($1)\t\t# Td1[s3>>16]\n\tsrl\t$1,$10,14\n\tlwr\t$13,3($2)\t\t# Td1[s0>>16]\n\tsrl\t$2,$11,14\n\tlwr\t$14,3($24)\t\t# Td1[s1>>16]\n\tsrl\t$24,$8,14\n\tlwr\t$15,3($25)\t\t# Td1[s2>>16]\n\tsrl\t$25,$9,14\n#endif\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\trotr\t$12,$12,24\n\trotr\t$13,$13,24\n\trotr\t$14,$14,24\n\trotr\t$15,$15,24\n# if defined(_MIPSEL)\n\tlw\t$16,0($1)\t\t# Td2[s2>>8]\n\tsrl\t$1,$9,22\n\tlw\t$17,0($2)\t\t# Td2[s3>>8]\n\tsrl\t$2,$10,22\n\tlw\t$18,0($24)\t\t# Td2[s0>>8]\n\tsrl\t$24,$11,22\n\tlw\t$19,0($25)\t\t# Td2[s1>>8]\n\tsrl\t$25,$8,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlw\t$20,0($1)\t\t# Td3[s1]\n\tins $1,$8,2,8\n\tlw\t$21,0($2)\t\t# Td3[s2]\n\tins $2,$9,2,8\n\tlw\t$22,0($24)\t\t# Td3[s3]\n\tins $24,$10,2,8\n\tlw\t$23,0($25)\t\t# Td3[s0]\n\tins $25,$11,2,8\n#else\n\tlw\t$16,0($1)\t\t# Td2[s2>>8]\n\tins $1,$9,2,8\n\tlw\t$17,0($2)\t\t# Td2[s3>>8]\n\tins $2,$10,2,8\n\tlw\t$18,0($24)\t\t# Td2[s0>>8]\n\tins $24,$11,2,8\n\tlw\t$19,0($25)\t\t# Td2[s1>>8]\n\tins $25,$8,2,8\n\n\tlw\t$20,0($1)\t\t# Td3[s1]\n\tsll\t$1,$8,2\n\tlw\t$21,0($2)\t\t# Td3[s2]\n\tsll\t$2,$9,2\n\tlw\t$22,0($24)\t\t# Td3[s3]\n\tsll\t$24,$10,2\n\tlw\t$23,0($25)\t\t# Td3[s0]\n\tsll\t$25,$11,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#endif\n\trotr\t$16,$16,16\n\trotr\t$17,$17,16\n\trotr\t$18,$18,16\n\trotr\t$19,$19,16\n\n\trotr\t$20,$20,8\n\trotr\t$21,$21,8\n\trotr\t$22,$22,8\n\trotr\t$23,$23,8\n#else\n\tlwl\t$16,1($1)\t\t# Td2[s2>>8]\n\tlwl\t$17,1($2)\t\t# Td2[s3>>8]\n\tlwl\t$18,1($24)\t\t# Td2[s0>>8]\n\tlwl\t$19,1($25)\t\t# Td2[s1>>8]\n\tlwr\t$16,2($1)\t\t# Td2[s2>>8]\n\tsrl\t$1,$9,22\n\tlwr\t$17,2($2)\t\t# Td2[s3>>8]\n\tsrl\t$2,$10,22\n\tlwr\t$18,2($24)\t\t# Td2[s0>>8]\n\tsrl\t$24,$11,22\n\tlwr\t$19,2($25)\t\t# Td2[s1>>8]\n\tsrl\t$25,$8,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlwl\t$20,0($1)\t\t# Td3[s1]\n\tlwl\t$21,0($2)\t\t# Td3[s2]\n\tlwl\t$22,0($24)\t\t# Td3[s3]\n\tlwl\t$23,0($25)\t\t# Td3[s0]\n\tlwr\t$20,1($1)\t\t# Td3[s1]\n\tsll\t$1,$8,2\n\tlwr\t$21,1($2)\t\t# Td3[s2]\n\tsll\t$2,$9,2\n\tlwr\t$22,1($24)\t\t# Td3[s3]\n\tsll\t$24,$10,2\n\tlwr\t$23,1($25)\t\t# Td3[s0]\n\tsll\t$25,$11,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#endif\n\n\txor\t$12,$16\n\tlw\t$16,0($1)\t\t# Td0[s0>>24]\n\txor\t$13,$17\n\tlw\t$17,0($2)\t\t# Td0[s1>>24]\n\txor\t$14,$18\n\tlw\t$18,0($24)\t\t# Td0[s2>>24]\n\txor\t$15,$19\n\tlw\t$19,0($25)\t\t# Td0[s3>>24]\n\n\txor\t$12,$20\n\tlw\t$8,0($3)\n\txor\t$13,$21\n\tlw\t$9,4($3)\n\txor\t$14,$22\n\tlw\t$10,8($3)\n\txor\t$15,$23\n\tlw\t$11,12($3)\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n\n\tsub\t$30,1\n\tadd $3,16\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\t.set\tnoreorder\n\tbnez\t$30,.Loop_dec\n\tsrl\t$1,$11,6\n#endif\n\n\t.set\treorder\n\tlw\t$16,1024($7)\t\t# prefetch Td4\n\tsrl\t$1,$11,8\n\tlw\t$17,1024+32($7)\n\tsrl\t$2,$8,8\n\tlw\t$18,1024+64($7)\n\tsrl\t$24,$9,8\n\tlw\t$19,1024+96($7)\n\tsrl\t$25,$10,8\n\tlw\t$20,1024+128($7)\n\tand\t$1,0xff\n\tlw\t$21,1024+160($7)\n\tand\t$2,0xff\n\tlw\t$22,1024+192($7)\n\tand\t$24,0xff\n\tlw\t$23,1024+224($7)\n\tand\t$25,0xff\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$12,1024($1)\t\t# Td4[s3>>16]\n\tsrl\t$1,$10,16\n\tlbu\t$13,1024($2)\t\t# Td4[s0>>16]\n\tsrl\t$2,$11,16\n\tlbu\t$14,1024($24)\t\t# Td4[s1>>16]\n\tsrl\t$24,$8,16\n\tlbu\t$15,1024($25)\t\t# Td4[s2>>16]\n\tsrl\t$25,$9,16\n\n\tand\t$1,0xff\n\tand\t$2,0xff\n\tand\t$24,0xff\n\tand\t$25,0xff\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n# if defined(_MIPSEL)\n\tlbu\t$16,1024($1)\t\t# Td4[s2>>8]\n\tins $1,$8,0,8\n\tlbu\t$17,1024($2)\t\t# Td4[s3>>8]\n\tins $2,$9,0,8\n\tlbu\t$18,1024($24)\t\t# Td4[s0>>8]\n\tins $24,$10,0,8\n\tlbu\t$19,1024($25)\t\t# Td4[s1>>8]\n\tins $25,$11,0,8\n\n\tlbu\t$20,1024($1)\t\t# Td4[s0>>24]\n\tsrl\t$1,$9,24\n\tlbu\t$21,1024($2)\t\t# Td4[s1>>24]\n\tsrl\t$2,$10,24\n\tlbu\t$22,1024($24)\t\t# Td4[s2>>24]\n\tsrl\t$24,$11,24\n\tlbu\t$23,1024($25)\t\t# Td4[s3>>24]\n\tsrl\t$25,$8,24\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n# else\n\tlbu\t$16,1024($1)\t\t# Td4[s2>>8]\n\tand\t$1,$8,0xff\n\tlbu\t$17,1024($2)\t\t# Td4[s3>>8]\n\tand\t$2,$9,0xff\n\tlbu\t$18,1024($24)\t\t# Td4[s0>>8]\n\tand\t$24,$10,0xff\n\tlbu\t$19,1024($25)\t\t# Td4[s1>>8]\n\tand\t$25,$11,0xff\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$20,1024($1)\t\t# Td4[s0>>24]\n\tins $1,$9,0,8\n\tlbu\t$21,1024($2)\t\t# Td4[s1>>24]\n\tins $2,$10,0,8\n\tlbu\t$22,1024($24)\t\t# Td4[s2>>24]\n\tins $24,$11,0,8\n\tlbu\t$23,1024($25)\t\t# Td4[s3>>24]\n\tins $25,$8,0,8\n# endif\n\tsll\t$12,$12,8\n\tsll\t$13,$13,8\n\tsll\t$14,$14,8\n\tsll\t$15,$15,8\n\n\tins\t$12,$16,16,8\n\tlbu\t$16,1024($1)\t\t# Td4[s1]\n\tins\t$13,$17,16,8\n\tlbu\t$17,1024($2)\t\t# Td4[s2]\n\tins\t$14,$18,16,8\n\tlbu\t$18,1024($24)\t\t# Td4[s3]\n\tins\t$15,$19,16,8\n\tlbu\t$19,1024($25)\t\t# Td4[s0]\n\n\tins\t$12,$20,0,8\n\tlw\t$8,0($3)\n\tins\t$13,$21,0,8\n\tlw\t$9,4($3)\n\tins\t$14,$22,0,8\n\tlw\t$10,8($3)\n\tins\t$15,$23,0,8\n\tlw\t$11,12($3)\n\n\tins\t$12,$16,24,8\n\tins\t$13,$17,24,8\n\tins\t$14,$18,24,8\n\tins\t$15,$19,24,8\n#else\n\tlbu\t$16,1024($1)\t\t# Td4[s2>>8]\n\tand\t$1,$8,0xff\n\tlbu\t$17,1024($2)\t\t# Td4[s3>>8]\n\tand\t$2,$9,0xff\n\tlbu\t$18,1024($24)\t\t# Td4[s0>>8]\n\tand\t$24,$10,0xff\n\tlbu\t$19,1024($25)\t\t# Td4[s1>>8]\n\tand\t$25,$11,0xff\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$20,1024($1)\t\t# Td4[s0>>24]\n\tsrl\t$1,$9,24\n\tlbu\t$21,1024($2)\t\t# Td4[s1>>24]\n\tsrl\t$2,$10,24\n\tlbu\t$22,1024($24)\t\t# Td4[s2>>24]\n\tsrl\t$24,$11,24\n\tlbu\t$23,1024($25)\t\t# Td4[s3>>24]\n\tsrl\t$25,$8,24\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\n\tsll\t$12,$12,8\n\tsll\t$13,$13,8\n\tsll\t$14,$14,8\n\tsll\t$15,$15,8\n\n\tsll\t$16,$16,16\n\tsll\t$17,$17,16\n\tsll\t$18,$18,16\n\tsll\t$19,$19,16\n\n\txor\t$12,$16\n\tlbu\t$16,1024($1)\t\t# Td4[s1]\n\txor\t$13,$17\n\tlbu\t$17,1024($2)\t\t# Td4[s2]\n\txor\t$14,$18\n\tlbu\t$18,1024($24)\t\t# Td4[s3]\n\txor\t$15,$19\n\tlbu\t$19,1024($25)\t\t# Td4[s0]\n\n\t#sll\t$20,$20,0\n\tlw\t$8,0($3)\n\t#sll\t$21,$21,0\n\tlw\t$9,4($3)\n\t#sll\t$22,$22,0\n\tlw\t$10,8($3)\n\t#sll\t$23,$23,0\n\tlw\t$11,12($3)\n\n\txor\t$12,$20\n\txor\t$13,$21\n\txor\t$14,$22\n\txor\t$15,$23\n\n\tsll\t$16,$16,24\n\tsll\t$17,$17,24\n\tsll\t$18,$18,24\n\tsll\t$19,$19,24\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n#endif\n\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\n\tjr\t$31\n.end\t_mips_AES_decrypt\n\n.align\t5\n.globl\tAES_decrypt\n.ent\tAES_decrypt\nAES_decrypt:\n\t.frame\t$29,64,$31\n\t.mask\t0xc0ff0000,-4\n\t.set\tnoreorder\n\t.cpload\t$25\n\tsub $29,64\n\tsw\t$31,64-1*4($29)\n\tsw\t$30,64-2*4($29)\n\tsw\t$23,64-3*4($29)\n\tsw\t$22,64-4*4($29)\n\tsw\t$21,64-5*4($29)\n\tsw\t$20,64-6*4($29)\n\tsw\t$19,64-7*4($29)\n\tsw\t$18,64-8*4($29)\n\tsw\t$17,64-9*4($29)\n\tsw\t$16,64-10*4($29)\n\t.set\treorder\n\tla\t$7,AES_Td\t\t# PIC-ified 'load address'\n\n\tlwl\t$8,0+3($4)\n\tlwl\t$9,4+3($4)\n\tlwl\t$10,8+3($4)\n\tlwl\t$11,12+3($4)\n\tlwr\t$8,0+0($4)\n\tlwr\t$9,4+0($4)\n\tlwr\t$10,8+0($4)\n\tlwr\t$11,12+0($4)\n\n\tbal\t_mips_AES_decrypt\n\n\tswr\t$8,0+0($5)\n\tswr\t$9,4+0($5)\n\tswr\t$10,8+0($5)\n\tswr\t$11,12+0($5)\n\tswl\t$8,0+3($5)\n\tswl\t$9,4+3($5)\n\tswl\t$10,8+3($5)\n\tswl\t$11,12+3($5)\n\n\t.set\tnoreorder\n\tlw\t$31,64-1*4($29)\n\tlw\t$30,64-2*4($29)\n\tlw\t$23,64-3*4($29)\n\tlw\t$22,64-4*4($29)\n\tlw\t$21,64-5*4($29)\n\tlw\t$20,64-6*4($29)\n\tlw\t$19,64-7*4($29)\n\tlw\t$18,64-8*4($29)\n\tlw\t$17,64-9*4($29)\n\tlw\t$16,64-10*4($29)\n\tjr\t$31\n\tadd $29,64\n.end\tAES_decrypt\n.align\t5\n.ent\t_mips_AES_set_encrypt_key\n_mips_AES_set_encrypt_key:\n\t.frame\t$29,0,$31\n\t.set\tnoreorder\n\tbeqz\t$4,.Lekey_done\n\tli\t$2,-1\n\tbeqz\t$6,.Lekey_done\n\tadd $3,$7,256\n\n\t.set\treorder\n\tlwl\t$8,0+3($4)\t# load 128 bits\n\tlwl\t$9,4+3($4)\n\tlwl\t$10,8+3($4)\n\tlwl\t$11,12+3($4)\n\tli\t$1,128\n\tlwr\t$8,0+0($4)\n\tlwr\t$9,4+0($4)\n\tlwr\t$10,8+0($4)\n\tlwr\t$11,12+0($4)\n\t.set\tnoreorder\n\tbeq\t$5,$1,.L128bits\n\tli\t$30,10\n\n\t.set\treorder\n\tlwl\t$12,16+3($4)\t# load 192 bits\n\tlwl\t$13,20+3($4)\n\tli\t$1,192\n\tlwr\t$12,16+0($4)\n\tlwr\t$13,20+0($4)\n\t.set\tnoreorder\n\tbeq\t$5,$1,.L192bits\n\tli\t$30,8\n\n\t.set\treorder\n\tlwl\t$14,24+3($4)\t# load 256 bits\n\tlwl\t$15,28+3($4)\n\tli\t$1,256\n\tlwr\t$14,24+0($4)\n\tlwr\t$15,28+0($4)\n\t.set\tnoreorder\n\tbeq\t$5,$1,.L256bits\n\tli\t$30,7\n\n\tb\t.Lekey_done\n\tli\t$2,-2\n\n.align\t4\n.L128bits:\n\t.set\treorder\n\tsrl\t$1,$11,16\n\tsrl\t$2,$11,8\n\tand\t$1,0xff\n\tand\t$2,0xff\n\tand\t$24,$11,0xff\n\tsrl\t$25,$11,24\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$1,0($1)\n\tlbu\t$2,0($2)\n\tlbu\t$24,0($24)\n\tlbu\t$25,0($25)\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tsw\t$11,12($6)\n\tsub\t$30,1\n\tadd $6,16\n\n\tsll\t$1,$1,8\n\t#sll\t$2,$2,0\n\tsll\t$24,$24,24\n\tsll\t$25,$25,16\n\n\txor\t$8,$1\n\tlw\t$1,0($3)\n\txor\t$8,$2\n\txor\t$8,$24\n\txor\t$8,$25\n\txor\t$8,$1\n\n\txor\t$9,$8\n\txor\t$10,$9\n\txor\t$11,$10\n\n\t.set\tnoreorder\n\tbnez\t$30,.L128bits\n\tadd $3,4\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tli\t$30,10\n\tsw\t$11,12($6)\n\tli\t$2,0\n\tsw\t$30,80($6)\n\tb\t.Lekey_done\n\tsub $6,10*16\n\n.align\t4\n.L192bits:\n\t.set\treorder\n\tsrl\t$1,$13,16\n\tsrl\t$2,$13,8\n\tand\t$1,0xff\n\tand\t$2,0xff\n\tand\t$24,$13,0xff\n\tsrl\t$25,$13,24\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$1,0($1)\n\tlbu\t$2,0($2)\n\tlbu\t$24,0($24)\n\tlbu\t$25,0($25)\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tsw\t$11,12($6)\n\tsw\t$12,16($6)\n\tsw\t$13,20($6)\n\tsub\t$30,1\n\tadd $6,24\n\n\tsll\t$1,$1,8\n\t#sll\t$2,$2,0\n\tsll\t$24,$24,24\n\tsll\t$25,$25,16\n\n\txor\t$8,$1\n\tlw\t$1,0($3)\n\txor\t$8,$2\n\txor\t$8,$24\n\txor\t$8,$25\n\txor\t$8,$1\n\n\txor\t$9,$8\n\txor\t$10,$9\n\txor\t$11,$10\n\txor\t$12,$11\n\txor\t$13,$12\n\n\t.set\tnoreorder\n\tbnez\t$30,.L192bits\n\tadd $3,4\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tli\t$30,12\n\tsw\t$11,12($6)\n\tli\t$2,0\n\tsw\t$30,48($6)\n\tb\t.Lekey_done\n\tsub $6,12*16\n\n.align\t4\n.L256bits:\n\t.set\treorder\n\tsrl\t$1,$15,16\n\tsrl\t$2,$15,8\n\tand\t$1,0xff\n\tand\t$2,0xff\n\tand\t$24,$15,0xff\n\tsrl\t$25,$15,24\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$1,0($1)\n\tlbu\t$2,0($2)\n\tlbu\t$24,0($24)\n\tlbu\t$25,0($25)\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tsw\t$11,12($6)\n\tsw\t$12,16($6)\n\tsw\t$13,20($6)\n\tsw\t$14,24($6)\n\tsw\t$15,28($6)\n\tsub\t$30,1\n\n\tsll\t$1,$1,8\n\t#sll\t$2,$2,0\n\tsll\t$24,$24,24\n\tsll\t$25,$25,16\n\n\txor\t$8,$1\n\tlw\t$1,0($3)\n\txor\t$8,$2\n\txor\t$8,$24\n\txor\t$8,$25\n\txor\t$8,$1\n\n\txor\t$9,$8\n\txor\t$10,$9\n\txor\t$11,$10\n\tbeqz\t$30,.L256bits_done\n\n\tsrl\t$1,$11,24\n\tsrl\t$2,$11,16\n\tsrl\t$24,$11,8\n\tand\t$25,$11,0xff\n\tand\t$2,0xff\n\tand\t$24,0xff\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$1,0($1)\n\tlbu\t$2,0($2)\n\tlbu\t$24,0($24)\n\tlbu\t$25,0($25)\n\tsll\t$1,24\n\tsll\t$2,16\n\tsll\t$24,8\n\n\txor\t$12,$1\n\txor\t$12,$2\n\txor\t$12,$24\n\txor\t$12,$25\n\n\txor\t$13,$12\n\txor\t$14,$13\n\txor\t$15,$14\n\n\tadd $6,32\n\t.set\tnoreorder\n\tb\t.L256bits\n\tadd $3,4\n\n.L256bits_done:\n\tsw\t$8,32($6)\n\tsw\t$9,36($6)\n\tsw\t$10,40($6)\n\tli\t$30,14\n\tsw\t$11,44($6)\n\tli\t$2,0\n\tsw\t$30,48($6)\n\tsub $6,12*16\n\n.Lekey_done:\n\tjr\t$31\n\tnop\n.end\t_mips_AES_set_encrypt_key\n\n.globl\tAES_set_encrypt_key\n.ent\tAES_set_encrypt_key\nAES_set_encrypt_key:\n\t.frame\t$29,32,$31\n\t.mask\t0xc0000000,-4\n\t.set\tnoreorder\n\t.cpload\t$25\n\tsub $29,32\n\tsw\t$31,32-1*4($29)\n\tsw\t$30,32-2*4($29)\n\t.set\treorder\n\tla\t$7,AES_Te4\t\t# PIC-ified 'load address'\n\n\tbal\t_mips_AES_set_encrypt_key\n\n\t.set\tnoreorder\n\tmove\t$4,$2\n\tlw\t$31,32-1*4($29)\n\tlw\t$30,32-2*4($29)\n\tjr\t$31\n\tadd $29,32\n.end\tAES_set_encrypt_key\n.align\t5\n.globl\tAES_set_decrypt_key\n.ent\tAES_set_decrypt_key\nAES_set_decrypt_key:\n\t.frame\t$29,32,$31\n\t.mask\t0xc0000000,-4\n\t.set\tnoreorder\n\t.cpload\t$25\n\tsub $29,32\n\tsw\t$31,32-1*4($29)\n\tsw\t$30,32-2*4($29)\n\t.set\treorder\n\tla\t$7,AES_Te4\t\t# PIC-ified 'load address'\n\n\tbal\t_mips_AES_set_encrypt_key\n\n\tbltz\t$2,.Ldkey_done\n\n\tsll\t$1,$30,4\n\tadd $4,$6,0\n\tadd $5,$6,$1\n.align\t4\n.Lswap:\n\tlw\t$8,0($4)\n\tlw\t$9,4($4)\n\tlw\t$10,8($4)\n\tlw\t$11,12($4)\n\tlw\t$12,0($5)\n\tlw\t$13,4($5)\n\tlw\t$14,8($5)\n\tlw\t$15,12($5)\n\tsw\t$8,0($5)\n\tsw\t$9,4($5)\n\tsw\t$10,8($5)\n\tsw\t$11,12($5)\n\tadd $4,16\n\tsub $5,16\n\tsw\t$12,-16($4)\n\tsw\t$13,-12($4)\n\tsw\t$14,-8($4)\n\tsw\t$15,-4($4)\n\tbne\t$4,$5,.Lswap\n\n\tlw\t$8,16($6)\t\t# modulo-scheduled\n\tlui\t$2,0x8080\n\tsub\t$30,1\n\tor\t$2,0x8080\n\tsll\t$30,2\n\tadd $6,16\n\tlui\t$25,0x1b1b\n\tnor\t$24,$0,$2\n\tor\t$25,0x1b1b\n.align\t4\n.Lmix:\n\tand\t$1,$8,$2\n\tand\t$9,$8,$24\n\tsrl\t$10,$1,7\n\taddu\t$9,$9\t\t# tp2<<1\n\tsubu\t$1,$10\n\tand\t$1,$25\n\txor\t$9,$1\n\n\tand\t$1,$9,$2\n\tand\t$10,$9,$24\n\tsrl\t$11,$1,7\n\taddu\t$10,$10\t\t# tp4<<1\n\tsubu\t$1,$11\n\tand\t$1,$25\n\txor\t$10,$1\n\n\tand\t$1,$10,$2\n\tand\t$11,$10,$24\n\tsrl\t$12,$1,7\n\taddu\t$11,$11\t\t# tp8<<1\n\tsubu\t$1,$12\n\tand\t$1,$25\n\txor\t$11,$1\n\n\txor\t$12,$11,$8\n\txor\t$15,$11,$10\n\txor\t$13,$12,$9\n\txor\t$14,$12,$10\n\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\trotr\t$8,$14,16\n\t xor\t$15,$9\n\trotr\t$9,$12,24\n\txor\t$15,$8\n\trotr\t$10,$13,8\n\txor\t$15,$9\n\tlw\t$8,4($6)\t\t# modulo-scheduled\n\txor\t$15,$10\n#else\n\tsll\t$8,$14,16\n\t xor\t$15,$9\n\tsrl\t$9,$14,16\n\txor\t$15,$8\n\tsll\t$8,$12,8\n\txor\t$15,$9\n\tsrl\t$9,$12,24\n\txor\t$15,$8\n\tsll\t$8,$13,24\n\txor\t$15,$9\n\tsrl\t$9,$13,8\n\txor\t$15,$8\n\tlw\t$8,4($6)\t\t# modulo-scheduled\n\txor\t$15,$9\n#endif\n\tsub\t$30,1\n\tsw\t$15,0($6)\n\tadd $6,4\n\tbnez\t$30,.Lmix\n\n\tli\t$2,0\n.Ldkey_done:\n\t.set\tnoreorder\n\tmove\t$4,$2\n\tlw\t$31,32-1*4($29)\n\tlw\t$30,32-2*4($29)\n\tjr\t$31\n\tadd $29,32\n.end\tAES_set_decrypt_key\n.rdata\n.align\t10\nAES_Te:\n.byte\t0xc6,0x63,0x63,0xa5,\t0xf8,0x7c,0x7c,0x84\t# Te0\n.byte\t0xee,0x77,0x77,0x99,\t0xf6,0x7b,0x7b,0x8d\n.byte\t0xff,0xf2,0xf2,0x0d,\t0xd6,0x6b,0x6b,0xbd\n.byte\t0xde,0x6f,0x6f,0xb1,\t0x91,0xc5,0xc5,0x54\n.byte\t0x60,0x30,0x30,0x50,\t0x02,0x01,0x01,0x03\n.byte\t0xce,0x67,0x67,0xa9,\t0x56,0x2b,0x2b,0x7d\n.byte\t0xe7,0xfe,0xfe,0x19,\t0xb5,0xd7,0xd7,0x62\n.byte\t0x4d,0xab,0xab,0xe6,\t0xec,0x76,0x76,0x9a\n.byte\t0x8f,0xca,0xca,0x45,\t0x1f,0x82,0x82,0x9d\n.byte\t0x89,0xc9,0xc9,0x40,\t0xfa,0x7d,0x7d,0x87\n.byte\t0xef,0xfa,0xfa,0x15,\t0xb2,0x59,0x59,0xeb\n.byte\t0x8e,0x47,0x47,0xc9,\t0xfb,0xf0,0xf0,0x0b\n.byte\t0x41,0xad,0xad,0xec,\t0xb3,0xd4,0xd4,0x67\n.byte\t0x5f,0xa2,0xa2,0xfd,\t0x45,0xaf,0xaf,0xea\n.byte\t0x23,0x9c,0x9c,0xbf,\t0x53,0xa4,0xa4,0xf7\n.byte\t0xe4,0x72,0x72,0x96,\t0x9b,0xc0,0xc0,0x5b\n.byte\t0x75,0xb7,0xb7,0xc2,\t0xe1,0xfd,0xfd,0x1c\n.byte\t0x3d,0x93,0x93,0xae,\t0x4c,0x26,0x26,0x6a\n.byte\t0x6c,0x36,0x36,0x5a,\t0x7e,0x3f,0x3f,0x41\n.byte\t0xf5,0xf7,0xf7,0x02,\t0x83,0xcc,0xcc,0x4f\n.byte\t0x68,0x34,0x34,0x5c,\t0x51,0xa5,0xa5,0xf4\n.byte\t0xd1,0xe5,0xe5,0x34,\t0xf9,0xf1,0xf1,0x08\n.byte\t0xe2,0x71,0x71,0x93,\t0xab,0xd8,0xd8,0x73\n.byte\t0x62,0x31,0x31,0x53,\t0x2a,0x15,0x15,0x3f\n.byte\t0x08,0x04,0x04,0x0c,\t0x95,0xc7,0xc7,0x52\n.byte\t0x46,0x23,0x23,0x65,\t0x9d,0xc3,0xc3,0x5e\n.byte\t0x30,0x18,0x18,0x28,\t0x37,0x96,0x96,0xa1\n.byte\t0x0a,0x05,0x05,0x0f,\t0x2f,0x9a,0x9a,0xb5\n.byte\t0x0e,0x07,0x07,0x09,\t0x24,0x12,0x12,0x36\n.byte\t0x1b,0x80,0x80,0x9b,\t0xdf,0xe2,0xe2,0x3d\n.byte\t0xcd,0xeb,0xeb,0x26,\t0x4e,0x27,0x27,0x69\n.byte\t0x7f,0xb2,0xb2,0xcd,\t0xea,0x75,0x75,0x9f\n.byte\t0x12,0x09,0x09,0x1b,\t0x1d,0x83,0x83,0x9e\n.byte\t0x58,0x2c,0x2c,0x74,\t0x34,0x1a,0x1a,0x2e\n.byte\t0x36,0x1b,0x1b,0x2d,\t0xdc,0x6e,0x6e,0xb2\n.byte\t0xb4,0x5a,0x5a,0xee,\t0x5b,0xa0,0xa0,0xfb\n.byte\t0xa4,0x52,0x52,0xf6,\t0x76,0x3b,0x3b,0x4d\n.byte\t0xb7,0xd6,0xd6,0x61,\t0x7d,0xb3,0xb3,0xce\n.byte\t0x52,0x29,0x29,0x7b,\t0xdd,0xe3,0xe3,0x3e\n.byte\t0x5e,0x2f,0x2f,0x71,\t0x13,0x84,0x84,0x97\n.byte\t0xa6,0x53,0x53,0xf5,\t0xb9,0xd1,0xd1,0x68\n.byte\t0x00,0x00,0x00,0x00,\t0xc1,0xed,0xed,0x2c\n.byte\t0x40,0x20,0x20,0x60,\t0xe3,0xfc,0xfc,0x1f\n.byte\t0x79,0xb1,0xb1,0xc8,\t0xb6,0x5b,0x5b,0xed\n.byte\t0xd4,0x6a,0x6a,0xbe,\t0x8d,0xcb,0xcb,0x46\n.byte\t0x67,0xbe,0xbe,0xd9,\t0x72,0x39,0x39,0x4b\n.byte\t0x94,0x4a,0x4a,0xde,\t0x98,0x4c,0x4c,0xd4\n.byte\t0xb0,0x58,0x58,0xe8,\t0x85,0xcf,0xcf,0x4a\n.byte\t0xbb,0xd0,0xd0,0x6b,\t0xc5,0xef,0xef,0x2a\n.byte\t0x4f,0xaa,0xaa,0xe5,\t0xed,0xfb,0xfb,0x16\n.byte\t0x86,0x43,0x43,0xc5,\t0x9a,0x4d,0x4d,0xd7\n.byte\t0x66,0x33,0x33,0x55,\t0x11,0x85,0x85,0x94\n.byte\t0x8a,0x45,0x45,0xcf,\t0xe9,0xf9,0xf9,0x10\n.byte\t0x04,0x02,0x02,0x06,\t0xfe,0x7f,0x7f,0x81\n.byte\t0xa0,0x50,0x50,0xf0,\t0x78,0x3c,0x3c,0x44\n.byte\t0x25,0x9f,0x9f,0xba,\t0x4b,0xa8,0xa8,0xe3\n.byte\t0xa2,0x51,0x51,0xf3,\t0x5d,0xa3,0xa3,0xfe\n.byte\t0x80,0x40,0x40,0xc0,\t0x05,0x8f,0x8f,0x8a\n.byte\t0x3f,0x92,0x92,0xad,\t0x21,0x9d,0x9d,0xbc\n.byte\t0x70,0x38,0x38,0x48,\t0xf1,0xf5,0xf5,0x04\n.byte\t0x63,0xbc,0xbc,0xdf,\t0x77,0xb6,0xb6,0xc1\n.byte\t0xaf,0xda,0xda,0x75,\t0x42,0x21,0x21,0x63\n.byte\t0x20,0x10,0x10,0x30,\t0xe5,0xff,0xff,0x1a\n.byte\t0xfd,0xf3,0xf3,0x0e,\t0xbf,0xd2,0xd2,0x6d\n.byte\t0x81,0xcd,0xcd,0x4c,\t0x18,0x0c,0x0c,0x14\n.byte\t0x26,0x13,0x13,0x35,\t0xc3,0xec,0xec,0x2f\n.byte\t0xbe,0x5f,0x5f,0xe1,\t0x35,0x97,0x97,0xa2\n.byte\t0x88,0x44,0x44,0xcc,\t0x2e,0x17,0x17,0x39\n.byte\t0x93,0xc4,0xc4,0x57,\t0x55,0xa7,0xa7,0xf2\n.byte\t0xfc,0x7e,0x7e,0x82,\t0x7a,0x3d,0x3d,0x47\n.byte\t0xc8,0x64,0x64,0xac,\t0xba,0x5d,0x5d,0xe7\n.byte\t0x32,0x19,0x19,0x2b,\t0xe6,0x73,0x73,0x95\n.byte\t0xc0,0x60,0x60,0xa0,\t0x19,0x81,0x81,0x98\n.byte\t0x9e,0x4f,0x4f,0xd1,\t0xa3,0xdc,0xdc,0x7f\n.byte\t0x44,0x22,0x22,0x66,\t0x54,0x2a,0x2a,0x7e\n.byte\t0x3b,0x90,0x90,0xab,\t0x0b,0x88,0x88,0x83\n.byte\t0x8c,0x46,0x46,0xca,\t0xc7,0xee,0xee,0x29\n.byte\t0x6b,0xb8,0xb8,0xd3,\t0x28,0x14,0x14,0x3c\n.byte\t0xa7,0xde,0xde,0x79,\t0xbc,0x5e,0x5e,0xe2\n.byte\t0x16,0x0b,0x0b,0x1d,\t0xad,0xdb,0xdb,0x76\n.byte\t0xdb,0xe0,0xe0,0x3b,\t0x64,0x32,0x32,0x56\n.byte\t0x74,0x3a,0x3a,0x4e,\t0x14,0x0a,0x0a,0x1e\n.byte\t0x92,0x49,0x49,0xdb,\t0x0c,0x06,0x06,0x0a\n.byte\t0x48,0x24,0x24,0x6c,\t0xb8,0x5c,0x5c,0xe4\n.byte\t0x9f,0xc2,0xc2,0x5d,\t0xbd,0xd3,0xd3,0x6e\n.byte\t0x43,0xac,0xac,0xef,\t0xc4,0x62,0x62,0xa6\n.byte\t0x39,0x91,0x91,0xa8,\t0x31,0x95,0x95,0xa4\n.byte\t0xd3,0xe4,0xe4,0x37,\t0xf2,0x79,0x79,0x8b\n.byte\t0xd5,0xe7,0xe7,0x32,\t0x8b,0xc8,0xc8,0x43\n.byte\t0x6e,0x37,0x37,0x59,\t0xda,0x6d,0x6d,0xb7\n.byte\t0x01,0x8d,0x8d,0x8c,\t0xb1,0xd5,0xd5,0x64\n.byte\t0x9c,0x4e,0x4e,0xd2,\t0x49,0xa9,0xa9,0xe0\n.byte\t0xd8,0x6c,0x6c,0xb4,\t0xac,0x56,0x56,0xfa\n.byte\t0xf3,0xf4,0xf4,0x07,\t0xcf,0xea,0xea,0x25\n.byte\t0xca,0x65,0x65,0xaf,\t0xf4,0x7a,0x7a,0x8e\n.byte\t0x47,0xae,0xae,0xe9,\t0x10,0x08,0x08,0x18\n.byte\t0x6f,0xba,0xba,0xd5,\t0xf0,0x78,0x78,0x88\n.byte\t0x4a,0x25,0x25,0x6f,\t0x5c,0x2e,0x2e,0x72\n.byte\t0x38,0x1c,0x1c,0x24,\t0x57,0xa6,0xa6,0xf1\n.byte\t0x73,0xb4,0xb4,0xc7,\t0x97,0xc6,0xc6,0x51\n.byte\t0xcb,0xe8,0xe8,0x23,\t0xa1,0xdd,0xdd,0x7c\n.byte\t0xe8,0x74,0x74,0x9c,\t0x3e,0x1f,0x1f,0x21\n.byte\t0x96,0x4b,0x4b,0xdd,\t0x61,0xbd,0xbd,0xdc\n.byte\t0x0d,0x8b,0x8b,0x86,\t0x0f,0x8a,0x8a,0x85\n.byte\t0xe0,0x70,0x70,0x90,\t0x7c,0x3e,0x3e,0x42\n.byte\t0x71,0xb5,0xb5,0xc4,\t0xcc,0x66,0x66,0xaa\n.byte\t0x90,0x48,0x48,0xd8,\t0x06,0x03,0x03,0x05\n.byte\t0xf7,0xf6,0xf6,0x01,\t0x1c,0x0e,0x0e,0x12\n.byte\t0xc2,0x61,0x61,0xa3,\t0x6a,0x35,0x35,0x5f\n.byte\t0xae,0x57,0x57,0xf9,\t0x69,0xb9,0xb9,0xd0\n.byte\t0x17,0x86,0x86,0x91,\t0x99,0xc1,0xc1,0x58\n.byte\t0x3a,0x1d,0x1d,0x27,\t0x27,0x9e,0x9e,0xb9\n.byte\t0xd9,0xe1,0xe1,0x38,\t0xeb,0xf8,0xf8,0x13\n.byte\t0x2b,0x98,0x98,0xb3,\t0x22,0x11,0x11,0x33\n.byte\t0xd2,0x69,0x69,0xbb,\t0xa9,0xd9,0xd9,0x70\n.byte\t0x07,0x8e,0x8e,0x89,\t0x33,0x94,0x94,0xa7\n.byte\t0x2d,0x9b,0x9b,0xb6,\t0x3c,0x1e,0x1e,0x22\n.byte\t0x15,0x87,0x87,0x92,\t0xc9,0xe9,0xe9,0x20\n.byte\t0x87,0xce,0xce,0x49,\t0xaa,0x55,0x55,0xff\n.byte\t0x50,0x28,0x28,0x78,\t0xa5,0xdf,0xdf,0x7a\n.byte\t0x03,0x8c,0x8c,0x8f,\t0x59,0xa1,0xa1,0xf8\n.byte\t0x09,0x89,0x89,0x80,\t0x1a,0x0d,0x0d,0x17\n.byte\t0x65,0xbf,0xbf,0xda,\t0xd7,0xe6,0xe6,0x31\n.byte\t0x84,0x42,0x42,0xc6,\t0xd0,0x68,0x68,0xb8\n.byte\t0x82,0x41,0x41,0xc3,\t0x29,0x99,0x99,0xb0\n.byte\t0x5a,0x2d,0x2d,0x77,\t0x1e,0x0f,0x0f,0x11\n.byte\t0x7b,0xb0,0xb0,0xcb,\t0xa8,0x54,0x54,0xfc\n.byte\t0x6d,0xbb,0xbb,0xd6,\t0x2c,0x16,0x16,0x3a\n\nAES_Td:\n.byte\t0x51,0xf4,0xa7,0x50,\t0x7e,0x41,0x65,0x53\t# Td0\n.byte\t0x1a,0x17,0xa4,0xc3,\t0x3a,0x27,0x5e,0x96\n.byte\t0x3b,0xab,0x6b,0xcb,\t0x1f,0x9d,0x45,0xf1\n.byte\t0xac,0xfa,0x58,0xab,\t0x4b,0xe3,0x03,0x93\n.byte\t0x20,0x30,0xfa,0x55,\t0xad,0x76,0x6d,0xf6\n.byte\t0x88,0xcc,0x76,0x91,\t0xf5,0x02,0x4c,0x25\n.byte\t0x4f,0xe5,0xd7,0xfc,\t0xc5,0x2a,0xcb,0xd7\n.byte\t0x26,0x35,0x44,0x80,\t0xb5,0x62,0xa3,0x8f\n.byte\t0xde,0xb1,0x5a,0x49,\t0x25,0xba,0x1b,0x67\n.byte\t0x45,0xea,0x0e,0x98,\t0x5d,0xfe,0xc0,0xe1\n.byte\t0xc3,0x2f,0x75,0x02,\t0x81,0x4c,0xf0,0x12\n.byte\t0x8d,0x46,0x97,0xa3,\t0x6b,0xd3,0xf9,0xc6\n.byte\t0x03,0x8f,0x5f,0xe7,\t0x15,0x92,0x9c,0x95\n.byte\t0xbf,0x6d,0x7a,0xeb,\t0x95,0x52,0x59,0xda\n.byte\t0xd4,0xbe,0x83,0x2d,\t0x58,0x74,0x21,0xd3\n.byte\t0x49,0xe0,0x69,0x29,\t0x8e,0xc9,0xc8,0x44\n.byte\t0x75,0xc2,0x89,0x6a,\t0xf4,0x8e,0x79,0x78\n.byte\t0x99,0x58,0x3e,0x6b,\t0x27,0xb9,0x71,0xdd\n.byte\t0xbe,0xe1,0x4f,0xb6,\t0xf0,0x88,0xad,0x17\n.byte\t0xc9,0x20,0xac,0x66,\t0x7d,0xce,0x3a,0xb4\n.byte\t0x63,0xdf,0x4a,0x18,\t0xe5,0x1a,0x31,0x82\n.byte\t0x97,0x51,0x33,0x60,\t0x62,0x53,0x7f,0x45\n.byte\t0xb1,0x64,0x77,0xe0,\t0xbb,0x6b,0xae,0x84\n.byte\t0xfe,0x81,0xa0,0x1c,\t0xf9,0x08,0x2b,0x94\n.byte\t0x70,0x48,0x68,0x58,\t0x8f,0x45,0xfd,0x19\n.byte\t0x94,0xde,0x6c,0x87,\t0x52,0x7b,0xf8,0xb7\n.byte\t0xab,0x73,0xd3,0x23,\t0x72,0x4b,0x02,0xe2\n.byte\t0xe3,0x1f,0x8f,0x57,\t0x66,0x55,0xab,0x2a\n.byte\t0xb2,0xeb,0x28,0x07,\t0x2f,0xb5,0xc2,0x03\n.byte\t0x86,0xc5,0x7b,0x9a,\t0xd3,0x37,0x08,0xa5\n.byte\t0x30,0x28,0x87,0xf2,\t0x23,0xbf,0xa5,0xb2\n.byte\t0x02,0x03,0x6a,0xba,\t0xed,0x16,0x82,0x5c\n.byte\t0x8a,0xcf,0x1c,0x2b,\t0xa7,0x79,0xb4,0x92\n.byte\t0xf3,0x07,0xf2,0xf0,\t0x4e,0x69,0xe2,0xa1\n.byte\t0x65,0xda,0xf4,0xcd,\t0x06,0x05,0xbe,0xd5\n.byte\t0xd1,0x34,0x62,0x1f,\t0xc4,0xa6,0xfe,0x8a\n.byte\t0x34,0x2e,0x53,0x9d,\t0xa2,0xf3,0x55,0xa0\n.byte\t0x05,0x8a,0xe1,0x32,\t0xa4,0xf6,0xeb,0x75\n.byte\t0x0b,0x83,0xec,0x39,\t0x40,0x60,0xef,0xaa\n.byte\t0x5e,0x71,0x9f,0x06,\t0xbd,0x6e,0x10,0x51\n.byte\t0x3e,0x21,0x8a,0xf9,\t0x96,0xdd,0x06,0x3d\n.byte\t0xdd,0x3e,0x05,0xae,\t0x4d,0xe6,0xbd,0x46\n.byte\t0x91,0x54,0x8d,0xb5,\t0x71,0xc4,0x5d,0x05\n.byte\t0x04,0x06,0xd4,0x6f,\t0x60,0x50,0x15,0xff\n.byte\t0x19,0x98,0xfb,0x24,\t0xd6,0xbd,0xe9,0x97\n.byte\t0x89,0x40,0x43,0xcc,\t0x67,0xd9,0x9e,0x77\n.byte\t0xb0,0xe8,0x42,0xbd,\t0x07,0x89,0x8b,0x88\n.byte\t0xe7,0x19,0x5b,0x38,\t0x79,0xc8,0xee,0xdb\n.byte\t0xa1,0x7c,0x0a,0x47,\t0x7c,0x42,0x0f,0xe9\n.byte\t0xf8,0x84,0x1e,0xc9,\t0x00,0x00,0x00,0x00\n.byte\t0x09,0x80,0x86,0x83,\t0x32,0x2b,0xed,0x48\n.byte\t0x1e,0x11,0x70,0xac,\t0x6c,0x5a,0x72,0x4e\n.byte\t0xfd,0x0e,0xff,0xfb,\t0x0f,0x85,0x38,0x56\n.byte\t0x3d,0xae,0xd5,0x1e,\t0x36,0x2d,0x39,0x27\n.byte\t0x0a,0x0f,0xd9,0x64,\t0x68,0x5c,0xa6,0x21\n.byte\t0x9b,0x5b,0x54,0xd1,\t0x24,0x36,0x2e,0x3a\n.byte\t0x0c,0x0a,0x67,0xb1,\t0x93,0x57,0xe7,0x0f\n.byte\t0xb4,0xee,0x96,0xd2,\t0x1b,0x9b,0x91,0x9e\n.byte\t0x80,0xc0,0xc5,0x4f,\t0x61,0xdc,0x20,0xa2\n.byte\t0x5a,0x77,0x4b,0x69,\t0x1c,0x12,0x1a,0x16\n.byte\t0xe2,0x93,0xba,0x0a,\t0xc0,0xa0,0x2a,0xe5\n.byte\t0x3c,0x22,0xe0,0x43,\t0x12,0x1b,0x17,0x1d\n.byte\t0x0e,0x09,0x0d,0x0b,\t0xf2,0x8b,0xc7,0xad\n.byte\t0x2d,0xb6,0xa8,0xb9,\t0x14,0x1e,0xa9,0xc8\n.byte\t0x57,0xf1,0x19,0x85,\t0xaf,0x75,0x07,0x4c\n.byte\t0xee,0x99,0xdd,0xbb,\t0xa3,0x7f,0x60,0xfd\n.byte\t0xf7,0x01,0x26,0x9f,\t0x5c,0x72,0xf5,0xbc\n.byte\t0x44,0x66,0x3b,0xc5,\t0x5b,0xfb,0x7e,0x34\n.byte\t0x8b,0x43,0x29,0x76,\t0xcb,0x23,0xc6,0xdc\n.byte\t0xb6,0xed,0xfc,0x68,\t0xb8,0xe4,0xf1,0x63\n.byte\t0xd7,0x31,0xdc,0xca,\t0x42,0x63,0x85,0x10\n.byte\t0x13,0x97,0x22,0x40,\t0x84,0xc6,0x11,0x20\n.byte\t0x85,0x4a,0x24,0x7d,\t0xd2,0xbb,0x3d,0xf8\n.byte\t0xae,0xf9,0x32,0x11,\t0xc7,0x29,0xa1,0x6d\n.byte\t0x1d,0x9e,0x2f,0x4b,\t0xdc,0xb2,0x30,0xf3\n.byte\t0x0d,0x86,0x52,0xec,\t0x77,0xc1,0xe3,0xd0\n.byte\t0x2b,0xb3,0x16,0x6c,\t0xa9,0x70,0xb9,0x99\n.byte\t0x11,0x94,0x48,0xfa,\t0x47,0xe9,0x64,0x22\n.byte\t0xa8,0xfc,0x8c,0xc4,\t0xa0,0xf0,0x3f,0x1a\n.byte\t0x56,0x7d,0x2c,0xd8,\t0x22,0x33,0x90,0xef\n.byte\t0x87,0x49,0x4e,0xc7,\t0xd9,0x38,0xd1,0xc1\n.byte\t0x8c,0xca,0xa2,0xfe,\t0x98,0xd4,0x0b,0x36\n.byte\t0xa6,0xf5,0x81,0xcf,\t0xa5,0x7a,0xde,0x28\n.byte\t0xda,0xb7,0x8e,0x26,\t0x3f,0xad,0xbf,0xa4\n.byte\t0x2c,0x3a,0x9d,0xe4,\t0x50,0x78,0x92,0x0d\n.byte\t0x6a,0x5f,0xcc,0x9b,\t0x54,0x7e,0x46,0x62\n.byte\t0xf6,0x8d,0x13,0xc2,\t0x90,0xd8,0xb8,0xe8\n.byte\t0x2e,0x39,0xf7,0x5e,\t0x82,0xc3,0xaf,0xf5\n.byte\t0x9f,0x5d,0x80,0xbe,\t0x69,0xd0,0x93,0x7c\n.byte\t0x6f,0xd5,0x2d,0xa9,\t0xcf,0x25,0x12,0xb3\n.byte\t0xc8,0xac,0x99,0x3b,\t0x10,0x18,0x7d,0xa7\n.byte\t0xe8,0x9c,0x63,0x6e,\t0xdb,0x3b,0xbb,0x7b\n.byte\t0xcd,0x26,0x78,0x09,\t0x6e,0x59,0x18,0xf4\n.byte\t0xec,0x9a,0xb7,0x01,\t0x83,0x4f,0x9a,0xa8\n.byte\t0xe6,0x95,0x6e,0x65,\t0xaa,0xff,0xe6,0x7e\n.byte\t0x21,0xbc,0xcf,0x08,\t0xef,0x15,0xe8,0xe6\n.byte\t0xba,0xe7,0x9b,0xd9,\t0x4a,0x6f,0x36,0xce\n.byte\t0xea,0x9f,0x09,0xd4,\t0x29,0xb0,0x7c,0xd6\n.byte\t0x31,0xa4,0xb2,0xaf,\t0x2a,0x3f,0x23,0x31\n.byte\t0xc6,0xa5,0x94,0x30,\t0x35,0xa2,0x66,0xc0\n.byte\t0x74,0x4e,0xbc,0x37,\t0xfc,0x82,0xca,0xa6\n.byte\t0xe0,0x90,0xd0,0xb0,\t0x33,0xa7,0xd8,0x15\n.byte\t0xf1,0x04,0x98,0x4a,\t0x41,0xec,0xda,0xf7\n.byte\t0x7f,0xcd,0x50,0x0e,\t0x17,0x91,0xf6,0x2f\n.byte\t0x76,0x4d,0xd6,0x8d,\t0x43,0xef,0xb0,0x4d\n.byte\t0xcc,0xaa,0x4d,0x54,\t0xe4,0x96,0x04,0xdf\n.byte\t0x9e,0xd1,0xb5,0xe3,\t0x4c,0x6a,0x88,0x1b\n.byte\t0xc1,0x2c,0x1f,0xb8,\t0x46,0x65,0x51,0x7f\n.byte\t0x9d,0x5e,0xea,0x04,\t0x01,0x8c,0x35,0x5d\n.byte\t0xfa,0x87,0x74,0x73,\t0xfb,0x0b,0x41,0x2e\n.byte\t0xb3,0x67,0x1d,0x5a,\t0x92,0xdb,0xd2,0x52\n.byte\t0xe9,0x10,0x56,0x33,\t0x6d,0xd6,0x47,0x13\n.byte\t0x9a,0xd7,0x61,0x8c,\t0x37,0xa1,0x0c,0x7a\n.byte\t0x59,0xf8,0x14,0x8e,\t0xeb,0x13,0x3c,0x89\n.byte\t0xce,0xa9,0x27,0xee,\t0xb7,0x61,0xc9,0x35\n.byte\t0xe1,0x1c,0xe5,0xed,\t0x7a,0x47,0xb1,0x3c\n.byte\t0x9c,0xd2,0xdf,0x59,\t0x55,0xf2,0x73,0x3f\n.byte\t0x18,0x14,0xce,0x79,\t0x73,0xc7,0x37,0xbf\n.byte\t0x53,0xf7,0xcd,0xea,\t0x5f,0xfd,0xaa,0x5b\n.byte\t0xdf,0x3d,0x6f,0x14,\t0x78,0x44,0xdb,0x86\n.byte\t0xca,0xaf,0xf3,0x81,\t0xb9,0x68,0xc4,0x3e\n.byte\t0x38,0x24,0x34,0x2c,\t0xc2,0xa3,0x40,0x5f\n.byte\t0x16,0x1d,0xc3,0x72,\t0xbc,0xe2,0x25,0x0c\n.byte\t0x28,0x3c,0x49,0x8b,\t0xff,0x0d,0x95,0x41\n.byte\t0x39,0xa8,0x01,0x71,\t0x08,0x0c,0xb3,0xde\n.byte\t0xd8,0xb4,0xe4,0x9c,\t0x64,0x56,0xc1,0x90\n.byte\t0x7b,0xcb,0x84,0x61,\t0xd5,0x32,0xb6,0x70\n.byte\t0x48,0x6c,0x5c,0x74,\t0xd0,0xb8,0x57,0x42\n\n.byte\t0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38\t# Td4\n.byte\t0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb\n.byte\t0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87\n.byte\t0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb\n.byte\t0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d\n.byte\t0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e\n.byte\t0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2\n.byte\t0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25\n.byte\t0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16\n.byte\t0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92\n.byte\t0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda\n.byte\t0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84\n.byte\t0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a\n.byte\t0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06\n.byte\t0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02\n.byte\t0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b\n.byte\t0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea\n.byte\t0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73\n.byte\t0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85\n.byte\t0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e\n.byte\t0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89\n.byte\t0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b\n.byte\t0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20\n.byte\t0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4\n.byte\t0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31\n.byte\t0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f\n.byte\t0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d\n.byte\t0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef\n.byte\t0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0\n.byte\t0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61\n.byte\t0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26\n.byte\t0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d\n\nAES_Te4:\n.byte\t0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5\t# Te4\n.byte\t0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76\n.byte\t0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0\n.byte\t0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0\n.byte\t0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc\n.byte\t0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15\n.byte\t0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a\n.byte\t0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75\n.byte\t0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0\n.byte\t0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84\n.byte\t0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b\n.byte\t0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf\n.byte\t0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85\n.byte\t0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8\n.byte\t0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5\n.byte\t0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2\n.byte\t0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17\n.byte\t0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73\n.byte\t0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88\n.byte\t0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb\n.byte\t0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c\n.byte\t0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79\n.byte\t0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9\n.byte\t0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08\n.byte\t0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6\n.byte\t0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a\n.byte\t0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e\n.byte\t0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e\n.byte\t0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94\n.byte\t0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf\n.byte\t0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68\n.byte\t0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16\n\n.byte\t0x01,0x00,0x00,0x00,\t0x02,0x00,0x00,0x00\t# rcon\n.byte\t0x04,0x00,0x00,0x00,\t0x08,0x00,0x00,0x00\n.byte\t0x10,0x00,0x00,0x00,\t0x20,0x00,0x00,0x00\n.byte\t0x40,0x00,0x00,0x00,\t0x80,0x00,0x00,0x00\n.byte\t0x1B,0x00,0x00,0x00,\t0x36,0x00,0x00,0x00\n"
  },
  {
    "path": "lib/aes_acc/asm/mips_be.S",
    "content": ".text\n#ifdef OPENSSL_FIPSCANISTER\n# include <openssl/fipssyms.h>\n#endif\n\n#if defined(__mips_smartmips) && !defined(_MIPS_ARCH_MIPS32R2)\n#define _MIPS_ARCH_MIPS32R2\n#endif\n\n#if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__))\n.option\tpic2\n#endif\n.set\tnoat\n.align\t5\n.ent\t_mips_AES_encrypt\n_mips_AES_encrypt:\n\t.frame\t$29,0,$31\n\t.set\treorder\n\tlw\t$12,0($6)\n\tlw\t$13,4($6)\n\tlw\t$14,8($6)\n\tlw\t$15,12($6)\n\tlw\t$30,240($6)\n\tadd $3,$6,16\n\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\n\tsub\t$30,1\n#if defined(__mips_smartmips)\n\text\t$1,$9,16,8\n.Loop_enc:\n\text\t$2,$10,16,8\n\text\t$24,$11,16,8\n\text\t$25,$8,16,8\n\tlwxs\t$12,$1($7)\t\t# Te1[s1>>16]\n\text\t$1,$10,8,8\n\tlwxs\t$13,$2($7)\t\t# Te1[s2>>16]\n\text\t$2,$11,8,8\n\tlwxs\t$14,$24($7)\t\t# Te1[s3>>16]\n\text\t$24,$8,8,8\n\tlwxs\t$15,$25($7)\t\t# Te1[s0>>16]\n\text\t$25,$9,8,8\n\n\tlwxs\t$16,$1($7)\t\t# Te2[s2>>8]\n\text\t$1,$11,0,8\n\tlwxs\t$17,$2($7)\t\t# Te2[s3>>8]\n\text\t$2,$8,0,8\n\tlwxs\t$18,$24($7)\t\t# Te2[s0>>8]\n\text\t$24,$9,0,8\n\tlwxs\t$19,$25($7)\t\t# Te2[s1>>8]\n\text\t$25,$10,0,8\n\n\tlwxs\t$20,$1($7)\t\t# Te3[s3]\n\text\t$1,$8,24,8\n\tlwxs\t$21,$2($7)\t\t# Te3[s0]\n\text\t$2,$9,24,8\n\tlwxs\t$22,$24($7)\t\t# Te3[s1]\n\text\t$24,$10,24,8\n\tlwxs\t$23,$25($7)\t\t# Te3[s2]\n\text\t$25,$11,24,8\n\n\trotr\t$12,$12,8\n\trotr\t$13,$13,8\n\trotr\t$14,$14,8\n\trotr\t$15,$15,8\n\n\trotr\t$16,$16,16\n\trotr\t$17,$17,16\n\trotr\t$18,$18,16\n\trotr\t$19,$19,16\n\n\txor\t$12,$16\n\tlwxs\t$16,$1($7)\t\t# Te0[s0>>24]\n\txor\t$13,$17\n\tlwxs\t$17,$2($7)\t\t# Te0[s1>>24]\n\txor\t$14,$18\n\tlwxs\t$18,$24($7)\t\t# Te0[s2>>24]\n\txor\t$15,$19\n\tlwxs\t$19,$25($7)\t\t# Te0[s3>>24]\n\n\trotr\t$20,$20,24\n\tlw\t$8,0($3)\n\trotr\t$21,$21,24\n\tlw\t$9,4($3)\n\trotr\t$22,$22,24\n\tlw\t$10,8($3)\n\trotr\t$23,$23,24\n\tlw\t$11,12($3)\n\n\txor\t$12,$20\n\txor\t$13,$21\n\txor\t$14,$22\n\txor\t$15,$23\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n\n\tsub\t$30,1\n\tadd $3,16\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\t.set\tnoreorder\n\tbnez\t$30,.Loop_enc\n\text\t$1,$9,16,8\n\n\tsrl\t$1,$9,14\n#else\n\tsrl\t$1,$9,14\n.Loop_enc:\n\tsrl\t$2,$10,14\n\tsrl\t$24,$11,14\n\tsrl\t$25,$8,14\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\tlw\t$12,0($1)\t\t# Te1[s1>>16]\n\tsrl\t$1,$10,6\n\tlw\t$13,0($2)\t\t# Te1[s2>>16]\n\tsrl\t$2,$11,6\n\tlw\t$14,0($24)\t\t# Te1[s3>>16]\n\tsrl\t$24,$8,6\n\tlw\t$15,0($25)\t\t# Te1[s0>>16]\n\tsrl\t$25,$9,6\n#else\n\tlwl\t$12,3($1)\t\t# Te1[s1>>16]\n\tlwl\t$13,3($2)\t\t# Te1[s2>>16]\n\tlwl\t$14,3($24)\t\t# Te1[s3>>16]\n\tlwl\t$15,3($25)\t\t# Te1[s0>>16]\n\tlwr\t$12,2($1)\t\t# Te1[s1>>16]\n\tsrl\t$1,$10,6\n\tlwr\t$13,2($2)\t\t# Te1[s2>>16]\n\tsrl\t$2,$11,6\n\tlwr\t$14,2($24)\t\t# Te1[s3>>16]\n\tsrl\t$24,$8,6\n\tlwr\t$15,2($25)\t\t# Te1[s0>>16]\n\tsrl\t$25,$9,6\n#endif\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\trotr\t$12,$12,8\n\trotr\t$13,$13,8\n\trotr\t$14,$14,8\n\trotr\t$15,$15,8\n# if defined(_MIPSEL)\n\tlw\t$16,0($1)\t\t# Te2[s2>>8]\n\tsll\t$1,$11,2\n\tlw\t$17,0($2)\t\t# Te2[s3>>8]\n\tsll\t$2,$8,2\n\tlw\t$18,0($24)\t\t# Te2[s0>>8]\n\tsll\t$24,$9,2\n\tlw\t$19,0($25)\t\t# Te2[s1>>8]\n\tsll\t$25,$10,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlw\t$20,0($1)\t\t# Te3[s3]\n\tins $1,$8,2,8\n\tlw\t$21,0($2)\t\t# Te3[s0]\n\tins $2,$9,2,8\n\tlw\t$22,0($24)\t\t# Te3[s1]\n\tins $24,$10,2,8\n\tlw\t$23,0($25)\t\t# Te3[s2]\n\tins $25,$11,2,8\n# else\n\tlw\t$16,0($1)\t\t# Te2[s2>>8]\n\tins $1,$11,2,8\n\tlw\t$17,0($2)\t\t# Te2[s3>>8]\n\tins $2,$8,2,8\n\tlw\t$18,0($24)\t\t# Te2[s0>>8]\n\tins $24,$9,2,8\n\tlw\t$19,0($25)\t\t# Te2[s1>>8]\n\tins $25,$10,2,8\n\n\tlw\t$20,0($1)\t\t# Te3[s3]\n\tsrl\t$1,$8,22\n\tlw\t$21,0($2)\t\t# Te3[s0]\n\tsrl\t$2,$9,22\n\tlw\t$22,0($24)\t\t# Te3[s1]\n\tsrl\t$24,$10,22\n\tlw\t$23,0($25)\t\t# Te3[s2]\n\tsrl\t$25,$11,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n# endif\n\trotr\t$16,$16,16\n\trotr\t$17,$17,16\n\trotr\t$18,$18,16\n\trotr\t$19,$19,16\n\n\trotr\t$20,$20,24\n\trotr\t$21,$21,24\n\trotr\t$22,$22,24\n\trotr\t$23,$23,24\n#else\n\tlwl\t$16,2($1)\t\t# Te2[s2>>8]\n\tlwl\t$17,2($2)\t\t# Te2[s3>>8]\n\tlwl\t$18,2($24)\t\t# Te2[s0>>8]\n\tlwl\t$19,2($25)\t\t# Te2[s1>>8]\n\tlwr\t$16,1($1)\t\t# Te2[s2>>8]\n\tsll\t$1,$11,2\n\tlwr\t$17,1($2)\t\t# Te2[s3>>8]\n\tsll\t$2,$8,2\n\tlwr\t$18,1($24)\t\t# Te2[s0>>8]\n\tsll\t$24,$9,2\n\tlwr\t$19,1($25)\t\t# Te2[s1>>8]\n\tsll\t$25,$10,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlwl\t$20,1($1)\t\t# Te3[s3]\n\tlwl\t$21,1($2)\t\t# Te3[s0]\n\tlwl\t$22,1($24)\t\t# Te3[s1]\n\tlwl\t$23,1($25)\t\t# Te3[s2]\n\tlwr\t$20,0($1)\t\t# Te3[s3]\n\tsrl\t$1,$8,22\n\tlwr\t$21,0($2)\t\t# Te3[s0]\n\tsrl\t$2,$9,22\n\tlwr\t$22,0($24)\t\t# Te3[s1]\n\tsrl\t$24,$10,22\n\tlwr\t$23,0($25)\t\t# Te3[s2]\n\tsrl\t$25,$11,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#endif\n\txor\t$12,$16\n\tlw\t$16,0($1)\t\t# Te0[s0>>24]\n\txor\t$13,$17\n\tlw\t$17,0($2)\t\t# Te0[s1>>24]\n\txor\t$14,$18\n\tlw\t$18,0($24)\t\t# Te0[s2>>24]\n\txor\t$15,$19\n\tlw\t$19,0($25)\t\t# Te0[s3>>24]\n\n\txor\t$12,$20\n\tlw\t$8,0($3)\n\txor\t$13,$21\n\tlw\t$9,4($3)\n\txor\t$14,$22\n\tlw\t$10,8($3)\n\txor\t$15,$23\n\tlw\t$11,12($3)\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n\n\tsub\t$30,1\n\tadd $3,16\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\t.set\tnoreorder\n\tbnez\t$30,.Loop_enc\n\tsrl\t$1,$9,14\n#endif\n\n\t.set\treorder\n\tsrl\t$2,$10,14\n\tsrl\t$24,$11,14\n\tsrl\t$25,$8,14\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$12,2($1)\t\t# Te4[s1>>16]\n\tsrl\t$1,$10,6\n\tlbu\t$13,2($2)\t\t# Te4[s2>>16]\n\tsrl\t$2,$11,6\n\tlbu\t$14,2($24)\t\t# Te4[s3>>16]\n\tsrl\t$24,$8,6\n\tlbu\t$15,2($25)\t\t# Te4[s0>>16]\n\tsrl\t$25,$9,6\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n# if defined(_MIPSEL)\n\tlbu\t$16,2($1)\t\t# Te4[s2>>8]\n\tins $1,$8,2,8\n\tlbu\t$17,2($2)\t\t# Te4[s3>>8]\n\tins $2,$9,2,8\n\tlbu\t$18,2($24)\t\t# Te4[s0>>8]\n\tins $24,$10,2,8\n\tlbu\t$19,2($25)\t\t# Te4[s1>>8]\n\tins $25,$11,2,8\n\n\tlbu\t$20,2($1)\t\t# Te4[s0>>24]\n\tsll\t$1,$11,2\n\tlbu\t$21,2($2)\t\t# Te4[s1>>24]\n\tsll\t$2,$8,2\n\tlbu\t$22,2($24)\t\t# Te4[s2>>24]\n\tsll\t$24,$9,2\n\tlbu\t$23,2($25)\t\t# Te4[s3>>24]\n\tsll\t$25,$10,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n# else\n\tlbu\t$16,2($1)\t\t# Te4[s2>>8]\n\tsrl\t$1,$8,22\n\tlbu\t$17,2($2)\t\t# Te4[s3>>8]\n\tsrl\t$2,$9,22\n\tlbu\t$18,2($24)\t\t# Te4[s0>>8]\n\tsrl\t$24,$10,22\n\tlbu\t$19,2($25)\t\t# Te4[s1>>8]\n\tsrl\t$25,$11,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$20,2($1)\t\t# Te4[s0>>24]\n\tins $1,$11,2,8\n\tlbu\t$21,2($2)\t\t# Te4[s1>>24]\n\tins $2,$8,2,8\n\tlbu\t$22,2($24)\t\t# Te4[s2>>24]\n\tins $24,$9,2,8\n\tlbu\t$23,2($25)\t\t# Te4[s3>>24]\n\tins $25,$10,2,8\n# endif\n\tsll\t$12,$12,16\n\tsll\t$13,$13,16\n\tsll\t$14,$14,16\n\tsll\t$15,$15,16\n\n\tins\t$12,$16,8,8\n\tlbu\t$16,2($1)\t\t# Te4[s3]\n\tins\t$13,$17,8,8\n\tlbu\t$17,2($2)\t\t# Te4[s0]\n\tins\t$14,$18,8,8\n\tlbu\t$18,2($24)\t\t# Te4[s1]\n\tins\t$15,$19,8,8\n\tlbu\t$19,2($25)\t\t# Te4[s2]\n\n\tins\t$12,$20,24,8\n\tlw\t$8,0($3)\n\tins\t$13,$21,24,8\n\tlw\t$9,4($3)\n\tins\t$14,$22,24,8\n\tlw\t$10,8($3)\n\tins\t$15,$23,24,8\n\tlw\t$11,12($3)\n\n\tins\t$12,$16,0,8\n\tins\t$13,$17,0,8\n\tins\t$14,$18,0,8\n\tins\t$15,$19,0,8\n#else\n\tlbu\t$16,2($1)\t\t# Te4[s2>>8]\n\tsrl\t$1,$8,22\n\tlbu\t$17,2($2)\t\t# Te4[s3>>8]\n\tsrl\t$2,$9,22\n\tlbu\t$18,2($24)\t\t# Te4[s0>>8]\n\tsrl\t$24,$10,22\n\tlbu\t$19,2($25)\t\t# Te4[s1>>8]\n\tsrl\t$25,$11,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$20,2($1)\t\t# Te4[s0>>24]\n\tsll\t$1,$11,2\n\tlbu\t$21,2($2)\t\t# Te4[s1>>24]\n\tsll\t$2,$8,2\n\tlbu\t$22,2($24)\t\t# Te4[s2>>24]\n\tsll\t$24,$9,2\n\tlbu\t$23,2($25)\t\t# Te4[s3>>24]\n\tsll\t$25,$10,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\n\tsll\t$12,$12,16\n\tsll\t$13,$13,16\n\tsll\t$14,$14,16\n\tsll\t$15,$15,16\n\n\tsll\t$16,$16,8\n\tsll\t$17,$17,8\n\tsll\t$18,$18,8\n\tsll\t$19,$19,8\n\n\txor\t$12,$16\n\tlbu\t$16,2($1)\t\t# Te4[s3]\n\txor\t$13,$17\n\tlbu\t$17,2($2)\t\t# Te4[s0]\n\txor\t$14,$18\n\tlbu\t$18,2($24)\t\t# Te4[s1]\n\txor\t$15,$19\n\tlbu\t$19,2($25)\t\t# Te4[s2]\n\n\tsll\t$20,$20,24\n\tlw\t$8,0($3)\n\tsll\t$21,$21,24\n\tlw\t$9,4($3)\n\tsll\t$22,$22,24\n\tlw\t$10,8($3)\n\tsll\t$23,$23,24\n\tlw\t$11,12($3)\n\n\txor\t$12,$20\n\txor\t$13,$21\n\txor\t$14,$22\n\txor\t$15,$23\n\n\t#sll\t$16,$16,0\n\t#sll\t$17,$17,0\n\t#sll\t$18,$18,0\n\t#sll\t$19,$19,0\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n#endif\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\n\tjr\t$31\n.end\t_mips_AES_encrypt\n\n.align\t5\n.globl\tAES_encrypt\n.ent\tAES_encrypt\nAES_encrypt:\n\t.frame\t$29,64,$31\n\t.mask\t0xc0ff0000,-4\n\t.set\tnoreorder\n\t.cpload\t$25\n\tsub $29,64\n\tsw\t$31,64-1*4($29)\n\tsw\t$30,64-2*4($29)\n\tsw\t$23,64-3*4($29)\n\tsw\t$22,64-4*4($29)\n\tsw\t$21,64-5*4($29)\n\tsw\t$20,64-6*4($29)\n\tsw\t$19,64-7*4($29)\n\tsw\t$18,64-8*4($29)\n\tsw\t$17,64-9*4($29)\n\tsw\t$16,64-10*4($29)\n\t.set\treorder\n\tla\t$7,AES_Te\t\t# PIC-ified 'load address'\n\n\tlwl\t$8,0+0($4)\n\tlwl\t$9,4+0($4)\n\tlwl\t$10,8+0($4)\n\tlwl\t$11,12+0($4)\n\tlwr\t$8,0+3($4)\n\tlwr\t$9,4+3($4)\n\tlwr\t$10,8+3($4)\n\tlwr\t$11,12+3($4)\n\n\tbal\t_mips_AES_encrypt\n\n\tswr\t$8,0+3($5)\n\tswr\t$9,4+3($5)\n\tswr\t$10,8+3($5)\n\tswr\t$11,12+3($5)\n\tswl\t$8,0+0($5)\n\tswl\t$9,4+0($5)\n\tswl\t$10,8+0($5)\n\tswl\t$11,12+0($5)\n\n\t.set\tnoreorder\n\tlw\t$31,64-1*4($29)\n\tlw\t$30,64-2*4($29)\n\tlw\t$23,64-3*4($29)\n\tlw\t$22,64-4*4($29)\n\tlw\t$21,64-5*4($29)\n\tlw\t$20,64-6*4($29)\n\tlw\t$19,64-7*4($29)\n\tlw\t$18,64-8*4($29)\n\tlw\t$17,64-9*4($29)\n\tlw\t$16,64-10*4($29)\n\tjr\t$31\n\tadd $29,64\n.end\tAES_encrypt\n.align\t5\n.ent\t_mips_AES_decrypt\n_mips_AES_decrypt:\n\t.frame\t$29,0,$31\n\t.set\treorder\n\tlw\t$12,0($6)\n\tlw\t$13,4($6)\n\tlw\t$14,8($6)\n\tlw\t$15,12($6)\n\tlw\t$30,240($6)\n\tadd $3,$6,16\n\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\n\tsub\t$30,1\n#if defined(__mips_smartmips)\n\text\t$1,$11,16,8\n.Loop_dec:\n\text\t$2,$8,16,8\n\text\t$24,$9,16,8\n\text\t$25,$10,16,8\n\tlwxs\t$12,$1($7)\t\t# Td1[s3>>16]\n\text\t$1,$10,8,8\n\tlwxs\t$13,$2($7)\t\t# Td1[s0>>16]\n\text\t$2,$11,8,8\n\tlwxs\t$14,$24($7)\t\t# Td1[s1>>16]\n\text\t$24,$8,8,8\n\tlwxs\t$15,$25($7)\t\t# Td1[s2>>16]\n\text\t$25,$9,8,8\n\n\tlwxs\t$16,$1($7)\t\t# Td2[s2>>8]\n\text\t$1,$9,0,8\n\tlwxs\t$17,$2($7)\t\t# Td2[s3>>8]\n\text\t$2,$10,0,8\n\tlwxs\t$18,$24($7)\t\t# Td2[s0>>8]\n\text\t$24,$11,0,8\n\tlwxs\t$19,$25($7)\t\t# Td2[s1>>8]\n\text\t$25,$8,0,8\n\n\tlwxs\t$20,$1($7)\t\t# Td3[s1]\n\text\t$1,$8,24,8\n\tlwxs\t$21,$2($7)\t\t# Td3[s2]\n\text\t$2,$9,24,8\n\tlwxs\t$22,$24($7)\t\t# Td3[s3]\n\text\t$24,$10,24,8\n\tlwxs\t$23,$25($7)\t\t# Td3[s0]\n\text\t$25,$11,24,8\n\n\trotr\t$12,$12,8\n\trotr\t$13,$13,8\n\trotr\t$14,$14,8\n\trotr\t$15,$15,8\n\n\trotr\t$16,$16,16\n\trotr\t$17,$17,16\n\trotr\t$18,$18,16\n\trotr\t$19,$19,16\n\n\txor\t$12,$16\n\tlwxs\t$16,$1($7)\t\t# Td0[s0>>24]\n\txor\t$13,$17\n\tlwxs\t$17,$2($7)\t\t# Td0[s1>>24]\n\txor\t$14,$18\n\tlwxs\t$18,$24($7)\t\t# Td0[s2>>24]\n\txor\t$15,$19\n\tlwxs\t$19,$25($7)\t\t# Td0[s3>>24]\n\n\trotr\t$20,$20,24\n\tlw\t$8,0($3)\n\trotr\t$21,$21,24\n\tlw\t$9,4($3)\n\trotr\t$22,$22,24\n\tlw\t$10,8($3)\n\trotr\t$23,$23,24\n\tlw\t$11,12($3)\n\n\txor\t$12,$20\n\txor\t$13,$21\n\txor\t$14,$22\n\txor\t$15,$23\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n\n\tsub\t$30,1\n\tadd $3,16\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\t.set\tnoreorder\n\tbnez\t$30,.Loop_dec\n\text\t$1,$11,16,8\n\n\tsrl\t$1,$11,14\n#else\n\tsrl\t$1,$11,14\n.Loop_dec:\n\tsrl\t$2,$8,14\n\tsrl\t$24,$9,14\n\tsrl\t$25,$10,14\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\tlw\t$12,0($1)\t\t# Td1[s3>>16]\n\tsrl\t$1,$10,6\n\tlw\t$13,0($2)\t\t# Td1[s0>>16]\n\tsrl\t$2,$11,6\n\tlw\t$14,0($24)\t\t# Td1[s1>>16]\n\tsrl\t$24,$8,6\n\tlw\t$15,0($25)\t\t# Td1[s2>>16]\n\tsrl\t$25,$9,6\n#else\n\tlwl\t$12,3($1)\t\t# Td1[s3>>16]\n\tlwl\t$13,3($2)\t\t# Td1[s0>>16]\n\tlwl\t$14,3($24)\t\t# Td1[s1>>16]\n\tlwl\t$15,3($25)\t\t# Td1[s2>>16]\n\tlwr\t$12,2($1)\t\t# Td1[s3>>16]\n\tsrl\t$1,$10,6\n\tlwr\t$13,2($2)\t\t# Td1[s0>>16]\n\tsrl\t$2,$11,6\n\tlwr\t$14,2($24)\t\t# Td1[s1>>16]\n\tsrl\t$24,$8,6\n\tlwr\t$15,2($25)\t\t# Td1[s2>>16]\n\tsrl\t$25,$9,6\n#endif\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\trotr\t$12,$12,8\n\trotr\t$13,$13,8\n\trotr\t$14,$14,8\n\trotr\t$15,$15,8\n# if defined(_MIPSEL)\n\tlw\t$16,0($1)\t\t# Td2[s2>>8]\n\tsll\t$1,$9,2\n\tlw\t$17,0($2)\t\t# Td2[s3>>8]\n\tsll\t$2,$10,2\n\tlw\t$18,0($24)\t\t# Td2[s0>>8]\n\tsll\t$24,$11,2\n\tlw\t$19,0($25)\t\t# Td2[s1>>8]\n\tsll\t$25,$8,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlw\t$20,0($1)\t\t# Td3[s1]\n\tins $1,$8,2,8\n\tlw\t$21,0($2)\t\t# Td3[s2]\n\tins $2,$9,2,8\n\tlw\t$22,0($24)\t\t# Td3[s3]\n\tins $24,$10,2,8\n\tlw\t$23,0($25)\t\t# Td3[s0]\n\tins $25,$11,2,8\n#else\n\tlw\t$16,0($1)\t\t# Td2[s2>>8]\n\tins $1,$9,2,8\n\tlw\t$17,0($2)\t\t# Td2[s3>>8]\n\tins $2,$10,2,8\n\tlw\t$18,0($24)\t\t# Td2[s0>>8]\n\tins $24,$11,2,8\n\tlw\t$19,0($25)\t\t# Td2[s1>>8]\n\tins $25,$8,2,8\n\n\tlw\t$20,0($1)\t\t# Td3[s1]\n\tsrl\t$1,$8,22\n\tlw\t$21,0($2)\t\t# Td3[s2]\n\tsrl\t$2,$9,22\n\tlw\t$22,0($24)\t\t# Td3[s3]\n\tsrl\t$24,$10,22\n\tlw\t$23,0($25)\t\t# Td3[s0]\n\tsrl\t$25,$11,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#endif\n\trotr\t$16,$16,16\n\trotr\t$17,$17,16\n\trotr\t$18,$18,16\n\trotr\t$19,$19,16\n\n\trotr\t$20,$20,24\n\trotr\t$21,$21,24\n\trotr\t$22,$22,24\n\trotr\t$23,$23,24\n#else\n\tlwl\t$16,2($1)\t\t# Td2[s2>>8]\n\tlwl\t$17,2($2)\t\t# Td2[s3>>8]\n\tlwl\t$18,2($24)\t\t# Td2[s0>>8]\n\tlwl\t$19,2($25)\t\t# Td2[s1>>8]\n\tlwr\t$16,1($1)\t\t# Td2[s2>>8]\n\tsll\t$1,$9,2\n\tlwr\t$17,1($2)\t\t# Td2[s3>>8]\n\tsll\t$2,$10,2\n\tlwr\t$18,1($24)\t\t# Td2[s0>>8]\n\tsll\t$24,$11,2\n\tlwr\t$19,1($25)\t\t# Td2[s1>>8]\n\tsll\t$25,$8,2\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlwl\t$20,1($1)\t\t# Td3[s1]\n\tlwl\t$21,1($2)\t\t# Td3[s2]\n\tlwl\t$22,1($24)\t\t# Td3[s3]\n\tlwl\t$23,1($25)\t\t# Td3[s0]\n\tlwr\t$20,0($1)\t\t# Td3[s1]\n\tsrl\t$1,$8,22\n\tlwr\t$21,0($2)\t\t# Td3[s2]\n\tsrl\t$2,$9,22\n\tlwr\t$22,0($24)\t\t# Td3[s3]\n\tsrl\t$24,$10,22\n\tlwr\t$23,0($25)\t\t# Td3[s0]\n\tsrl\t$25,$11,22\n\n\tand\t$1,0x3fc\n\tand\t$2,0x3fc\n\tand\t$24,0x3fc\n\tand\t$25,0x3fc\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#endif\n\n\txor\t$12,$16\n\tlw\t$16,0($1)\t\t# Td0[s0>>24]\n\txor\t$13,$17\n\tlw\t$17,0($2)\t\t# Td0[s1>>24]\n\txor\t$14,$18\n\tlw\t$18,0($24)\t\t# Td0[s2>>24]\n\txor\t$15,$19\n\tlw\t$19,0($25)\t\t# Td0[s3>>24]\n\n\txor\t$12,$20\n\tlw\t$8,0($3)\n\txor\t$13,$21\n\tlw\t$9,4($3)\n\txor\t$14,$22\n\tlw\t$10,8($3)\n\txor\t$15,$23\n\tlw\t$11,12($3)\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n\n\tsub\t$30,1\n\tadd $3,16\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\t.set\tnoreorder\n\tbnez\t$30,.Loop_dec\n\tsrl\t$1,$11,14\n#endif\n\n\t.set\treorder\n\tlw\t$16,1024($7)\t\t# prefetch Td4\n\tsrl\t$1,$11,16\n\tlw\t$17,1024+32($7)\n\tsrl\t$2,$8,16\n\tlw\t$18,1024+64($7)\n\tsrl\t$24,$9,16\n\tlw\t$19,1024+96($7)\n\tsrl\t$25,$10,16\n\tlw\t$20,1024+128($7)\n\tand\t$1,0xff\n\tlw\t$21,1024+160($7)\n\tand\t$2,0xff\n\tlw\t$22,1024+192($7)\n\tand\t$24,0xff\n\tlw\t$23,1024+224($7)\n\tand\t$25,0xff\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$12,1024($1)\t\t# Td4[s3>>16]\n\tsrl\t$1,$10,8\n\tlbu\t$13,1024($2)\t\t# Td4[s0>>16]\n\tsrl\t$2,$11,8\n\tlbu\t$14,1024($24)\t\t# Td4[s1>>16]\n\tsrl\t$24,$8,8\n\tlbu\t$15,1024($25)\t\t# Td4[s2>>16]\n\tsrl\t$25,$9,8\n\n\tand\t$1,0xff\n\tand\t$2,0xff\n\tand\t$24,0xff\n\tand\t$25,0xff\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n# if defined(_MIPSEL)\n\tlbu\t$16,1024($1)\t\t# Td4[s2>>8]\n\tins $1,$8,0,8\n\tlbu\t$17,1024($2)\t\t# Td4[s3>>8]\n\tins $2,$9,0,8\n\tlbu\t$18,1024($24)\t\t# Td4[s0>>8]\n\tins $24,$10,0,8\n\tlbu\t$19,1024($25)\t\t# Td4[s1>>8]\n\tins $25,$11,0,8\n\n\tlbu\t$20,1024($1)\t\t# Td4[s0>>24]\n\tand\t$1,$9,0xff\n\tlbu\t$21,1024($2)\t\t# Td4[s1>>24]\n\tand\t$2,$10,0xff\n\tlbu\t$22,1024($24)\t\t# Td4[s2>>24]\n\tand\t$24,$11,0xff\n\tlbu\t$23,1024($25)\t\t# Td4[s3>>24]\n\tand\t$25,$8,0xff\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n# else\n\tlbu\t$16,1024($1)\t\t# Td4[s2>>8]\n\tsrl\t$1,$8,24\n\tlbu\t$17,1024($2)\t\t# Td4[s3>>8]\n\tsrl\t$2,$9,24\n\tlbu\t$18,1024($24)\t\t# Td4[s0>>8]\n\tsrl\t$24,$10,24\n\tlbu\t$19,1024($25)\t\t# Td4[s1>>8]\n\tsrl\t$25,$11,24\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$20,1024($1)\t\t# Td4[s0>>24]\n\tins $1,$9,0,8\n\tlbu\t$21,1024($2)\t\t# Td4[s1>>24]\n\tins $2,$10,0,8\n\tlbu\t$22,1024($24)\t\t# Td4[s2>>24]\n\tins $24,$11,0,8\n\tlbu\t$23,1024($25)\t\t# Td4[s3>>24]\n\tins $25,$8,0,8\n# endif\n\tsll\t$12,$12,16\n\tsll\t$13,$13,16\n\tsll\t$14,$14,16\n\tsll\t$15,$15,16\n\n\tins\t$12,$16,8,8\n\tlbu\t$16,1024($1)\t\t# Td4[s1]\n\tins\t$13,$17,8,8\n\tlbu\t$17,1024($2)\t\t# Td4[s2]\n\tins\t$14,$18,8,8\n\tlbu\t$18,1024($24)\t\t# Td4[s3]\n\tins\t$15,$19,8,8\n\tlbu\t$19,1024($25)\t\t# Td4[s0]\n\n\tins\t$12,$20,24,8\n\tlw\t$8,0($3)\n\tins\t$13,$21,24,8\n\tlw\t$9,4($3)\n\tins\t$14,$22,24,8\n\tlw\t$10,8($3)\n\tins\t$15,$23,24,8\n\tlw\t$11,12($3)\n\n\tins\t$12,$16,0,8\n\tins\t$13,$17,0,8\n\tins\t$14,$18,0,8\n\tins\t$15,$19,0,8\n#else\n\tlbu\t$16,1024($1)\t\t# Td4[s2>>8]\n\tsrl\t$1,$8,24\n\tlbu\t$17,1024($2)\t\t# Td4[s3>>8]\n\tsrl\t$2,$9,24\n\tlbu\t$18,1024($24)\t\t# Td4[s0>>8]\n\tsrl\t$24,$10,24\n\tlbu\t$19,1024($25)\t\t# Td4[s1>>8]\n\tsrl\t$25,$11,24\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$20,1024($1)\t\t# Td4[s0>>24]\n\tand\t$1,$9,0xff\n\tlbu\t$21,1024($2)\t\t# Td4[s1>>24]\n\tand\t$2,$10,0xff\n\tlbu\t$22,1024($24)\t\t# Td4[s2>>24]\n\tand\t$24,$11,0xff\n\tlbu\t$23,1024($25)\t\t# Td4[s3>>24]\n\tand\t$25,$8,0xff\n\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\n\tsll\t$12,$12,16\n\tsll\t$13,$13,16\n\tsll\t$14,$14,16\n\tsll\t$15,$15,16\n\n\tsll\t$16,$16,8\n\tsll\t$17,$17,8\n\tsll\t$18,$18,8\n\tsll\t$19,$19,8\n\n\txor\t$12,$16\n\tlbu\t$16,1024($1)\t\t# Td4[s1]\n\txor\t$13,$17\n\tlbu\t$17,1024($2)\t\t# Td4[s2]\n\txor\t$14,$18\n\tlbu\t$18,1024($24)\t\t# Td4[s3]\n\txor\t$15,$19\n\tlbu\t$19,1024($25)\t\t# Td4[s0]\n\n\tsll\t$20,$20,24\n\tlw\t$8,0($3)\n\tsll\t$21,$21,24\n\tlw\t$9,4($3)\n\tsll\t$22,$22,24\n\tlw\t$10,8($3)\n\tsll\t$23,$23,24\n\tlw\t$11,12($3)\n\n\txor\t$12,$20\n\txor\t$13,$21\n\txor\t$14,$22\n\txor\t$15,$23\n\n\t#sll\t$16,$16,0\n\t#sll\t$17,$17,0\n\t#sll\t$18,$18,0\n\t#sll\t$19,$19,0\n\n\txor\t$12,$16\n\txor\t$13,$17\n\txor\t$14,$18\n\txor\t$15,$19\n#endif\n\n\txor\t$8,$12\n\txor\t$9,$13\n\txor\t$10,$14\n\txor\t$11,$15\n\n\tjr\t$31\n.end\t_mips_AES_decrypt\n\n.align\t5\n.globl\tAES_decrypt\n.ent\tAES_decrypt\nAES_decrypt:\n\t.frame\t$29,64,$31\n\t.mask\t0xc0ff0000,-4\n\t.set\tnoreorder\n\t.cpload\t$25\n\tsub $29,64\n\tsw\t$31,64-1*4($29)\n\tsw\t$30,64-2*4($29)\n\tsw\t$23,64-3*4($29)\n\tsw\t$22,64-4*4($29)\n\tsw\t$21,64-5*4($29)\n\tsw\t$20,64-6*4($29)\n\tsw\t$19,64-7*4($29)\n\tsw\t$18,64-8*4($29)\n\tsw\t$17,64-9*4($29)\n\tsw\t$16,64-10*4($29)\n\t.set\treorder\n\tla\t$7,AES_Td\t\t# PIC-ified 'load address'\n\n\tlwl\t$8,0+0($4)\n\tlwl\t$9,4+0($4)\n\tlwl\t$10,8+0($4)\n\tlwl\t$11,12+0($4)\n\tlwr\t$8,0+3($4)\n\tlwr\t$9,4+3($4)\n\tlwr\t$10,8+3($4)\n\tlwr\t$11,12+3($4)\n\n\tbal\t_mips_AES_decrypt\n\n\tswr\t$8,0+3($5)\n\tswr\t$9,4+3($5)\n\tswr\t$10,8+3($5)\n\tswr\t$11,12+3($5)\n\tswl\t$8,0+0($5)\n\tswl\t$9,4+0($5)\n\tswl\t$10,8+0($5)\n\tswl\t$11,12+0($5)\n\n\t.set\tnoreorder\n\tlw\t$31,64-1*4($29)\n\tlw\t$30,64-2*4($29)\n\tlw\t$23,64-3*4($29)\n\tlw\t$22,64-4*4($29)\n\tlw\t$21,64-5*4($29)\n\tlw\t$20,64-6*4($29)\n\tlw\t$19,64-7*4($29)\n\tlw\t$18,64-8*4($29)\n\tlw\t$17,64-9*4($29)\n\tlw\t$16,64-10*4($29)\n\tjr\t$31\n\tadd $29,64\n.end\tAES_decrypt\n.align\t5\n.ent\t_mips_AES_set_encrypt_key\n_mips_AES_set_encrypt_key:\n\t.frame\t$29,0,$31\n\t.set\tnoreorder\n\tbeqz\t$4,.Lekey_done\n\tli\t$2,-1\n\tbeqz\t$6,.Lekey_done\n\tadd $3,$7,256\n\n\t.set\treorder\n\tlwl\t$8,0+0($4)\t# load 128 bits\n\tlwl\t$9,4+0($4)\n\tlwl\t$10,8+0($4)\n\tlwl\t$11,12+0($4)\n\tli\t$1,128\n\tlwr\t$8,0+3($4)\n\tlwr\t$9,4+3($4)\n\tlwr\t$10,8+3($4)\n\tlwr\t$11,12+3($4)\n\t.set\tnoreorder\n\tbeq\t$5,$1,.L128bits\n\tli\t$30,10\n\n\t.set\treorder\n\tlwl\t$12,16+0($4)\t# load 192 bits\n\tlwl\t$13,20+0($4)\n\tli\t$1,192\n\tlwr\t$12,16+3($4)\n\tlwr\t$13,20+3($4)\n\t.set\tnoreorder\n\tbeq\t$5,$1,.L192bits\n\tli\t$30,8\n\n\t.set\treorder\n\tlwl\t$14,24+0($4)\t# load 256 bits\n\tlwl\t$15,28+0($4)\n\tli\t$1,256\n\tlwr\t$14,24+3($4)\n\tlwr\t$15,28+3($4)\n\t.set\tnoreorder\n\tbeq\t$5,$1,.L256bits\n\tli\t$30,7\n\n\tb\t.Lekey_done\n\tli\t$2,-2\n\n.align\t4\n.L128bits:\n\t.set\treorder\n\tsrl\t$1,$11,16\n\tsrl\t$2,$11,8\n\tand\t$1,0xff\n\tand\t$2,0xff\n\tand\t$24,$11,0xff\n\tsrl\t$25,$11,24\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$1,0($1)\n\tlbu\t$2,0($2)\n\tlbu\t$24,0($24)\n\tlbu\t$25,0($25)\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tsw\t$11,12($6)\n\tsub\t$30,1\n\tadd $6,16\n\n\tsll\t$1,$1,24\n\tsll\t$2,$2,16\n\tsll\t$24,$24,8\n\t#sll\t$25,$25,0\n\n\txor\t$8,$1\n\tlw\t$1,0($3)\n\txor\t$8,$2\n\txor\t$8,$24\n\txor\t$8,$25\n\txor\t$8,$1\n\n\txor\t$9,$8\n\txor\t$10,$9\n\txor\t$11,$10\n\n\t.set\tnoreorder\n\tbnez\t$30,.L128bits\n\tadd $3,4\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tli\t$30,10\n\tsw\t$11,12($6)\n\tli\t$2,0\n\tsw\t$30,80($6)\n\tb\t.Lekey_done\n\tsub $6,10*16\n\n.align\t4\n.L192bits:\n\t.set\treorder\n\tsrl\t$1,$13,16\n\tsrl\t$2,$13,8\n\tand\t$1,0xff\n\tand\t$2,0xff\n\tand\t$24,$13,0xff\n\tsrl\t$25,$13,24\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$1,0($1)\n\tlbu\t$2,0($2)\n\tlbu\t$24,0($24)\n\tlbu\t$25,0($25)\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tsw\t$11,12($6)\n\tsw\t$12,16($6)\n\tsw\t$13,20($6)\n\tsub\t$30,1\n\tadd $6,24\n\n\tsll\t$1,$1,24\n\tsll\t$2,$2,16\n\tsll\t$24,$24,8\n\t#sll\t$25,$25,0\n\n\txor\t$8,$1\n\tlw\t$1,0($3)\n\txor\t$8,$2\n\txor\t$8,$24\n\txor\t$8,$25\n\txor\t$8,$1\n\n\txor\t$9,$8\n\txor\t$10,$9\n\txor\t$11,$10\n\txor\t$12,$11\n\txor\t$13,$12\n\n\t.set\tnoreorder\n\tbnez\t$30,.L192bits\n\tadd $3,4\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tli\t$30,12\n\tsw\t$11,12($6)\n\tli\t$2,0\n\tsw\t$30,48($6)\n\tb\t.Lekey_done\n\tsub $6,12*16\n\n.align\t4\n.L256bits:\n\t.set\treorder\n\tsrl\t$1,$15,16\n\tsrl\t$2,$15,8\n\tand\t$1,0xff\n\tand\t$2,0xff\n\tand\t$24,$15,0xff\n\tsrl\t$25,$15,24\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$1,0($1)\n\tlbu\t$2,0($2)\n\tlbu\t$24,0($24)\n\tlbu\t$25,0($25)\n\n\tsw\t$8,0($6)\n\tsw\t$9,4($6)\n\tsw\t$10,8($6)\n\tsw\t$11,12($6)\n\tsw\t$12,16($6)\n\tsw\t$13,20($6)\n\tsw\t$14,24($6)\n\tsw\t$15,28($6)\n\tsub\t$30,1\n\n\tsll\t$1,$1,24\n\tsll\t$2,$2,16\n\tsll\t$24,$24,8\n\t#sll\t$25,$25,0\n\n\txor\t$8,$1\n\tlw\t$1,0($3)\n\txor\t$8,$2\n\txor\t$8,$24\n\txor\t$8,$25\n\txor\t$8,$1\n\n\txor\t$9,$8\n\txor\t$10,$9\n\txor\t$11,$10\n\tbeqz\t$30,.L256bits_done\n\n\tsrl\t$1,$11,24\n\tsrl\t$2,$11,16\n\tsrl\t$24,$11,8\n\tand\t$25,$11,0xff\n\tand\t$2,0xff\n\tand\t$24,0xff\n\tadd $1,$7\n\tadd $2,$7\n\tadd $24,$7\n\tadd $25,$7\n\tlbu\t$1,0($1)\n\tlbu\t$2,0($2)\n\tlbu\t$24,0($24)\n\tlbu\t$25,0($25)\n\tsll\t$1,24\n\tsll\t$2,16\n\tsll\t$24,8\n\n\txor\t$12,$1\n\txor\t$12,$2\n\txor\t$12,$24\n\txor\t$12,$25\n\n\txor\t$13,$12\n\txor\t$14,$13\n\txor\t$15,$14\n\n\tadd $6,32\n\t.set\tnoreorder\n\tb\t.L256bits\n\tadd $3,4\n\n.L256bits_done:\n\tsw\t$8,32($6)\n\tsw\t$9,36($6)\n\tsw\t$10,40($6)\n\tli\t$30,14\n\tsw\t$11,44($6)\n\tli\t$2,0\n\tsw\t$30,48($6)\n\tsub $6,12*16\n\n.Lekey_done:\n\tjr\t$31\n\tnop\n.end\t_mips_AES_set_encrypt_key\n\n.globl\tAES_set_encrypt_key\n.ent\tAES_set_encrypt_key\nAES_set_encrypt_key:\n\t.frame\t$29,32,$31\n\t.mask\t0xc0000000,-4\n\t.set\tnoreorder\n\t.cpload\t$25\n\tsub $29,32\n\tsw\t$31,32-1*4($29)\n\tsw\t$30,32-2*4($29)\n\t.set\treorder\n\tla\t$7,AES_Te4\t\t# PIC-ified 'load address'\n\n\tbal\t_mips_AES_set_encrypt_key\n\n\t.set\tnoreorder\n\tmove\t$4,$2\n\tlw\t$31,32-1*4($29)\n\tlw\t$30,32-2*4($29)\n\tjr\t$31\n\tadd $29,32\n.end\tAES_set_encrypt_key\n.align\t5\n.globl\tAES_set_decrypt_key\n.ent\tAES_set_decrypt_key\nAES_set_decrypt_key:\n\t.frame\t$29,32,$31\n\t.mask\t0xc0000000,-4\n\t.set\tnoreorder\n\t.cpload\t$25\n\tsub $29,32\n\tsw\t$31,32-1*4($29)\n\tsw\t$30,32-2*4($29)\n\t.set\treorder\n\tla\t$7,AES_Te4\t\t# PIC-ified 'load address'\n\n\tbal\t_mips_AES_set_encrypt_key\n\n\tbltz\t$2,.Ldkey_done\n\n\tsll\t$1,$30,4\n\tadd $4,$6,0\n\tadd $5,$6,$1\n.align\t4\n.Lswap:\n\tlw\t$8,0($4)\n\tlw\t$9,4($4)\n\tlw\t$10,8($4)\n\tlw\t$11,12($4)\n\tlw\t$12,0($5)\n\tlw\t$13,4($5)\n\tlw\t$14,8($5)\n\tlw\t$15,12($5)\n\tsw\t$8,0($5)\n\tsw\t$9,4($5)\n\tsw\t$10,8($5)\n\tsw\t$11,12($5)\n\tadd $4,16\n\tsub $5,16\n\tsw\t$12,-16($4)\n\tsw\t$13,-12($4)\n\tsw\t$14,-8($4)\n\tsw\t$15,-4($4)\n\tbne\t$4,$5,.Lswap\n\n\tlw\t$8,16($6)\t\t# modulo-scheduled\n\tlui\t$2,0x8080\n\tsub\t$30,1\n\tor\t$2,0x8080\n\tsll\t$30,2\n\tadd $6,16\n\tlui\t$25,0x1b1b\n\tnor\t$24,$0,$2\n\tor\t$25,0x1b1b\n.align\t4\n.Lmix:\n\tand\t$1,$8,$2\n\tand\t$9,$8,$24\n\tsrl\t$10,$1,7\n\taddu\t$9,$9\t\t# tp2<<1\n\tsubu\t$1,$10\n\tand\t$1,$25\n\txor\t$9,$1\n\n\tand\t$1,$9,$2\n\tand\t$10,$9,$24\n\tsrl\t$11,$1,7\n\taddu\t$10,$10\t\t# tp4<<1\n\tsubu\t$1,$11\n\tand\t$1,$25\n\txor\t$10,$1\n\n\tand\t$1,$10,$2\n\tand\t$11,$10,$24\n\tsrl\t$12,$1,7\n\taddu\t$11,$11\t\t# tp8<<1\n\tsubu\t$1,$12\n\tand\t$1,$25\n\txor\t$11,$1\n\n\txor\t$12,$11,$8\n\txor\t$15,$11,$10\n\txor\t$13,$12,$9\n\txor\t$14,$12,$10\n\n#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)\n\trotr\t$8,$14,16\n\t xor\t$15,$9\n\trotr\t$9,$12,8\n\txor\t$15,$8\n\trotr\t$10,$13,24\n\txor\t$15,$9\n\tlw\t$8,4($6)\t\t# modulo-scheduled\n\txor\t$15,$10\n#else\n\tsrl\t$8,$14,16\n\t xor\t$15,$9\n\tsll\t$9,$14,16\n\txor\t$15,$8\n\tsrl\t$8,$12,8\n\txor\t$15,$9\n\tsll\t$9,$12,24\n\txor\t$15,$8\n\tsrl\t$8,$13,24\n\txor\t$15,$9\n\tsll\t$9,$13,8\n\txor\t$15,$8\n\tlw\t$8,4($6)\t\t# modulo-scheduled\n\txor\t$15,$9\n#endif\n\tsub\t$30,1\n\tsw\t$15,0($6)\n\tadd $6,4\n\tbnez\t$30,.Lmix\n\n\tli\t$2,0\n.Ldkey_done:\n\t.set\tnoreorder\n\tmove\t$4,$2\n\tlw\t$31,32-1*4($29)\n\tlw\t$30,32-2*4($29)\n\tjr\t$31\n\tadd $29,32\n.end\tAES_set_decrypt_key\n.rdata\n.align\t10\nAES_Te:\n.byte\t0xc6,0x63,0x63,0xa5,\t0xf8,0x7c,0x7c,0x84\t# Te0\n.byte\t0xee,0x77,0x77,0x99,\t0xf6,0x7b,0x7b,0x8d\n.byte\t0xff,0xf2,0xf2,0x0d,\t0xd6,0x6b,0x6b,0xbd\n.byte\t0xde,0x6f,0x6f,0xb1,\t0x91,0xc5,0xc5,0x54\n.byte\t0x60,0x30,0x30,0x50,\t0x02,0x01,0x01,0x03\n.byte\t0xce,0x67,0x67,0xa9,\t0x56,0x2b,0x2b,0x7d\n.byte\t0xe7,0xfe,0xfe,0x19,\t0xb5,0xd7,0xd7,0x62\n.byte\t0x4d,0xab,0xab,0xe6,\t0xec,0x76,0x76,0x9a\n.byte\t0x8f,0xca,0xca,0x45,\t0x1f,0x82,0x82,0x9d\n.byte\t0x89,0xc9,0xc9,0x40,\t0xfa,0x7d,0x7d,0x87\n.byte\t0xef,0xfa,0xfa,0x15,\t0xb2,0x59,0x59,0xeb\n.byte\t0x8e,0x47,0x47,0xc9,\t0xfb,0xf0,0xf0,0x0b\n.byte\t0x41,0xad,0xad,0xec,\t0xb3,0xd4,0xd4,0x67\n.byte\t0x5f,0xa2,0xa2,0xfd,\t0x45,0xaf,0xaf,0xea\n.byte\t0x23,0x9c,0x9c,0xbf,\t0x53,0xa4,0xa4,0xf7\n.byte\t0xe4,0x72,0x72,0x96,\t0x9b,0xc0,0xc0,0x5b\n.byte\t0x75,0xb7,0xb7,0xc2,\t0xe1,0xfd,0xfd,0x1c\n.byte\t0x3d,0x93,0x93,0xae,\t0x4c,0x26,0x26,0x6a\n.byte\t0x6c,0x36,0x36,0x5a,\t0x7e,0x3f,0x3f,0x41\n.byte\t0xf5,0xf7,0xf7,0x02,\t0x83,0xcc,0xcc,0x4f\n.byte\t0x68,0x34,0x34,0x5c,\t0x51,0xa5,0xa5,0xf4\n.byte\t0xd1,0xe5,0xe5,0x34,\t0xf9,0xf1,0xf1,0x08\n.byte\t0xe2,0x71,0x71,0x93,\t0xab,0xd8,0xd8,0x73\n.byte\t0x62,0x31,0x31,0x53,\t0x2a,0x15,0x15,0x3f\n.byte\t0x08,0x04,0x04,0x0c,\t0x95,0xc7,0xc7,0x52\n.byte\t0x46,0x23,0x23,0x65,\t0x9d,0xc3,0xc3,0x5e\n.byte\t0x30,0x18,0x18,0x28,\t0x37,0x96,0x96,0xa1\n.byte\t0x0a,0x05,0x05,0x0f,\t0x2f,0x9a,0x9a,0xb5\n.byte\t0x0e,0x07,0x07,0x09,\t0x24,0x12,0x12,0x36\n.byte\t0x1b,0x80,0x80,0x9b,\t0xdf,0xe2,0xe2,0x3d\n.byte\t0xcd,0xeb,0xeb,0x26,\t0x4e,0x27,0x27,0x69\n.byte\t0x7f,0xb2,0xb2,0xcd,\t0xea,0x75,0x75,0x9f\n.byte\t0x12,0x09,0x09,0x1b,\t0x1d,0x83,0x83,0x9e\n.byte\t0x58,0x2c,0x2c,0x74,\t0x34,0x1a,0x1a,0x2e\n.byte\t0x36,0x1b,0x1b,0x2d,\t0xdc,0x6e,0x6e,0xb2\n.byte\t0xb4,0x5a,0x5a,0xee,\t0x5b,0xa0,0xa0,0xfb\n.byte\t0xa4,0x52,0x52,0xf6,\t0x76,0x3b,0x3b,0x4d\n.byte\t0xb7,0xd6,0xd6,0x61,\t0x7d,0xb3,0xb3,0xce\n.byte\t0x52,0x29,0x29,0x7b,\t0xdd,0xe3,0xe3,0x3e\n.byte\t0x5e,0x2f,0x2f,0x71,\t0x13,0x84,0x84,0x97\n.byte\t0xa6,0x53,0x53,0xf5,\t0xb9,0xd1,0xd1,0x68\n.byte\t0x00,0x00,0x00,0x00,\t0xc1,0xed,0xed,0x2c\n.byte\t0x40,0x20,0x20,0x60,\t0xe3,0xfc,0xfc,0x1f\n.byte\t0x79,0xb1,0xb1,0xc8,\t0xb6,0x5b,0x5b,0xed\n.byte\t0xd4,0x6a,0x6a,0xbe,\t0x8d,0xcb,0xcb,0x46\n.byte\t0x67,0xbe,0xbe,0xd9,\t0x72,0x39,0x39,0x4b\n.byte\t0x94,0x4a,0x4a,0xde,\t0x98,0x4c,0x4c,0xd4\n.byte\t0xb0,0x58,0x58,0xe8,\t0x85,0xcf,0xcf,0x4a\n.byte\t0xbb,0xd0,0xd0,0x6b,\t0xc5,0xef,0xef,0x2a\n.byte\t0x4f,0xaa,0xaa,0xe5,\t0xed,0xfb,0xfb,0x16\n.byte\t0x86,0x43,0x43,0xc5,\t0x9a,0x4d,0x4d,0xd7\n.byte\t0x66,0x33,0x33,0x55,\t0x11,0x85,0x85,0x94\n.byte\t0x8a,0x45,0x45,0xcf,\t0xe9,0xf9,0xf9,0x10\n.byte\t0x04,0x02,0x02,0x06,\t0xfe,0x7f,0x7f,0x81\n.byte\t0xa0,0x50,0x50,0xf0,\t0x78,0x3c,0x3c,0x44\n.byte\t0x25,0x9f,0x9f,0xba,\t0x4b,0xa8,0xa8,0xe3\n.byte\t0xa2,0x51,0x51,0xf3,\t0x5d,0xa3,0xa3,0xfe\n.byte\t0x80,0x40,0x40,0xc0,\t0x05,0x8f,0x8f,0x8a\n.byte\t0x3f,0x92,0x92,0xad,\t0x21,0x9d,0x9d,0xbc\n.byte\t0x70,0x38,0x38,0x48,\t0xf1,0xf5,0xf5,0x04\n.byte\t0x63,0xbc,0xbc,0xdf,\t0x77,0xb6,0xb6,0xc1\n.byte\t0xaf,0xda,0xda,0x75,\t0x42,0x21,0x21,0x63\n.byte\t0x20,0x10,0x10,0x30,\t0xe5,0xff,0xff,0x1a\n.byte\t0xfd,0xf3,0xf3,0x0e,\t0xbf,0xd2,0xd2,0x6d\n.byte\t0x81,0xcd,0xcd,0x4c,\t0x18,0x0c,0x0c,0x14\n.byte\t0x26,0x13,0x13,0x35,\t0xc3,0xec,0xec,0x2f\n.byte\t0xbe,0x5f,0x5f,0xe1,\t0x35,0x97,0x97,0xa2\n.byte\t0x88,0x44,0x44,0xcc,\t0x2e,0x17,0x17,0x39\n.byte\t0x93,0xc4,0xc4,0x57,\t0x55,0xa7,0xa7,0xf2\n.byte\t0xfc,0x7e,0x7e,0x82,\t0x7a,0x3d,0x3d,0x47\n.byte\t0xc8,0x64,0x64,0xac,\t0xba,0x5d,0x5d,0xe7\n.byte\t0x32,0x19,0x19,0x2b,\t0xe6,0x73,0x73,0x95\n.byte\t0xc0,0x60,0x60,0xa0,\t0x19,0x81,0x81,0x98\n.byte\t0x9e,0x4f,0x4f,0xd1,\t0xa3,0xdc,0xdc,0x7f\n.byte\t0x44,0x22,0x22,0x66,\t0x54,0x2a,0x2a,0x7e\n.byte\t0x3b,0x90,0x90,0xab,\t0x0b,0x88,0x88,0x83\n.byte\t0x8c,0x46,0x46,0xca,\t0xc7,0xee,0xee,0x29\n.byte\t0x6b,0xb8,0xb8,0xd3,\t0x28,0x14,0x14,0x3c\n.byte\t0xa7,0xde,0xde,0x79,\t0xbc,0x5e,0x5e,0xe2\n.byte\t0x16,0x0b,0x0b,0x1d,\t0xad,0xdb,0xdb,0x76\n.byte\t0xdb,0xe0,0xe0,0x3b,\t0x64,0x32,0x32,0x56\n.byte\t0x74,0x3a,0x3a,0x4e,\t0x14,0x0a,0x0a,0x1e\n.byte\t0x92,0x49,0x49,0xdb,\t0x0c,0x06,0x06,0x0a\n.byte\t0x48,0x24,0x24,0x6c,\t0xb8,0x5c,0x5c,0xe4\n.byte\t0x9f,0xc2,0xc2,0x5d,\t0xbd,0xd3,0xd3,0x6e\n.byte\t0x43,0xac,0xac,0xef,\t0xc4,0x62,0x62,0xa6\n.byte\t0x39,0x91,0x91,0xa8,\t0x31,0x95,0x95,0xa4\n.byte\t0xd3,0xe4,0xe4,0x37,\t0xf2,0x79,0x79,0x8b\n.byte\t0xd5,0xe7,0xe7,0x32,\t0x8b,0xc8,0xc8,0x43\n.byte\t0x6e,0x37,0x37,0x59,\t0xda,0x6d,0x6d,0xb7\n.byte\t0x01,0x8d,0x8d,0x8c,\t0xb1,0xd5,0xd5,0x64\n.byte\t0x9c,0x4e,0x4e,0xd2,\t0x49,0xa9,0xa9,0xe0\n.byte\t0xd8,0x6c,0x6c,0xb4,\t0xac,0x56,0x56,0xfa\n.byte\t0xf3,0xf4,0xf4,0x07,\t0xcf,0xea,0xea,0x25\n.byte\t0xca,0x65,0x65,0xaf,\t0xf4,0x7a,0x7a,0x8e\n.byte\t0x47,0xae,0xae,0xe9,\t0x10,0x08,0x08,0x18\n.byte\t0x6f,0xba,0xba,0xd5,\t0xf0,0x78,0x78,0x88\n.byte\t0x4a,0x25,0x25,0x6f,\t0x5c,0x2e,0x2e,0x72\n.byte\t0x38,0x1c,0x1c,0x24,\t0x57,0xa6,0xa6,0xf1\n.byte\t0x73,0xb4,0xb4,0xc7,\t0x97,0xc6,0xc6,0x51\n.byte\t0xcb,0xe8,0xe8,0x23,\t0xa1,0xdd,0xdd,0x7c\n.byte\t0xe8,0x74,0x74,0x9c,\t0x3e,0x1f,0x1f,0x21\n.byte\t0x96,0x4b,0x4b,0xdd,\t0x61,0xbd,0xbd,0xdc\n.byte\t0x0d,0x8b,0x8b,0x86,\t0x0f,0x8a,0x8a,0x85\n.byte\t0xe0,0x70,0x70,0x90,\t0x7c,0x3e,0x3e,0x42\n.byte\t0x71,0xb5,0xb5,0xc4,\t0xcc,0x66,0x66,0xaa\n.byte\t0x90,0x48,0x48,0xd8,\t0x06,0x03,0x03,0x05\n.byte\t0xf7,0xf6,0xf6,0x01,\t0x1c,0x0e,0x0e,0x12\n.byte\t0xc2,0x61,0x61,0xa3,\t0x6a,0x35,0x35,0x5f\n.byte\t0xae,0x57,0x57,0xf9,\t0x69,0xb9,0xb9,0xd0\n.byte\t0x17,0x86,0x86,0x91,\t0x99,0xc1,0xc1,0x58\n.byte\t0x3a,0x1d,0x1d,0x27,\t0x27,0x9e,0x9e,0xb9\n.byte\t0xd9,0xe1,0xe1,0x38,\t0xeb,0xf8,0xf8,0x13\n.byte\t0x2b,0x98,0x98,0xb3,\t0x22,0x11,0x11,0x33\n.byte\t0xd2,0x69,0x69,0xbb,\t0xa9,0xd9,0xd9,0x70\n.byte\t0x07,0x8e,0x8e,0x89,\t0x33,0x94,0x94,0xa7\n.byte\t0x2d,0x9b,0x9b,0xb6,\t0x3c,0x1e,0x1e,0x22\n.byte\t0x15,0x87,0x87,0x92,\t0xc9,0xe9,0xe9,0x20\n.byte\t0x87,0xce,0xce,0x49,\t0xaa,0x55,0x55,0xff\n.byte\t0x50,0x28,0x28,0x78,\t0xa5,0xdf,0xdf,0x7a\n.byte\t0x03,0x8c,0x8c,0x8f,\t0x59,0xa1,0xa1,0xf8\n.byte\t0x09,0x89,0x89,0x80,\t0x1a,0x0d,0x0d,0x17\n.byte\t0x65,0xbf,0xbf,0xda,\t0xd7,0xe6,0xe6,0x31\n.byte\t0x84,0x42,0x42,0xc6,\t0xd0,0x68,0x68,0xb8\n.byte\t0x82,0x41,0x41,0xc3,\t0x29,0x99,0x99,0xb0\n.byte\t0x5a,0x2d,0x2d,0x77,\t0x1e,0x0f,0x0f,0x11\n.byte\t0x7b,0xb0,0xb0,0xcb,\t0xa8,0x54,0x54,0xfc\n.byte\t0x6d,0xbb,0xbb,0xd6,\t0x2c,0x16,0x16,0x3a\n\nAES_Td:\n.byte\t0x51,0xf4,0xa7,0x50,\t0x7e,0x41,0x65,0x53\t# Td0\n.byte\t0x1a,0x17,0xa4,0xc3,\t0x3a,0x27,0x5e,0x96\n.byte\t0x3b,0xab,0x6b,0xcb,\t0x1f,0x9d,0x45,0xf1\n.byte\t0xac,0xfa,0x58,0xab,\t0x4b,0xe3,0x03,0x93\n.byte\t0x20,0x30,0xfa,0x55,\t0xad,0x76,0x6d,0xf6\n.byte\t0x88,0xcc,0x76,0x91,\t0xf5,0x02,0x4c,0x25\n.byte\t0x4f,0xe5,0xd7,0xfc,\t0xc5,0x2a,0xcb,0xd7\n.byte\t0x26,0x35,0x44,0x80,\t0xb5,0x62,0xa3,0x8f\n.byte\t0xde,0xb1,0x5a,0x49,\t0x25,0xba,0x1b,0x67\n.byte\t0x45,0xea,0x0e,0x98,\t0x5d,0xfe,0xc0,0xe1\n.byte\t0xc3,0x2f,0x75,0x02,\t0x81,0x4c,0xf0,0x12\n.byte\t0x8d,0x46,0x97,0xa3,\t0x6b,0xd3,0xf9,0xc6\n.byte\t0x03,0x8f,0x5f,0xe7,\t0x15,0x92,0x9c,0x95\n.byte\t0xbf,0x6d,0x7a,0xeb,\t0x95,0x52,0x59,0xda\n.byte\t0xd4,0xbe,0x83,0x2d,\t0x58,0x74,0x21,0xd3\n.byte\t0x49,0xe0,0x69,0x29,\t0x8e,0xc9,0xc8,0x44\n.byte\t0x75,0xc2,0x89,0x6a,\t0xf4,0x8e,0x79,0x78\n.byte\t0x99,0x58,0x3e,0x6b,\t0x27,0xb9,0x71,0xdd\n.byte\t0xbe,0xe1,0x4f,0xb6,\t0xf0,0x88,0xad,0x17\n.byte\t0xc9,0x20,0xac,0x66,\t0x7d,0xce,0x3a,0xb4\n.byte\t0x63,0xdf,0x4a,0x18,\t0xe5,0x1a,0x31,0x82\n.byte\t0x97,0x51,0x33,0x60,\t0x62,0x53,0x7f,0x45\n.byte\t0xb1,0x64,0x77,0xe0,\t0xbb,0x6b,0xae,0x84\n.byte\t0xfe,0x81,0xa0,0x1c,\t0xf9,0x08,0x2b,0x94\n.byte\t0x70,0x48,0x68,0x58,\t0x8f,0x45,0xfd,0x19\n.byte\t0x94,0xde,0x6c,0x87,\t0x52,0x7b,0xf8,0xb7\n.byte\t0xab,0x73,0xd3,0x23,\t0x72,0x4b,0x02,0xe2\n.byte\t0xe3,0x1f,0x8f,0x57,\t0x66,0x55,0xab,0x2a\n.byte\t0xb2,0xeb,0x28,0x07,\t0x2f,0xb5,0xc2,0x03\n.byte\t0x86,0xc5,0x7b,0x9a,\t0xd3,0x37,0x08,0xa5\n.byte\t0x30,0x28,0x87,0xf2,\t0x23,0xbf,0xa5,0xb2\n.byte\t0x02,0x03,0x6a,0xba,\t0xed,0x16,0x82,0x5c\n.byte\t0x8a,0xcf,0x1c,0x2b,\t0xa7,0x79,0xb4,0x92\n.byte\t0xf3,0x07,0xf2,0xf0,\t0x4e,0x69,0xe2,0xa1\n.byte\t0x65,0xda,0xf4,0xcd,\t0x06,0x05,0xbe,0xd5\n.byte\t0xd1,0x34,0x62,0x1f,\t0xc4,0xa6,0xfe,0x8a\n.byte\t0x34,0x2e,0x53,0x9d,\t0xa2,0xf3,0x55,0xa0\n.byte\t0x05,0x8a,0xe1,0x32,\t0xa4,0xf6,0xeb,0x75\n.byte\t0x0b,0x83,0xec,0x39,\t0x40,0x60,0xef,0xaa\n.byte\t0x5e,0x71,0x9f,0x06,\t0xbd,0x6e,0x10,0x51\n.byte\t0x3e,0x21,0x8a,0xf9,\t0x96,0xdd,0x06,0x3d\n.byte\t0xdd,0x3e,0x05,0xae,\t0x4d,0xe6,0xbd,0x46\n.byte\t0x91,0x54,0x8d,0xb5,\t0x71,0xc4,0x5d,0x05\n.byte\t0x04,0x06,0xd4,0x6f,\t0x60,0x50,0x15,0xff\n.byte\t0x19,0x98,0xfb,0x24,\t0xd6,0xbd,0xe9,0x97\n.byte\t0x89,0x40,0x43,0xcc,\t0x67,0xd9,0x9e,0x77\n.byte\t0xb0,0xe8,0x42,0xbd,\t0x07,0x89,0x8b,0x88\n.byte\t0xe7,0x19,0x5b,0x38,\t0x79,0xc8,0xee,0xdb\n.byte\t0xa1,0x7c,0x0a,0x47,\t0x7c,0x42,0x0f,0xe9\n.byte\t0xf8,0x84,0x1e,0xc9,\t0x00,0x00,0x00,0x00\n.byte\t0x09,0x80,0x86,0x83,\t0x32,0x2b,0xed,0x48\n.byte\t0x1e,0x11,0x70,0xac,\t0x6c,0x5a,0x72,0x4e\n.byte\t0xfd,0x0e,0xff,0xfb,\t0x0f,0x85,0x38,0x56\n.byte\t0x3d,0xae,0xd5,0x1e,\t0x36,0x2d,0x39,0x27\n.byte\t0x0a,0x0f,0xd9,0x64,\t0x68,0x5c,0xa6,0x21\n.byte\t0x9b,0x5b,0x54,0xd1,\t0x24,0x36,0x2e,0x3a\n.byte\t0x0c,0x0a,0x67,0xb1,\t0x93,0x57,0xe7,0x0f\n.byte\t0xb4,0xee,0x96,0xd2,\t0x1b,0x9b,0x91,0x9e\n.byte\t0x80,0xc0,0xc5,0x4f,\t0x61,0xdc,0x20,0xa2\n.byte\t0x5a,0x77,0x4b,0x69,\t0x1c,0x12,0x1a,0x16\n.byte\t0xe2,0x93,0xba,0x0a,\t0xc0,0xa0,0x2a,0xe5\n.byte\t0x3c,0x22,0xe0,0x43,\t0x12,0x1b,0x17,0x1d\n.byte\t0x0e,0x09,0x0d,0x0b,\t0xf2,0x8b,0xc7,0xad\n.byte\t0x2d,0xb6,0xa8,0xb9,\t0x14,0x1e,0xa9,0xc8\n.byte\t0x57,0xf1,0x19,0x85,\t0xaf,0x75,0x07,0x4c\n.byte\t0xee,0x99,0xdd,0xbb,\t0xa3,0x7f,0x60,0xfd\n.byte\t0xf7,0x01,0x26,0x9f,\t0x5c,0x72,0xf5,0xbc\n.byte\t0x44,0x66,0x3b,0xc5,\t0x5b,0xfb,0x7e,0x34\n.byte\t0x8b,0x43,0x29,0x76,\t0xcb,0x23,0xc6,0xdc\n.byte\t0xb6,0xed,0xfc,0x68,\t0xb8,0xe4,0xf1,0x63\n.byte\t0xd7,0x31,0xdc,0xca,\t0x42,0x63,0x85,0x10\n.byte\t0x13,0x97,0x22,0x40,\t0x84,0xc6,0x11,0x20\n.byte\t0x85,0x4a,0x24,0x7d,\t0xd2,0xbb,0x3d,0xf8\n.byte\t0xae,0xf9,0x32,0x11,\t0xc7,0x29,0xa1,0x6d\n.byte\t0x1d,0x9e,0x2f,0x4b,\t0xdc,0xb2,0x30,0xf3\n.byte\t0x0d,0x86,0x52,0xec,\t0x77,0xc1,0xe3,0xd0\n.byte\t0x2b,0xb3,0x16,0x6c,\t0xa9,0x70,0xb9,0x99\n.byte\t0x11,0x94,0x48,0xfa,\t0x47,0xe9,0x64,0x22\n.byte\t0xa8,0xfc,0x8c,0xc4,\t0xa0,0xf0,0x3f,0x1a\n.byte\t0x56,0x7d,0x2c,0xd8,\t0x22,0x33,0x90,0xef\n.byte\t0x87,0x49,0x4e,0xc7,\t0xd9,0x38,0xd1,0xc1\n.byte\t0x8c,0xca,0xa2,0xfe,\t0x98,0xd4,0x0b,0x36\n.byte\t0xa6,0xf5,0x81,0xcf,\t0xa5,0x7a,0xde,0x28\n.byte\t0xda,0xb7,0x8e,0x26,\t0x3f,0xad,0xbf,0xa4\n.byte\t0x2c,0x3a,0x9d,0xe4,\t0x50,0x78,0x92,0x0d\n.byte\t0x6a,0x5f,0xcc,0x9b,\t0x54,0x7e,0x46,0x62\n.byte\t0xf6,0x8d,0x13,0xc2,\t0x90,0xd8,0xb8,0xe8\n.byte\t0x2e,0x39,0xf7,0x5e,\t0x82,0xc3,0xaf,0xf5\n.byte\t0x9f,0x5d,0x80,0xbe,\t0x69,0xd0,0x93,0x7c\n.byte\t0x6f,0xd5,0x2d,0xa9,\t0xcf,0x25,0x12,0xb3\n.byte\t0xc8,0xac,0x99,0x3b,\t0x10,0x18,0x7d,0xa7\n.byte\t0xe8,0x9c,0x63,0x6e,\t0xdb,0x3b,0xbb,0x7b\n.byte\t0xcd,0x26,0x78,0x09,\t0x6e,0x59,0x18,0xf4\n.byte\t0xec,0x9a,0xb7,0x01,\t0x83,0x4f,0x9a,0xa8\n.byte\t0xe6,0x95,0x6e,0x65,\t0xaa,0xff,0xe6,0x7e\n.byte\t0x21,0xbc,0xcf,0x08,\t0xef,0x15,0xe8,0xe6\n.byte\t0xba,0xe7,0x9b,0xd9,\t0x4a,0x6f,0x36,0xce\n.byte\t0xea,0x9f,0x09,0xd4,\t0x29,0xb0,0x7c,0xd6\n.byte\t0x31,0xa4,0xb2,0xaf,\t0x2a,0x3f,0x23,0x31\n.byte\t0xc6,0xa5,0x94,0x30,\t0x35,0xa2,0x66,0xc0\n.byte\t0x74,0x4e,0xbc,0x37,\t0xfc,0x82,0xca,0xa6\n.byte\t0xe0,0x90,0xd0,0xb0,\t0x33,0xa7,0xd8,0x15\n.byte\t0xf1,0x04,0x98,0x4a,\t0x41,0xec,0xda,0xf7\n.byte\t0x7f,0xcd,0x50,0x0e,\t0x17,0x91,0xf6,0x2f\n.byte\t0x76,0x4d,0xd6,0x8d,\t0x43,0xef,0xb0,0x4d\n.byte\t0xcc,0xaa,0x4d,0x54,\t0xe4,0x96,0x04,0xdf\n.byte\t0x9e,0xd1,0xb5,0xe3,\t0x4c,0x6a,0x88,0x1b\n.byte\t0xc1,0x2c,0x1f,0xb8,\t0x46,0x65,0x51,0x7f\n.byte\t0x9d,0x5e,0xea,0x04,\t0x01,0x8c,0x35,0x5d\n.byte\t0xfa,0x87,0x74,0x73,\t0xfb,0x0b,0x41,0x2e\n.byte\t0xb3,0x67,0x1d,0x5a,\t0x92,0xdb,0xd2,0x52\n.byte\t0xe9,0x10,0x56,0x33,\t0x6d,0xd6,0x47,0x13\n.byte\t0x9a,0xd7,0x61,0x8c,\t0x37,0xa1,0x0c,0x7a\n.byte\t0x59,0xf8,0x14,0x8e,\t0xeb,0x13,0x3c,0x89\n.byte\t0xce,0xa9,0x27,0xee,\t0xb7,0x61,0xc9,0x35\n.byte\t0xe1,0x1c,0xe5,0xed,\t0x7a,0x47,0xb1,0x3c\n.byte\t0x9c,0xd2,0xdf,0x59,\t0x55,0xf2,0x73,0x3f\n.byte\t0x18,0x14,0xce,0x79,\t0x73,0xc7,0x37,0xbf\n.byte\t0x53,0xf7,0xcd,0xea,\t0x5f,0xfd,0xaa,0x5b\n.byte\t0xdf,0x3d,0x6f,0x14,\t0x78,0x44,0xdb,0x86\n.byte\t0xca,0xaf,0xf3,0x81,\t0xb9,0x68,0xc4,0x3e\n.byte\t0x38,0x24,0x34,0x2c,\t0xc2,0xa3,0x40,0x5f\n.byte\t0x16,0x1d,0xc3,0x72,\t0xbc,0xe2,0x25,0x0c\n.byte\t0x28,0x3c,0x49,0x8b,\t0xff,0x0d,0x95,0x41\n.byte\t0x39,0xa8,0x01,0x71,\t0x08,0x0c,0xb3,0xde\n.byte\t0xd8,0xb4,0xe4,0x9c,\t0x64,0x56,0xc1,0x90\n.byte\t0x7b,0xcb,0x84,0x61,\t0xd5,0x32,0xb6,0x70\n.byte\t0x48,0x6c,0x5c,0x74,\t0xd0,0xb8,0x57,0x42\n\n.byte\t0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38\t# Td4\n.byte\t0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb\n.byte\t0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87\n.byte\t0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb\n.byte\t0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d\n.byte\t0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e\n.byte\t0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2\n.byte\t0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25\n.byte\t0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16\n.byte\t0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92\n.byte\t0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda\n.byte\t0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84\n.byte\t0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a\n.byte\t0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06\n.byte\t0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02\n.byte\t0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b\n.byte\t0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea\n.byte\t0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73\n.byte\t0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85\n.byte\t0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e\n.byte\t0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89\n.byte\t0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b\n.byte\t0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20\n.byte\t0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4\n.byte\t0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31\n.byte\t0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f\n.byte\t0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d\n.byte\t0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef\n.byte\t0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0\n.byte\t0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61\n.byte\t0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26\n.byte\t0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d\n\nAES_Te4:\n.byte\t0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5\t# Te4\n.byte\t0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76\n.byte\t0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0\n.byte\t0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0\n.byte\t0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc\n.byte\t0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15\n.byte\t0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a\n.byte\t0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75\n.byte\t0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0\n.byte\t0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84\n.byte\t0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b\n.byte\t0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf\n.byte\t0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85\n.byte\t0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8\n.byte\t0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5\n.byte\t0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2\n.byte\t0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17\n.byte\t0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73\n.byte\t0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88\n.byte\t0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb\n.byte\t0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c\n.byte\t0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79\n.byte\t0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9\n.byte\t0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08\n.byte\t0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6\n.byte\t0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a\n.byte\t0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e\n.byte\t0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e\n.byte\t0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94\n.byte\t0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf\n.byte\t0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68\n.byte\t0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16\n\n.byte\t0x01,0x00,0x00,0x00,\t0x02,0x00,0x00,0x00\t# rcon\n.byte\t0x04,0x00,0x00,0x00,\t0x08,0x00,0x00,0x00\n.byte\t0x10,0x00,0x00,0x00,\t0x20,0x00,0x00,0x00\n.byte\t0x40,0x00,0x00,0x00,\t0x80,0x00,0x00,0x00\n.byte\t0x1B,0x00,0x00,0x00,\t0x36,0x00,0x00,0x00\n"
  },
  {
    "path": "lib/aes_acc/asm/x64.S",
    "content": ".text\t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.type\t_vpaes_encrypt_core,@function\n.align\t16\n_vpaes_encrypt_core:\n\tmovq\t%rdx,%r9\n\tmovq\t$16,%r11\n\tmovl\t240(%rdx),%eax\n\tmovdqa\t%xmm9,%xmm1\n\tmovdqa\t.Lk_ipt(%rip),%xmm2\n\tpandn\t%xmm0,%xmm1\n\tmovdqu\t(%r9),%xmm5\n\tpsrld\t$4,%xmm1\n\tpand\t%xmm9,%xmm0\n.byte\t102,15,56,0,208\n\tmovdqa\t.Lk_ipt+16(%rip),%xmm0\n.byte\t102,15,56,0,193\n\tpxor\t%xmm5,%xmm2\n\taddq\t$16,%r9\n\tpxor\t%xmm2,%xmm0\n\tleaq\t.Lk_mc_backward(%rip),%r10\n\tjmp\t.Lenc_entry\n\n.align\t16\n.Lenc_loop:\n\n\tmovdqa\t%xmm13,%xmm4\n\tmovdqa\t%xmm12,%xmm0\n.byte\t102,15,56,0,226\n.byte\t102,15,56,0,195\n\tpxor\t%xmm5,%xmm4\n\tmovdqa\t%xmm15,%xmm5\n\tpxor\t%xmm4,%xmm0\n\tmovdqa\t-64(%r11,%r10,1),%xmm1\n.byte\t102,15,56,0,234\n\tmovdqa\t(%r11,%r10,1),%xmm4\n\tmovdqa\t%xmm14,%xmm2\n.byte\t102,15,56,0,211\n\tmovdqa\t%xmm0,%xmm3\n\tpxor\t%xmm5,%xmm2\n.byte\t102,15,56,0,193\n\taddq\t$16,%r9\n\tpxor\t%xmm2,%xmm0\n.byte\t102,15,56,0,220\n\taddq\t$16,%r11\n\tpxor\t%xmm0,%xmm3\n.byte\t102,15,56,0,193\n\tandq\t$0x30,%r11\n\tsubq\t$1,%rax\n\tpxor\t%xmm3,%xmm0\n\n.Lenc_entry:\n\n\tmovdqa\t%xmm9,%xmm1\n\tmovdqa\t%xmm11,%xmm5\n\tpandn\t%xmm0,%xmm1\n\tpsrld\t$4,%xmm1\n\tpand\t%xmm9,%xmm0\n.byte\t102,15,56,0,232\n\tmovdqa\t%xmm10,%xmm3\n\tpxor\t%xmm1,%xmm0\n.byte\t102,15,56,0,217\n\tmovdqa\t%xmm10,%xmm4\n\tpxor\t%xmm5,%xmm3\n.byte\t102,15,56,0,224\n\tmovdqa\t%xmm10,%xmm2\n\tpxor\t%xmm5,%xmm4\n.byte\t102,15,56,0,211\n\tmovdqa\t%xmm10,%xmm3\n\tpxor\t%xmm0,%xmm2\n.byte\t102,15,56,0,220\n\tmovdqu\t(%r9),%xmm5\n\tpxor\t%xmm1,%xmm3\n\tjnz\t.Lenc_loop\n\n\n\tmovdqa\t-96(%r10),%xmm4\n\tmovdqa\t-80(%r10),%xmm0\n.byte\t102,15,56,0,226\n\tpxor\t%xmm5,%xmm4\n.byte\t102,15,56,0,195\n\tmovdqa\t64(%r11,%r10,1),%xmm1\n\tpxor\t%xmm4,%xmm0\n.byte\t102,15,56,0,193\n\t.byte\t0xf3,0xc3\n.size\t_vpaes_encrypt_core,.-_vpaes_encrypt_core\n\n\n\n\n\n\n.type\t_vpaes_decrypt_core,@function\n.align\t16\n_vpaes_decrypt_core:\n\tmovq\t%rdx,%r9\n\tmovl\t240(%rdx),%eax\n\tmovdqa\t%xmm9,%xmm1\n\tmovdqa\t.Lk_dipt(%rip),%xmm2\n\tpandn\t%xmm0,%xmm1\n\tmovq\t%rax,%r11\n\tpsrld\t$4,%xmm1\n\tmovdqu\t(%r9),%xmm5\n\tshlq\t$4,%r11\n\tpand\t%xmm9,%xmm0\n.byte\t102,15,56,0,208\n\tmovdqa\t.Lk_dipt+16(%rip),%xmm0\n\txorq\t$0x30,%r11\n\tleaq\t.Lk_dsbd(%rip),%r10\n.byte\t102,15,56,0,193\n\tandq\t$0x30,%r11\n\tpxor\t%xmm5,%xmm2\n\tmovdqa\t.Lk_mc_forward+48(%rip),%xmm5\n\tpxor\t%xmm2,%xmm0\n\taddq\t$16,%r9\n\taddq\t%r10,%r11\n\tjmp\t.Ldec_entry\n\n.align\t16\n.Ldec_loop:\n\n\n\n\tmovdqa\t-32(%r10),%xmm4\n\tmovdqa\t-16(%r10),%xmm1\n.byte\t102,15,56,0,226\n.byte\t102,15,56,0,203\n\tpxor\t%xmm4,%xmm0\n\tmovdqa\t0(%r10),%xmm4\n\tpxor\t%xmm1,%xmm0\n\tmovdqa\t16(%r10),%xmm1\n\n.byte\t102,15,56,0,226\n.byte\t102,15,56,0,197\n.byte\t102,15,56,0,203\n\tpxor\t%xmm4,%xmm0\n\tmovdqa\t32(%r10),%xmm4\n\tpxor\t%xmm1,%xmm0\n\tmovdqa\t48(%r10),%xmm1\n\n.byte\t102,15,56,0,226\n.byte\t102,15,56,0,197\n.byte\t102,15,56,0,203\n\tpxor\t%xmm4,%xmm0\n\tmovdqa\t64(%r10),%xmm4\n\tpxor\t%xmm1,%xmm0\n\tmovdqa\t80(%r10),%xmm1\n\n.byte\t102,15,56,0,226\n.byte\t102,15,56,0,197\n.byte\t102,15,56,0,203\n\tpxor\t%xmm4,%xmm0\n\taddq\t$16,%r9\n.byte\t102,15,58,15,237,12\n\tpxor\t%xmm1,%xmm0\n\tsubq\t$1,%rax\n\n.Ldec_entry:\n\n\tmovdqa\t%xmm9,%xmm1\n\tpandn\t%xmm0,%xmm1\n\tmovdqa\t%xmm11,%xmm2\n\tpsrld\t$4,%xmm1\n\tpand\t%xmm9,%xmm0\n.byte\t102,15,56,0,208\n\tmovdqa\t%xmm10,%xmm3\n\tpxor\t%xmm1,%xmm0\n.byte\t102,15,56,0,217\n\tmovdqa\t%xmm10,%xmm4\n\tpxor\t%xmm2,%xmm3\n.byte\t102,15,56,0,224\n\tpxor\t%xmm2,%xmm4\n\tmovdqa\t%xmm10,%xmm2\n.byte\t102,15,56,0,211\n\tmovdqa\t%xmm10,%xmm3\n\tpxor\t%xmm0,%xmm2\n.byte\t102,15,56,0,220\n\tmovdqu\t(%r9),%xmm0\n\tpxor\t%xmm1,%xmm3\n\tjnz\t.Ldec_loop\n\n\n\tmovdqa\t96(%r10),%xmm4\n.byte\t102,15,56,0,226\n\tpxor\t%xmm0,%xmm4\n\tmovdqa\t112(%r10),%xmm0\n\tmovdqa\t-352(%r11),%xmm2\n.byte\t102,15,56,0,195\n\tpxor\t%xmm4,%xmm0\n.byte\t102,15,56,0,194\n\t.byte\t0xf3,0xc3\n.size\t_vpaes_decrypt_core,.-_vpaes_decrypt_core\n\n\n\n\n\n\n.type\t_vpaes_schedule_core,@function\n.align\t16\n_vpaes_schedule_core:\n\n\n\n\n\n\tcall\t_vpaes_preheat\n\tmovdqa\t.Lk_rcon(%rip),%xmm8\n\tmovdqu\t(%rdi),%xmm0\n\n\n\tmovdqa\t%xmm0,%xmm3\n\tleaq\t.Lk_ipt(%rip),%r11\n\tcall\t_vpaes_schedule_transform\n\tmovdqa\t%xmm0,%xmm7\n\n\tleaq\t.Lk_sr(%rip),%r10\n\ttestq\t%rcx,%rcx\n\tjnz\t.Lschedule_am_decrypting\n\n\n\tmovdqu\t%xmm0,(%rdx)\n\tjmp\t.Lschedule_go\n\n.Lschedule_am_decrypting:\n\n\tmovdqa\t(%r8,%r10,1),%xmm1\n.byte\t102,15,56,0,217\n\tmovdqu\t%xmm3,(%rdx)\n\txorq\t$0x30,%r8\n\n.Lschedule_go:\n\tcmpl\t$192,%esi\n\tja\t.Lschedule_256\n\tje\t.Lschedule_192\n\n\n\n\n\n\n\n\n\n\n.Lschedule_128:\n\tmovl\t$10,%esi\n\n.Loop_schedule_128:\n\tcall\t_vpaes_schedule_round\n\tdecq\t%rsi\n\tjz\t.Lschedule_mangle_last\n\tcall\t_vpaes_schedule_mangle\n\tjmp\t.Loop_schedule_128\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.align\t16\n.Lschedule_192:\n\tmovdqu\t8(%rdi),%xmm0\n\tcall\t_vpaes_schedule_transform\n\tmovdqa\t%xmm0,%xmm6\n\tpxor\t%xmm4,%xmm4\n\tmovhlps\t%xmm4,%xmm6\n\tmovl\t$4,%esi\n\n.Loop_schedule_192:\n\tcall\t_vpaes_schedule_round\n.byte\t102,15,58,15,198,8\n\tcall\t_vpaes_schedule_mangle\n\tcall\t_vpaes_schedule_192_smear\n\tcall\t_vpaes_schedule_mangle\n\tcall\t_vpaes_schedule_round\n\tdecq\t%rsi\n\tjz\t.Lschedule_mangle_last\n\tcall\t_vpaes_schedule_mangle\n\tcall\t_vpaes_schedule_192_smear\n\tjmp\t.Loop_schedule_192\n\n\n\n\n\n\n\n\n\n\n\n.align\t16\n.Lschedule_256:\n\tmovdqu\t16(%rdi),%xmm0\n\tcall\t_vpaes_schedule_transform\n\tmovl\t$7,%esi\n\n.Loop_schedule_256:\n\tcall\t_vpaes_schedule_mangle\n\tmovdqa\t%xmm0,%xmm6\n\n\n\tcall\t_vpaes_schedule_round\n\tdecq\t%rsi\n\tjz\t.Lschedule_mangle_last\n\tcall\t_vpaes_schedule_mangle\n\n\n\tpshufd\t$0xFF,%xmm0,%xmm0\n\tmovdqa\t%xmm7,%xmm5\n\tmovdqa\t%xmm6,%xmm7\n\tcall\t_vpaes_schedule_low_round\n\tmovdqa\t%xmm5,%xmm7\n\n\tjmp\t.Loop_schedule_256\n\n\n\n\n\n\n\n\n\n\n\n\n.align\t16\n.Lschedule_mangle_last:\n\n\tleaq\t.Lk_deskew(%rip),%r11\n\ttestq\t%rcx,%rcx\n\tjnz\t.Lschedule_mangle_last_dec\n\n\n\tmovdqa\t(%r8,%r10,1),%xmm1\n.byte\t102,15,56,0,193\n\tleaq\t.Lk_opt(%rip),%r11\n\taddq\t$32,%rdx\n\n.Lschedule_mangle_last_dec:\n\taddq\t$-16,%rdx\n\tpxor\t.Lk_s63(%rip),%xmm0\n\tcall\t_vpaes_schedule_transform\n\tmovdqu\t%xmm0,(%rdx)\n\n\n\tpxor\t%xmm0,%xmm0\n\tpxor\t%xmm1,%xmm1\n\tpxor\t%xmm2,%xmm2\n\tpxor\t%xmm3,%xmm3\n\tpxor\t%xmm4,%xmm4\n\tpxor\t%xmm5,%xmm5\n\tpxor\t%xmm6,%xmm6\n\tpxor\t%xmm7,%xmm7\n\t.byte\t0xf3,0xc3\n.size\t_vpaes_schedule_core,.-_vpaes_schedule_core\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.type\t_vpaes_schedule_192_smear,@function\n.align\t16\n_vpaes_schedule_192_smear:\n\tpshufd\t$0x80,%xmm6,%xmm1\n\tpshufd\t$0xFE,%xmm7,%xmm0\n\tpxor\t%xmm1,%xmm6\n\tpxor\t%xmm1,%xmm1\n\tpxor\t%xmm0,%xmm6\n\tmovdqa\t%xmm6,%xmm0\n\tmovhlps\t%xmm1,%xmm6\n\t.byte\t0xf3,0xc3\n.size\t_vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.type\t_vpaes_schedule_round,@function\n.align\t16\n_vpaes_schedule_round:\n\n\tpxor\t%xmm1,%xmm1\n.byte\t102,65,15,58,15,200,15\n.byte\t102,69,15,58,15,192,15\n\tpxor\t%xmm1,%xmm7\n\n\n\tpshufd\t$0xFF,%xmm0,%xmm0\n.byte\t102,15,58,15,192,1\n\n\n\n\n_vpaes_schedule_low_round:\n\n\tmovdqa\t%xmm7,%xmm1\n\tpslldq\t$4,%xmm7\n\tpxor\t%xmm1,%xmm7\n\tmovdqa\t%xmm7,%xmm1\n\tpslldq\t$8,%xmm7\n\tpxor\t%xmm1,%xmm7\n\tpxor\t.Lk_s63(%rip),%xmm7\n\n\n\tmovdqa\t%xmm9,%xmm1\n\tpandn\t%xmm0,%xmm1\n\tpsrld\t$4,%xmm1\n\tpand\t%xmm9,%xmm0\n\tmovdqa\t%xmm11,%xmm2\n.byte\t102,15,56,0,208\n\tpxor\t%xmm1,%xmm0\n\tmovdqa\t%xmm10,%xmm3\n.byte\t102,15,56,0,217\n\tpxor\t%xmm2,%xmm3\n\tmovdqa\t%xmm10,%xmm4\n.byte\t102,15,56,0,224\n\tpxor\t%xmm2,%xmm4\n\tmovdqa\t%xmm10,%xmm2\n.byte\t102,15,56,0,211\n\tpxor\t%xmm0,%xmm2\n\tmovdqa\t%xmm10,%xmm3\n.byte\t102,15,56,0,220\n\tpxor\t%xmm1,%xmm3\n\tmovdqa\t%xmm13,%xmm4\n.byte\t102,15,56,0,226\n\tmovdqa\t%xmm12,%xmm0\n.byte\t102,15,56,0,195\n\tpxor\t%xmm4,%xmm0\n\n\n\tpxor\t%xmm7,%xmm0\n\tmovdqa\t%xmm0,%xmm7\n\t.byte\t0xf3,0xc3\n.size\t_vpaes_schedule_round,.-_vpaes_schedule_round\n\n\n\n\n\n\n\n\n\n\n.type\t_vpaes_schedule_transform,@function\n.align\t16\n_vpaes_schedule_transform:\n\tmovdqa\t%xmm9,%xmm1\n\tpandn\t%xmm0,%xmm1\n\tpsrld\t$4,%xmm1\n\tpand\t%xmm9,%xmm0\n\tmovdqa\t(%r11),%xmm2\n.byte\t102,15,56,0,208\n\tmovdqa\t16(%r11),%xmm0\n.byte\t102,15,56,0,193\n\tpxor\t%xmm2,%xmm0\n\t.byte\t0xf3,0xc3\n.size\t_vpaes_schedule_transform,.-_vpaes_schedule_transform\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.type\t_vpaes_schedule_mangle,@function\n.align\t16\n_vpaes_schedule_mangle:\n\tmovdqa\t%xmm0,%xmm4\n\tmovdqa\t.Lk_mc_forward(%rip),%xmm5\n\ttestq\t%rcx,%rcx\n\tjnz\t.Lschedule_mangle_dec\n\n\n\taddq\t$16,%rdx\n\tpxor\t.Lk_s63(%rip),%xmm4\n.byte\t102,15,56,0,229\n\tmovdqa\t%xmm4,%xmm3\n.byte\t102,15,56,0,229\n\tpxor\t%xmm4,%xmm3\n.byte\t102,15,56,0,229\n\tpxor\t%xmm4,%xmm3\n\n\tjmp\t.Lschedule_mangle_both\n.align\t16\n.Lschedule_mangle_dec:\n\n\tleaq\t.Lk_dksd(%rip),%r11\n\tmovdqa\t%xmm9,%xmm1\n\tpandn\t%xmm4,%xmm1\n\tpsrld\t$4,%xmm1\n\tpand\t%xmm9,%xmm4\n\n\tmovdqa\t0(%r11),%xmm2\n.byte\t102,15,56,0,212\n\tmovdqa\t16(%r11),%xmm3\n.byte\t102,15,56,0,217\n\tpxor\t%xmm2,%xmm3\n.byte\t102,15,56,0,221\n\n\tmovdqa\t32(%r11),%xmm2\n.byte\t102,15,56,0,212\n\tpxor\t%xmm3,%xmm2\n\tmovdqa\t48(%r11),%xmm3\n.byte\t102,15,56,0,217\n\tpxor\t%xmm2,%xmm3\n.byte\t102,15,56,0,221\n\n\tmovdqa\t64(%r11),%xmm2\n.byte\t102,15,56,0,212\n\tpxor\t%xmm3,%xmm2\n\tmovdqa\t80(%r11),%xmm3\n.byte\t102,15,56,0,217\n\tpxor\t%xmm2,%xmm3\n.byte\t102,15,56,0,221\n\n\tmovdqa\t96(%r11),%xmm2\n.byte\t102,15,56,0,212\n\tpxor\t%xmm3,%xmm2\n\tmovdqa\t112(%r11),%xmm3\n.byte\t102,15,56,0,217\n\tpxor\t%xmm2,%xmm3\n\n\taddq\t$-16,%rdx\n\n.Lschedule_mangle_both:\n\tmovdqa\t(%r8,%r10,1),%xmm1\n.byte\t102,15,56,0,217\n\taddq\t$-16,%r8\n\tandq\t$0x30,%r8\n\tmovdqu\t%xmm3,(%rdx)\n\t.byte\t0xf3,0xc3\n.size\t_vpaes_schedule_mangle,.-_vpaes_schedule_mangle\n\n\n\n\n.globl\tvpaes_set_encrypt_key\n.type\tvpaes_set_encrypt_key,@function\n.align\t16\nvpaes_set_encrypt_key:\n\tmovl\t%esi,%eax\n\tshrl\t$5,%eax\n\taddl\t$5,%eax\n\tmovl\t%eax,240(%rdx)\n\n\tmovl\t$0,%ecx\n\tmovl\t$0x30,%r8d\n\tcall\t_vpaes_schedule_core\n\txorl\t%eax,%eax\n\t.byte\t0xf3,0xc3\n.size\tvpaes_set_encrypt_key,.-vpaes_set_encrypt_key\n\n.globl\tvpaes_set_decrypt_key\n.type\tvpaes_set_decrypt_key,@function\n.align\t16\nvpaes_set_decrypt_key:\n\tmovl\t%esi,%eax\n\tshrl\t$5,%eax\n\taddl\t$5,%eax\n\tmovl\t%eax,240(%rdx)\n\tshll\t$4,%eax\n\tleaq\t16(%rdx,%rax,1),%rdx\n\n\tmovl\t$1,%ecx\n\tmovl\t%esi,%r8d\n\tshrl\t$1,%r8d\n\tandl\t$32,%r8d\n\txorl\t$32,%r8d\n\tcall\t_vpaes_schedule_core\n\txorl\t%eax,%eax\n\t.byte\t0xf3,0xc3\n.size\tvpaes_set_decrypt_key,.-vpaes_set_decrypt_key\n\n.globl\tvpaes_encrypt\n.type\tvpaes_encrypt,@function\n.align\t16\nvpaes_encrypt:\n\tmovdqu\t(%rdi),%xmm0\n\tcall\t_vpaes_preheat\n\tcall\t_vpaes_encrypt_core\n\tmovdqu\t%xmm0,(%rsi)\n\t.byte\t0xf3,0xc3\n.size\tvpaes_encrypt,.-vpaes_encrypt\n\n.globl\tvpaes_decrypt\n.type\tvpaes_decrypt,@function\n.align\t16\nvpaes_decrypt:\n\tmovdqu\t(%rdi),%xmm0\n\tcall\t_vpaes_preheat\n\tcall\t_vpaes_decrypt_core\n\tmovdqu\t%xmm0,(%rsi)\n\t.byte\t0xf3,0xc3\n.size\tvpaes_decrypt,.-vpaes_decrypt\n.globl\tvpaes_cbc_encrypt\n.type\tvpaes_cbc_encrypt,@function\n.align\t16\nvpaes_cbc_encrypt:\n\txchgq\t%rcx,%rdx\n\tsubq\t$16,%rcx\n\tjc\t.Lcbc_abort\n\tmovdqu\t(%r8),%xmm6\n\tsubq\t%rdi,%rsi\n\tcall\t_vpaes_preheat\n\tcmpl\t$0,%r9d\n\tje\t.Lcbc_dec_loop\n\tjmp\t.Lcbc_enc_loop\n.align\t16\n.Lcbc_enc_loop:\n\tmovdqu\t(%rdi),%xmm0\n\tpxor\t%xmm6,%xmm0\n\tcall\t_vpaes_encrypt_core\n\tmovdqa\t%xmm0,%xmm6\n\tmovdqu\t%xmm0,(%rsi,%rdi,1)\n\tleaq\t16(%rdi),%rdi\n\tsubq\t$16,%rcx\n\tjnc\t.Lcbc_enc_loop\n\tjmp\t.Lcbc_done\n.align\t16\n.Lcbc_dec_loop:\n\tmovdqu\t(%rdi),%xmm0\n\tmovdqa\t%xmm0,%xmm7\n\tcall\t_vpaes_decrypt_core\n\tpxor\t%xmm6,%xmm0\n\tmovdqa\t%xmm7,%xmm6\n\tmovdqu\t%xmm0,(%rsi,%rdi,1)\n\tleaq\t16(%rdi),%rdi\n\tsubq\t$16,%rcx\n\tjnc\t.Lcbc_dec_loop\n.Lcbc_done:\n\tmovdqu\t%xmm6,(%r8)\n.Lcbc_abort:\n\t.byte\t0xf3,0xc3\n.size\tvpaes_cbc_encrypt,.-vpaes_cbc_encrypt\n\n\n\n\n\n\n.type\t_vpaes_preheat,@function\n.align\t16\n_vpaes_preheat:\n\tleaq\t.Lk_s0F(%rip),%r10\n\tmovdqa\t-32(%r10),%xmm10\n\tmovdqa\t-16(%r10),%xmm11\n\tmovdqa\t0(%r10),%xmm9\n\tmovdqa\t48(%r10),%xmm13\n\tmovdqa\t64(%r10),%xmm12\n\tmovdqa\t80(%r10),%xmm15\n\tmovdqa\t96(%r10),%xmm14\n\t.byte\t0xf3,0xc3\n.size\t_vpaes_preheat,.-_vpaes_preheat\n\n\n\n\n\n.type\t_vpaes_consts,@object\n.align\t64\n_vpaes_consts:\n.Lk_inv:\n.quad\t0x0E05060F0D080180, 0x040703090A0B0C02\n.quad\t0x01040A060F0B0780, 0x030D0E0C02050809\n\n.Lk_s0F:\n.quad\t0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F\n\n.Lk_ipt:\n.quad\t0xC2B2E8985A2A7000, 0xCABAE09052227808\n.quad\t0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81\n\n.Lk_sb1:\n.quad\t0xB19BE18FCB503E00, 0xA5DF7A6E142AF544\n.quad\t0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF\n.Lk_sb2:\n.quad\t0xE27A93C60B712400, 0x5EB7E955BC982FCD\n.quad\t0x69EB88400AE12900, 0xC2A163C8AB82234A\n.Lk_sbo:\n.quad\t0xD0D26D176FBDC700, 0x15AABF7AC502A878\n.quad\t0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA\n\n.Lk_mc_forward:\n.quad\t0x0407060500030201, 0x0C0F0E0D080B0A09\n.quad\t0x080B0A0904070605, 0x000302010C0F0E0D\n.quad\t0x0C0F0E0D080B0A09, 0x0407060500030201\n.quad\t0x000302010C0F0E0D, 0x080B0A0904070605\n\n.Lk_mc_backward:\n.quad\t0x0605040702010003, 0x0E0D0C0F0A09080B\n.quad\t0x020100030E0D0C0F, 0x0A09080B06050407\n.quad\t0x0E0D0C0F0A09080B, 0x0605040702010003\n.quad\t0x0A09080B06050407, 0x020100030E0D0C0F\n\n.Lk_sr:\n.quad\t0x0706050403020100, 0x0F0E0D0C0B0A0908\n.quad\t0x030E09040F0A0500, 0x0B06010C07020D08\n.quad\t0x0F060D040B020900, 0x070E050C030A0108\n.quad\t0x0B0E0104070A0D00, 0x0306090C0F020508\n\n.Lk_rcon:\n.quad\t0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81\n\n.Lk_s63:\n.quad\t0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B\n\n.Lk_opt:\n.quad\t0xFF9F4929D6B66000, 0xF7974121DEBE6808\n.quad\t0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0\n\n.Lk_deskew:\n.quad\t0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A\n.quad\t0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77\n\n\n\n\n\n.Lk_dksd:\n.quad\t0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9\n.quad\t0x41C277F4B5368300, 0x5FDC69EAAB289D1E\n.Lk_dksb:\n.quad\t0x9A4FCA1F8550D500, 0x03D653861CC94C99\n.quad\t0x115BEDA7B6FC4A00, 0xD993256F7E3482C8\n.Lk_dkse:\n.quad\t0xD5031CCA1FC9D600, 0x53859A4C994F5086\n.quad\t0xA23196054FDC7BE8, 0xCD5EF96A20B31487\n.Lk_dks9:\n.quad\t0xB6116FC87ED9A700, 0x4AED933482255BFC\n.quad\t0x4576516227143300, 0x8BB89FACE9DAFDCE\n\n\n\n\n\n.Lk_dipt:\n.quad\t0x0F505B040B545F00, 0x154A411E114E451A\n.quad\t0x86E383E660056500, 0x12771772F491F194\n\n.Lk_dsb9:\n.quad\t0x851C03539A86D600, 0xCAD51F504F994CC9\n.quad\t0xC03B1789ECD74900, 0x725E2C9EB2FBA565\n.Lk_dsbd:\n.quad\t0x7D57CCDFE6B1A200, 0xF56E9B13882A4439\n.quad\t0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3\n.Lk_dsbb:\n.quad\t0xD022649296B44200, 0x602646F6B0F2D404\n.quad\t0xC19498A6CD596700, 0xF3FF0C3E3255AA6B\n.Lk_dsbe:\n.quad\t0x46F2929626D4D000, 0x2242600464B4F6B0\n.quad\t0x0C55A6CDFFAAC100, 0x9467F36B98593E32\n.Lk_dsbo:\n.quad\t0x1387EA537EF94000, 0xC7AA6DB9D4943E2D\n.quad\t0x12D7560F93441D00, 0xCA4B8159D8C58E9C\n.byte\t86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0\n.align\t64\n.size\t_vpaes_consts,.-_vpaes_consts\n"
  },
  {
    "path": "lib/aes_acc/asm/x86.S",
    "content": ".file\t\"aes-586.s\"\n.text\n.type\t_x86_AES_encrypt_compact,@function\n.align\t16\n_x86_AES_encrypt_compact:\n\tmovl\t%edi,20(%esp)\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tmovl\t240(%edi),%esi\n\tleal\t-2(%esi,%esi,1),%esi\n\tleal\t(%edi,%esi,8),%esi\n\tmovl\t%esi,24(%esp)\n\tmovl\t-128(%ebp),%edi\n\tmovl\t-96(%ebp),%esi\n\tmovl\t-64(%ebp),%edi\n\tmovl\t-32(%ebp),%esi\n\tmovl\t(%ebp),%edi\n\tmovl\t32(%ebp),%esi\n\tmovl\t64(%ebp),%edi\n\tmovl\t96(%ebp),%esi\n.align\t16\n.L000loop:\n\tmovl\t%eax,%esi\n\tandl\t$255,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%bh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,4(%esp)\n\n\tmovl\t%ebx,%esi\n\tandl\t$255,%esi\n\tshrl\t$16,%ebx\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%ch,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,8(%esp)\n\n\tmovl\t%ecx,%esi\n\tandl\t$255,%esi\n\tshrl\t$24,%ecx\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%dh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edx\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovzbl\t%bh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\n\tandl\t$255,%edx\n\tmovzbl\t-128(%ebp,%edx,1),%edx\n\tmovzbl\t%ah,%eax\n\tmovzbl\t-128(%ebp,%eax,1),%eax\n\tshll\t$8,%eax\n\txorl\t%eax,%edx\n\tmovl\t4(%esp),%eax\n\tandl\t$255,%ebx\n\tmovzbl\t-128(%ebp,%ebx,1),%ebx\n\tshll\t$16,%ebx\n\txorl\t%ebx,%edx\n\tmovl\t8(%esp),%ebx\n\tmovzbl\t-128(%ebp,%ecx,1),%ecx\n\tshll\t$24,%ecx\n\txorl\t%ecx,%edx\n\tmovl\t%esi,%ecx\n\n\tmovl\t$2155905152,%ebp\n\tandl\t%ecx,%ebp\n\tleal\t(%ecx,%ecx,1),%edi\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tandl\t$4278124286,%edi\n\tsubl\t%ebp,%esi\n\tmovl\t%ecx,%ebp\n\tandl\t$454761243,%esi\n\trorl\t$16,%ebp\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\txorl\t%esi,%ecx\n\trorl\t$24,%edi\n\txorl\t%ebp,%esi\n\troll\t$24,%ecx\n\txorl\t%edi,%esi\n\tmovl\t$2155905152,%ebp\n\txorl\t%esi,%ecx\n\tandl\t%edx,%ebp\n\tleal\t(%edx,%edx,1),%edi\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tandl\t$4278124286,%edi\n\tsubl\t%ebp,%esi\n\tmovl\t%edx,%ebp\n\tandl\t$454761243,%esi\n\trorl\t$16,%ebp\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\txorl\t%esi,%edx\n\trorl\t$24,%edi\n\txorl\t%ebp,%esi\n\troll\t$24,%edx\n\txorl\t%edi,%esi\n\tmovl\t$2155905152,%ebp\n\txorl\t%esi,%edx\n\tandl\t%eax,%ebp\n\tleal\t(%eax,%eax,1),%edi\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tandl\t$4278124286,%edi\n\tsubl\t%ebp,%esi\n\tmovl\t%eax,%ebp\n\tandl\t$454761243,%esi\n\trorl\t$16,%ebp\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\txorl\t%esi,%eax\n\trorl\t$24,%edi\n\txorl\t%ebp,%esi\n\troll\t$24,%eax\n\txorl\t%edi,%esi\n\tmovl\t$2155905152,%ebp\n\txorl\t%esi,%eax\n\tandl\t%ebx,%ebp\n\tleal\t(%ebx,%ebx,1),%edi\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tandl\t$4278124286,%edi\n\tsubl\t%ebp,%esi\n\tmovl\t%ebx,%ebp\n\tandl\t$454761243,%esi\n\trorl\t$16,%ebp\n\txorl\t%edi,%esi\n\tmovl\t%ebx,%edi\n\txorl\t%esi,%ebx\n\trorl\t$24,%edi\n\txorl\t%ebp,%esi\n\troll\t$24,%ebx\n\txorl\t%edi,%esi\n\txorl\t%esi,%ebx\n\tmovl\t20(%esp),%edi\n\tmovl\t28(%esp),%ebp\n\taddl\t$16,%edi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tcmpl\t24(%esp),%edi\n\tmovl\t%edi,20(%esp)\n\tjb\t.L000loop\n\tmovl\t%eax,%esi\n\tandl\t$255,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%bh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,4(%esp)\n\n\tmovl\t%ebx,%esi\n\tandl\t$255,%esi\n\tshrl\t$16,%ebx\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%ch,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,8(%esp)\n\n\tmovl\t%ecx,%esi\n\tandl\t$255,%esi\n\tshrl\t$24,%ecx\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%dh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edx\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovzbl\t%bh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\n\tmovl\t20(%esp),%edi\n\tandl\t$255,%edx\n\tmovzbl\t-128(%ebp,%edx,1),%edx\n\tmovzbl\t%ah,%eax\n\tmovzbl\t-128(%ebp,%eax,1),%eax\n\tshll\t$8,%eax\n\txorl\t%eax,%edx\n\tmovl\t4(%esp),%eax\n\tandl\t$255,%ebx\n\tmovzbl\t-128(%ebp,%ebx,1),%ebx\n\tshll\t$16,%ebx\n\txorl\t%ebx,%edx\n\tmovl\t8(%esp),%ebx\n\tmovzbl\t-128(%ebp,%ecx,1),%ecx\n\tshll\t$24,%ecx\n\txorl\t%ecx,%edx\n\tmovl\t%esi,%ecx\n\n\txorl\t16(%edi),%eax\n\txorl\t20(%edi),%ebx\n\txorl\t24(%edi),%ecx\n\txorl\t28(%edi),%edx\n\tret\n.size\t_x86_AES_encrypt_compact,.-_x86_AES_encrypt_compact\n.type\t_sse_AES_encrypt_compact,@function\n.align\t16\n_sse_AES_encrypt_compact:\n\tpxor\t(%edi),%mm0\n\tpxor\t8(%edi),%mm4\n\tmovl\t240(%edi),%esi\n\tleal\t-2(%esi,%esi,1),%esi\n\tleal\t(%edi,%esi,8),%esi\n\tmovl\t%esi,24(%esp)\n\tmovl\t$454761243,%eax\n\tmovl\t%eax,8(%esp)\n\tmovl\t%eax,12(%esp)\n\tmovl\t-128(%ebp),%eax\n\tmovl\t-96(%ebp),%ebx\n\tmovl\t-64(%ebp),%ecx\n\tmovl\t-32(%ebp),%edx\n\tmovl\t(%ebp),%eax\n\tmovl\t32(%ebp),%ebx\n\tmovl\t64(%ebp),%ecx\n\tmovl\t96(%ebp),%edx\n.align\t16\n.L001loop:\n\tpshufw\t$8,%mm0,%mm1\n\tpshufw\t$13,%mm4,%mm5\n\tmovd\t%mm1,%eax\n\tmovd\t%mm5,%ebx\n\tmovl\t%edi,20(%esp)\n\tmovzbl\t%al,%esi\n\tmovzbl\t%ah,%edx\n\tpshufw\t$13,%mm0,%mm2\n\tmovzbl\t-128(%ebp,%esi,1),%ecx\n\tmovzbl\t%bl,%edi\n\tmovzbl\t-128(%ebp,%edx,1),%edx\n\tshrl\t$16,%eax\n\tshll\t$8,%edx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bh,%edi\n\tshll\t$16,%esi\n\tpshufw\t$8,%mm4,%mm6\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%ah,%edi\n\tshll\t$24,%esi\n\tshrl\t$16,%ebx\n\torl\t%esi,%edx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bh,%edi\n\tshll\t$8,%esi\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%al,%edi\n\tshll\t$24,%esi\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bl,%edi\n\tmovd\t%mm2,%eax\n\tmovd\t%ecx,%mm0\n\tmovzbl\t-128(%ebp,%edi,1),%ecx\n\tmovzbl\t%ah,%edi\n\tshll\t$16,%ecx\n\tmovd\t%mm6,%ebx\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bh,%edi\n\tshll\t$24,%esi\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bl,%edi\n\tshll\t$8,%esi\n\tshrl\t$16,%ebx\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%al,%edi\n\tshrl\t$16,%eax\n\tmovd\t%ecx,%mm1\n\tmovzbl\t-128(%ebp,%edi,1),%ecx\n\tmovzbl\t%ah,%edi\n\tshll\t$16,%ecx\n\tandl\t$255,%eax\n\torl\t%esi,%ecx\n\tpunpckldq\t%mm1,%mm0\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bh,%edi\n\tshll\t$24,%esi\n\tandl\t$255,%ebx\n\tmovzbl\t-128(%ebp,%eax,1),%eax\n\torl\t%esi,%ecx\n\tshll\t$16,%eax\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\torl\t%eax,%edx\n\tshll\t$8,%esi\n\tmovzbl\t-128(%ebp,%ebx,1),%ebx\n\torl\t%esi,%ecx\n\torl\t%ebx,%edx\n\tmovl\t20(%esp),%edi\n\tmovd\t%ecx,%mm4\n\tmovd\t%edx,%mm5\n\tpunpckldq\t%mm5,%mm4\n\taddl\t$16,%edi\n\tcmpl\t24(%esp),%edi\n\tja\t.L002out\n\tmovq\t8(%esp),%mm2\n\tpxor\t%mm3,%mm3\n\tpxor\t%mm7,%mm7\n\tmovq\t%mm0,%mm1\n\tmovq\t%mm4,%mm5\n\tpcmpgtb\t%mm0,%mm3\n\tpcmpgtb\t%mm4,%mm7\n\tpand\t%mm2,%mm3\n\tpand\t%mm2,%mm7\n\tpshufw\t$177,%mm0,%mm2\n\tpshufw\t$177,%mm4,%mm6\n\tpaddb\t%mm0,%mm0\n\tpaddb\t%mm4,%mm4\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tpshufw\t$177,%mm2,%mm3\n\tpshufw\t$177,%mm6,%mm7\n\tpxor\t%mm0,%mm1\n\tpxor\t%mm4,%mm5\n\tpxor\t%mm2,%mm0\n\tpxor\t%mm6,%mm4\n\tmovq\t%mm3,%mm2\n\tmovq\t%mm7,%mm6\n\tpslld\t$8,%mm3\n\tpslld\t$8,%mm7\n\tpsrld\t$24,%mm2\n\tpsrld\t$24,%mm6\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tpxor\t%mm2,%mm0\n\tpxor\t%mm6,%mm4\n\tmovq\t%mm1,%mm3\n\tmovq\t%mm5,%mm7\n\tmovq\t(%edi),%mm2\n\tmovq\t8(%edi),%mm6\n\tpsrld\t$8,%mm1\n\tpsrld\t$8,%mm5\n\tmovl\t-128(%ebp),%eax\n\tpslld\t$24,%mm3\n\tpslld\t$24,%mm7\n\tmovl\t-64(%ebp),%ebx\n\tpxor\t%mm1,%mm0\n\tpxor\t%mm5,%mm4\n\tmovl\t(%ebp),%ecx\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tmovl\t64(%ebp),%edx\n\tpxor\t%mm2,%mm0\n\tpxor\t%mm6,%mm4\n\tjmp\t.L001loop\n.align\t16\n.L002out:\n\tpxor\t(%edi),%mm0\n\tpxor\t8(%edi),%mm4\n\tret\n.size\t_sse_AES_encrypt_compact,.-_sse_AES_encrypt_compact\n.type\t_x86_AES_encrypt,@function\n.align\t16\n_x86_AES_encrypt:\n\tmovl\t%edi,20(%esp)\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tmovl\t240(%edi),%esi\n\tleal\t-2(%esi,%esi,1),%esi\n\tleal\t(%edi,%esi,8),%esi\n\tmovl\t%esi,24(%esp)\n.align\t16\n.L003loop:\n\tmovl\t%eax,%esi\n\tandl\t$255,%esi\n\tmovl\t(%ebp,%esi,8),%esi\n\tmovzbl\t%bh,%edi\n\txorl\t3(%ebp,%edi,8),%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\txorl\t2(%ebp,%edi,8),%esi\n\tmovl\t%edx,%edi\n\tshrl\t$24,%edi\n\txorl\t1(%ebp,%edi,8),%esi\n\tmovl\t%esi,4(%esp)\n\n\tmovl\t%ebx,%esi\n\tandl\t$255,%esi\n\tshrl\t$16,%ebx\n\tmovl\t(%ebp,%esi,8),%esi\n\tmovzbl\t%ch,%edi\n\txorl\t3(%ebp,%edi,8),%esi\n\tmovl\t%edx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\txorl\t2(%ebp,%edi,8),%esi\n\tmovl\t%eax,%edi\n\tshrl\t$24,%edi\n\txorl\t1(%ebp,%edi,8),%esi\n\tmovl\t%esi,8(%esp)\n\n\tmovl\t%ecx,%esi\n\tandl\t$255,%esi\n\tshrl\t$24,%ecx\n\tmovl\t(%ebp,%esi,8),%esi\n\tmovzbl\t%dh,%edi\n\txorl\t3(%ebp,%edi,8),%esi\n\tmovl\t%eax,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edx\n\tandl\t$255,%edi\n\txorl\t2(%ebp,%edi,8),%esi\n\tmovzbl\t%bh,%edi\n\txorl\t1(%ebp,%edi,8),%esi\n\n\tmovl\t20(%esp),%edi\n\tmovl\t(%ebp,%edx,8),%edx\n\tmovzbl\t%ah,%eax\n\txorl\t3(%ebp,%eax,8),%edx\n\tmovl\t4(%esp),%eax\n\tandl\t$255,%ebx\n\txorl\t2(%ebp,%ebx,8),%edx\n\tmovl\t8(%esp),%ebx\n\txorl\t1(%ebp,%ecx,8),%edx\n\tmovl\t%esi,%ecx\n\n\taddl\t$16,%edi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tcmpl\t24(%esp),%edi\n\tmovl\t%edi,20(%esp)\n\tjb\t.L003loop\n\tmovl\t%eax,%esi\n\tandl\t$255,%esi\n\tmovl\t2(%ebp,%esi,8),%esi\n\tandl\t$255,%esi\n\tmovzbl\t%bh,%edi\n\tmovl\t(%ebp,%edi,8),%edi\n\tandl\t$65280,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovl\t(%ebp,%edi,8),%edi\n\tandl\t$16711680,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$24,%edi\n\tmovl\t2(%ebp,%edi,8),%edi\n\tandl\t$4278190080,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,4(%esp)\n\tmovl\t%ebx,%esi\n\tandl\t$255,%esi\n\tshrl\t$16,%ebx\n\tmovl\t2(%ebp,%esi,8),%esi\n\tandl\t$255,%esi\n\tmovzbl\t%ch,%edi\n\tmovl\t(%ebp,%edi,8),%edi\n\tandl\t$65280,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovl\t(%ebp,%edi,8),%edi\n\tandl\t$16711680,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$24,%edi\n\tmovl\t2(%ebp,%edi,8),%edi\n\tandl\t$4278190080,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,8(%esp)\n\tmovl\t%ecx,%esi\n\tandl\t$255,%esi\n\tshrl\t$24,%ecx\n\tmovl\t2(%ebp,%esi,8),%esi\n\tandl\t$255,%esi\n\tmovzbl\t%dh,%edi\n\tmovl\t(%ebp,%edi,8),%edi\n\tandl\t$65280,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edx\n\tandl\t$255,%edi\n\tmovl\t(%ebp,%edi,8),%edi\n\tandl\t$16711680,%edi\n\txorl\t%edi,%esi\n\tmovzbl\t%bh,%edi\n\tmovl\t2(%ebp,%edi,8),%edi\n\tandl\t$4278190080,%edi\n\txorl\t%edi,%esi\n\tmovl\t20(%esp),%edi\n\tandl\t$255,%edx\n\tmovl\t2(%ebp,%edx,8),%edx\n\tandl\t$255,%edx\n\tmovzbl\t%ah,%eax\n\tmovl\t(%ebp,%eax,8),%eax\n\tandl\t$65280,%eax\n\txorl\t%eax,%edx\n\tmovl\t4(%esp),%eax\n\tandl\t$255,%ebx\n\tmovl\t(%ebp,%ebx,8),%ebx\n\tandl\t$16711680,%ebx\n\txorl\t%ebx,%edx\n\tmovl\t8(%esp),%ebx\n\tmovl\t2(%ebp,%ecx,8),%ecx\n\tandl\t$4278190080,%ecx\n\txorl\t%ecx,%edx\n\tmovl\t%esi,%ecx\n\taddl\t$16,%edi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tret\n.align\t64\n.LAES_Te:\n.long\t2774754246,2774754246\n.long\t2222750968,2222750968\n.long\t2574743534,2574743534\n.long\t2373680118,2373680118\n.long\t234025727,234025727\n.long\t3177933782,3177933782\n.long\t2976870366,2976870366\n.long\t1422247313,1422247313\n.long\t1345335392,1345335392\n.long\t50397442,50397442\n.long\t2842126286,2842126286\n.long\t2099981142,2099981142\n.long\t436141799,436141799\n.long\t1658312629,1658312629\n.long\t3870010189,3870010189\n.long\t2591454956,2591454956\n.long\t1170918031,1170918031\n.long\t2642575903,2642575903\n.long\t1086966153,1086966153\n.long\t2273148410,2273148410\n.long\t368769775,368769775\n.long\t3948501426,3948501426\n.long\t3376891790,3376891790\n.long\t200339707,200339707\n.long\t3970805057,3970805057\n.long\t1742001331,1742001331\n.long\t4255294047,4255294047\n.long\t3937382213,3937382213\n.long\t3214711843,3214711843\n.long\t4154762323,4154762323\n.long\t2524082916,2524082916\n.long\t1539358875,1539358875\n.long\t3266819957,3266819957\n.long\t486407649,486407649\n.long\t2928907069,2928907069\n.long\t1780885068,1780885068\n.long\t1513502316,1513502316\n.long\t1094664062,1094664062\n.long\t49805301,49805301\n.long\t1338821763,1338821763\n.long\t1546925160,1546925160\n.long\t4104496465,4104496465\n.long\t887481809,887481809\n.long\t150073849,150073849\n.long\t2473685474,2473685474\n.long\t1943591083,1943591083\n.long\t1395732834,1395732834\n.long\t1058346282,1058346282\n.long\t201589768,201589768\n.long\t1388824469,1388824469\n.long\t1696801606,1696801606\n.long\t1589887901,1589887901\n.long\t672667696,672667696\n.long\t2711000631,2711000631\n.long\t251987210,251987210\n.long\t3046808111,3046808111\n.long\t151455502,151455502\n.long\t907153956,907153956\n.long\t2608889883,2608889883\n.long\t1038279391,1038279391\n.long\t652995533,652995533\n.long\t1764173646,1764173646\n.long\t3451040383,3451040383\n.long\t2675275242,2675275242\n.long\t453576978,453576978\n.long\t2659418909,2659418909\n.long\t1949051992,1949051992\n.long\t773462580,773462580\n.long\t756751158,756751158\n.long\t2993581788,2993581788\n.long\t3998898868,3998898868\n.long\t4221608027,4221608027\n.long\t4132590244,4132590244\n.long\t1295727478,1295727478\n.long\t1641469623,1641469623\n.long\t3467883389,3467883389\n.long\t2066295122,2066295122\n.long\t1055122397,1055122397\n.long\t1898917726,1898917726\n.long\t2542044179,2542044179\n.long\t4115878822,4115878822\n.long\t1758581177,1758581177\n.long\t0,0\n.long\t753790401,753790401\n.long\t1612718144,1612718144\n.long\t536673507,536673507\n.long\t3367088505,3367088505\n.long\t3982187446,3982187446\n.long\t3194645204,3194645204\n.long\t1187761037,1187761037\n.long\t3653156455,3653156455\n.long\t1262041458,1262041458\n.long\t3729410708,3729410708\n.long\t3561770136,3561770136\n.long\t3898103984,3898103984\n.long\t1255133061,1255133061\n.long\t1808847035,1808847035\n.long\t720367557,720367557\n.long\t3853167183,3853167183\n.long\t385612781,385612781\n.long\t3309519750,3309519750\n.long\t3612167578,3612167578\n.long\t1429418854,1429418854\n.long\t2491778321,2491778321\n.long\t3477423498,3477423498\n.long\t284817897,284817897\n.long\t100794884,100794884\n.long\t2172616702,2172616702\n.long\t4031795360,4031795360\n.long\t1144798328,1144798328\n.long\t3131023141,3131023141\n.long\t3819481163,3819481163\n.long\t4082192802,4082192802\n.long\t4272137053,4272137053\n.long\t3225436288,3225436288\n.long\t2324664069,2324664069\n.long\t2912064063,2912064063\n.long\t3164445985,3164445985\n.long\t1211644016,1211644016\n.long\t83228145,83228145\n.long\t3753688163,3753688163\n.long\t3249976951,3249976951\n.long\t1977277103,1977277103\n.long\t1663115586,1663115586\n.long\t806359072,806359072\n.long\t452984805,452984805\n.long\t250868733,250868733\n.long\t1842533055,1842533055\n.long\t1288555905,1288555905\n.long\t336333848,336333848\n.long\t890442534,890442534\n.long\t804056259,804056259\n.long\t3781124030,3781124030\n.long\t2727843637,2727843637\n.long\t3427026056,3427026056\n.long\t957814574,957814574\n.long\t1472513171,1472513171\n.long\t4071073621,4071073621\n.long\t2189328124,2189328124\n.long\t1195195770,1195195770\n.long\t2892260552,2892260552\n.long\t3881655738,3881655738\n.long\t723065138,723065138\n.long\t2507371494,2507371494\n.long\t2690670784,2690670784\n.long\t2558624025,2558624025\n.long\t3511635870,3511635870\n.long\t2145180835,2145180835\n.long\t1713513028,1713513028\n.long\t2116692564,2116692564\n.long\t2878378043,2878378043\n.long\t2206763019,2206763019\n.long\t3393603212,3393603212\n.long\t703524551,703524551\n.long\t3552098411,3552098411\n.long\t1007948840,1007948840\n.long\t2044649127,2044649127\n.long\t3797835452,3797835452\n.long\t487262998,487262998\n.long\t1994120109,1994120109\n.long\t1004593371,1004593371\n.long\t1446130276,1446130276\n.long\t1312438900,1312438900\n.long\t503974420,503974420\n.long\t3679013266,3679013266\n.long\t168166924,168166924\n.long\t1814307912,1814307912\n.long\t3831258296,3831258296\n.long\t1573044895,1573044895\n.long\t1859376061,1859376061\n.long\t4021070915,4021070915\n.long\t2791465668,2791465668\n.long\t2828112185,2828112185\n.long\t2761266481,2761266481\n.long\t937747667,937747667\n.long\t2339994098,2339994098\n.long\t854058965,854058965\n.long\t1137232011,1137232011\n.long\t1496790894,1496790894\n.long\t3077402074,3077402074\n.long\t2358086913,2358086913\n.long\t1691735473,1691735473\n.long\t3528347292,3528347292\n.long\t3769215305,3769215305\n.long\t3027004632,3027004632\n.long\t4199962284,4199962284\n.long\t133494003,133494003\n.long\t636152527,636152527\n.long\t2942657994,2942657994\n.long\t2390391540,2390391540\n.long\t3920539207,3920539207\n.long\t403179536,403179536\n.long\t3585784431,3585784431\n.long\t2289596656,2289596656\n.long\t1864705354,1864705354\n.long\t1915629148,1915629148\n.long\t605822008,605822008\n.long\t4054230615,4054230615\n.long\t3350508659,3350508659\n.long\t1371981463,1371981463\n.long\t602466507,602466507\n.long\t2094914977,2094914977\n.long\t2624877800,2624877800\n.long\t555687742,555687742\n.long\t3712699286,3712699286\n.long\t3703422305,3703422305\n.long\t2257292045,2257292045\n.long\t2240449039,2240449039\n.long\t2423288032,2423288032\n.long\t1111375484,1111375484\n.long\t3300242801,3300242801\n.long\t2858837708,2858837708\n.long\t3628615824,3628615824\n.long\t84083462,84083462\n.long\t32962295,32962295\n.long\t302911004,302911004\n.long\t2741068226,2741068226\n.long\t1597322602,1597322602\n.long\t4183250862,4183250862\n.long\t3501832553,3501832553\n.long\t2441512471,2441512471\n.long\t1489093017,1489093017\n.long\t656219450,656219450\n.long\t3114180135,3114180135\n.long\t954327513,954327513\n.long\t335083755,335083755\n.long\t3013122091,3013122091\n.long\t856756514,856756514\n.long\t3144247762,3144247762\n.long\t1893325225,1893325225\n.long\t2307821063,2307821063\n.long\t2811532339,2811532339\n.long\t3063651117,3063651117\n.long\t572399164,572399164\n.long\t2458355477,2458355477\n.long\t552200649,552200649\n.long\t1238290055,1238290055\n.long\t4283782570,4283782570\n.long\t2015897680,2015897680\n.long\t2061492133,2061492133\n.long\t2408352771,2408352771\n.long\t4171342169,4171342169\n.long\t2156497161,2156497161\n.long\t386731290,386731290\n.long\t3669999461,3669999461\n.long\t837215959,837215959\n.long\t3326231172,3326231172\n.long\t3093850320,3093850320\n.long\t3275833730,3275833730\n.long\t2962856233,2962856233\n.long\t1999449434,1999449434\n.long\t286199582,286199582\n.long\t3417354363,3417354363\n.long\t4233385128,4233385128\n.long\t3602627437,3602627437\n.long\t974525996,974525996\n.byte\t99,124,119,123,242,107,111,197\n.byte\t48,1,103,43,254,215,171,118\n.byte\t202,130,201,125,250,89,71,240\n.byte\t173,212,162,175,156,164,114,192\n.byte\t183,253,147,38,54,63,247,204\n.byte\t52,165,229,241,113,216,49,21\n.byte\t4,199,35,195,24,150,5,154\n.byte\t7,18,128,226,235,39,178,117\n.byte\t9,131,44,26,27,110,90,160\n.byte\t82,59,214,179,41,227,47,132\n.byte\t83,209,0,237,32,252,177,91\n.byte\t106,203,190,57,74,76,88,207\n.byte\t208,239,170,251,67,77,51,133\n.byte\t69,249,2,127,80,60,159,168\n.byte\t81,163,64,143,146,157,56,245\n.byte\t188,182,218,33,16,255,243,210\n.byte\t205,12,19,236,95,151,68,23\n.byte\t196,167,126,61,100,93,25,115\n.byte\t96,129,79,220,34,42,144,136\n.byte\t70,238,184,20,222,94,11,219\n.byte\t224,50,58,10,73,6,36,92\n.byte\t194,211,172,98,145,149,228,121\n.byte\t231,200,55,109,141,213,78,169\n.byte\t108,86,244,234,101,122,174,8\n.byte\t186,120,37,46,28,166,180,198\n.byte\t232,221,116,31,75,189,139,138\n.byte\t112,62,181,102,72,3,246,14\n.byte\t97,53,87,185,134,193,29,158\n.byte\t225,248,152,17,105,217,142,148\n.byte\t155,30,135,233,206,85,40,223\n.byte\t140,161,137,13,191,230,66,104\n.byte\t65,153,45,15,176,84,187,22\n.byte\t99,124,119,123,242,107,111,197\n.byte\t48,1,103,43,254,215,171,118\n.byte\t202,130,201,125,250,89,71,240\n.byte\t173,212,162,175,156,164,114,192\n.byte\t183,253,147,38,54,63,247,204\n.byte\t52,165,229,241,113,216,49,21\n.byte\t4,199,35,195,24,150,5,154\n.byte\t7,18,128,226,235,39,178,117\n.byte\t9,131,44,26,27,110,90,160\n.byte\t82,59,214,179,41,227,47,132\n.byte\t83,209,0,237,32,252,177,91\n.byte\t106,203,190,57,74,76,88,207\n.byte\t208,239,170,251,67,77,51,133\n.byte\t69,249,2,127,80,60,159,168\n.byte\t81,163,64,143,146,157,56,245\n.byte\t188,182,218,33,16,255,243,210\n.byte\t205,12,19,236,95,151,68,23\n.byte\t196,167,126,61,100,93,25,115\n.byte\t96,129,79,220,34,42,144,136\n.byte\t70,238,184,20,222,94,11,219\n.byte\t224,50,58,10,73,6,36,92\n.byte\t194,211,172,98,145,149,228,121\n.byte\t231,200,55,109,141,213,78,169\n.byte\t108,86,244,234,101,122,174,8\n.byte\t186,120,37,46,28,166,180,198\n.byte\t232,221,116,31,75,189,139,138\n.byte\t112,62,181,102,72,3,246,14\n.byte\t97,53,87,185,134,193,29,158\n.byte\t225,248,152,17,105,217,142,148\n.byte\t155,30,135,233,206,85,40,223\n.byte\t140,161,137,13,191,230,66,104\n.byte\t65,153,45,15,176,84,187,22\n.byte\t99,124,119,123,242,107,111,197\n.byte\t48,1,103,43,254,215,171,118\n.byte\t202,130,201,125,250,89,71,240\n.byte\t173,212,162,175,156,164,114,192\n.byte\t183,253,147,38,54,63,247,204\n.byte\t52,165,229,241,113,216,49,21\n.byte\t4,199,35,195,24,150,5,154\n.byte\t7,18,128,226,235,39,178,117\n.byte\t9,131,44,26,27,110,90,160\n.byte\t82,59,214,179,41,227,47,132\n.byte\t83,209,0,237,32,252,177,91\n.byte\t106,203,190,57,74,76,88,207\n.byte\t208,239,170,251,67,77,51,133\n.byte\t69,249,2,127,80,60,159,168\n.byte\t81,163,64,143,146,157,56,245\n.byte\t188,182,218,33,16,255,243,210\n.byte\t205,12,19,236,95,151,68,23\n.byte\t196,167,126,61,100,93,25,115\n.byte\t96,129,79,220,34,42,144,136\n.byte\t70,238,184,20,222,94,11,219\n.byte\t224,50,58,10,73,6,36,92\n.byte\t194,211,172,98,145,149,228,121\n.byte\t231,200,55,109,141,213,78,169\n.byte\t108,86,244,234,101,122,174,8\n.byte\t186,120,37,46,28,166,180,198\n.byte\t232,221,116,31,75,189,139,138\n.byte\t112,62,181,102,72,3,246,14\n.byte\t97,53,87,185,134,193,29,158\n.byte\t225,248,152,17,105,217,142,148\n.byte\t155,30,135,233,206,85,40,223\n.byte\t140,161,137,13,191,230,66,104\n.byte\t65,153,45,15,176,84,187,22\n.byte\t99,124,119,123,242,107,111,197\n.byte\t48,1,103,43,254,215,171,118\n.byte\t202,130,201,125,250,89,71,240\n.byte\t173,212,162,175,156,164,114,192\n.byte\t183,253,147,38,54,63,247,204\n.byte\t52,165,229,241,113,216,49,21\n.byte\t4,199,35,195,24,150,5,154\n.byte\t7,18,128,226,235,39,178,117\n.byte\t9,131,44,26,27,110,90,160\n.byte\t82,59,214,179,41,227,47,132\n.byte\t83,209,0,237,32,252,177,91\n.byte\t106,203,190,57,74,76,88,207\n.byte\t208,239,170,251,67,77,51,133\n.byte\t69,249,2,127,80,60,159,168\n.byte\t81,163,64,143,146,157,56,245\n.byte\t188,182,218,33,16,255,243,210\n.byte\t205,12,19,236,95,151,68,23\n.byte\t196,167,126,61,100,93,25,115\n.byte\t96,129,79,220,34,42,144,136\n.byte\t70,238,184,20,222,94,11,219\n.byte\t224,50,58,10,73,6,36,92\n.byte\t194,211,172,98,145,149,228,121\n.byte\t231,200,55,109,141,213,78,169\n.byte\t108,86,244,234,101,122,174,8\n.byte\t186,120,37,46,28,166,180,198\n.byte\t232,221,116,31,75,189,139,138\n.byte\t112,62,181,102,72,3,246,14\n.byte\t97,53,87,185,134,193,29,158\n.byte\t225,248,152,17,105,217,142,148\n.byte\t155,30,135,233,206,85,40,223\n.byte\t140,161,137,13,191,230,66,104\n.byte\t65,153,45,15,176,84,187,22\n.long\t1,2,4,8\n.long\t16,32,64,128\n.long\t27,54,0,0\n.long\t0,0,0,0\n.size\t_x86_AES_encrypt,.-_x86_AES_encrypt\n.globl\tAES_encrypt\n.type\tAES_encrypt,@function\n.align\t16\nAES_encrypt:\n.L_AES_encrypt_begin:\n\tpushl\t%ebp\n\tpushl\t%ebx\n\tpushl\t%esi\n\tpushl\t%edi\n\tmovl\t20(%esp),%esi\n\tmovl\t28(%esp),%edi\n\tmovl\t%esp,%eax\n\tsubl\t$36,%esp\n\tandl\t$-64,%esp\n\tleal\t-127(%edi),%ebx\n\tsubl\t%esp,%ebx\n\tnegl\t%ebx\n\tandl\t$960,%ebx\n\tsubl\t%ebx,%esp\n\taddl\t$4,%esp\n\tmovl\t%eax,28(%esp)\n\tcall\t.L004pic_point\n.L004pic_point:\n\tpopl\t%ebp\n\tleal\tOPENSSL_ia32cap_P,%eax\n\tleal\t.LAES_Te-.L004pic_point(%ebp),%ebp\n\tleal\t764(%esp),%ebx\n\tsubl\t%ebp,%ebx\n\tandl\t$768,%ebx\n\tleal\t2176(%ebp,%ebx,1),%ebp\n\tbtl\t$25,(%eax)\n\tjnc\t.L005x86\n\tmovq\t(%esi),%mm0\n\tmovq\t8(%esi),%mm4\n\tcall\t_sse_AES_encrypt_compact\n\tmovl\t28(%esp),%esp\n\tmovl\t24(%esp),%esi\n\tmovq\t%mm0,(%esi)\n\tmovq\t%mm4,8(%esi)\n\temms\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n.align\t16\n.L005x86:\n\tmovl\t%ebp,24(%esp)\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tcall\t_x86_AES_encrypt_compact\n\tmovl\t28(%esp),%esp\n\tmovl\t24(%esp),%esi\n\tmovl\t%eax,(%esi)\n\tmovl\t%ebx,4(%esi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n.size\tAES_encrypt,.-.L_AES_encrypt_begin\n.type\t_x86_AES_decrypt_compact,@function\n.align\t16\n_x86_AES_decrypt_compact:\n\tmovl\t%edi,20(%esp)\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tmovl\t240(%edi),%esi\n\tleal\t-2(%esi,%esi,1),%esi\n\tleal\t(%edi,%esi,8),%esi\n\tmovl\t%esi,24(%esp)\n\tmovl\t-128(%ebp),%edi\n\tmovl\t-96(%ebp),%esi\n\tmovl\t-64(%ebp),%edi\n\tmovl\t-32(%ebp),%esi\n\tmovl\t(%ebp),%edi\n\tmovl\t32(%ebp),%esi\n\tmovl\t64(%ebp),%edi\n\tmovl\t96(%ebp),%esi\n.align\t16\n.L006loop:\n\tmovl\t%eax,%esi\n\tandl\t$255,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%dh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ebx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,4(%esp)\n\tmovl\t%ebx,%esi\n\tandl\t$255,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%ah,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,8(%esp)\n\tmovl\t%ecx,%esi\n\tandl\t$255,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%bh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tandl\t$255,%edx\n\tmovzbl\t-128(%ebp,%edx,1),%edx\n\tmovzbl\t%ch,%ecx\n\tmovzbl\t-128(%ebp,%ecx,1),%ecx\n\tshll\t$8,%ecx\n\txorl\t%ecx,%edx\n\tmovl\t%esi,%ecx\n\tshrl\t$16,%ebx\n\tandl\t$255,%ebx\n\tmovzbl\t-128(%ebp,%ebx,1),%ebx\n\tshll\t$16,%ebx\n\txorl\t%ebx,%edx\n\tshrl\t$24,%eax\n\tmovzbl\t-128(%ebp,%eax,1),%eax\n\tshll\t$24,%eax\n\txorl\t%eax,%edx\n\tmovl\t$2155905152,%edi\n\tandl\t%ecx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%ecx,%ecx,1),%eax\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%eax\n\tandl\t$454761243,%esi\n\txorl\t%esi,%eax\n\tmovl\t$2155905152,%edi\n\tandl\t%eax,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%eax,%eax,1),%ebx\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ebx\n\tandl\t$454761243,%esi\n\txorl\t%ecx,%eax\n\txorl\t%esi,%ebx\n\tmovl\t$2155905152,%edi\n\tandl\t%ebx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%ebx,%ebx,1),%ebp\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ebp\n\tandl\t$454761243,%esi\n\txorl\t%ecx,%ebx\n\troll\t$8,%ecx\n\txorl\t%esi,%ebp\n\txorl\t%eax,%ecx\n\txorl\t%ebp,%eax\n\txorl\t%ebx,%ecx\n\txorl\t%ebp,%ebx\n\troll\t$24,%eax\n\txorl\t%ebp,%ecx\n\troll\t$16,%ebx\n\txorl\t%eax,%ecx\n\troll\t$8,%ebp\n\txorl\t%ebx,%ecx\n\tmovl\t4(%esp),%eax\n\txorl\t%ebp,%ecx\n\tmovl\t%ecx,12(%esp)\n\tmovl\t$2155905152,%edi\n\tandl\t%edx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%edx,%edx,1),%ebx\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ebx\n\tandl\t$454761243,%esi\n\txorl\t%esi,%ebx\n\tmovl\t$2155905152,%edi\n\tandl\t%ebx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%ebx,%ebx,1),%ecx\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ecx\n\tandl\t$454761243,%esi\n\txorl\t%edx,%ebx\n\txorl\t%esi,%ecx\n\tmovl\t$2155905152,%edi\n\tandl\t%ecx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%ecx,%ecx,1),%ebp\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ebp\n\tandl\t$454761243,%esi\n\txorl\t%edx,%ecx\n\troll\t$8,%edx\n\txorl\t%esi,%ebp\n\txorl\t%ebx,%edx\n\txorl\t%ebp,%ebx\n\txorl\t%ecx,%edx\n\txorl\t%ebp,%ecx\n\troll\t$24,%ebx\n\txorl\t%ebp,%edx\n\troll\t$16,%ecx\n\txorl\t%ebx,%edx\n\troll\t$8,%ebp\n\txorl\t%ecx,%edx\n\tmovl\t8(%esp),%ebx\n\txorl\t%ebp,%edx\n\tmovl\t%edx,16(%esp)\n\tmovl\t$2155905152,%edi\n\tandl\t%eax,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%eax,%eax,1),%ecx\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ecx\n\tandl\t$454761243,%esi\n\txorl\t%esi,%ecx\n\tmovl\t$2155905152,%edi\n\tandl\t%ecx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%ecx,%ecx,1),%edx\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%edx\n\tandl\t$454761243,%esi\n\txorl\t%eax,%ecx\n\txorl\t%esi,%edx\n\tmovl\t$2155905152,%edi\n\tandl\t%edx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%edx,%edx,1),%ebp\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ebp\n\tandl\t$454761243,%esi\n\txorl\t%eax,%edx\n\troll\t$8,%eax\n\txorl\t%esi,%ebp\n\txorl\t%ecx,%eax\n\txorl\t%ebp,%ecx\n\txorl\t%edx,%eax\n\txorl\t%ebp,%edx\n\troll\t$24,%ecx\n\txorl\t%ebp,%eax\n\troll\t$16,%edx\n\txorl\t%ecx,%eax\n\troll\t$8,%ebp\n\txorl\t%edx,%eax\n\txorl\t%ebp,%eax\n\tmovl\t$2155905152,%edi\n\tandl\t%ebx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%ebx,%ebx,1),%ecx\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ecx\n\tandl\t$454761243,%esi\n\txorl\t%esi,%ecx\n\tmovl\t$2155905152,%edi\n\tandl\t%ecx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%ecx,%ecx,1),%edx\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%edx\n\tandl\t$454761243,%esi\n\txorl\t%ebx,%ecx\n\txorl\t%esi,%edx\n\tmovl\t$2155905152,%edi\n\tandl\t%edx,%edi\n\tmovl\t%edi,%esi\n\tshrl\t$7,%edi\n\tleal\t(%edx,%edx,1),%ebp\n\tsubl\t%edi,%esi\n\tandl\t$4278124286,%ebp\n\tandl\t$454761243,%esi\n\txorl\t%ebx,%edx\n\troll\t$8,%ebx\n\txorl\t%esi,%ebp\n\txorl\t%ecx,%ebx\n\txorl\t%ebp,%ecx\n\txorl\t%edx,%ebx\n\txorl\t%ebp,%edx\n\troll\t$24,%ecx\n\txorl\t%ebp,%ebx\n\troll\t$16,%edx\n\txorl\t%ecx,%ebx\n\troll\t$8,%ebp\n\txorl\t%edx,%ebx\n\tmovl\t12(%esp),%ecx\n\txorl\t%ebp,%ebx\n\tmovl\t16(%esp),%edx\n\tmovl\t20(%esp),%edi\n\tmovl\t28(%esp),%ebp\n\taddl\t$16,%edi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tcmpl\t24(%esp),%edi\n\tmovl\t%edi,20(%esp)\n\tjb\t.L006loop\n\tmovl\t%eax,%esi\n\tandl\t$255,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%dh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ebx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,4(%esp)\n\tmovl\t%ebx,%esi\n\tandl\t$255,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%ah,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,8(%esp)\n\tmovl\t%ecx,%esi\n\tandl\t$255,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%esi\n\tmovzbl\t%bh,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t-128(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t20(%esp),%edi\n\tandl\t$255,%edx\n\tmovzbl\t-128(%ebp,%edx,1),%edx\n\tmovzbl\t%ch,%ecx\n\tmovzbl\t-128(%ebp,%ecx,1),%ecx\n\tshll\t$8,%ecx\n\txorl\t%ecx,%edx\n\tmovl\t%esi,%ecx\n\tshrl\t$16,%ebx\n\tandl\t$255,%ebx\n\tmovzbl\t-128(%ebp,%ebx,1),%ebx\n\tshll\t$16,%ebx\n\txorl\t%ebx,%edx\n\tmovl\t8(%esp),%ebx\n\tshrl\t$24,%eax\n\tmovzbl\t-128(%ebp,%eax,1),%eax\n\tshll\t$24,%eax\n\txorl\t%eax,%edx\n\tmovl\t4(%esp),%eax\n\txorl\t16(%edi),%eax\n\txorl\t20(%edi),%ebx\n\txorl\t24(%edi),%ecx\n\txorl\t28(%edi),%edx\n\tret\n.size\t_x86_AES_decrypt_compact,.-_x86_AES_decrypt_compact\n.type\t_sse_AES_decrypt_compact,@function\n.align\t16\n_sse_AES_decrypt_compact:\n\tpxor\t(%edi),%mm0\n\tpxor\t8(%edi),%mm4\n\tmovl\t240(%edi),%esi\n\tleal\t-2(%esi,%esi,1),%esi\n\tleal\t(%edi,%esi,8),%esi\n\tmovl\t%esi,24(%esp)\n\tmovl\t$454761243,%eax\n\tmovl\t%eax,8(%esp)\n\tmovl\t%eax,12(%esp)\n\tmovl\t-128(%ebp),%eax\n\tmovl\t-96(%ebp),%ebx\n\tmovl\t-64(%ebp),%ecx\n\tmovl\t-32(%ebp),%edx\n\tmovl\t(%ebp),%eax\n\tmovl\t32(%ebp),%ebx\n\tmovl\t64(%ebp),%ecx\n\tmovl\t96(%ebp),%edx\n.align\t16\n.L007loop:\n\tpshufw\t$12,%mm0,%mm1\n\tpshufw\t$9,%mm4,%mm5\n\tmovd\t%mm1,%eax\n\tmovd\t%mm5,%ebx\n\tmovl\t%edi,20(%esp)\n\tmovzbl\t%al,%esi\n\tmovzbl\t%ah,%edx\n\tpshufw\t$6,%mm0,%mm2\n\tmovzbl\t-128(%ebp,%esi,1),%ecx\n\tmovzbl\t%bl,%edi\n\tmovzbl\t-128(%ebp,%edx,1),%edx\n\tshrl\t$16,%eax\n\tshll\t$8,%edx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bh,%edi\n\tshll\t$16,%esi\n\tpshufw\t$3,%mm4,%mm6\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%ah,%edi\n\tshll\t$24,%esi\n\tshrl\t$16,%ebx\n\torl\t%esi,%edx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bh,%edi\n\tshll\t$24,%esi\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%al,%edi\n\tshll\t$8,%esi\n\tmovd\t%mm2,%eax\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bl,%edi\n\tshll\t$16,%esi\n\tmovd\t%mm6,%ebx\n\tmovd\t%ecx,%mm0\n\tmovzbl\t-128(%ebp,%edi,1),%ecx\n\tmovzbl\t%al,%edi\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bl,%edi\n\torl\t%esi,%edx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%ah,%edi\n\tshll\t$16,%esi\n\tshrl\t$16,%eax\n\torl\t%esi,%edx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%bh,%edi\n\tshrl\t$16,%ebx\n\tshll\t$8,%esi\n\tmovd\t%edx,%mm1\n\tmovzbl\t-128(%ebp,%edi,1),%edx\n\tmovzbl\t%bh,%edi\n\tshll\t$24,%edx\n\tandl\t$255,%ebx\n\torl\t%esi,%edx\n\tpunpckldq\t%mm1,%mm0\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\tmovzbl\t%al,%edi\n\tshll\t$8,%esi\n\tmovzbl\t%ah,%eax\n\tmovzbl\t-128(%ebp,%ebx,1),%ebx\n\torl\t%esi,%ecx\n\tmovzbl\t-128(%ebp,%edi,1),%esi\n\torl\t%ebx,%edx\n\tshll\t$16,%esi\n\tmovzbl\t-128(%ebp,%eax,1),%eax\n\torl\t%esi,%edx\n\tshll\t$24,%eax\n\torl\t%eax,%ecx\n\tmovl\t20(%esp),%edi\n\tmovd\t%edx,%mm4\n\tmovd\t%ecx,%mm5\n\tpunpckldq\t%mm5,%mm4\n\taddl\t$16,%edi\n\tcmpl\t24(%esp),%edi\n\tja\t.L008out\n\tmovq\t%mm0,%mm3\n\tmovq\t%mm4,%mm7\n\tpshufw\t$228,%mm0,%mm2\n\tpshufw\t$228,%mm4,%mm6\n\tmovq\t%mm0,%mm1\n\tmovq\t%mm4,%mm5\n\tpshufw\t$177,%mm0,%mm0\n\tpshufw\t$177,%mm4,%mm4\n\tpslld\t$8,%mm2\n\tpslld\t$8,%mm6\n\tpsrld\t$8,%mm3\n\tpsrld\t$8,%mm7\n\tpxor\t%mm2,%mm0\n\tpxor\t%mm6,%mm4\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tpslld\t$16,%mm2\n\tpslld\t$16,%mm6\n\tpsrld\t$16,%mm3\n\tpsrld\t$16,%mm7\n\tpxor\t%mm2,%mm0\n\tpxor\t%mm6,%mm4\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tmovq\t8(%esp),%mm3\n\tpxor\t%mm2,%mm2\n\tpxor\t%mm6,%mm6\n\tpcmpgtb\t%mm1,%mm2\n\tpcmpgtb\t%mm5,%mm6\n\tpand\t%mm3,%mm2\n\tpand\t%mm3,%mm6\n\tpaddb\t%mm1,%mm1\n\tpaddb\t%mm5,%mm5\n\tpxor\t%mm2,%mm1\n\tpxor\t%mm6,%mm5\n\tmovq\t%mm1,%mm3\n\tmovq\t%mm5,%mm7\n\tmovq\t%mm1,%mm2\n\tmovq\t%mm5,%mm6\n\tpxor\t%mm1,%mm0\n\tpxor\t%mm5,%mm4\n\tpslld\t$24,%mm3\n\tpslld\t$24,%mm7\n\tpsrld\t$8,%mm2\n\tpsrld\t$8,%mm6\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tpxor\t%mm2,%mm0\n\tpxor\t%mm6,%mm4\n\tmovq\t8(%esp),%mm2\n\tpxor\t%mm3,%mm3\n\tpxor\t%mm7,%mm7\n\tpcmpgtb\t%mm1,%mm3\n\tpcmpgtb\t%mm5,%mm7\n\tpand\t%mm2,%mm3\n\tpand\t%mm2,%mm7\n\tpaddb\t%mm1,%mm1\n\tpaddb\t%mm5,%mm5\n\tpxor\t%mm3,%mm1\n\tpxor\t%mm7,%mm5\n\tpshufw\t$177,%mm1,%mm3\n\tpshufw\t$177,%mm5,%mm7\n\tpxor\t%mm1,%mm0\n\tpxor\t%mm5,%mm4\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tpxor\t%mm3,%mm3\n\tpxor\t%mm7,%mm7\n\tpcmpgtb\t%mm1,%mm3\n\tpcmpgtb\t%mm5,%mm7\n\tpand\t%mm2,%mm3\n\tpand\t%mm2,%mm7\n\tpaddb\t%mm1,%mm1\n\tpaddb\t%mm5,%mm5\n\tpxor\t%mm3,%mm1\n\tpxor\t%mm7,%mm5\n\tpxor\t%mm1,%mm0\n\tpxor\t%mm5,%mm4\n\tmovq\t%mm1,%mm3\n\tmovq\t%mm5,%mm7\n\tpshufw\t$177,%mm1,%mm2\n\tpshufw\t$177,%mm5,%mm6\n\tpxor\t%mm2,%mm0\n\tpxor\t%mm6,%mm4\n\tpslld\t$8,%mm1\n\tpslld\t$8,%mm5\n\tpsrld\t$8,%mm3\n\tpsrld\t$8,%mm7\n\tmovq\t(%edi),%mm2\n\tmovq\t8(%edi),%mm6\n\tpxor\t%mm1,%mm0\n\tpxor\t%mm5,%mm4\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tmovl\t-128(%ebp),%eax\n\tpslld\t$16,%mm1\n\tpslld\t$16,%mm5\n\tmovl\t-64(%ebp),%ebx\n\tpsrld\t$16,%mm3\n\tpsrld\t$16,%mm7\n\tmovl\t(%ebp),%ecx\n\tpxor\t%mm1,%mm0\n\tpxor\t%mm5,%mm4\n\tmovl\t64(%ebp),%edx\n\tpxor\t%mm3,%mm0\n\tpxor\t%mm7,%mm4\n\tpxor\t%mm2,%mm0\n\tpxor\t%mm6,%mm4\n\tjmp\t.L007loop\n.align\t16\n.L008out:\n\tpxor\t(%edi),%mm0\n\tpxor\t8(%edi),%mm4\n\tret\n.size\t_sse_AES_decrypt_compact,.-_sse_AES_decrypt_compact\n.type\t_x86_AES_decrypt,@function\n.align\t16\n_x86_AES_decrypt:\n\tmovl\t%edi,20(%esp)\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tmovl\t240(%edi),%esi\n\tleal\t-2(%esi,%esi,1),%esi\n\tleal\t(%edi,%esi,8),%esi\n\tmovl\t%esi,24(%esp)\n.align\t16\n.L009loop:\n\tmovl\t%eax,%esi\n\tandl\t$255,%esi\n\tmovl\t(%ebp,%esi,8),%esi\n\tmovzbl\t%dh,%edi\n\txorl\t3(%ebp,%edi,8),%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\txorl\t2(%ebp,%edi,8),%esi\n\tmovl\t%ebx,%edi\n\tshrl\t$24,%edi\n\txorl\t1(%ebp,%edi,8),%esi\n\tmovl\t%esi,4(%esp)\n\n\tmovl\t%ebx,%esi\n\tandl\t$255,%esi\n\tmovl\t(%ebp,%esi,8),%esi\n\tmovzbl\t%ah,%edi\n\txorl\t3(%ebp,%edi,8),%esi\n\tmovl\t%edx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\txorl\t2(%ebp,%edi,8),%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$24,%edi\n\txorl\t1(%ebp,%edi,8),%esi\n\tmovl\t%esi,8(%esp)\n\n\tmovl\t%ecx,%esi\n\tandl\t$255,%esi\n\tmovl\t(%ebp,%esi,8),%esi\n\tmovzbl\t%bh,%edi\n\txorl\t3(%ebp,%edi,8),%esi\n\tmovl\t%eax,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\txorl\t2(%ebp,%edi,8),%esi\n\tmovl\t%edx,%edi\n\tshrl\t$24,%edi\n\txorl\t1(%ebp,%edi,8),%esi\n\n\tmovl\t20(%esp),%edi\n\tandl\t$255,%edx\n\tmovl\t(%ebp,%edx,8),%edx\n\tmovzbl\t%ch,%ecx\n\txorl\t3(%ebp,%ecx,8),%edx\n\tmovl\t%esi,%ecx\n\tshrl\t$16,%ebx\n\tandl\t$255,%ebx\n\txorl\t2(%ebp,%ebx,8),%edx\n\tmovl\t8(%esp),%ebx\n\tshrl\t$24,%eax\n\txorl\t1(%ebp,%eax,8),%edx\n\tmovl\t4(%esp),%eax\n\n\taddl\t$16,%edi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tcmpl\t24(%esp),%edi\n\tmovl\t%edi,20(%esp)\n\tjb\t.L009loop\n\tleal\t2176(%ebp),%ebp\n\tmovl\t-128(%ebp),%edi\n\tmovl\t-96(%ebp),%esi\n\tmovl\t-64(%ebp),%edi\n\tmovl\t-32(%ebp),%esi\n\tmovl\t(%ebp),%edi\n\tmovl\t32(%ebp),%esi\n\tmovl\t64(%ebp),%edi\n\tmovl\t96(%ebp),%esi\n\tleal\t-128(%ebp),%ebp\n\tmovl\t%eax,%esi\n\tandl\t$255,%esi\n\tmovzbl\t(%ebp,%esi,1),%esi\n\tmovzbl\t%dh,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ebx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,4(%esp)\n\tmovl\t%ebx,%esi\n\tandl\t$255,%esi\n\tmovzbl\t(%ebp,%esi,1),%esi\n\tmovzbl\t%ah,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%ecx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t%esi,8(%esp)\n\tmovl\t%ecx,%esi\n\tandl\t$255,%esi\n\tmovzbl\t(%ebp,%esi,1),%esi\n\tmovzbl\t%bh,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$8,%edi\n\txorl\t%edi,%esi\n\tmovl\t%eax,%edi\n\tshrl\t$16,%edi\n\tandl\t$255,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$16,%edi\n\txorl\t%edi,%esi\n\tmovl\t%edx,%edi\n\tshrl\t$24,%edi\n\tmovzbl\t(%ebp,%edi,1),%edi\n\tshll\t$24,%edi\n\txorl\t%edi,%esi\n\tmovl\t20(%esp),%edi\n\tandl\t$255,%edx\n\tmovzbl\t(%ebp,%edx,1),%edx\n\tmovzbl\t%ch,%ecx\n\tmovzbl\t(%ebp,%ecx,1),%ecx\n\tshll\t$8,%ecx\n\txorl\t%ecx,%edx\n\tmovl\t%esi,%ecx\n\tshrl\t$16,%ebx\n\tandl\t$255,%ebx\n\tmovzbl\t(%ebp,%ebx,1),%ebx\n\tshll\t$16,%ebx\n\txorl\t%ebx,%edx\n\tmovl\t8(%esp),%ebx\n\tshrl\t$24,%eax\n\tmovzbl\t(%ebp,%eax,1),%eax\n\tshll\t$24,%eax\n\txorl\t%eax,%edx\n\tmovl\t4(%esp),%eax\n\tleal\t-2048(%ebp),%ebp\n\taddl\t$16,%edi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tret\n.align\t64\n.LAES_Td:\n.long\t1353184337,1353184337\n.long\t1399144830,1399144830\n.long\t3282310938,3282310938\n.long\t2522752826,2522752826\n.long\t3412831035,3412831035\n.long\t4047871263,4047871263\n.long\t2874735276,2874735276\n.long\t2466505547,2466505547\n.long\t1442459680,1442459680\n.long\t4134368941,4134368941\n.long\t2440481928,2440481928\n.long\t625738485,625738485\n.long\t4242007375,4242007375\n.long\t3620416197,3620416197\n.long\t2151953702,2151953702\n.long\t2409849525,2409849525\n.long\t1230680542,1230680542\n.long\t1729870373,1729870373\n.long\t2551114309,2551114309\n.long\t3787521629,3787521629\n.long\t41234371,41234371\n.long\t317738113,317738113\n.long\t2744600205,2744600205\n.long\t3338261355,3338261355\n.long\t3881799427,3881799427\n.long\t2510066197,2510066197\n.long\t3950669247,3950669247\n.long\t3663286933,3663286933\n.long\t763608788,763608788\n.long\t3542185048,3542185048\n.long\t694804553,694804553\n.long\t1154009486,1154009486\n.long\t1787413109,1787413109\n.long\t2021232372,2021232372\n.long\t1799248025,1799248025\n.long\t3715217703,3715217703\n.long\t3058688446,3058688446\n.long\t397248752,397248752\n.long\t1722556617,1722556617\n.long\t3023752829,3023752829\n.long\t407560035,407560035\n.long\t2184256229,2184256229\n.long\t1613975959,1613975959\n.long\t1165972322,1165972322\n.long\t3765920945,3765920945\n.long\t2226023355,2226023355\n.long\t480281086,480281086\n.long\t2485848313,2485848313\n.long\t1483229296,1483229296\n.long\t436028815,436028815\n.long\t2272059028,2272059028\n.long\t3086515026,3086515026\n.long\t601060267,601060267\n.long\t3791801202,3791801202\n.long\t1468997603,1468997603\n.long\t715871590,715871590\n.long\t120122290,120122290\n.long\t63092015,63092015\n.long\t2591802758,2591802758\n.long\t2768779219,2768779219\n.long\t4068943920,4068943920\n.long\t2997206819,2997206819\n.long\t3127509762,3127509762\n.long\t1552029421,1552029421\n.long\t723308426,723308426\n.long\t2461301159,2461301159\n.long\t4042393587,4042393587\n.long\t2715969870,2715969870\n.long\t3455375973,3455375973\n.long\t3586000134,3586000134\n.long\t526529745,526529745\n.long\t2331944644,2331944644\n.long\t2639474228,2639474228\n.long\t2689987490,2689987490\n.long\t853641733,853641733\n.long\t1978398372,1978398372\n.long\t971801355,971801355\n.long\t2867814464,2867814464\n.long\t111112542,111112542\n.long\t1360031421,1360031421\n.long\t4186579262,4186579262\n.long\t1023860118,1023860118\n.long\t2919579357,2919579357\n.long\t1186850381,1186850381\n.long\t3045938321,3045938321\n.long\t90031217,90031217\n.long\t1876166148,1876166148\n.long\t4279586912,4279586912\n.long\t620468249,620468249\n.long\t2548678102,2548678102\n.long\t3426959497,3426959497\n.long\t2006899047,2006899047\n.long\t3175278768,3175278768\n.long\t2290845959,2290845959\n.long\t945494503,945494503\n.long\t3689859193,3689859193\n.long\t1191869601,1191869601\n.long\t3910091388,3910091388\n.long\t3374220536,3374220536\n.long\t0,0\n.long\t2206629897,2206629897\n.long\t1223502642,1223502642\n.long\t2893025566,2893025566\n.long\t1316117100,1316117100\n.long\t4227796733,4227796733\n.long\t1446544655,1446544655\n.long\t517320253,517320253\n.long\t658058550,658058550\n.long\t1691946762,1691946762\n.long\t564550760,564550760\n.long\t3511966619,3511966619\n.long\t976107044,976107044\n.long\t2976320012,2976320012\n.long\t266819475,266819475\n.long\t3533106868,3533106868\n.long\t2660342555,2660342555\n.long\t1338359936,1338359936\n.long\t2720062561,2720062561\n.long\t1766553434,1766553434\n.long\t370807324,370807324\n.long\t179999714,179999714\n.long\t3844776128,3844776128\n.long\t1138762300,1138762300\n.long\t488053522,488053522\n.long\t185403662,185403662\n.long\t2915535858,2915535858\n.long\t3114841645,3114841645\n.long\t3366526484,3366526484\n.long\t2233069911,2233069911\n.long\t1275557295,1275557295\n.long\t3151862254,3151862254\n.long\t4250959779,4250959779\n.long\t2670068215,2670068215\n.long\t3170202204,3170202204\n.long\t3309004356,3309004356\n.long\t880737115,880737115\n.long\t1982415755,1982415755\n.long\t3703972811,3703972811\n.long\t1761406390,1761406390\n.long\t1676797112,1676797112\n.long\t3403428311,3403428311\n.long\t277177154,277177154\n.long\t1076008723,1076008723\n.long\t538035844,538035844\n.long\t2099530373,2099530373\n.long\t4164795346,4164795346\n.long\t288553390,288553390\n.long\t1839278535,1839278535\n.long\t1261411869,1261411869\n.long\t4080055004,4080055004\n.long\t3964831245,3964831245\n.long\t3504587127,3504587127\n.long\t1813426987,1813426987\n.long\t2579067049,2579067049\n.long\t4199060497,4199060497\n.long\t577038663,577038663\n.long\t3297574056,3297574056\n.long\t440397984,440397984\n.long\t3626794326,3626794326\n.long\t4019204898,4019204898\n.long\t3343796615,3343796615\n.long\t3251714265,3251714265\n.long\t4272081548,4272081548\n.long\t906744984,906744984\n.long\t3481400742,3481400742\n.long\t685669029,685669029\n.long\t646887386,646887386\n.long\t2764025151,2764025151\n.long\t3835509292,3835509292\n.long\t227702864,227702864\n.long\t2613862250,2613862250\n.long\t1648787028,1648787028\n.long\t3256061430,3256061430\n.long\t3904428176,3904428176\n.long\t1593260334,1593260334\n.long\t4121936770,4121936770\n.long\t3196083615,3196083615\n.long\t2090061929,2090061929\n.long\t2838353263,2838353263\n.long\t3004310991,3004310991\n.long\t999926984,999926984\n.long\t2809993232,2809993232\n.long\t1852021992,1852021992\n.long\t2075868123,2075868123\n.long\t158869197,158869197\n.long\t4095236462,4095236462\n.long\t28809964,28809964\n.long\t2828685187,2828685187\n.long\t1701746150,1701746150\n.long\t2129067946,2129067946\n.long\t147831841,147831841\n.long\t3873969647,3873969647\n.long\t3650873274,3650873274\n.long\t3459673930,3459673930\n.long\t3557400554,3557400554\n.long\t3598495785,3598495785\n.long\t2947720241,2947720241\n.long\t824393514,824393514\n.long\t815048134,815048134\n.long\t3227951669,3227951669\n.long\t935087732,935087732\n.long\t2798289660,2798289660\n.long\t2966458592,2966458592\n.long\t366520115,366520115\n.long\t1251476721,1251476721\n.long\t4158319681,4158319681\n.long\t240176511,240176511\n.long\t804688151,804688151\n.long\t2379631990,2379631990\n.long\t1303441219,1303441219\n.long\t1414376140,1414376140\n.long\t3741619940,3741619940\n.long\t3820343710,3820343710\n.long\t461924940,461924940\n.long\t3089050817,3089050817\n.long\t2136040774,2136040774\n.long\t82468509,82468509\n.long\t1563790337,1563790337\n.long\t1937016826,1937016826\n.long\t776014843,776014843\n.long\t1511876531,1511876531\n.long\t1389550482,1389550482\n.long\t861278441,861278441\n.long\t323475053,323475053\n.long\t2355222426,2355222426\n.long\t2047648055,2047648055\n.long\t2383738969,2383738969\n.long\t2302415851,2302415851\n.long\t3995576782,3995576782\n.long\t902390199,902390199\n.long\t3991215329,3991215329\n.long\t1018251130,1018251130\n.long\t1507840668,1507840668\n.long\t1064563285,1064563285\n.long\t2043548696,2043548696\n.long\t3208103795,3208103795\n.long\t3939366739,3939366739\n.long\t1537932639,1537932639\n.long\t342834655,342834655\n.long\t2262516856,2262516856\n.long\t2180231114,2180231114\n.long\t1053059257,1053059257\n.long\t741614648,741614648\n.long\t1598071746,1598071746\n.long\t1925389590,1925389590\n.long\t203809468,203809468\n.long\t2336832552,2336832552\n.long\t1100287487,1100287487\n.long\t1895934009,1895934009\n.long\t3736275976,3736275976\n.long\t2632234200,2632234200\n.long\t2428589668,2428589668\n.long\t1636092795,1636092795\n.long\t1890988757,1890988757\n.long\t1952214088,1952214088\n.long\t1113045200,1113045200\n.byte\t82,9,106,213,48,54,165,56\n.byte\t191,64,163,158,129,243,215,251\n.byte\t124,227,57,130,155,47,255,135\n.byte\t52,142,67,68,196,222,233,203\n.byte\t84,123,148,50,166,194,35,61\n.byte\t238,76,149,11,66,250,195,78\n.byte\t8,46,161,102,40,217,36,178\n.byte\t118,91,162,73,109,139,209,37\n.byte\t114,248,246,100,134,104,152,22\n.byte\t212,164,92,204,93,101,182,146\n.byte\t108,112,72,80,253,237,185,218\n.byte\t94,21,70,87,167,141,157,132\n.byte\t144,216,171,0,140,188,211,10\n.byte\t247,228,88,5,184,179,69,6\n.byte\t208,44,30,143,202,63,15,2\n.byte\t193,175,189,3,1,19,138,107\n.byte\t58,145,17,65,79,103,220,234\n.byte\t151,242,207,206,240,180,230,115\n.byte\t150,172,116,34,231,173,53,133\n.byte\t226,249,55,232,28,117,223,110\n.byte\t71,241,26,113,29,41,197,137\n.byte\t111,183,98,14,170,24,190,27\n.byte\t252,86,62,75,198,210,121,32\n.byte\t154,219,192,254,120,205,90,244\n.byte\t31,221,168,51,136,7,199,49\n.byte\t177,18,16,89,39,128,236,95\n.byte\t96,81,127,169,25,181,74,13\n.byte\t45,229,122,159,147,201,156,239\n.byte\t160,224,59,77,174,42,245,176\n.byte\t200,235,187,60,131,83,153,97\n.byte\t23,43,4,126,186,119,214,38\n.byte\t225,105,20,99,85,33,12,125\n.byte\t82,9,106,213,48,54,165,56\n.byte\t191,64,163,158,129,243,215,251\n.byte\t124,227,57,130,155,47,255,135\n.byte\t52,142,67,68,196,222,233,203\n.byte\t84,123,148,50,166,194,35,61\n.byte\t238,76,149,11,66,250,195,78\n.byte\t8,46,161,102,40,217,36,178\n.byte\t118,91,162,73,109,139,209,37\n.byte\t114,248,246,100,134,104,152,22\n.byte\t212,164,92,204,93,101,182,146\n.byte\t108,112,72,80,253,237,185,218\n.byte\t94,21,70,87,167,141,157,132\n.byte\t144,216,171,0,140,188,211,10\n.byte\t247,228,88,5,184,179,69,6\n.byte\t208,44,30,143,202,63,15,2\n.byte\t193,175,189,3,1,19,138,107\n.byte\t58,145,17,65,79,103,220,234\n.byte\t151,242,207,206,240,180,230,115\n.byte\t150,172,116,34,231,173,53,133\n.byte\t226,249,55,232,28,117,223,110\n.byte\t71,241,26,113,29,41,197,137\n.byte\t111,183,98,14,170,24,190,27\n.byte\t252,86,62,75,198,210,121,32\n.byte\t154,219,192,254,120,205,90,244\n.byte\t31,221,168,51,136,7,199,49\n.byte\t177,18,16,89,39,128,236,95\n.byte\t96,81,127,169,25,181,74,13\n.byte\t45,229,122,159,147,201,156,239\n.byte\t160,224,59,77,174,42,245,176\n.byte\t200,235,187,60,131,83,153,97\n.byte\t23,43,4,126,186,119,214,38\n.byte\t225,105,20,99,85,33,12,125\n.byte\t82,9,106,213,48,54,165,56\n.byte\t191,64,163,158,129,243,215,251\n.byte\t124,227,57,130,155,47,255,135\n.byte\t52,142,67,68,196,222,233,203\n.byte\t84,123,148,50,166,194,35,61\n.byte\t238,76,149,11,66,250,195,78\n.byte\t8,46,161,102,40,217,36,178\n.byte\t118,91,162,73,109,139,209,37\n.byte\t114,248,246,100,134,104,152,22\n.byte\t212,164,92,204,93,101,182,146\n.byte\t108,112,72,80,253,237,185,218\n.byte\t94,21,70,87,167,141,157,132\n.byte\t144,216,171,0,140,188,211,10\n.byte\t247,228,88,5,184,179,69,6\n.byte\t208,44,30,143,202,63,15,2\n.byte\t193,175,189,3,1,19,138,107\n.byte\t58,145,17,65,79,103,220,234\n.byte\t151,242,207,206,240,180,230,115\n.byte\t150,172,116,34,231,173,53,133\n.byte\t226,249,55,232,28,117,223,110\n.byte\t71,241,26,113,29,41,197,137\n.byte\t111,183,98,14,170,24,190,27\n.byte\t252,86,62,75,198,210,121,32\n.byte\t154,219,192,254,120,205,90,244\n.byte\t31,221,168,51,136,7,199,49\n.byte\t177,18,16,89,39,128,236,95\n.byte\t96,81,127,169,25,181,74,13\n.byte\t45,229,122,159,147,201,156,239\n.byte\t160,224,59,77,174,42,245,176\n.byte\t200,235,187,60,131,83,153,97\n.byte\t23,43,4,126,186,119,214,38\n.byte\t225,105,20,99,85,33,12,125\n.byte\t82,9,106,213,48,54,165,56\n.byte\t191,64,163,158,129,243,215,251\n.byte\t124,227,57,130,155,47,255,135\n.byte\t52,142,67,68,196,222,233,203\n.byte\t84,123,148,50,166,194,35,61\n.byte\t238,76,149,11,66,250,195,78\n.byte\t8,46,161,102,40,217,36,178\n.byte\t118,91,162,73,109,139,209,37\n.byte\t114,248,246,100,134,104,152,22\n.byte\t212,164,92,204,93,101,182,146\n.byte\t108,112,72,80,253,237,185,218\n.byte\t94,21,70,87,167,141,157,132\n.byte\t144,216,171,0,140,188,211,10\n.byte\t247,228,88,5,184,179,69,6\n.byte\t208,44,30,143,202,63,15,2\n.byte\t193,175,189,3,1,19,138,107\n.byte\t58,145,17,65,79,103,220,234\n.byte\t151,242,207,206,240,180,230,115\n.byte\t150,172,116,34,231,173,53,133\n.byte\t226,249,55,232,28,117,223,110\n.byte\t71,241,26,113,29,41,197,137\n.byte\t111,183,98,14,170,24,190,27\n.byte\t252,86,62,75,198,210,121,32\n.byte\t154,219,192,254,120,205,90,244\n.byte\t31,221,168,51,136,7,199,49\n.byte\t177,18,16,89,39,128,236,95\n.byte\t96,81,127,169,25,181,74,13\n.byte\t45,229,122,159,147,201,156,239\n.byte\t160,224,59,77,174,42,245,176\n.byte\t200,235,187,60,131,83,153,97\n.byte\t23,43,4,126,186,119,214,38\n.byte\t225,105,20,99,85,33,12,125\n.size\t_x86_AES_decrypt,.-_x86_AES_decrypt\n.globl\tAES_decrypt\n.type\tAES_decrypt,@function\n.align\t16\nAES_decrypt:\n.L_AES_decrypt_begin:\n\tpushl\t%ebp\n\tpushl\t%ebx\n\tpushl\t%esi\n\tpushl\t%edi\n\tmovl\t20(%esp),%esi\n\tmovl\t28(%esp),%edi\n\tmovl\t%esp,%eax\n\tsubl\t$36,%esp\n\tandl\t$-64,%esp\n\tleal\t-127(%edi),%ebx\n\tsubl\t%esp,%ebx\n\tnegl\t%ebx\n\tandl\t$960,%ebx\n\tsubl\t%ebx,%esp\n\taddl\t$4,%esp\n\tmovl\t%eax,28(%esp)\n\tcall\t.L010pic_point\n.L010pic_point:\n\tpopl\t%ebp\n\tleal\tOPENSSL_ia32cap_P,%eax\n\tleal\t.LAES_Td-.L010pic_point(%ebp),%ebp\n\tleal\t764(%esp),%ebx\n\tsubl\t%ebp,%ebx\n\tandl\t$768,%ebx\n\tleal\t2176(%ebp,%ebx,1),%ebp\n\tbtl\t$25,(%eax)\n\tjnc\t.L011x86\n\tmovq\t(%esi),%mm0\n\tmovq\t8(%esi),%mm4\n\tcall\t_sse_AES_decrypt_compact\n\tmovl\t28(%esp),%esp\n\tmovl\t24(%esp),%esi\n\tmovq\t%mm0,(%esi)\n\tmovq\t%mm4,8(%esi)\n\temms\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n.align\t16\n.L011x86:\n\tmovl\t%ebp,24(%esp)\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tcall\t_x86_AES_decrypt_compact\n\tmovl\t28(%esp),%esp\n\tmovl\t24(%esp),%esi\n\tmovl\t%eax,(%esi)\n\tmovl\t%ebx,4(%esi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n.size\tAES_decrypt,.-.L_AES_decrypt_begin\n.globl\tAES_cbc_encrypt\n.type\tAES_cbc_encrypt,@function\n.align\t16\nAES_cbc_encrypt:\n.L_AES_cbc_encrypt_begin:\n\tpushl\t%ebp\n\tpushl\t%ebx\n\tpushl\t%esi\n\tpushl\t%edi\n\tmovl\t28(%esp),%ecx\n\tcmpl\t$0,%ecx\n\tje\t.L012drop_out\n\tcall\t.L013pic_point\n.L013pic_point:\n\tpopl\t%ebp\n\tleal\tOPENSSL_ia32cap_P,%eax\n\tcmpl\t$0,40(%esp)\n\tleal\t.LAES_Te-.L013pic_point(%ebp),%ebp\n\tjne\t.L014picked_te\n\tleal\t.LAES_Td-.LAES_Te(%ebp),%ebp\n.L014picked_te:\n\tpushfl\n\tcld\n\tcmpl\t$512,%ecx\n\tjb\t.L015slow_way\n\ttestl\t$15,%ecx\n\tjnz\t.L015slow_way\n\tbtl\t$28,(%eax)\n\tjc\t.L015slow_way\n\tleal\t-324(%esp),%esi\n\tandl\t$-64,%esi\n\tmovl\t%ebp,%eax\n\tleal\t2304(%ebp),%ebx\n\tmovl\t%esi,%edx\n\tandl\t$4095,%eax\n\tandl\t$4095,%ebx\n\tandl\t$4095,%edx\n\tcmpl\t%ebx,%edx\n\tjb\t.L016tbl_break_out\n\tsubl\t%ebx,%edx\n\tsubl\t%edx,%esi\n\tjmp\t.L017tbl_ok\n.align\t4\n.L016tbl_break_out:\n\tsubl\t%eax,%edx\n\tandl\t$4095,%edx\n\taddl\t$384,%edx\n\tsubl\t%edx,%esi\n.align\t4\n.L017tbl_ok:\n\tleal\t24(%esp),%edx\n\txchgl\t%esi,%esp\n\taddl\t$4,%esp\n\tmovl\t%ebp,24(%esp)\n\tmovl\t%esi,28(%esp)\n\tmovl\t(%edx),%eax\n\tmovl\t4(%edx),%ebx\n\tmovl\t12(%edx),%edi\n\tmovl\t16(%edx),%esi\n\tmovl\t20(%edx),%edx\n\tmovl\t%eax,32(%esp)\n\tmovl\t%ebx,36(%esp)\n\tmovl\t%ecx,40(%esp)\n\tmovl\t%edi,44(%esp)\n\tmovl\t%esi,48(%esp)\n\tmovl\t$0,316(%esp)\n\tmovl\t%edi,%ebx\n\tmovl\t$61,%ecx\n\tsubl\t%ebp,%ebx\n\tmovl\t%edi,%esi\n\tandl\t$4095,%ebx\n\tleal\t76(%esp),%edi\n\tcmpl\t$2304,%ebx\n\tjb\t.L018do_copy\n\tcmpl\t$3852,%ebx\n\tjb\t.L019skip_copy\n.align\t4\n.L018do_copy:\n\tmovl\t%edi,44(%esp)\n.long\t2784229001\n.L019skip_copy:\n\tmovl\t$16,%edi\n.align\t4\n.L020prefetch_tbl:\n\tmovl\t(%ebp),%eax\n\tmovl\t32(%ebp),%ebx\n\tmovl\t64(%ebp),%ecx\n\tmovl\t96(%ebp),%esi\n\tleal\t128(%ebp),%ebp\n\tsubl\t$1,%edi\n\tjnz\t.L020prefetch_tbl\n\tsubl\t$2048,%ebp\n\tmovl\t32(%esp),%esi\n\tmovl\t48(%esp),%edi\n\tcmpl\t$0,%edx\n\tje\t.L021fast_decrypt\n\tmovl\t(%edi),%eax\n\tmovl\t4(%edi),%ebx\n.align\t16\n.L022fast_enc_loop:\n\tmovl\t8(%edi),%ecx\n\tmovl\t12(%edi),%edx\n\txorl\t(%esi),%eax\n\txorl\t4(%esi),%ebx\n\txorl\t8(%esi),%ecx\n\txorl\t12(%esi),%edx\n\tmovl\t44(%esp),%edi\n\tcall\t_x86_AES_encrypt\n\tmovl\t32(%esp),%esi\n\tmovl\t36(%esp),%edi\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tleal\t16(%esi),%esi\n\tmovl\t40(%esp),%ecx\n\tmovl\t%esi,32(%esp)\n\tleal\t16(%edi),%edx\n\tmovl\t%edx,36(%esp)\n\tsubl\t$16,%ecx\n\tmovl\t%ecx,40(%esp)\n\tjnz\t.L022fast_enc_loop\n\tmovl\t48(%esp),%esi\n\tmovl\t8(%edi),%ecx\n\tmovl\t12(%edi),%edx\n\tmovl\t%eax,(%esi)\n\tmovl\t%ebx,4(%esi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\tcmpl\t$0,316(%esp)\n\tmovl\t44(%esp),%edi\n\tje\t.L023skip_ezero\n\tmovl\t$60,%ecx\n\txorl\t%eax,%eax\n.align\t4\n.long\t2884892297\n.L023skip_ezero:\n\tmovl\t28(%esp),%esp\n\tpopfl\n.L012drop_out:\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n\tpushfl\n.align\t16\n.L021fast_decrypt:\n\tcmpl\t36(%esp),%esi\n\tje\t.L024fast_dec_in_place\n\tmovl\t%edi,52(%esp)\n.align\t4\n.align\t16\n.L025fast_dec_loop:\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tmovl\t44(%esp),%edi\n\tcall\t_x86_AES_decrypt\n\tmovl\t52(%esp),%edi\n\tmovl\t40(%esp),%esi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tmovl\t36(%esp),%edi\n\tmovl\t32(%esp),%esi\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t40(%esp),%ecx\n\tmovl\t%esi,52(%esp)\n\tleal\t16(%esi),%esi\n\tmovl\t%esi,32(%esp)\n\tleal\t16(%edi),%edi\n\tmovl\t%edi,36(%esp)\n\tsubl\t$16,%ecx\n\tmovl\t%ecx,40(%esp)\n\tjnz\t.L025fast_dec_loop\n\tmovl\t52(%esp),%edi\n\tmovl\t48(%esp),%esi\n\tmovl\t(%edi),%eax\n\tmovl\t4(%edi),%ebx\n\tmovl\t8(%edi),%ecx\n\tmovl\t12(%edi),%edx\n\tmovl\t%eax,(%esi)\n\tmovl\t%ebx,4(%esi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\tjmp\t.L026fast_dec_out\n.align\t16\n.L024fast_dec_in_place:\n.L027fast_dec_in_place_loop:\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tleal\t60(%esp),%edi\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t44(%esp),%edi\n\tcall\t_x86_AES_decrypt\n\tmovl\t48(%esp),%edi\n\tmovl\t36(%esp),%esi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tmovl\t%eax,(%esi)\n\tmovl\t%ebx,4(%esi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\tleal\t16(%esi),%esi\n\tmovl\t%esi,36(%esp)\n\tleal\t60(%esp),%esi\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t32(%esp),%esi\n\tmovl\t40(%esp),%ecx\n\tleal\t16(%esi),%esi\n\tmovl\t%esi,32(%esp)\n\tsubl\t$16,%ecx\n\tmovl\t%ecx,40(%esp)\n\tjnz\t.L027fast_dec_in_place_loop\n.align\t4\n.L026fast_dec_out:\n\tcmpl\t$0,316(%esp)\n\tmovl\t44(%esp),%edi\n\tje\t.L028skip_dzero\n\tmovl\t$60,%ecx\n\txorl\t%eax,%eax\n.align\t4\n.long\t2884892297\n.L028skip_dzero:\n\tmovl\t28(%esp),%esp\n\tpopfl\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n\tpushfl\n.align\t16\n.L015slow_way:\n\tmovl\t(%eax),%eax\n\tmovl\t36(%esp),%edi\n\tleal\t-80(%esp),%esi\n\tandl\t$-64,%esi\n\tleal\t-143(%edi),%ebx\n\tsubl\t%esi,%ebx\n\tnegl\t%ebx\n\tandl\t$960,%ebx\n\tsubl\t%ebx,%esi\n\tleal\t768(%esi),%ebx\n\tsubl\t%ebp,%ebx\n\tandl\t$768,%ebx\n\tleal\t2176(%ebp,%ebx,1),%ebp\n\tleal\t24(%esp),%edx\n\txchgl\t%esi,%esp\n\taddl\t$4,%esp\n\tmovl\t%ebp,24(%esp)\n\tmovl\t%esi,28(%esp)\n\tmovl\t%eax,52(%esp)\n\tmovl\t(%edx),%eax\n\tmovl\t4(%edx),%ebx\n\tmovl\t16(%edx),%esi\n\tmovl\t20(%edx),%edx\n\tmovl\t%eax,32(%esp)\n\tmovl\t%ebx,36(%esp)\n\tmovl\t%ecx,40(%esp)\n\tmovl\t%edi,44(%esp)\n\tmovl\t%esi,48(%esp)\n\tmovl\t%esi,%edi\n\tmovl\t%eax,%esi\n\tcmpl\t$0,%edx\n\tje\t.L029slow_decrypt\n\tcmpl\t$16,%ecx\n\tmovl\t%ebx,%edx\n\tjb\t.L030slow_enc_tail\n\tbtl\t$25,52(%esp)\n\tjnc\t.L031slow_enc_x86\n\tmovq\t(%edi),%mm0\n\tmovq\t8(%edi),%mm4\n.align\t16\n.L032slow_enc_loop_sse:\n\tpxor\t(%esi),%mm0\n\tpxor\t8(%esi),%mm4\n\tmovl\t44(%esp),%edi\n\tcall\t_sse_AES_encrypt_compact\n\tmovl\t32(%esp),%esi\n\tmovl\t36(%esp),%edi\n\tmovl\t40(%esp),%ecx\n\tmovq\t%mm0,(%edi)\n\tmovq\t%mm4,8(%edi)\n\tleal\t16(%esi),%esi\n\tmovl\t%esi,32(%esp)\n\tleal\t16(%edi),%edx\n\tmovl\t%edx,36(%esp)\n\tsubl\t$16,%ecx\n\tcmpl\t$16,%ecx\n\tmovl\t%ecx,40(%esp)\n\tjae\t.L032slow_enc_loop_sse\n\ttestl\t$15,%ecx\n\tjnz\t.L030slow_enc_tail\n\tmovl\t48(%esp),%esi\n\tmovq\t%mm0,(%esi)\n\tmovq\t%mm4,8(%esi)\n\temms\n\tmovl\t28(%esp),%esp\n\tpopfl\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n\tpushfl\n.align\t16\n.L031slow_enc_x86:\n\tmovl\t(%edi),%eax\n\tmovl\t4(%edi),%ebx\n.align\t4\n.L033slow_enc_loop_x86:\n\tmovl\t8(%edi),%ecx\n\tmovl\t12(%edi),%edx\n\txorl\t(%esi),%eax\n\txorl\t4(%esi),%ebx\n\txorl\t8(%esi),%ecx\n\txorl\t12(%esi),%edx\n\tmovl\t44(%esp),%edi\n\tcall\t_x86_AES_encrypt_compact\n\tmovl\t32(%esp),%esi\n\tmovl\t36(%esp),%edi\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t40(%esp),%ecx\n\tleal\t16(%esi),%esi\n\tmovl\t%esi,32(%esp)\n\tleal\t16(%edi),%edx\n\tmovl\t%edx,36(%esp)\n\tsubl\t$16,%ecx\n\tcmpl\t$16,%ecx\n\tmovl\t%ecx,40(%esp)\n\tjae\t.L033slow_enc_loop_x86\n\ttestl\t$15,%ecx\n\tjnz\t.L030slow_enc_tail\n\tmovl\t48(%esp),%esi\n\tmovl\t8(%edi),%ecx\n\tmovl\t12(%edi),%edx\n\tmovl\t%eax,(%esi)\n\tmovl\t%ebx,4(%esi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\tmovl\t28(%esp),%esp\n\tpopfl\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n\tpushfl\n.align\t16\n.L030slow_enc_tail:\n\temms\n\tmovl\t%edx,%edi\n\tmovl\t$16,%ebx\n\tsubl\t%ecx,%ebx\n\tcmpl\t%esi,%edi\n\tje\t.L034enc_in_place\n.align\t4\n.long\t2767451785\n\tjmp\t.L035enc_skip_in_place\n.L034enc_in_place:\n\tleal\t(%edi,%ecx,1),%edi\n.L035enc_skip_in_place:\n\tmovl\t%ebx,%ecx\n\txorl\t%eax,%eax\n.align\t4\n.long\t2868115081\n\tmovl\t48(%esp),%edi\n\tmovl\t%edx,%esi\n\tmovl\t(%edi),%eax\n\tmovl\t4(%edi),%ebx\n\tmovl\t$16,40(%esp)\n\tjmp\t.L033slow_enc_loop_x86\n.align\t16\n.L029slow_decrypt:\n\tbtl\t$25,52(%esp)\n\tjnc\t.L036slow_dec_loop_x86\n.align\t4\n.L037slow_dec_loop_sse:\n\tmovq\t(%esi),%mm0\n\tmovq\t8(%esi),%mm4\n\tmovl\t44(%esp),%edi\n\tcall\t_sse_AES_decrypt_compact\n\tmovl\t32(%esp),%esi\n\tleal\t60(%esp),%eax\n\tmovl\t36(%esp),%ebx\n\tmovl\t40(%esp),%ecx\n\tmovl\t48(%esp),%edi\n\tmovq\t(%esi),%mm1\n\tmovq\t8(%esi),%mm5\n\tpxor\t(%edi),%mm0\n\tpxor\t8(%edi),%mm4\n\tmovq\t%mm1,(%edi)\n\tmovq\t%mm5,8(%edi)\n\tsubl\t$16,%ecx\n\tjc\t.L038slow_dec_partial_sse\n\tmovq\t%mm0,(%ebx)\n\tmovq\t%mm4,8(%ebx)\n\tleal\t16(%ebx),%ebx\n\tmovl\t%ebx,36(%esp)\n\tleal\t16(%esi),%esi\n\tmovl\t%esi,32(%esp)\n\tmovl\t%ecx,40(%esp)\n\tjnz\t.L037slow_dec_loop_sse\n\temms\n\tmovl\t28(%esp),%esp\n\tpopfl\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n\tpushfl\n.align\t16\n.L038slow_dec_partial_sse:\n\tmovq\t%mm0,(%eax)\n\tmovq\t%mm4,8(%eax)\n\temms\n\taddl\t$16,%ecx\n\tmovl\t%ebx,%edi\n\tmovl\t%eax,%esi\n.align\t4\n.long\t2767451785\n\tmovl\t28(%esp),%esp\n\tpopfl\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n\tpushfl\n.align\t16\n.L036slow_dec_loop_x86:\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tleal\t60(%esp),%edi\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t44(%esp),%edi\n\tcall\t_x86_AES_decrypt_compact\n\tmovl\t48(%esp),%edi\n\tmovl\t40(%esp),%esi\n\txorl\t(%edi),%eax\n\txorl\t4(%edi),%ebx\n\txorl\t8(%edi),%ecx\n\txorl\t12(%edi),%edx\n\tsubl\t$16,%esi\n\tjc\t.L039slow_dec_partial_x86\n\tmovl\t%esi,40(%esp)\n\tmovl\t36(%esp),%esi\n\tmovl\t%eax,(%esi)\n\tmovl\t%ebx,4(%esi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\tleal\t16(%esi),%esi\n\tmovl\t%esi,36(%esp)\n\tleal\t60(%esp),%esi\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t32(%esp),%esi\n\tleal\t16(%esi),%esi\n\tmovl\t%esi,32(%esp)\n\tjnz\t.L036slow_dec_loop_x86\n\tmovl\t28(%esp),%esp\n\tpopfl\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n\tpushfl\n.align\t16\n.L039slow_dec_partial_x86:\n\tleal\t60(%esp),%esi\n\tmovl\t%eax,(%esi)\n\tmovl\t%ebx,4(%esi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\tmovl\t32(%esp),%esi\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t40(%esp),%ecx\n\tmovl\t36(%esp),%edi\n\tleal\t60(%esp),%esi\n.align\t4\n.long\t2767451785\n\tmovl\t28(%esp),%esp\n\tpopfl\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n.size\tAES_cbc_encrypt,.-.L_AES_cbc_encrypt_begin\n.type\t_x86_AES_set_encrypt_key,@function\n.align\t16\n_x86_AES_set_encrypt_key:\n\tpushl\t%ebp\n\tpushl\t%ebx\n\tpushl\t%esi\n\tpushl\t%edi\n\tmovl\t24(%esp),%esi\n\tmovl\t32(%esp),%edi\n\ttestl\t$-1,%esi\n\tjz\t.L040badpointer\n\ttestl\t$-1,%edi\n\tjz\t.L040badpointer\n\tcall\t.L041pic_point\n.L041pic_point:\n\tpopl\t%ebp\n\tleal\t.LAES_Te-.L041pic_point(%ebp),%ebp\n\tleal\t2176(%ebp),%ebp\n\tmovl\t-128(%ebp),%eax\n\tmovl\t-96(%ebp),%ebx\n\tmovl\t-64(%ebp),%ecx\n\tmovl\t-32(%ebp),%edx\n\tmovl\t(%ebp),%eax\n\tmovl\t32(%ebp),%ebx\n\tmovl\t64(%ebp),%ecx\n\tmovl\t96(%ebp),%edx\n\tmovl\t28(%esp),%ecx\n\tcmpl\t$128,%ecx\n\tje\t.L04210rounds\n\tcmpl\t$192,%ecx\n\tje\t.L04312rounds\n\tcmpl\t$256,%ecx\n\tje\t.L04414rounds\n\tmovl\t$-2,%eax\n\tjmp\t.L045exit\n.L04210rounds:\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\txorl\t%ecx,%ecx\n\tjmp\t.L04610shortcut\n.align\t4\n.L04710loop:\n\tmovl\t(%edi),%eax\n\tmovl\t12(%edi),%edx\n.L04610shortcut:\n\tmovzbl\t%dl,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tmovzbl\t%dh,%esi\n\tshll\t$24,%ebx\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tshrl\t$16,%edx\n\tmovzbl\t%dl,%esi\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tmovzbl\t%dh,%esi\n\tshll\t$8,%ebx\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tshll\t$16,%ebx\n\txorl\t%ebx,%eax\n\txorl\t896(%ebp,%ecx,4),%eax\n\tmovl\t%eax,16(%edi)\n\txorl\t4(%edi),%eax\n\tmovl\t%eax,20(%edi)\n\txorl\t8(%edi),%eax\n\tmovl\t%eax,24(%edi)\n\txorl\t12(%edi),%eax\n\tmovl\t%eax,28(%edi)\n\tincl\t%ecx\n\taddl\t$16,%edi\n\tcmpl\t$10,%ecx\n\tjl\t.L04710loop\n\tmovl\t$10,80(%edi)\n\txorl\t%eax,%eax\n\tjmp\t.L045exit\n.L04312rounds:\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t16(%esi),%ecx\n\tmovl\t20(%esi),%edx\n\tmovl\t%ecx,16(%edi)\n\tmovl\t%edx,20(%edi)\n\txorl\t%ecx,%ecx\n\tjmp\t.L04812shortcut\n.align\t4\n.L04912loop:\n\tmovl\t(%edi),%eax\n\tmovl\t20(%edi),%edx\n.L04812shortcut:\n\tmovzbl\t%dl,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tmovzbl\t%dh,%esi\n\tshll\t$24,%ebx\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tshrl\t$16,%edx\n\tmovzbl\t%dl,%esi\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tmovzbl\t%dh,%esi\n\tshll\t$8,%ebx\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tshll\t$16,%ebx\n\txorl\t%ebx,%eax\n\txorl\t896(%ebp,%ecx,4),%eax\n\tmovl\t%eax,24(%edi)\n\txorl\t4(%edi),%eax\n\tmovl\t%eax,28(%edi)\n\txorl\t8(%edi),%eax\n\tmovl\t%eax,32(%edi)\n\txorl\t12(%edi),%eax\n\tmovl\t%eax,36(%edi)\n\tcmpl\t$7,%ecx\n\tje\t.L05012break\n\tincl\t%ecx\n\txorl\t16(%edi),%eax\n\tmovl\t%eax,40(%edi)\n\txorl\t20(%edi),%eax\n\tmovl\t%eax,44(%edi)\n\taddl\t$24,%edi\n\tjmp\t.L04912loop\n.L05012break:\n\tmovl\t$12,72(%edi)\n\txorl\t%eax,%eax\n\tjmp\t.L045exit\n.L04414rounds:\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t8(%esi),%ecx\n\tmovl\t12(%esi),%edx\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,8(%edi)\n\tmovl\t%edx,12(%edi)\n\tmovl\t16(%esi),%eax\n\tmovl\t20(%esi),%ebx\n\tmovl\t24(%esi),%ecx\n\tmovl\t28(%esi),%edx\n\tmovl\t%eax,16(%edi)\n\tmovl\t%ebx,20(%edi)\n\tmovl\t%ecx,24(%edi)\n\tmovl\t%edx,28(%edi)\n\txorl\t%ecx,%ecx\n\tjmp\t.L05114shortcut\n.align\t4\n.L05214loop:\n\tmovl\t28(%edi),%edx\n.L05114shortcut:\n\tmovl\t(%edi),%eax\n\tmovzbl\t%dl,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tmovzbl\t%dh,%esi\n\tshll\t$24,%ebx\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tshrl\t$16,%edx\n\tmovzbl\t%dl,%esi\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tmovzbl\t%dh,%esi\n\tshll\t$8,%ebx\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tshll\t$16,%ebx\n\txorl\t%ebx,%eax\n\txorl\t896(%ebp,%ecx,4),%eax\n\tmovl\t%eax,32(%edi)\n\txorl\t4(%edi),%eax\n\tmovl\t%eax,36(%edi)\n\txorl\t8(%edi),%eax\n\tmovl\t%eax,40(%edi)\n\txorl\t12(%edi),%eax\n\tmovl\t%eax,44(%edi)\n\tcmpl\t$6,%ecx\n\tje\t.L05314break\n\tincl\t%ecx\n\tmovl\t%eax,%edx\n\tmovl\t16(%edi),%eax\n\tmovzbl\t%dl,%esi\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tmovzbl\t%dh,%esi\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tshrl\t$16,%edx\n\tshll\t$8,%ebx\n\tmovzbl\t%dl,%esi\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tmovzbl\t%dh,%esi\n\tshll\t$16,%ebx\n\txorl\t%ebx,%eax\n\tmovzbl\t-128(%ebp,%esi,1),%ebx\n\tshll\t$24,%ebx\n\txorl\t%ebx,%eax\n\tmovl\t%eax,48(%edi)\n\txorl\t20(%edi),%eax\n\tmovl\t%eax,52(%edi)\n\txorl\t24(%edi),%eax\n\tmovl\t%eax,56(%edi)\n\txorl\t28(%edi),%eax\n\tmovl\t%eax,60(%edi)\n\taddl\t$32,%edi\n\tjmp\t.L05214loop\n.L05314break:\n\tmovl\t$14,48(%edi)\n\txorl\t%eax,%eax\n\tjmp\t.L045exit\n.L040badpointer:\n\tmovl\t$-1,%eax\n.L045exit:\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n.size\t_x86_AES_set_encrypt_key,.-_x86_AES_set_encrypt_key\n.globl\tAES_set_encrypt_key\n.type\tAES_set_encrypt_key,@function\n.align\t16\nAES_set_encrypt_key:\n.L_AES_set_encrypt_key_begin:\n\tcall\t_x86_AES_set_encrypt_key\n\tret\n.size\tAES_set_encrypt_key,.-.L_AES_set_encrypt_key_begin\n.globl\tAES_set_decrypt_key\n.type\tAES_set_decrypt_key,@function\n.align\t16\nAES_set_decrypt_key:\n.L_AES_set_decrypt_key_begin:\n\tcall\t_x86_AES_set_encrypt_key\n\tcmpl\t$0,%eax\n\tje\t.L054proceed\n\tret\n.L054proceed:\n\tpushl\t%ebp\n\tpushl\t%ebx\n\tpushl\t%esi\n\tpushl\t%edi\n\tmovl\t28(%esp),%esi\n\tmovl\t240(%esi),%ecx\n\tleal\t(,%ecx,4),%ecx\n\tleal\t(%esi,%ecx,4),%edi\n.align\t4\n.L055invert:\n\tmovl\t(%esi),%eax\n\tmovl\t4(%esi),%ebx\n\tmovl\t(%edi),%ecx\n\tmovl\t4(%edi),%edx\n\tmovl\t%eax,(%edi)\n\tmovl\t%ebx,4(%edi)\n\tmovl\t%ecx,(%esi)\n\tmovl\t%edx,4(%esi)\n\tmovl\t8(%esi),%eax\n\tmovl\t12(%esi),%ebx\n\tmovl\t8(%edi),%ecx\n\tmovl\t12(%edi),%edx\n\tmovl\t%eax,8(%edi)\n\tmovl\t%ebx,12(%edi)\n\tmovl\t%ecx,8(%esi)\n\tmovl\t%edx,12(%esi)\n\taddl\t$16,%esi\n\tsubl\t$16,%edi\n\tcmpl\t%edi,%esi\n\tjne\t.L055invert\n\tmovl\t28(%esp),%edi\n\tmovl\t240(%edi),%esi\n\tleal\t-2(%esi,%esi,1),%esi\n\tleal\t(%edi,%esi,8),%esi\n\tmovl\t%esi,28(%esp)\n\tmovl\t16(%edi),%eax\n.align\t4\n.L056permute:\n\taddl\t$16,%edi\n\tmovl\t$2155905152,%ebp\n\tandl\t%eax,%ebp\n\tleal\t(%eax,%eax,1),%ebx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%ebx\n\tandl\t$454761243,%esi\n\txorl\t%esi,%ebx\n\tmovl\t$2155905152,%ebp\n\tandl\t%ebx,%ebp\n\tleal\t(%ebx,%ebx,1),%ecx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%ecx\n\tandl\t$454761243,%esi\n\txorl\t%eax,%ebx\n\txorl\t%esi,%ecx\n\tmovl\t$2155905152,%ebp\n\tandl\t%ecx,%ebp\n\tleal\t(%ecx,%ecx,1),%edx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\txorl\t%eax,%ecx\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%edx\n\tandl\t$454761243,%esi\n\troll\t$8,%eax\n\txorl\t%esi,%edx\n\tmovl\t4(%edi),%ebp\n\txorl\t%ebx,%eax\n\txorl\t%edx,%ebx\n\txorl\t%ecx,%eax\n\troll\t$24,%ebx\n\txorl\t%edx,%ecx\n\txorl\t%edx,%eax\n\troll\t$16,%ecx\n\txorl\t%ebx,%eax\n\troll\t$8,%edx\n\txorl\t%ecx,%eax\n\tmovl\t%ebp,%ebx\n\txorl\t%edx,%eax\n\tmovl\t%eax,(%edi)\n\tmovl\t$2155905152,%ebp\n\tandl\t%ebx,%ebp\n\tleal\t(%ebx,%ebx,1),%ecx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%ecx\n\tandl\t$454761243,%esi\n\txorl\t%esi,%ecx\n\tmovl\t$2155905152,%ebp\n\tandl\t%ecx,%ebp\n\tleal\t(%ecx,%ecx,1),%edx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%edx\n\tandl\t$454761243,%esi\n\txorl\t%ebx,%ecx\n\txorl\t%esi,%edx\n\tmovl\t$2155905152,%ebp\n\tandl\t%edx,%ebp\n\tleal\t(%edx,%edx,1),%eax\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\txorl\t%ebx,%edx\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%eax\n\tandl\t$454761243,%esi\n\troll\t$8,%ebx\n\txorl\t%esi,%eax\n\tmovl\t8(%edi),%ebp\n\txorl\t%ecx,%ebx\n\txorl\t%eax,%ecx\n\txorl\t%edx,%ebx\n\troll\t$24,%ecx\n\txorl\t%eax,%edx\n\txorl\t%eax,%ebx\n\troll\t$16,%edx\n\txorl\t%ecx,%ebx\n\troll\t$8,%eax\n\txorl\t%edx,%ebx\n\tmovl\t%ebp,%ecx\n\txorl\t%eax,%ebx\n\tmovl\t%ebx,4(%edi)\n\tmovl\t$2155905152,%ebp\n\tandl\t%ecx,%ebp\n\tleal\t(%ecx,%ecx,1),%edx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%edx\n\tandl\t$454761243,%esi\n\txorl\t%esi,%edx\n\tmovl\t$2155905152,%ebp\n\tandl\t%edx,%ebp\n\tleal\t(%edx,%edx,1),%eax\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%eax\n\tandl\t$454761243,%esi\n\txorl\t%ecx,%edx\n\txorl\t%esi,%eax\n\tmovl\t$2155905152,%ebp\n\tandl\t%eax,%ebp\n\tleal\t(%eax,%eax,1),%ebx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\txorl\t%ecx,%eax\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%ebx\n\tandl\t$454761243,%esi\n\troll\t$8,%ecx\n\txorl\t%esi,%ebx\n\tmovl\t12(%edi),%ebp\n\txorl\t%edx,%ecx\n\txorl\t%ebx,%edx\n\txorl\t%eax,%ecx\n\troll\t$24,%edx\n\txorl\t%ebx,%eax\n\txorl\t%ebx,%ecx\n\troll\t$16,%eax\n\txorl\t%edx,%ecx\n\troll\t$8,%ebx\n\txorl\t%eax,%ecx\n\tmovl\t%ebp,%edx\n\txorl\t%ebx,%ecx\n\tmovl\t%ecx,8(%edi)\n\tmovl\t$2155905152,%ebp\n\tandl\t%edx,%ebp\n\tleal\t(%edx,%edx,1),%eax\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%eax\n\tandl\t$454761243,%esi\n\txorl\t%esi,%eax\n\tmovl\t$2155905152,%ebp\n\tandl\t%eax,%ebp\n\tleal\t(%eax,%eax,1),%ebx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%ebx\n\tandl\t$454761243,%esi\n\txorl\t%edx,%eax\n\txorl\t%esi,%ebx\n\tmovl\t$2155905152,%ebp\n\tandl\t%ebx,%ebp\n\tleal\t(%ebx,%ebx,1),%ecx\n\tmovl\t%ebp,%esi\n\tshrl\t$7,%ebp\n\txorl\t%edx,%ebx\n\tsubl\t%ebp,%esi\n\tandl\t$4278124286,%ecx\n\tandl\t$454761243,%esi\n\troll\t$8,%edx\n\txorl\t%esi,%ecx\n\tmovl\t16(%edi),%ebp\n\txorl\t%eax,%edx\n\txorl\t%ecx,%eax\n\txorl\t%ebx,%edx\n\troll\t$24,%eax\n\txorl\t%ecx,%ebx\n\txorl\t%ecx,%edx\n\troll\t$16,%ebx\n\txorl\t%eax,%edx\n\troll\t$8,%ecx\n\txorl\t%ebx,%edx\n\tmovl\t%ebp,%eax\n\txorl\t%ecx,%edx\n\tmovl\t%edx,12(%edi)\n\tcmpl\t28(%esp),%edi\n\tjb\t.L056permute\n\txorl\t%eax,%eax\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tpopl\t%ebp\n\tret\n.size\tAES_set_decrypt_key,.-.L_AES_set_decrypt_key_begin\n.byte\t65,69,83,32,102,111,114,32,120,56,54,44,32,67,82,89\n.byte\t80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114\n.byte\t111,64,111,112,101,110,115,115,108,46,111,114,103,62,0\n.comm\tOPENSSL_ia32cap_P,16,4\n"
  },
  {
    "path": "lib/aes_faster_c/aes.cpp",
    "content": "/*\n *  FIPS-197 compliant AES implementation\n *\n *  Copyright (C) 2006-2014, Brainspark B.V.\n *\n *  This file is part of PolarSSL (http://www.polarssl.org)\n *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>\n *\n *  All rights reserved.\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License along\n *  with this program; if not, write to the Free Software Foundation, Inc.,\n *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n */\n/*\n *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.\n *\n *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf\n *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf\n */\n\n/*\n#if !defined(POLARSSL_CONFIG_FILE)\n#include \"polarssl/config.h\"\n#else\n#include POLARSSL_CONFIG_FILE\n#endif\n*/\n//#if defined(POLARSSL_AES_C)\n\n\n#include \"aes.h\"\n/*\n#if defined(POLARSSL_PADLOCK_C)\n#include \"polarssl/padlock.h\"\n#endif\n#if defined(POLARSSL_AESNI_C)\n#include \"polarssl/aesni.h\"\n#endif\n\n#if defined(POLARSSL_PLATFORM_C)\n#include \"polarssl/platform.h\"\n#else\n#define polarssl_printf printf\n#endif\n*/\n\n#if !defined(POLARSSL_AES_ALT)\n\n/* Implementation that should never be optimized out by the compiler */\nstatic void polarssl_zeroize( void *v, size_t n ) {\n    volatile unsigned char *p = (unsigned char *)v; while( n-- ) *p++ = 0;\n}\n\n/*\n * 32-bit integer manipulation macros (little endian)\n */\n#ifndef GET_UINT32_LE\n#define GET_UINT32_LE(n,b,i)                            \\\n{                                                       \\\n    (n) = ( (uint32_t) (b)[(i)    ]       )             \\\n        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \\\n        | ( (uint32_t) (b)[(i) + 2] << 16 )             \\\n        | ( (uint32_t) (b)[(i) + 3] << 24 );            \\\n}\n#endif\n\n#ifndef PUT_UINT32_LE\n#define PUT_UINT32_LE(n,b,i)                            \\\n{                                                       \\\n    (b)[(i)    ] = (unsigned char) ( (n)       );       \\\n    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \\\n    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \\\n    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \\\n}\n#endif\n\n#if defined(POLARSSL_PADLOCK_C) &&                      \\\n    ( defined(POLARSSL_HAVE_X86) || defined(PADLOCK_ALIGN16) )\nstatic int aes_padlock_ace = -1;\n#endif\n\n#if defined(POLARSSL_AES_ROM_TABLES)\n/*\n * Forward S-box\n */\nstatic const unsigned char FSb[256] =\n{\n    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,\n    0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,\n    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,\n    0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,\n    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,\n    0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,\n    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,\n    0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,\n    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,\n    0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,\n    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,\n    0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,\n    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,\n    0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,\n    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,\n    0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,\n    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,\n    0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,\n    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,\n    0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,\n    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,\n    0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,\n    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,\n    0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,\n    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,\n    0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,\n    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,\n    0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,\n    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,\n    0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,\n    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,\n    0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16\n};\n\n/*\n * Forward tables\n */\n#define FT \\\n\\\n    V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \\\n    V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \\\n    V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \\\n    V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \\\n    V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \\\n    V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \\\n    V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \\\n    V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \\\n    V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \\\n    V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \\\n    V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \\\n    V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \\\n    V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \\\n    V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \\\n    V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \\\n    V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \\\n    V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \\\n    V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \\\n    V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \\\n    V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \\\n    V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \\\n    V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \\\n    V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \\\n    V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \\\n    V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \\\n    V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \\\n    V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \\\n    V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \\\n    V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \\\n    V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \\\n    V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \\\n    V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \\\n    V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \\\n    V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \\\n    V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \\\n    V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \\\n    V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \\\n    V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \\\n    V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \\\n    V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \\\n    V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \\\n    V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \\\n    V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \\\n    V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \\\n    V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \\\n    V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \\\n    V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \\\n    V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \\\n    V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \\\n    V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \\\n    V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \\\n    V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \\\n    V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \\\n    V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \\\n    V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \\\n    V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \\\n    V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \\\n    V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \\\n    V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \\\n    V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \\\n    V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \\\n    V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \\\n    V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \\\n    V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)\n\n#define V(a,b,c,d) 0x##a##b##c##d\nstatic const uint32_t FT0[256] = { FT };\n#undef V\n\n#define V(a,b,c,d) 0x##b##c##d##a\nstatic const uint32_t FT1[256] = { FT };\n#undef V\n\n#define V(a,b,c,d) 0x##c##d##a##b\nstatic const uint32_t FT2[256] = { FT };\n#undef V\n\n#define V(a,b,c,d) 0x##d##a##b##c\nstatic const uint32_t FT3[256] = { FT };\n#undef V\n\n#undef FT\n\n/*\n * Reverse S-box\n */\nstatic const unsigned char RSb[256] =\n{\n    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,\n    0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,\n    0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,\n    0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,\n    0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,\n    0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,\n    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,\n    0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,\n    0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,\n    0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,\n    0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,\n    0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,\n    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,\n    0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,\n    0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,\n    0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,\n    0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,\n    0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,\n    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,\n    0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,\n    0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,\n    0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,\n    0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,\n    0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,\n    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,\n    0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,\n    0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,\n    0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,\n    0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,\n    0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,\n    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,\n    0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D\n};\n\n/*\n * Reverse tables\n */\n#define RT \\\n\\\n    V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \\\n    V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \\\n    V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \\\n    V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \\\n    V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \\\n    V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \\\n    V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \\\n    V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \\\n    V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \\\n    V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \\\n    V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \\\n    V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \\\n    V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \\\n    V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \\\n    V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \\\n    V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \\\n    V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \\\n    V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \\\n    V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \\\n    V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \\\n    V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \\\n    V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \\\n    V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \\\n    V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \\\n    V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \\\n    V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \\\n    V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \\\n    V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \\\n    V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \\\n    V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \\\n    V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \\\n    V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \\\n    V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \\\n    V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \\\n    V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \\\n    V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \\\n    V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \\\n    V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \\\n    V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \\\n    V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \\\n    V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \\\n    V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \\\n    V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \\\n    V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \\\n    V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \\\n    V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \\\n    V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \\\n    V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \\\n    V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \\\n    V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \\\n    V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \\\n    V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \\\n    V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \\\n    V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \\\n    V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \\\n    V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \\\n    V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \\\n    V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \\\n    V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \\\n    V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \\\n    V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \\\n    V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \\\n    V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \\\n    V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)\n\n#define V(a,b,c,d) 0x##a##b##c##d\nstatic const uint32_t RT0[256] = { RT };\n#undef V\n\n#define V(a,b,c,d) 0x##b##c##d##a\nstatic const uint32_t RT1[256] = { RT };\n#undef V\n\n#define V(a,b,c,d) 0x##c##d##a##b\nstatic const uint32_t RT2[256] = { RT };\n#undef V\n\n#define V(a,b,c,d) 0x##d##a##b##c\nstatic const uint32_t RT3[256] = { RT };\n#undef V\n\n#undef RT\n\n/*\n * Round constants\n */\nstatic const uint32_t RCON[10] =\n{\n    0x00000001, 0x00000002, 0x00000004, 0x00000008,\n    0x00000010, 0x00000020, 0x00000040, 0x00000080,\n    0x0000001B, 0x00000036\n};\n\n#else /* POLARSSL_AES_ROM_TABLES */\n\n/*\n * Forward S-box & tables\n */\nstatic unsigned char FSb[256];\nstatic uint32_t FT0[256];\nstatic uint32_t FT1[256];\nstatic uint32_t FT2[256];\nstatic uint32_t FT3[256];\n\n/*\n * Reverse S-box & tables\n */\nstatic unsigned char RSb[256];\nstatic uint32_t RT0[256];\nstatic uint32_t RT1[256];\nstatic uint32_t RT2[256];\nstatic uint32_t RT3[256];\n\n/*\n * Round constants\n */\nstatic uint32_t RCON[10];\n\n/*\n * Tables generation code\n */\n#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )\n#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )\n#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )\n\nstatic int aes_init_done = 0;\n\nstatic void aes_gen_tables( void )\n{\n    int i, x, y, z;\n    int pow[256];\n    int log[256];\n\n    /*\n     * compute pow and log tables over GF(2^8)\n     */\n    for( i = 0, x = 1; i < 256; i++ )\n    {\n        pow[i] = x;\n        log[x] = i;\n        x = ( x ^ XTIME( x ) ) & 0xFF;\n    }\n\n    /*\n     * calculate the round constants\n     */\n    for( i = 0, x = 1; i < 10; i++ )\n    {\n        RCON[i] = (uint32_t) x;\n        x = XTIME( x ) & 0xFF;\n    }\n\n    /*\n     * generate the forward and reverse S-boxes\n     */\n    FSb[0x00] = 0x63;\n    RSb[0x63] = 0x00;\n\n    for( i = 1; i < 256; i++ )\n    {\n        x = pow[255 - log[i]];\n\n        y  = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;\n        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;\n        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;\n        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;\n        x ^= y ^ 0x63;\n\n        FSb[i] = (unsigned char) x;\n        RSb[x] = (unsigned char) i;\n    }\n\n    /*\n     * generate the forward and reverse tables\n     */\n    for( i = 0; i < 256; i++ )\n    {\n        x = FSb[i];\n        y = XTIME( x ) & 0xFF;\n        z =  ( y ^ x ) & 0xFF;\n\n        FT0[i] = ( (uint32_t) y       ) ^\n                 ( (uint32_t) x <<  8 ) ^\n                 ( (uint32_t) x << 16 ) ^\n                 ( (uint32_t) z << 24 );\n\n        FT1[i] = ROTL8( FT0[i] );\n        FT2[i] = ROTL8( FT1[i] );\n        FT3[i] = ROTL8( FT2[i] );\n\n        x = RSb[i];\n\n        RT0[i] = ( (uint32_t) MUL( 0x0E, x )       ) ^\n                 ( (uint32_t) MUL( 0x09, x ) <<  8 ) ^\n                 ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^\n                 ( (uint32_t) MUL( 0x0B, x ) << 24 );\n\n        RT1[i] = ROTL8( RT0[i] );\n        RT2[i] = ROTL8( RT1[i] );\n        RT3[i] = ROTL8( RT2[i] );\n    }\n}\n\n#endif /* POLARSSL_AES_ROM_TABLES */\n\nvoid aes_init( aes_context *ctx )\n{\n    memset( ctx, 0, sizeof( aes_context ) );\n}\n\nvoid aes_free( aes_context *ctx )\n{\n    if( ctx == NULL )\n        return;\n\n    polarssl_zeroize( ctx, sizeof( aes_context ) );\n}\n\n/*\n * AES key schedule (encryption)\n */\nint aes_setkey_enc( aes_context *ctx, const unsigned char *key,\n                    unsigned int keysize )\n{\n    unsigned int i;\n    uint32_t *RK;\n\n#if !defined(POLARSSL_AES_ROM_TABLES)\n    if( aes_init_done == 0 )\n    {\n        aes_gen_tables();\n        aes_init_done = 1;\n\n    }\n#endif\n\n    switch( keysize )\n    {\n        case 128: ctx->nr = 10; break;\n        case 192: ctx->nr = 12; break;\n        case 256: ctx->nr = 14; break;\n        default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );\n    }\n\n#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)\n    if( aes_padlock_ace == -1 )\n        aes_padlock_ace = padlock_supports( PADLOCK_ACE );\n\n    if( aes_padlock_ace )\n        ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );\n    else\n#endif\n    ctx->rk = RK = ctx->buf;\n\n#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)\n    if( aesni_supports( POLARSSL_AESNI_AES ) )\n        return( aesni_setkey_enc( (unsigned char *) ctx->rk, key, keysize ) );\n#endif\n\n    for( i = 0; i < ( keysize >> 5 ); i++ )\n    {\n        GET_UINT32_LE( RK[i], key, i << 2 );\n    }\n\n    switch( ctx->nr )\n    {\n        case 10:\n\n            for( i = 0; i < 10; i++, RK += 4 )\n            {\n                RK[4]  = RK[0] ^ RCON[i] ^\n                ( (uint32_t) FSb[ ( RK[3] >>  8 ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( RK[3]       ) & 0xFF ] << 24 );\n\n                RK[5]  = RK[1] ^ RK[4];\n                RK[6]  = RK[2] ^ RK[5];\n                RK[7]  = RK[3] ^ RK[6];\n            }\n            break;\n\n        case 12:\n\n            for( i = 0; i < 8; i++, RK += 6 )\n            {\n                RK[6]  = RK[0] ^ RCON[i] ^\n                ( (uint32_t) FSb[ ( RK[5] >>  8 ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( RK[5]       ) & 0xFF ] << 24 );\n\n                RK[7]  = RK[1] ^ RK[6];\n                RK[8]  = RK[2] ^ RK[7];\n                RK[9]  = RK[3] ^ RK[8];\n                RK[10] = RK[4] ^ RK[9];\n                RK[11] = RK[5] ^ RK[10];\n            }\n            break;\n\n        case 14:\n\n            for( i = 0; i < 7; i++, RK += 8 )\n            {\n                RK[8]  = RK[0] ^ RCON[i] ^\n                ( (uint32_t) FSb[ ( RK[7] >>  8 ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( RK[7]       ) & 0xFF ] << 24 );\n\n                RK[9]  = RK[1] ^ RK[8];\n                RK[10] = RK[2] ^ RK[9];\n                RK[11] = RK[3] ^ RK[10];\n\n                RK[12] = RK[4] ^\n                ( (uint32_t) FSb[ ( RK[11]       ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( RK[11] >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );\n\n                RK[13] = RK[5] ^ RK[12];\n                RK[14] = RK[6] ^ RK[13];\n                RK[15] = RK[7] ^ RK[14];\n            }\n            break;\n    }\n\n    return( 0 );\n}\n\n/*\n * AES key schedule (decryption)\n */\nint aes_setkey_dec( aes_context *ctx, const unsigned char *key,\n                    unsigned int keysize )\n{\n    int i, j, ret;\n    aes_context cty;\n    uint32_t *RK;\n    uint32_t *SK;\n\n    aes_init( &cty );\n\n#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)\n    if( aes_padlock_ace == -1 )\n        aes_padlock_ace = padlock_supports( PADLOCK_ACE );\n\n    if( aes_padlock_ace )\n        ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );\n    else\n#endif\n    ctx->rk = RK = ctx->buf;\n\n    /* Also checks keysize */\n    if( ( ret = aes_setkey_enc( &cty, key, keysize ) ) != 0 )\n        goto exit;\n\n    ctx->nr = cty.nr;\n\n#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)\n    if( aesni_supports( POLARSSL_AESNI_AES ) )\n    {\n        aesni_inverse_key( (unsigned char *) ctx->rk,\n                           (const unsigned char *) cty.rk, ctx->nr );\n        goto exit;\n    }\n#endif\n\n    SK = cty.rk + cty.nr * 4;\n\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n\n    for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )\n    {\n        for( j = 0; j < 4; j++, SK++ )\n        {\n            *RK++ = RT0[ FSb[ ( *SK       ) & 0xFF ] ] ^\n                    RT1[ FSb[ ( *SK >>  8 ) & 0xFF ] ] ^\n                    RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^\n                    RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];\n        }\n    }\n\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n\nexit:\n    aes_free( &cty );\n\n    return( ret );\n}\n\n#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \\\n{                                               \\\n    X0 = *RK++ ^ FT0[ ( Y0       ) & 0xFF ] ^   \\\n                 FT1[ ( Y1 >>  8 ) & 0xFF ] ^   \\\n                 FT2[ ( Y2 >> 16 ) & 0xFF ] ^   \\\n                 FT3[ ( Y3 >> 24 ) & 0xFF ];    \\\n                                                \\\n    X1 = *RK++ ^ FT0[ ( Y1       ) & 0xFF ] ^   \\\n                 FT1[ ( Y2 >>  8 ) & 0xFF ] ^   \\\n                 FT2[ ( Y3 >> 16 ) & 0xFF ] ^   \\\n                 FT3[ ( Y0 >> 24 ) & 0xFF ];    \\\n                                                \\\n    X2 = *RK++ ^ FT0[ ( Y2       ) & 0xFF ] ^   \\\n                 FT1[ ( Y3 >>  8 ) & 0xFF ] ^   \\\n                 FT2[ ( Y0 >> 16 ) & 0xFF ] ^   \\\n                 FT3[ ( Y1 >> 24 ) & 0xFF ];    \\\n                                                \\\n    X3 = *RK++ ^ FT0[ ( Y3       ) & 0xFF ] ^   \\\n                 FT1[ ( Y0 >>  8 ) & 0xFF ] ^   \\\n                 FT2[ ( Y1 >> 16 ) & 0xFF ] ^   \\\n                 FT3[ ( Y2 >> 24 ) & 0xFF ];    \\\n}\n\n#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \\\n{                                               \\\n    X0 = *RK++ ^ RT0[ ( Y0       ) & 0xFF ] ^   \\\n                 RT1[ ( Y3 >>  8 ) & 0xFF ] ^   \\\n                 RT2[ ( Y2 >> 16 ) & 0xFF ] ^   \\\n                 RT3[ ( Y1 >> 24 ) & 0xFF ];    \\\n                                                \\\n    X1 = *RK++ ^ RT0[ ( Y1       ) & 0xFF ] ^   \\\n                 RT1[ ( Y0 >>  8 ) & 0xFF ] ^   \\\n                 RT2[ ( Y3 >> 16 ) & 0xFF ] ^   \\\n                 RT3[ ( Y2 >> 24 ) & 0xFF ];    \\\n                                                \\\n    X2 = *RK++ ^ RT0[ ( Y2       ) & 0xFF ] ^   \\\n                 RT1[ ( Y1 >>  8 ) & 0xFF ] ^   \\\n                 RT2[ ( Y0 >> 16 ) & 0xFF ] ^   \\\n                 RT3[ ( Y3 >> 24 ) & 0xFF ];    \\\n                                                \\\n    X3 = *RK++ ^ RT0[ ( Y3       ) & 0xFF ] ^   \\\n                 RT1[ ( Y2 >>  8 ) & 0xFF ] ^   \\\n                 RT2[ ( Y1 >> 16 ) & 0xFF ] ^   \\\n                 RT3[ ( Y0 >> 24 ) & 0xFF ];    \\\n}\n\n/*\n * AES-ECB block encryption/decryption\n */\nint aes_crypt_ecb( aes_context *ctx,\n                    int mode,\n                    const unsigned char input[16],\n                    unsigned char output[16] )\n{\n    int i;\n    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;\n\n#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)\n    if( aesni_supports( POLARSSL_AESNI_AES ) )\n        return( aesni_crypt_ecb( ctx, mode, input, output ) );\n#endif\n\n#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)\n    if( aes_padlock_ace )\n    {\n        if( padlock_xcryptecb( ctx, mode, input, output ) == 0 )\n            return( 0 );\n\n        // If padlock data misaligned, we just fall back to\n        // unaccelerated mode\n        //\n    }\n#endif\n\n    RK = ctx->rk;\n\n    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;\n    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;\n    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;\n    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;\n\n    if( mode == AES_DECRYPT )\n    {\n        for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )\n        {\n            AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );\n            AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );\n        }\n\n        AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );\n\n        X0 = *RK++ ^ \\\n                ( (uint32_t) RSb[ ( Y0       ) & 0xFF ]       ) ^\n                ( (uint32_t) RSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );\n\n        X1 = *RK++ ^ \\\n                ( (uint32_t) RSb[ ( Y1       ) & 0xFF ]       ) ^\n                ( (uint32_t) RSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );\n\n        X2 = *RK++ ^ \\\n                ( (uint32_t) RSb[ ( Y2       ) & 0xFF ]       ) ^\n                ( (uint32_t) RSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );\n\n        X3 = *RK++ ^ \\\n                ( (uint32_t) RSb[ ( Y3       ) & 0xFF ]       ) ^\n                ( (uint32_t) RSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );\n    }\n    else /* AES_ENCRYPT */\n    {\n        for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )\n        {\n            AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );\n            AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );\n        }\n\n        AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );\n\n        X0 = *RK++ ^ \\\n                ( (uint32_t) FSb[ ( Y0       ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );\n\n        X1 = *RK++ ^ \\\n                ( (uint32_t) FSb[ ( Y1       ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );\n\n        X2 = *RK++ ^ \\\n                ( (uint32_t) FSb[ ( Y2       ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );\n\n        X3 = *RK++ ^ \\\n                ( (uint32_t) FSb[ ( Y3       ) & 0xFF ]       ) ^\n                ( (uint32_t) FSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^\n                ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^\n                ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );\n    }\n\n    PUT_UINT32_LE( X0, output,  0 );\n    PUT_UINT32_LE( X1, output,  4 );\n    PUT_UINT32_LE( X2, output,  8 );\n    PUT_UINT32_LE( X3, output, 12 );\n\n    return( 0 );\n}\n\n#if defined(POLARSSL_CIPHER_MODE_CBC)\n/*\n * AES-CBC buffer encryption/decryption\n */\nint aes_crypt_cbc( aes_context *ctx,\n                    int mode,\n                    size_t length,\n                    unsigned char iv[16],\n                    const unsigned char *input,\n                    unsigned char *output )\n{\n    int i;\n    unsigned char temp[16];\n\n    if( length % 16 )\n        return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );\n\n#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)\n    if( aes_padlock_ace )\n    {\n        if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )\n            return( 0 );\n\n        // If padlock data misaligned, we just fall back to\n        // unaccelerated mode\n        //\n    }\n#endif\n\n    if( mode == AES_DECRYPT )\n    {\n        while( length > 0 )\n        {\n            memcpy( temp, input, 16 );\n            aes_crypt_ecb( ctx, mode, input, output );\n\n            for( i = 0; i < 16; i++ )\n                output[i] = (unsigned char)( output[i] ^ iv[i] );\n\n            memcpy( iv, temp, 16 );\n\n            input  += 16;\n            output += 16;\n            length -= 16;\n        }\n    }\n    else\n    {\n        while( length > 0 )\n        {\n            for( i = 0; i < 16; i++ )\n                output[i] = (unsigned char)( input[i] ^ iv[i] );\n\n            aes_crypt_ecb( ctx, mode, output, output );\n            memcpy( iv, output, 16 );\n\n            input  += 16;\n            output += 16;\n            length -= 16;\n        }\n    }\n\n    return( 0 );\n}\n#endif /* POLARSSL_CIPHER_MODE_CBC */\n\n#if defined(POLARSSL_CIPHER_MODE_CFB)\n/*\n * AES-CFB128 buffer encryption/decryption\n */\nint aes_crypt_cfb128( aes_context *ctx,\n                       int mode,\n                       size_t length,\n                       size_t *iv_off,\n                       unsigned char iv[16],\n                       const unsigned char *input,\n                       unsigned char *output )\n{\n    int c;\n    size_t n = *iv_off;\n\n    if( mode == AES_DECRYPT )\n    {\n        while( length-- )\n        {\n            if( n == 0 )\n                aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );\n\n            c = *input++;\n            *output++ = (unsigned char)( c ^ iv[n] );\n            iv[n] = (unsigned char) c;\n\n            n = ( n + 1 ) & 0x0F;\n        }\n    }\n    else\n    {\n        while( length-- )\n        {\n            if( n == 0 )\n                aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );\n\n            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );\n\n            n = ( n + 1 ) & 0x0F;\n        }\n    }\n\n    *iv_off = n;\n\n    return( 0 );\n}\n\n/*\n * AES-CFB8 buffer encryption/decryption\n */\n#include <stdio.h>\nint aes_crypt_cfb8( aes_context *ctx,\n                       int mode,\n                       size_t length,\n                       unsigned char iv[16],\n                       const unsigned char *input,\n                       unsigned char *output )\n{\n    unsigned char c;\n    unsigned char ov[17];\n\n    while( length-- )\n    {\n        memcpy( ov, iv, 16 );\n        aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );\n\n        if( mode == AES_DECRYPT )\n            ov[16] = *input;\n\n        c = *output++ = (unsigned char)( iv[0] ^ *input++ );\n\n        if( mode == AES_ENCRYPT )\n            ov[16] = c;\n\n        memcpy( iv, ov + 1, 16 );\n    }\n\n    return( 0 );\n}\n#endif /*POLARSSL_CIPHER_MODE_CFB */\n\n#if defined(POLARSSL_CIPHER_MODE_CTR)\n/*\n * AES-CTR buffer encryption/decryption\n */\nint aes_crypt_ctr( aes_context *ctx,\n                       size_t length,\n                       size_t *nc_off,\n                       unsigned char nonce_counter[16],\n                       unsigned char stream_block[16],\n                       const unsigned char *input,\n                       unsigned char *output )\n{\n    int c, i;\n    size_t n = *nc_off;\n\n    while( length-- )\n    {\n        if( n == 0 ) {\n            aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );\n\n            for( i = 16; i > 0; i-- )\n                if( ++nonce_counter[i - 1] != 0 )\n                    break;\n        }\n        c = *input++;\n        *output++ = (unsigned char)( c ^ stream_block[n] );\n\n        n = ( n + 1 ) & 0x0F;\n    }\n\n    *nc_off = n;\n\n    return( 0 );\n}\n#endif /* POLARSSL_CIPHER_MODE_CTR */\n\n#endif /* !POLARSSL_AES_ALT */\n\n#if defined(POLARSSL_SELF_TEST)\n\n#include <stdio.h>\n\n/*\n * AES test vectors from:\n *\n * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip\n */\nstatic const unsigned char aes_test_ecb_dec[3][16] =\n{\n    { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,\n      0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },\n    { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,\n      0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },\n    { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,\n      0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }\n};\n\nstatic const unsigned char aes_test_ecb_enc[3][16] =\n{\n    { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,\n      0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },\n    { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,\n      0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },\n    { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,\n      0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }\n};\n\n#if defined(POLARSSL_CIPHER_MODE_CBC)\nstatic const unsigned char aes_test_cbc_dec[3][16] =\n{\n    { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,\n      0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },\n    { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,\n      0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },\n    { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,\n      0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }\n};\n\nstatic const unsigned char aes_test_cbc_enc[3][16] =\n{\n    { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,\n      0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },\n    { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,\n      0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },\n    { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,\n      0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }\n};\n#endif /* POLARSSL_CIPHER_MODE_CBC */\n\n#if defined(POLARSSL_CIPHER_MODE_CFB)\n/*\n * AES-CFB128 test vectors from:\n *\n * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf\n */\nstatic const unsigned char aes_test_cfb128_key[3][32] =\n{\n    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,\n      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },\n    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,\n      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,\n      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },\n    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,\n      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,\n      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,\n      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }\n};\n\nstatic const unsigned char aes_test_cfb128_iv[16] =\n{\n    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F\n};\n\nstatic const unsigned char aes_test_cfb128_pt[64] =\n{\n    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,\n    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,\n    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,\n    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,\n    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,\n    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,\n    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,\n    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10\n};\n\nstatic const unsigned char aes_test_cfb128_ct[3][64] =\n{\n    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,\n      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,\n      0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,\n      0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,\n      0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,\n      0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,\n      0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,\n      0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },\n    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,\n      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,\n      0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,\n      0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,\n      0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,\n      0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,\n      0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,\n      0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },\n    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,\n      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,\n      0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,\n      0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,\n      0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,\n      0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,\n      0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,\n      0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }\n};\n#endif /* POLARSSL_CIPHER_MODE_CFB */\n\n#if defined(POLARSSL_CIPHER_MODE_CTR)\n/*\n * AES-CTR test vectors from:\n *\n * http://www.faqs.org/rfcs/rfc3686.html\n */\n\nstatic const unsigned char aes_test_ctr_key[3][16] =\n{\n    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,\n      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },\n    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,\n      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },\n    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,\n      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }\n};\n\nstatic const unsigned char aes_test_ctr_nonce_counter[3][16] =\n{\n    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },\n    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,\n      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },\n    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,\n      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }\n};\n\nstatic const unsigned char aes_test_ctr_pt[3][48] =\n{\n    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,\n      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },\n\n    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\n      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },\n\n    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\n      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,\n      0x20, 0x21, 0x22, 0x23 }\n};\n\nstatic const unsigned char aes_test_ctr_ct[3][48] =\n{\n    { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,\n      0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },\n    { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,\n      0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,\n      0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,\n      0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },\n    { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,\n      0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,\n      0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,\n      0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,\n      0x25, 0xB2, 0x07, 0x2F }\n};\n\nstatic const int aes_test_ctr_len[3] =\n    { 16, 32, 36 };\n#endif /* POLARSSL_CIPHER_MODE_CTR */\n\n/*\n * Checkup routine\n */\nint aes_self_test( int verbose )\n{\n    int ret = 0, i, j, u, v;\n    unsigned char key[32];\n    unsigned char buf[64];\n    unsigned char iv[16];\n#if defined(POLARSSL_CIPHER_MODE_CBC)\n    unsigned char prv[16];\n#endif\n#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB)\n    size_t offset;\n#endif\n#if defined(POLARSSL_CIPHER_MODE_CTR)\n    int len;\n    unsigned char nonce_counter[16];\n    unsigned char stream_block[16];\n#endif\n    aes_context ctx;\n\n    memset( key, 0, 32 );\n    aes_init( &ctx );\n\n    /*\n     * ECB mode\n     */\n    for( i = 0; i < 6; i++ )\n    {\n        u = i >> 1;\n        v = i  & 1;\n\n        if( verbose != 0 )\n            polarssl_printf( \"  AES-ECB-%3d (%s): \", 128 + u * 64,\n                             ( v == AES_DECRYPT ) ? \"dec\" : \"enc\" );\n\n        memset( buf, 0, 16 );\n\n\n        if( v == AES_DECRYPT )\n        {\n            aes_setkey_dec( &ctx, key, 128 + u * 64 );\n\n            for( j = 0; j < 10000; j++ )\n                aes_crypt_ecb( &ctx, v, buf, buf );\n\n            if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )\n            {\n                if( verbose != 0 )\n                    polarssl_printf( \"failed\\n\" );\n\n                ret = 1;\n                goto exit;\n            }\n        }\n        else\n        {\n            aes_setkey_enc( &ctx, key, 128 + u * 64 );\n\n            for( j = 0; j < 10000; j++ )\n                aes_crypt_ecb( &ctx, v, buf, buf );\n\n            if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )\n            {\n                if( verbose != 0 )\n                    polarssl_printf( \"failed\\n\" );\n\n                ret = 1;\n                goto exit;\n            }\n        }\n\n        if( verbose != 0 )\n            polarssl_printf( \"passed\\n\" );\n    }\n\n    if( verbose != 0 )\n        polarssl_printf( \"\\n\" );\n\n#if defined(POLARSSL_CIPHER_MODE_CBC)\n    /*\n     * CBC mode\n     */\n    for( i = 0; i < 6; i++ )\n    {\n        u = i >> 1;\n        v = i  & 1;\n\n        if( verbose != 0 )\n            polarssl_printf( \"  AES-CBC-%3d (%s): \", 128 + u * 64,\n                             ( v == AES_DECRYPT ) ? \"dec\" : \"enc\" );\n\n        memset( iv , 0, 16 );\n        memset( prv, 0, 16 );\n        memset( buf, 0, 16 );\n\n        if( v == AES_DECRYPT )\n        {\n            aes_setkey_dec( &ctx, key, 128 + u * 64 );\n\n            for( j = 0; j < 10000; j++ )\n                aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );\n\n            if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )\n            {\n                if( verbose != 0 )\n                    polarssl_printf( \"failed\\n\" );\n\n                ret = 1;\n                goto exit;\n            }\n        }\n        else\n        {\n            aes_setkey_enc( &ctx, key, 128 + u * 64 );\n\n            for( j = 0; j < 10000; j++ )\n            {\n                unsigned char tmp[16];\n\n                aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );\n\n                memcpy( tmp, prv, 16 );\n                memcpy( prv, buf, 16 );\n                memcpy( buf, tmp, 16 );\n            }\n\n            if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )\n            {\n                if( verbose != 0 )\n                    polarssl_printf( \"failed\\n\" );\n\n                ret = 1;\n                goto exit;\n            }\n        }\n\n        if( verbose != 0 )\n            polarssl_printf( \"passed\\n\" );\n    }\n\n    if( verbose != 0 )\n        polarssl_printf( \"\\n\" );\n#endif /* POLARSSL_CIPHER_MODE_CBC */\n\n#if defined(POLARSSL_CIPHER_MODE_CFB)\n    /*\n     * CFB128 mode\n     */\n    for( i = 0; i < 6; i++ )\n    {\n        u = i >> 1;\n        v = i  & 1;\n\n        if( verbose != 0 )\n            polarssl_printf( \"  AES-CFB128-%3d (%s): \", 128 + u * 64,\n                             ( v == AES_DECRYPT ) ? \"dec\" : \"enc\" );\n\n        memcpy( iv,  aes_test_cfb128_iv, 16 );\n        memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );\n\n        offset = 0;\n        aes_setkey_enc( &ctx, key, 128 + u * 64 );\n\n        if( v == AES_DECRYPT )\n        {\n            memcpy( buf, aes_test_cfb128_ct[u], 64 );\n            aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );\n\n            if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )\n            {\n                if( verbose != 0 )\n                    polarssl_printf( \"failed\\n\" );\n\n                ret = 1;\n                goto exit;\n            }\n        }\n        else\n        {\n            memcpy( buf, aes_test_cfb128_pt, 64 );\n            aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );\n\n            if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )\n            {\n                if( verbose != 0 )\n                    polarssl_printf( \"failed\\n\" );\n\n                ret = 1;\n                goto exit;\n            }\n        }\n\n        if( verbose != 0 )\n            polarssl_printf( \"passed\\n\" );\n    }\n\n    if( verbose != 0 )\n        polarssl_printf( \"\\n\" );\n#endif /* POLARSSL_CIPHER_MODE_CFB */\n\n#if defined(POLARSSL_CIPHER_MODE_CTR)\n    /*\n     * CTR mode\n     */\n    for( i = 0; i < 6; i++ )\n    {\n        u = i >> 1;\n        v = i  & 1;\n\n        if( verbose != 0 )\n            polarssl_printf( \"  AES-CTR-128 (%s): \",\n                             ( v == AES_DECRYPT ) ? \"dec\" : \"enc\" );\n\n        memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );\n        memcpy( key, aes_test_ctr_key[u], 16 );\n\n        offset = 0;\n        aes_setkey_enc( &ctx, key, 128 );\n\n        if( v == AES_DECRYPT )\n        {\n            len = aes_test_ctr_len[u];\n            memcpy( buf, aes_test_ctr_ct[u], len );\n\n            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,\n                           buf, buf );\n\n            if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )\n            {\n                if( verbose != 0 )\n                    polarssl_printf( \"failed\\n\" );\n\n                ret = 1;\n                goto exit;\n            }\n        }\n        else\n        {\n            len = aes_test_ctr_len[u];\n            memcpy( buf, aes_test_ctr_pt[u], len );\n\n            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,\n                           buf, buf );\n\n            if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )\n            {\n                if( verbose != 0 )\n                    polarssl_printf( \"failed\\n\" );\n\n                ret = 1;\n                goto exit;\n            }\n        }\n\n        if( verbose != 0 )\n            polarssl_printf( \"passed\\n\" );\n    }\n\n    if( verbose != 0 )\n        polarssl_printf( \"\\n\" );\n#endif /* POLARSSL_CIPHER_MODE_CTR */\n\n    ret = 0;\n\nexit:\n    aes_free( &ctx );\n\n    return( ret );\n}\n\n#endif /* POLARSSL_SELF_TEST */\n\n//#endif /* POLARSSL_AES_C */\n"
  },
  {
    "path": "lib/aes_faster_c/aes.h",
    "content": "/**\n * \\file aes.h\n *\n * \\brief AES block cipher\n *\n *  Copyright (C) 2006-2014, Brainspark B.V.\n *\n *  This file is part of PolarSSL (http://www.polarssl.org)\n *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>\n *\n *  All rights reserved.\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License along\n *  with this program; if not, write to the Free Software Foundation, Inc.,\n *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n */\n#ifndef POLARSSL_AES_H\n#define POLARSSL_AES_H\n/*\n#if !defined(POLARSSL_CONFIG_FILE)\n#include \"config.h\"\n#else\n#include POLARSSL_CONFIG_FILE\n#endif\n*/\n\n////////modification begin\n#define POLARSSL_AES_ROM_TABLES\n#define POLARSSL_CIPHER_MODE_CBC\n#define POLARSSL_CIPHER_MODE_CFB\n//#define POLARSSL_SELF_TEST\n#define polarssl_printf printf\n///////add end\n\n\n\n#include <string.h>\n\n#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)\n#include <basetsd.h>\ntypedef UINT32 uint32_t;\n#else\n#include <inttypes.h>\n#endif\n\n/* padlock.c and aesni.c rely on these values! */\n#define AES_ENCRYPT     1\n#define AES_DECRYPT     0\n\n#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */\n#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */\n\n#if !defined(POLARSSL_AES_ALT)\n// Regular implementation\n//\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          AES context structure\n *\n * \\note           buf is able to hold 32 extra bytes, which can be used:\n *                 - for alignment purposes if VIA padlock is used, and/or\n *                 - to simplify key expansion in the 256-bit case by\n *                 generating an extra round key\n */\ntypedef struct\n{\n    int nr;                     /*!<  number of rounds  */\n    uint32_t *rk;               /*!<  AES round keys    */\n    uint32_t buf[68];           /*!<  unaligned data    */\n}\naes_context;\n\n/**\n * \\brief          Initialize AES context\n *\n * \\param ctx      AES context to be initialized\n */\nvoid aes_init( aes_context *ctx );\n\n/**\n * \\brief          Clear AES context\n *\n * \\param ctx      AES context to be cleared\n */\nvoid aes_free( aes_context *ctx );\n\n/**\n * \\brief          AES key schedule (encryption)\n *\n * \\param ctx      AES context to be initialized\n * \\param key      encryption key\n * \\param keysize  must be 128, 192 or 256\n *\n * \\return         0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH\n */\nint aes_setkey_enc( aes_context *ctx, const unsigned char *key,\n                    unsigned int keysize );\n\n/**\n * \\brief          AES key schedule (decryption)\n *\n * \\param ctx      AES context to be initialized\n * \\param key      decryption key\n * \\param keysize  must be 128, 192 or 256\n *\n * \\return         0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH\n */\nint aes_setkey_dec( aes_context *ctx, const unsigned char *key,\n                    unsigned int keysize );\n\n/**\n * \\brief          AES-ECB block encryption/decryption\n *\n * \\param ctx      AES context\n * \\param mode     AES_ENCRYPT or AES_DECRYPT\n * \\param input    16-byte input block\n * \\param output   16-byte output block\n *\n * \\return         0 if successful\n */\nint aes_crypt_ecb( aes_context *ctx,\n                    int mode,\n                    const unsigned char input[16],\n                    unsigned char output[16] );\n\n#if defined(POLARSSL_CIPHER_MODE_CBC)\n/**\n * \\brief          AES-CBC buffer encryption/decryption\n *                 Length should be a multiple of the block\n *                 size (16 bytes)\n *\n * \\param ctx      AES context\n * \\param mode     AES_ENCRYPT or AES_DECRYPT\n * \\param length   length of the input data\n * \\param iv       initialization vector (updated after use)\n * \\param input    buffer holding the input data\n * \\param output   buffer holding the output data\n *\n * \\return         0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH\n */\nint aes_crypt_cbc( aes_context *ctx,\n                    int mode,\n                    size_t length,\n                    unsigned char iv[16],\n                    const unsigned char *input,\n                    unsigned char *output );\n#endif /* POLARSSL_CIPHER_MODE_CBC */\n\n#if defined(POLARSSL_CIPHER_MODE_CFB)\n/**\n * \\brief          AES-CFB128 buffer encryption/decryption.\n *\n * Note: Due to the nature of CFB you should use the same key schedule for\n * both encryption and decryption. So a context initialized with\n * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.\n *\n * \\param ctx      AES context\n * \\param mode     AES_ENCRYPT or AES_DECRYPT\n * \\param length   length of the input data\n * \\param iv_off   offset in IV (updated after use)\n * \\param iv       initialization vector (updated after use)\n * \\param input    buffer holding the input data\n * \\param output   buffer holding the output data\n *\n * \\return         0 if successful\n */\nint aes_crypt_cfb128( aes_context *ctx,\n                       int mode,\n                       size_t length,\n                       size_t *iv_off,\n                       unsigned char iv[16],\n                       const unsigned char *input,\n                       unsigned char *output );\n\n/**\n * \\brief          AES-CFB8 buffer encryption/decryption.\n *\n * Note: Due to the nature of CFB you should use the same key schedule for\n * both encryption and decryption. So a context initialized with\n * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.\n *\n * \\param ctx      AES context\n * \\param mode     AES_ENCRYPT or AES_DECRYPT\n * \\param length   length of the input data\n * \\param iv       initialization vector (updated after use)\n * \\param input    buffer holding the input data\n * \\param output   buffer holding the output data\n *\n * \\return         0 if successful\n */\nint aes_crypt_cfb8( aes_context *ctx,\n                    int mode,\n                    size_t length,\n                    unsigned char iv[16],\n                    const unsigned char *input,\n                    unsigned char *output );\n#endif /*POLARSSL_CIPHER_MODE_CFB */\n\n#if defined(POLARSSL_CIPHER_MODE_CTR)\n/**\n * \\brief               AES-CTR buffer encryption/decryption\n *\n * Warning: You have to keep the maximum use of your counter in mind!\n *\n * Note: Due to the nature of CTR you should use the same key schedule for\n * both encryption and decryption. So a context initialized with\n * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.\n *\n * \\param ctx           AES context\n * \\param length        The length of the data\n * \\param nc_off        The offset in the current stream_block (for resuming\n *                      within current cipher stream). The offset pointer to\n *                      should be 0 at the start of a stream.\n * \\param nonce_counter The 128-bit nonce and counter.\n * \\param stream_block  The saved stream-block for resuming. Is overwritten\n *                      by the function.\n * \\param input         The input data stream\n * \\param output        The output data stream\n *\n * \\return         0 if successful\n */\nint aes_crypt_ctr( aes_context *ctx,\n                       size_t length,\n                       size_t *nc_off,\n                       unsigned char nonce_counter[16],\n                       unsigned char stream_block[16],\n                       const unsigned char *input,\n                       unsigned char *output );\n#endif /* POLARSSL_CIPHER_MODE_CTR */\n\n#ifdef __cplusplus\n}\n#endif\n\n#else  /* POLARSSL_AES_ALT */\n#include \"aes_alt.h\"\n#endif /* POLARSSL_AES_ALT */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if the test failed\n */\nint aes_self_test( int verbose );\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* aes.h */\n"
  },
  {
    "path": "lib/aes_faster_c/wrapper.cpp",
    "content": "#include \"aes.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n\n#if defined(AES256) && (AES256 == 1)\n#define AES_KEYSIZE 256\n#elif defined(AES192) && (AES192 == 1)\n#define AES_KEYSIZE 192\n#else\n#define AES_KEYSIZE 128\n#endif\n\n\nvoid AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)\n{\n\tstatic aes_context ctx;\n\tif(key!=0)\n\t{\n\t\taes_init( &ctx);\n\t\taes_setkey_enc(&ctx,key,AES_KEYSIZE);\n\t}\n\tint ret=aes_crypt_ecb( &ctx, AES_ENCRYPT, (const unsigned char*)input,(unsigned char*) output );\n\tassert(ret==0);\n\treturn ;\n}\nvoid AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)\n{\n\tstatic aes_context ctx;\n\tif(key!=0)\n\t{\n\t\taes_init( &ctx);\n\t\taes_setkey_dec(&ctx,key,AES_KEYSIZE);\n\t}\n\tint ret=aes_crypt_ecb( &ctx, AES_DECRYPT, (const unsigned char*)input,(unsigned char*) output );\n\tassert(ret==0);\n    return ;\n}\n\nvoid AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)\n{\n\tstatic aes_context ctx;\n\n\tchar tmp_iv[16];\n\tif(key!=0)\n\t{\n\t\taes_init( &ctx);\n\t\taes_setkey_enc(&ctx,key,AES_KEYSIZE);\n\t}\n\tmemcpy(tmp_iv,iv,16);\n\tint ret=aes_crypt_cbc( &ctx, AES_ENCRYPT, length, (unsigned char* )tmp_iv, (const unsigned char*)input,(unsigned char*) output );\n\tassert(ret==0);\n\treturn ;\n}\nvoid AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)\n{\n\tstatic aes_context ctx;\n\n\tchar tmp_iv[16];\n\tif(key!=0)\n\t{\n\t\taes_init( &ctx);\n\t\taes_setkey_dec(&ctx,key,AES_KEYSIZE);\n\t}\n\tmemcpy(tmp_iv,iv,16);\n\tint ret=aes_crypt_cbc( &ctx,AES_DECRYPT, length, (unsigned char*)tmp_iv, (const unsigned char*)input, (unsigned char*) output );\n\tassert(ret==0);\n}\n\nvoid AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)\n{\n\tstatic aes_context ctx;\n\n\tchar tmp_iv[16];\n\tif(key!=0)\n\t{\n\t\taes_init( &ctx);\n\t\taes_setkey_enc(&ctx,key,AES_KEYSIZE);\n\t}\n\tmemcpy(tmp_iv,iv,16);\n\tsize_t offset=0;\n\tint ret=aes_crypt_cfb128( &ctx, AES_ENCRYPT, length,&offset, (unsigned char* )tmp_iv, (const unsigned char*)input,(unsigned char*) output );\n\tassert(ret==0);\n\treturn ;\n}\nvoid AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)\n{\n\tstatic aes_context ctx;\n\n\tchar tmp_iv[16];\n\tif(key!=0)\n\t{\n\t\taes_init( &ctx);\n\t\taes_setkey_enc(&ctx,key,AES_KEYSIZE);// its aes_setkey_enc again, no typo\n\t}\n\tmemcpy(tmp_iv,iv,16);\n\tsize_t offset=0;\n\tint ret=aes_crypt_cfb128( &ctx,AES_DECRYPT, length,&offset, (unsigned char*)tmp_iv, (const unsigned char*)input, (unsigned char*) output );\n\tassert(ret==0);\n\treturn;\n}\n\n\n"
  },
  {
    "path": "lib/md5.cpp",
    "content": "/*\n * This file is adapted from PolarSSL 1.3.19 (GPL)\n */\n\n/*\n *  RFC 1321 compliant MD5 implementation\n *\n *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved\n *\n *  This file is part of mbed TLS (https://tls.mbed.org)\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License along\n *  with this program; if not, write to the Free Software Foundation, Inc.,\n *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n */\n/*\n *  The MD5 algorithm was designed by Ron Rivest in 1991.\n *\n *  http://www.ietf.org/rfc/rfc1321.txt\n */\n\n#include <string.h>\n#include <stddef.h>\n#include <stdint.h>\n\ntypedef struct\n{\n    uint32_t total[2];          /*!< number of bytes processed  */\n    uint32_t state[4];          /*!< intermediate digest state  */\n    unsigned char buffer[64];   /*!< data block being processed */\n\n    unsigned char ipad[64];     /*!< HMAC: inner padding        */\n    unsigned char opad[64];     /*!< HMAC: outer padding        */\n}\nmd5_context;\n\n/* Implementation that should never be optimized out by the compiler */\nstatic void polarssl_zeroize( void *v, size_t n ) {\n    volatile unsigned char *p = (unsigned char *) v; while( n-- ) *p++ = 0;\n}\n\n/*\n * 32-bit integer manipulation macros (little endian)\n */\n#ifndef GET_UINT32_LE\n#define GET_UINT32_LE(n,b,i)                            \\\n{                                                       \\\n    (n) = ( (uint32_t) (b)[(i)    ]       )             \\\n        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \\\n        | ( (uint32_t) (b)[(i) + 2] << 16 )             \\\n        | ( (uint32_t) (b)[(i) + 3] << 24 );            \\\n}\n#endif\n\n#ifndef PUT_UINT32_LE\n#define PUT_UINT32_LE(n,b,i)                                    \\\n{                                                               \\\n    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \\\n    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \\\n    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \\\n    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \\\n}\n#endif\n\nvoid md5_init( md5_context *ctx )\n{\n    memset( ctx, 0, sizeof( md5_context ) );\n}\n\nvoid md5_free( md5_context *ctx )\n{\n    if( ctx == NULL )\n        return;\n\n    polarssl_zeroize( ctx, sizeof( md5_context ) );\n}\n\n/*\n * MD5 context setup\n */\nvoid md5_starts( md5_context *ctx )\n{\n    ctx->total[0] = 0;\n    ctx->total[1] = 0;\n\n    ctx->state[0] = 0x67452301;\n    ctx->state[1] = 0xEFCDAB89;\n    ctx->state[2] = 0x98BADCFE;\n    ctx->state[3] = 0x10325476;\n}\n\nvoid md5_process( md5_context *ctx, const unsigned char data[64] )\n{\n    uint32_t X[16], A, B, C, D;\n\n    GET_UINT32_LE( X[ 0], data,  0 );\n    GET_UINT32_LE( X[ 1], data,  4 );\n    GET_UINT32_LE( X[ 2], data,  8 );\n    GET_UINT32_LE( X[ 3], data, 12 );\n    GET_UINT32_LE( X[ 4], data, 16 );\n    GET_UINT32_LE( X[ 5], data, 20 );\n    GET_UINT32_LE( X[ 6], data, 24 );\n    GET_UINT32_LE( X[ 7], data, 28 );\n    GET_UINT32_LE( X[ 8], data, 32 );\n    GET_UINT32_LE( X[ 9], data, 36 );\n    GET_UINT32_LE( X[10], data, 40 );\n    GET_UINT32_LE( X[11], data, 44 );\n    GET_UINT32_LE( X[12], data, 48 );\n    GET_UINT32_LE( X[13], data, 52 );\n    GET_UINT32_LE( X[14], data, 56 );\n    GET_UINT32_LE( X[15], data, 60 );\n\n#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))\n\n#define P(a,b,c,d,k,s,t)                                \\\n{                                                       \\\n    a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \\\n}\n\n    A = ctx->state[0];\n    B = ctx->state[1];\n    C = ctx->state[2];\n    D = ctx->state[3];\n\n#define F(x,y,z) (z ^ (x & (y ^ z)))\n\n    P( A, B, C, D,  0,  7, 0xD76AA478 );\n    P( D, A, B, C,  1, 12, 0xE8C7B756 );\n    P( C, D, A, B,  2, 17, 0x242070DB );\n    P( B, C, D, A,  3, 22, 0xC1BDCEEE );\n    P( A, B, C, D,  4,  7, 0xF57C0FAF );\n    P( D, A, B, C,  5, 12, 0x4787C62A );\n    P( C, D, A, B,  6, 17, 0xA8304613 );\n    P( B, C, D, A,  7, 22, 0xFD469501 );\n    P( A, B, C, D,  8,  7, 0x698098D8 );\n    P( D, A, B, C,  9, 12, 0x8B44F7AF );\n    P( C, D, A, B, 10, 17, 0xFFFF5BB1 );\n    P( B, C, D, A, 11, 22, 0x895CD7BE );\n    P( A, B, C, D, 12,  7, 0x6B901122 );\n    P( D, A, B, C, 13, 12, 0xFD987193 );\n    P( C, D, A, B, 14, 17, 0xA679438E );\n    P( B, C, D, A, 15, 22, 0x49B40821 );\n\n#undef F\n\n#define F(x,y,z) (y ^ (z & (x ^ y)))\n\n    P( A, B, C, D,  1,  5, 0xF61E2562 );\n    P( D, A, B, C,  6,  9, 0xC040B340 );\n    P( C, D, A, B, 11, 14, 0x265E5A51 );\n    P( B, C, D, A,  0, 20, 0xE9B6C7AA );\n    P( A, B, C, D,  5,  5, 0xD62F105D );\n    P( D, A, B, C, 10,  9, 0x02441453 );\n    P( C, D, A, B, 15, 14, 0xD8A1E681 );\n    P( B, C, D, A,  4, 20, 0xE7D3FBC8 );\n    P( A, B, C, D,  9,  5, 0x21E1CDE6 );\n    P( D, A, B, C, 14,  9, 0xC33707D6 );\n    P( C, D, A, B,  3, 14, 0xF4D50D87 );\n    P( B, C, D, A,  8, 20, 0x455A14ED );\n    P( A, B, C, D, 13,  5, 0xA9E3E905 );\n    P( D, A, B, C,  2,  9, 0xFCEFA3F8 );\n    P( C, D, A, B,  7, 14, 0x676F02D9 );\n    P( B, C, D, A, 12, 20, 0x8D2A4C8A );\n\n#undef F\n\n#define F(x,y,z) (x ^ y ^ z)\n\n    P( A, B, C, D,  5,  4, 0xFFFA3942 );\n    P( D, A, B, C,  8, 11, 0x8771F681 );\n    P( C, D, A, B, 11, 16, 0x6D9D6122 );\n    P( B, C, D, A, 14, 23, 0xFDE5380C );\n    P( A, B, C, D,  1,  4, 0xA4BEEA44 );\n    P( D, A, B, C,  4, 11, 0x4BDECFA9 );\n    P( C, D, A, B,  7, 16, 0xF6BB4B60 );\n    P( B, C, D, A, 10, 23, 0xBEBFBC70 );\n    P( A, B, C, D, 13,  4, 0x289B7EC6 );\n    P( D, A, B, C,  0, 11, 0xEAA127FA );\n    P( C, D, A, B,  3, 16, 0xD4EF3085 );\n    P( B, C, D, A,  6, 23, 0x04881D05 );\n    P( A, B, C, D,  9,  4, 0xD9D4D039 );\n    P( D, A, B, C, 12, 11, 0xE6DB99E5 );\n    P( C, D, A, B, 15, 16, 0x1FA27CF8 );\n    P( B, C, D, A,  2, 23, 0xC4AC5665 );\n\n#undef F\n\n#define F(x,y,z) (y ^ (x | ~z))\n\n    P( A, B, C, D,  0,  6, 0xF4292244 );\n    P( D, A, B, C,  7, 10, 0x432AFF97 );\n    P( C, D, A, B, 14, 15, 0xAB9423A7 );\n    P( B, C, D, A,  5, 21, 0xFC93A039 );\n    P( A, B, C, D, 12,  6, 0x655B59C3 );\n    P( D, A, B, C,  3, 10, 0x8F0CCC92 );\n    P( C, D, A, B, 10, 15, 0xFFEFF47D );\n    P( B, C, D, A,  1, 21, 0x85845DD1 );\n    P( A, B, C, D,  8,  6, 0x6FA87E4F );\n    P( D, A, B, C, 15, 10, 0xFE2CE6E0 );\n    P( C, D, A, B,  6, 15, 0xA3014314 );\n    P( B, C, D, A, 13, 21, 0x4E0811A1 );\n    P( A, B, C, D,  4,  6, 0xF7537E82 );\n    P( D, A, B, C, 11, 10, 0xBD3AF235 );\n    P( C, D, A, B,  2, 15, 0x2AD7D2BB );\n    P( B, C, D, A,  9, 21, 0xEB86D391 );\n\n#undef F\n\n    ctx->state[0] += A;\n    ctx->state[1] += B;\n    ctx->state[2] += C;\n    ctx->state[3] += D;\n}\n\n/*\n * MD5 process buffer\n */\nvoid md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )\n{\n    size_t fill;\n    uint32_t left;\n\n    if( ilen == 0 )\n        return;\n\n    left = ctx->total[0] & 0x3F;\n    fill = 64 - left;\n\n    ctx->total[0] += (uint32_t) ilen;\n    ctx->total[0] &= 0xFFFFFFFF;\n\n    if( ctx->total[0] < (uint32_t) ilen )\n        ctx->total[1]++;\n\n    if( left && ilen >= fill )\n    {\n        memcpy( (void *) (ctx->buffer + left), input, fill );\n        md5_process( ctx, ctx->buffer );\n        input += fill;\n        ilen  -= fill;\n        left = 0;\n    }\n\n    while( ilen >= 64 )\n    {\n        md5_process( ctx, input );\n        input += 64;\n        ilen  -= 64;\n    }\n\n    if( ilen > 0 )\n    {\n        memcpy( (void *) (ctx->buffer + left), input, ilen );\n    }\n}\n\nstatic const unsigned char md5_padding[64] =\n{\n 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n};\n\n/*\n * MD5 final digest\n */\nvoid md5_finish( md5_context *ctx, unsigned char output[16] )\n{\n    uint32_t last, padn;\n    uint32_t high, low;\n    unsigned char msglen[8];\n\n    high = ( ctx->total[0] >> 29 )\n         | ( ctx->total[1] <<  3 );\n    low  = ( ctx->total[0] <<  3 );\n\n    PUT_UINT32_LE( low,  msglen, 0 );\n    PUT_UINT32_LE( high, msglen, 4 );\n\n    last = ctx->total[0] & 0x3F;\n    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );\n\n    md5_update( ctx, md5_padding, padn );\n    md5_update( ctx, msglen, 8 );\n\n    PUT_UINT32_LE( ctx->state[0], output,  0 );\n    PUT_UINT32_LE( ctx->state[1], output,  4 );\n    PUT_UINT32_LE( ctx->state[2], output,  8 );\n    PUT_UINT32_LE( ctx->state[3], output, 12 );\n}\n\n/*\n * output = MD5( input buffer )\n */\nvoid md5( const unsigned char *input, size_t ilen, unsigned char output[16] )\n{\n    /*static md5_context ctx;\n    static int done=0;\n    if(done==0)\n    {\n        md5_init( &ctx );\n    \tdone=1;\n    }*/\n    md5_context ctx;\n    md5_init( &ctx );\n    md5_starts( &ctx );\n    md5_update( &ctx, input, ilen );\n    md5_finish( &ctx, output );\n    md5_free( &ctx );\n}\n\n\n/*\n * MD5 HMAC context setup\n */\nvoid md5_hmac_starts( md5_context *ctx, const unsigned char *key,\n                      size_t keylen )\n{\n    size_t i;\n    unsigned char sum[16];\n\n    if( keylen > 64 )\n    {\n        md5( key, keylen, sum );\n        keylen = 16;\n        key = sum;\n    }\n\n    memset( ctx->ipad, 0x36, 64 );\n    memset( ctx->opad, 0x5C, 64 );\n\n    for( i = 0; i < keylen; i++ )\n    {\n        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );\n        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );\n    }\n\n    md5_starts( ctx );\n    md5_update( ctx, ctx->ipad, 64 );\n\n    polarssl_zeroize( sum, sizeof( sum ) );\n}\n\n/*\n * MD5 HMAC process buffer\n */\nvoid md5_hmac_update( md5_context *ctx, const unsigned char *input,\n                      size_t ilen )\n{\n    md5_update( ctx, input, ilen );\n}\n\n/*\n * MD5 HMAC final digest\n */\nvoid md5_hmac_finish( md5_context *ctx, unsigned char output[16] )\n{\n    unsigned char tmpbuf[16];\n\n    md5_finish( ctx, tmpbuf );\n    md5_starts( ctx );\n    md5_update( ctx, ctx->opad, 64 );\n    md5_update( ctx, tmpbuf, 16 );\n    md5_finish( ctx, output );\n\n    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );\n}\n\n/*\n * MD5 HMAC context reset\n */\nvoid md5_hmac_reset( md5_context *ctx )\n{\n    md5_starts( ctx );\n    md5_update( ctx, ctx->ipad, 64 );\n}\n\n/*\n * output = HMAC-MD5( hmac key, input buffer )\n */\nvoid md5_hmac( const unsigned char *key, size_t keylen,\n               const unsigned char *input, size_t ilen,\n               unsigned char output[16] )\n{\n    md5_context ctx;\n\n    md5_init( &ctx );\n    md5_hmac_starts( &ctx, key, keylen );\n    md5_hmac_update( &ctx, input, ilen );\n    md5_hmac_finish( &ctx, output );\n    md5_free( &ctx );\n}\n"
  },
  {
    "path": "lib/md5.h",
    "content": "#ifndef UDP2RAW_MD5_H_\n#define UDP2RAW_MD5_H_\n#include <stdint.h>\n#include <stddef.h>\n\nvoid md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest);\n\n#endif\n"
  },
  {
    "path": "lib/pbkdf2-sha1.cpp",
    "content": "/*\n   this file is from https://github.com/kholia/PKCS5_PBKDF2\n\n*\n *  FIPS-180-1 compliant SHA-1 implementation\n *\n *  Copyright (C) 2006-2010, Brainspark B.V.\n *\n *  This file is part of PolarSSL (http://www.polarssl.org)\n *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>\n *\n *  All rights reserved.\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License along\n *  with this program; if not, write to the Free Software Foundation, Inc.,\n *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n *  The SHA-1 standard was published by NIST in 1993.\n *\n *  http://www.itl.nist.gov/fipspubs/fip180-1.htm\n *\n *  Copyright 2012 Mathias Olsson mathias@kompetensum.com\n *\n *  This file is dual licensed as either GPL version 2 or Apache License 2.0 at your choice\n *  http://www.gnu.org/licenses/old-licenses/gpl-2.0.html\n *  http://www.apache.org/licenses/\n *\n *  Note that PolarSSL uses GPL with a FOSS License Exception */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#if defined(TEST) ||defined(DEBUG)\n#undef TEST \n#undef DEBUG\n#warning \"undefined TEST/DEBUG\"\n#endif\n\ntypedef struct {\n\tunsigned long total[2];\t/*!< number of bytes processed  */\n\tunsigned long state[5];\t/*!< intermediate digest state  */\n\tunsigned char buffer[64];\t/*!< data block being processed */\n\n\tunsigned char ipad[64];\t/*!< HMAC: inner padding        */\n\tunsigned char opad[64];\t/*!< HMAC: outer padding        */\n} sha1_context;\n\n/*\n * 32-bit integer manipulation macros (big endian)\n */\n#ifndef GET_ULONG_BE\n#define GET_ULONG_BE(n,b,i)                             \\\n{                                                       \\\n    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \\\n        | ( (unsigned long) (b)[(i) + 1] << 16 )        \\\n        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \\\n        | ( (unsigned long) (b)[(i) + 3]       );       \\\n}\n#endif\n\n#ifndef PUT_ULONG_BE\n#define PUT_ULONG_BE(n,b,i)                             \\\n{                                                       \\\n    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \\\n    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \\\n    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \\\n    (b)[(i) + 3] = (unsigned char) ( (n)       );       \\\n}\n#endif\n\n/*\n * SHA-1 context setup\n */\nvoid sha1_starts(sha1_context * ctx)\n{\n\tctx->total[0] = 0;\n\tctx->total[1] = 0;\n\n\tctx->state[0] = 0x67452301;\n\tctx->state[1] = 0xEFCDAB89;\n\tctx->state[2] = 0x98BADCFE;\n\tctx->state[3] = 0x10325476;\n\tctx->state[4] = 0xC3D2E1F0;\n}\n\nstatic void sha1_process(sha1_context * ctx, const unsigned char data[64])\n{\n\tunsigned long temp, W[16], A, B, C, D, E;\n\n\tGET_ULONG_BE(W[0], data, 0);\n\tGET_ULONG_BE(W[1], data, 4);\n\tGET_ULONG_BE(W[2], data, 8);\n\tGET_ULONG_BE(W[3], data, 12);\n\tGET_ULONG_BE(W[4], data, 16);\n\tGET_ULONG_BE(W[5], data, 20);\n\tGET_ULONG_BE(W[6], data, 24);\n\tGET_ULONG_BE(W[7], data, 28);\n\tGET_ULONG_BE(W[8], data, 32);\n\tGET_ULONG_BE(W[9], data, 36);\n\tGET_ULONG_BE(W[10], data, 40);\n\tGET_ULONG_BE(W[11], data, 44);\n\tGET_ULONG_BE(W[12], data, 48);\n\tGET_ULONG_BE(W[13], data, 52);\n\tGET_ULONG_BE(W[14], data, 56);\n\tGET_ULONG_BE(W[15], data, 60);\n\n#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))\n\n#define R(t)                                            \\\n(                                                       \\\n    temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \\\n           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \\\n    ( W[t & 0x0F] = S(temp,1) )                         \\\n)\n\n#define P(a,b,c,d,e,x)                                  \\\n{                                                       \\\n    e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \\\n}\n\n\tA = ctx->state[0];\n\tB = ctx->state[1];\n\tC = ctx->state[2];\n\tD = ctx->state[3];\n\tE = ctx->state[4];\n\n#define F(x,y,z) (z ^ (x & (y ^ z)))\n#define K 0x5A827999\n\n\tP(A, B, C, D, E, W[0]);\n\tP(E, A, B, C, D, W[1]);\n\tP(D, E, A, B, C, W[2]);\n\tP(C, D, E, A, B, W[3]);\n\tP(B, C, D, E, A, W[4]);\n\tP(A, B, C, D, E, W[5]);\n\tP(E, A, B, C, D, W[6]);\n\tP(D, E, A, B, C, W[7]);\n\tP(C, D, E, A, B, W[8]);\n\tP(B, C, D, E, A, W[9]);\n\tP(A, B, C, D, E, W[10]);\n\tP(E, A, B, C, D, W[11]);\n\tP(D, E, A, B, C, W[12]);\n\tP(C, D, E, A, B, W[13]);\n\tP(B, C, D, E, A, W[14]);\n\tP(A, B, C, D, E, W[15]);\n\tP(E, A, B, C, D, R(16));\n\tP(D, E, A, B, C, R(17));\n\tP(C, D, E, A, B, R(18));\n\tP(B, C, D, E, A, R(19));\n\n#undef K\n#undef F\n\n#define F(x,y,z) (x ^ y ^ z)\n#define K 0x6ED9EBA1\n\n\tP(A, B, C, D, E, R(20));\n\tP(E, A, B, C, D, R(21));\n\tP(D, E, A, B, C, R(22));\n\tP(C, D, E, A, B, R(23));\n\tP(B, C, D, E, A, R(24));\n\tP(A, B, C, D, E, R(25));\n\tP(E, A, B, C, D, R(26));\n\tP(D, E, A, B, C, R(27));\n\tP(C, D, E, A, B, R(28));\n\tP(B, C, D, E, A, R(29));\n\tP(A, B, C, D, E, R(30));\n\tP(E, A, B, C, D, R(31));\n\tP(D, E, A, B, C, R(32));\n\tP(C, D, E, A, B, R(33));\n\tP(B, C, D, E, A, R(34));\n\tP(A, B, C, D, E, R(35));\n\tP(E, A, B, C, D, R(36));\n\tP(D, E, A, B, C, R(37));\n\tP(C, D, E, A, B, R(38));\n\tP(B, C, D, E, A, R(39));\n\n#undef K\n#undef F\n\n#define F(x,y,z) ((x & y) | (z & (x | y)))\n#define K 0x8F1BBCDC\n\n\tP(A, B, C, D, E, R(40));\n\tP(E, A, B, C, D, R(41));\n\tP(D, E, A, B, C, R(42));\n\tP(C, D, E, A, B, R(43));\n\tP(B, C, D, E, A, R(44));\n\tP(A, B, C, D, E, R(45));\n\tP(E, A, B, C, D, R(46));\n\tP(D, E, A, B, C, R(47));\n\tP(C, D, E, A, B, R(48));\n\tP(B, C, D, E, A, R(49));\n\tP(A, B, C, D, E, R(50));\n\tP(E, A, B, C, D, R(51));\n\tP(D, E, A, B, C, R(52));\n\tP(C, D, E, A, B, R(53));\n\tP(B, C, D, E, A, R(54));\n\tP(A, B, C, D, E, R(55));\n\tP(E, A, B, C, D, R(56));\n\tP(D, E, A, B, C, R(57));\n\tP(C, D, E, A, B, R(58));\n\tP(B, C, D, E, A, R(59));\n\n#undef K\n#undef F\n\n#define F(x,y,z) (x ^ y ^ z)\n#define K 0xCA62C1D6\n\n\tP(A, B, C, D, E, R(60));\n\tP(E, A, B, C, D, R(61));\n\tP(D, E, A, B, C, R(62));\n\tP(C, D, E, A, B, R(63));\n\tP(B, C, D, E, A, R(64));\n\tP(A, B, C, D, E, R(65));\n\tP(E, A, B, C, D, R(66));\n\tP(D, E, A, B, C, R(67));\n\tP(C, D, E, A, B, R(68));\n\tP(B, C, D, E, A, R(69));\n\tP(A, B, C, D, E, R(70));\n\tP(E, A, B, C, D, R(71));\n\tP(D, E, A, B, C, R(72));\n\tP(C, D, E, A, B, R(73));\n\tP(B, C, D, E, A, R(74));\n\tP(A, B, C, D, E, R(75));\n\tP(E, A, B, C, D, R(76));\n\tP(D, E, A, B, C, R(77));\n\tP(C, D, E, A, B, R(78));\n\tP(B, C, D, E, A, R(79));\n\n#undef K\n#undef F\n\n\tctx->state[0] += A;\n\tctx->state[1] += B;\n\tctx->state[2] += C;\n\tctx->state[3] += D;\n\tctx->state[4] += E;\n}\n\n/*\n * SHA-1 process buffer\n */\nvoid sha1_update(sha1_context * ctx, const unsigned char *input, int ilen)\n{\n\tint fill;\n\tunsigned long left;\n\n\tif (ilen <= 0)\n\t\treturn;\n\n\tleft = ctx->total[0] & 0x3F;\n\tfill = 64 - left;\n\n\tctx->total[0] += (unsigned long) ilen;\n\tctx->total[0] &= 0xFFFFFFFF;\n\n\tif (ctx->total[0] < (unsigned long) ilen)\n\t\tctx->total[1]++;\n\n\tif (left && ilen >= fill) {\n\t\tmemcpy((void *) (ctx->buffer + left), (void *) input, fill);\n\t\tsha1_process(ctx, ctx->buffer);\n\t\tinput += fill;\n\t\tilen -= fill;\n\t\tleft = 0;\n\t}\n\n\twhile (ilen >= 64) {\n\t\tsha1_process(ctx, input);\n\t\tinput += 64;\n\t\tilen -= 64;\n\t}\n\n\tif (ilen > 0) {\n\t\tmemcpy((void *) (ctx->buffer + left), (void *) input, ilen);\n\t}\n}\n\nstatic const unsigned char sha1_padding[64] = {\n\t0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n};\n\n/*\n * SHA-1 final digest\n */\nvoid sha1_finish(sha1_context * ctx, unsigned char output[20])\n{\n\tunsigned long last, padn;\n\tunsigned long high, low;\n\tunsigned char msglen[8];\n\n\thigh = (ctx->total[0] >> 29)\n\t    | (ctx->total[1] << 3);\n\tlow = (ctx->total[0] << 3);\n\n\tPUT_ULONG_BE(high, msglen, 0);\n\tPUT_ULONG_BE(low, msglen, 4);\n\n\tlast = ctx->total[0] & 0x3F;\n\tpadn = (last < 56) ? (56 - last) : (120 - last);\n\n\tsha1_update(ctx, (unsigned char *) sha1_padding, padn);\n\tsha1_update(ctx, msglen, 8);\n\n\tPUT_ULONG_BE(ctx->state[0], output, 0);\n\tPUT_ULONG_BE(ctx->state[1], output, 4);\n\tPUT_ULONG_BE(ctx->state[2], output, 8);\n\tPUT_ULONG_BE(ctx->state[3], output, 12);\n\tPUT_ULONG_BE(ctx->state[4], output, 16);\n}\n\n/*\n * output = SHA-1( input buffer )\n */\nvoid sha1(const unsigned char *input, int ilen, unsigned char output[20])\n{\n\tsha1_context ctx;\n\n\tsha1_starts(&ctx);\n\tsha1_update(&ctx, input, ilen);\n\tsha1_finish(&ctx, output);\n\n}\n\n\n/*\n * SHA-1 HMAC context setup\n */\nvoid sha1_hmac_starts(sha1_context * ctx, const unsigned char *key, int keylen)\n{\n\tint i;\n\tunsigned char sum[20];\n\n\tif (keylen > 64) {\n\t\tsha1(key, keylen, sum);\n\t\tkeylen = 20;\n\t\tkey = sum;\n\t}\n\n\tmemset(ctx->ipad, 0x36, 64);\n\tmemset(ctx->opad, 0x5C, 64);\n\n\tfor (i = 0; i < keylen; i++) {\n\t\tctx->ipad[i] = (unsigned char) (ctx->ipad[i] ^ key[i]);\n\t\tctx->opad[i] = (unsigned char) (ctx->opad[i] ^ key[i]);\n\t}\n\n\tsha1_starts(ctx);\n\tsha1_update(ctx, ctx->ipad, 64);\n\n}\n\n/*\n * SHA-1 HMAC process buffer\n */\nvoid sha1_hmac_update(sha1_context * ctx, const unsigned char *input, int ilen)\n{\n\tsha1_update(ctx, input, ilen);\n}\n\n/*\n * SHA-1 HMAC final digest\n */\nvoid sha1_hmac_finish(sha1_context * ctx, unsigned char output[20])\n{\n\tunsigned char tmpbuf[20];\n\n\tsha1_finish(ctx, tmpbuf);\n\tsha1_starts(ctx);\n\tsha1_update(ctx, ctx->opad, 64);\n\tsha1_update(ctx, tmpbuf, 20);\n\tsha1_finish(ctx, output);\n\n}\n\n/*\n * SHA1 HMAC context reset\n */\nvoid sha1_hmac_reset(sha1_context * ctx)\n{\n\tsha1_starts(ctx);\n\tsha1_update(ctx, ctx->ipad, 64);\n}\n\n/*\n * output = HMAC-SHA-1( hmac key, input buffer )\n */\nvoid sha1_hmac(const unsigned char *key, int keylen,\n    const unsigned char *input, int ilen, unsigned char output[20])\n{\n\tsha1_context ctx;\n\n\tsha1_hmac_starts(&ctx, key, keylen);\n\tsha1_hmac_update(&ctx, input, ilen);\n\tsha1_hmac_finish(&ctx, output);\n\n}\n\n\n\n\n\n\n\n#ifndef min\n#define min( a, b ) ( ((a) < (b)) ? (a) : (b) )\n#endif\n\nvoid PKCS5_PBKDF2_HMAC_SHA1(const unsigned char *password, size_t plen,\n    const unsigned char *salt, size_t slen,\n    const unsigned long iteration_count, const unsigned long key_length,\n    unsigned char *output)\n{\n\tsha1_context ctx;\n\tsha1_starts(&ctx);\n\n\t// Size of the generated digest\n\tunsigned char md_size = 20;\n\tunsigned char md1[20];\n\tunsigned char work[20];\n\n\tunsigned long counter = 1;\n\tunsigned long generated_key_length = 0;\n\twhile (generated_key_length < key_length) {\n\t\t// U1 ends up in md1 and work\n\t\tunsigned char c[4];\n\t\tc[0] = (counter >> 24) & 0xff;\n\t\tc[1] = (counter >> 16) & 0xff;\n\t\tc[2] = (counter >> 8) & 0xff;\n\t\tc[3] = (counter >> 0) & 0xff;\n\n\t\tsha1_hmac_starts(&ctx, password, plen);\n\t\tsha1_hmac_update(&ctx, salt, slen);\n\t\tsha1_hmac_update(&ctx, c, 4);\n\t\tsha1_hmac_finish(&ctx, md1);\n\t\tmemcpy(work, md1, md_size);\n\n\t\tunsigned long ic = 1;\n\t\tfor (ic = 1; ic < iteration_count; ic++) {\n\t\t\t// U2 ends up in md1\n\t\t\tsha1_hmac_starts(&ctx, password, plen);\n\t\t\tsha1_hmac_update(&ctx, md1, md_size);\n\t\t\tsha1_hmac_finish(&ctx, md1);\n\t\t\t// U1 xor U2\n\t\t\tunsigned long i = 0;\n\t\t\tfor (i = 0; i < md_size; i++) {\n\t\t\t\twork[i] ^= md1[i];\n\t\t\t}\n\t\t\t// and so on until iteration_count\n\t\t}\n\n\t\t// Copy the generated bytes to the key\n\t\tunsigned long bytes_to_write =\n\t\t    min((key_length - generated_key_length), md_size);\n\t\tmemcpy(output + generated_key_length, work, bytes_to_write);\n\t\tgenerated_key_length += bytes_to_write;\n\t\t++counter;\n\t}\n}\n\n\n#if defined(TEST)\n/*\n * FIPS-180-1 test vectors\n */\nstatic unsigned char sha1_test_buf[3][57] = {\n\t{\"abc\"},\n\t{\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\"},\n\t{\"\"}\n};\n\nstatic const int sha1_test_buflen[3] = {\n\t3, 56, 1000\n};\n\nstatic const unsigned char sha1_test_sum[3][20] = {\n\t{0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,\n\t    0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D},\n\t{0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,\n\t    0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1},\n\t{0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,\n\t    0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F}\n};\n\n/*\n * RFC 2202 test vectors\n */\nstatic unsigned char sha1_hmac_test_key[7][26] = {\n\t{\"\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\"\n\t\t    \"\\x0B\\x0B\\x0B\\x0B\"},\n\t{\"Jefe\"},\n\t{\"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t\t    \"\\xAA\\xAA\\xAA\\xAA\"},\n\t{\"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0A\\x0B\\x0C\\x0D\\x0E\\x0F\\x10\"\n\t\t    \"\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\"},\n\t{\"\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\"\n\t\t    \"\\x0C\\x0C\\x0C\\x0C\"},\n\t{\"\"},\t\t\t/* 0xAA 80 times */\n\t{\"\"}\n};\n\nstatic const int sha1_hmac_test_keylen[7] = {\n\t20, 4, 20, 25, 20, 80, 80\n};\n\nstatic unsigned char sha1_hmac_test_buf[7][74] = {\n\t{\"Hi There\"},\n\t{\"what do ya want for nothing?\"},\n\t{\"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t\t    \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t\t    \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t\t    \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t\t    \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"},\n\t{\"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t\t    \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t\t    \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t\t    \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t\t    \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"},\n\t{\"Test With Truncation\"},\n\t{\"Test Using Larger Than Block-Size Key - Hash Key First\"},\n\t{\"Test Using Larger Than Block-Size Key and Larger\"\n\t\t    \" Than One Block-Size Data\"}\n};\n\nstatic const int sha1_hmac_test_buflen[7] = {\n\t8, 28, 50, 50, 20, 54, 73\n};\n\nstatic const unsigned char sha1_hmac_test_sum[7][20] = {\n\t{0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,\n\t    0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00},\n\t{0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,\n\t    0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79},\n\t{0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,\n\t    0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3},\n\t{0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,\n\t    0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA},\n\t{0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,\n\t    0x7B, 0xE1},\n\t{0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,\n\t    0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12},\n\t{0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,\n\t    0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91}\n};\n\ntypedef struct {\n\tchar *t;\n\tchar *p;\n\tint plen;\n\tchar *s;\n\tint slen;\n\tint c;\n\tint dkLen;\n\tchar dk[1024];\t\t// Remember to set this to max dkLen\n} testvector;\n\nint do_test(testvector * tv)\n{\n\tprintf(\"Started %s\\n\", tv->t);\n\tfflush(stdout);\n\tchar *key = malloc(tv->dkLen);\n\tif (key == 0) {\n\t\treturn -1;\n\t}\n\n\tPKCS5_PBKDF2_HMAC(tv->p, tv->plen, tv->s, tv->slen, tv->c,\n\t    tv->dkLen, key);\n\n\tif (memcmp(tv->dk, key, tv->dkLen) != 0) {\n\t\t// Failed\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\n#ifdef DEBUG\nstatic void print_hex(unsigned char *str, int len)\n{\n\tint i;\n\tfor (i = 0; i < len; ++i)\n\t\tprintf(\"%02x\", str[i]);\n\tprintf(\"\\n\");\n}\n#endif\n\n/*\n * Checkup routine\n */\nint main(int argc,char * argv[])\n{\n\tint verbose = 1;\n\tint i, j, buflen;\n\tunsigned char buf[1024];\n\tunsigned char sha1sum[20];\n\n\tsha1_context ctx;\n\n\t/*\n\t * SHA-1\n\t */\n\tfor (i = 0; i < 3; i++) {\n\t\tif (verbose != 0)\n\t\t\tprintf(\"  SHA-1 test #%d: \", i + 1);\n\n\t\tsha1_starts(&ctx);\n\n\t\tif (i == 2) {\n\t\t\tmemset(buf, 'a', buflen = 1000);\n\n\t\t\tfor (j = 0; j < 1000; j++)\n\t\t\t\tsha1_update(&ctx, buf, buflen);\n\t\t} else\n\t\t\tsha1_update(&ctx, sha1_test_buf[i],\n\t\t\t    sha1_test_buflen[i]);\n\n\t\tsha1_finish(&ctx, sha1sum);\n\n\t\tif (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) {\n\t\t\tif (verbose != 0)\n\t\t\t\tprintf(\"failed\\n\");\n\n\t\t\treturn (1);\n\t\t}\n\n\t\tif (verbose != 0)\n\t\t\tprintf(\"passed\\n\");\n\t}\n\n\tif (verbose != 0)\n\t\tprintf(\"\\n\");\n\n\tfor (i = 0; i < 7; i++) {\n\t\tif (verbose != 0)\n\t\t\tprintf(\"  HMAC-SHA-1 test #%d: \", i + 1);\n\n\t\tif (i == 5 || i == 6) {\n\t\t\tmemset(buf, '\\xAA', buflen = 80);\n\t\t\tsha1_hmac_starts(&ctx, buf, buflen);\n\t\t} else\n\t\t\tsha1_hmac_starts(&ctx, sha1_hmac_test_key[i],\n\t\t\t    sha1_hmac_test_keylen[i]);\n\n\t\tsha1_hmac_update(&ctx, sha1_hmac_test_buf[i],\n\t\t    sha1_hmac_test_buflen[i]);\n\n\t\tsha1_hmac_finish(&ctx, sha1sum);\n\n\t\tbuflen = (i == 4) ? 12 : 20;\n\n\t\tif (memcmp(sha1sum, sha1_hmac_test_sum[i], buflen) != 0) {\n\t\t\tif (verbose != 0)\n\t\t\t\tprintf(\"failed\\n\");\n\n\t\t\treturn (1);\n\t\t}\n\n\t\tif (verbose != 0)\n\t\t\tprintf(\"passed\\n\");\n\t}\n\n\tif (verbose != 0)\n\t\tprintf(\"\\n\");\n\n\t// Test vectors from RFC 6070\n\n\ttestvector *tv = 0;\n\tint res = 0;\n\n/*\n    Input:\n       P = \"password\" (8 octets)\n       S = \"salt\" (4 octets)\n       c = 1\n       dkLen = 20\n\n     Output:\n       DK = 0c 60 c8 0f 96 1f 0e 71\n            f3 a9 b5 24 af 60 12 06\n            2f e0 37 a6             (20 octets)\n\n*/\n\ttestvector t1 = {\n\t\t\"Test 1\",\n\t\t\"password\", 8, \"salt\", 4, 1, 20,\n\t\t.dk = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,\n\t\t\t    0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,\n\t\t    0x2f, 0xe0, 0x37, 0xa6}\n\t};\n\n\ttv = &t1;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n/*\n       Input:\n             P = \"password\" (8 octets)\n             S = \"salt\" (4 octets)\n             c = 2\n             dkLen = 20\n\n           Output:\n             DK = ea 6c 01 4d c7 2d 6f 8c\n                  cd 1e d9 2a ce 1d 41 f0\n                  d8 de 89 57             (20 octets)\n\n*/\n\n\ttestvector t2 = {\n\t\t\"Test 2\",\n\t\t\"password\", 8, \"salt\", 4, 2, 20,\n\t\t{0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,\n\t\t\t    0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,\n\t\t    0xd8, 0xde, 0x89, 0x57}\n\t};\n\n\ttv = &t2;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n/*\n             Input:\n                  P = \"password\" (8 octets)\n                  S = \"salt\" (4 octets)\n                  c = 4096\n                  dkLen = 20\n\n                Output:\n                  DK = 4b 00 79 01 b7 65 48 9a\n                       be ad 49 d9 26 f7 21 d0\n                       65 a4 29 c1             (20 octets)\n\n\n*/\n\ttestvector t3 = {\n\t\t\"Test 3\",\n\t\t\"password\", 8, \"salt\", 4, 4096, 20,\n\t\t{0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,\n\t\t\t    0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,\n\t\t    0x65, 0xa4, 0x29, 0xc1}\n\t};\n\n\ttv = &t3;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n/*\n                  Input:\n                     P = \"password\" (8 octets)\n                     S = \"salt\" (4 octets)\n                     c = 16777216\n                     dkLen = 20\n\n                   Output:\n                     DK = ee fe 3d 61 cd 4d a4 e4\n                          e9 94 5b 3d 6b a2 15 8c\n                          26 34 e9 84             (20 octets)\n\n*/\n\ttestvector t4 = {\n\t\t\"Test 4\",\n\t\t\"password\", 8, \"salt\", 4, 16777216, 20,\n\t\t{0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,\n\t\t\t    0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,\n\t\t    0x26, 0x34, 0xe9, 0x84}\n\t};\n\n\ttv = &t4;\n\t// res = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n/*\n                     Input:\n                        P = \"passwordPASSWORDpassword\" (24 octets)\n                        S = \"saltSALTsaltSALTsaltSALTsaltSALTsalt\" (36 octets)\n                        c = 4096\n                        dkLen = 25\n\n                      Output:\n                        DK = 3d 2e ec 4f e4 1c 84 9b\n                             80 c8 d8 36 62 c0 e4 4a\n                             8b 29 1a 96 4c f2 f0 70\n                             38                      (25 octets)\n\n*/\n\ttestvector t5 = {\n\t\t\"Test 5\",\n\t\t\"passwordPASSWORDpassword\", 24,\n\t\t    \"saltSALTsaltSALTsaltSALTsaltSALTsalt\", 36, 4096, 25,\n\t\t{0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,\n\t\t\t    0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,\n\t\t\t    0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,\n\t\t    0x38}\n\t};\n\n\ttv = &t5;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n/*\n                        Input:\n                           P = \"pass\\0word\" (9 octets)\n                           S = \"sa\\0lt\" (5 octets)\n                           c = 4096\n                           dkLen = 16\n\n                         Output:\n                           DK = 56 fa 6a a7 55 48 09 9d\n                                cc 37 d7 f0 34 25 e0 c3 (16 octets)\n*/\n\ttestvector t6 = {\n\t\t\"Test 6\",\n\t\t\"pass\\0word\", 9, \"sa\\0lt\", 5, 4096, 16,\n\t\t{0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,\n\t\t\t    0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3,\n\t\t    }\n\t};\n\n\ttv = &t6;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n\tprintf(\"All tests successful\\n\");\n\treturn 0;\n}\n\n#endif\n/*\nint main()\n{\n}*/\n"
  },
  {
    "path": "lib/pbkdf2-sha1.h",
    "content": "#pragma once\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nvoid sha1(const unsigned char *input, int ilen, unsigned char output[20]);\n\nvoid sha1_hmac(const unsigned char *key, int keylen, const unsigned char *input, int ilen, unsigned char output[20]);\n\nvoid PKCS5_PBKDF2_HMAC_SHA1(const unsigned char *password, size_t plen,\n    const unsigned char *salt, size_t slen,\n    const unsigned long iteration_count, const unsigned long key_length,\n    unsigned char *output);\n"
  },
  {
    "path": "lib/pbkdf2-sha256.cpp",
    "content": "/*\n   this file is from https://github.com/kholia/PKCS5_PBKDF2, with additional code of hkdf_sha256\n\n *  FIPS-180-2 compliant SHA-256 implementation\n *\n *  Copyright (C) 2006-2010, Brainspark B.V.\n *\n *  This file is part of PolarSSL (http://www.polarssl.org)\n *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>\n *\n *  All rights reserved.\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License along\n *  with this program; if not, write to the Free Software Foundation, Inc.,\n *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n */\n/*\n *  The SHA-256 Secure Hash Standard was published by NIST in 2002.\n *\n *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\n */\n\n#include <string.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n\n#if defined(TEST) ||defined(DEBUG)\n#undef TEST \n#undef DEBUG\n#warning \"undefined TEST/DEBUG\"\n#endif\n\n\ntypedef struct {\n\tunsigned long total[2];\t/*!< number of bytes processed  */\n\tunsigned long state[8];\t/*!< intermediate digest state  */\n\tunsigned char buffer[64];\t/*!< data block being processed */\n\n\tunsigned char ipad[64];\t/*!< HMAC: inner padding        */\n\tunsigned char opad[64];\t/*!< HMAC: outer padding        */\n\tint is224;\t\t/*!< 0 => SHA-256, else SHA-224 */\n} sha2_context;\n\n\n/*\n * 32-bit integer manipulation macros (big endian)\n */\n#ifndef GET_ULONG_BE\n#define GET_ULONG_BE(n,b,i)                             \\\n{                                                       \\\n    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \\\n        | ( (unsigned long) (b)[(i) + 1] << 16 )        \\\n        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \\\n        | ( (unsigned long) (b)[(i) + 3]       );       \\\n}\n#endif\n\n#ifndef PUT_ULONG_BE\n#define PUT_ULONG_BE(n,b,i)                             \\\n{                                                       \\\n    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \\\n    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \\\n    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \\\n    (b)[(i) + 3] = (unsigned char) ( (n)       );       \\\n}\n#endif\n\n/*\n * SHA-256 context setup\n */\nvoid sha2_starts( sha2_context *ctx, int is224 )\n{\n    ctx->total[0] = 0;\n    ctx->total[1] = 0;\n\n    if( is224 == 0 )\n    {\n        /* SHA-256 */\n        ctx->state[0] = 0x6A09E667;\n        ctx->state[1] = 0xBB67AE85;\n        ctx->state[2] = 0x3C6EF372;\n        ctx->state[3] = 0xA54FF53A;\n        ctx->state[4] = 0x510E527F;\n        ctx->state[5] = 0x9B05688C;\n        ctx->state[6] = 0x1F83D9AB;\n        ctx->state[7] = 0x5BE0CD19;\n    }\n    else\n    {\n        /* SHA-224 */\n        ctx->state[0] = 0xC1059ED8;\n        ctx->state[1] = 0x367CD507;\n        ctx->state[2] = 0x3070DD17;\n        ctx->state[3] = 0xF70E5939;\n        ctx->state[4] = 0xFFC00B31;\n        ctx->state[5] = 0x68581511;\n        ctx->state[6] = 0x64F98FA7;\n        ctx->state[7] = 0xBEFA4FA4;\n    }\n\n    ctx->is224 = is224;\n}\n\nstatic void sha2_process( sha2_context *ctx, const unsigned char data[64] )\n{\n    unsigned long temp1, temp2, W[64];\n    unsigned long A, B, C, D, E, F, G, H;\n\n    GET_ULONG_BE( W[ 0], data,  0 );\n    GET_ULONG_BE( W[ 1], data,  4 );\n    GET_ULONG_BE( W[ 2], data,  8 );\n    GET_ULONG_BE( W[ 3], data, 12 );\n    GET_ULONG_BE( W[ 4], data, 16 );\n    GET_ULONG_BE( W[ 5], data, 20 );\n    GET_ULONG_BE( W[ 6], data, 24 );\n    GET_ULONG_BE( W[ 7], data, 28 );\n    GET_ULONG_BE( W[ 8], data, 32 );\n    GET_ULONG_BE( W[ 9], data, 36 );\n    GET_ULONG_BE( W[10], data, 40 );\n    GET_ULONG_BE( W[11], data, 44 );\n    GET_ULONG_BE( W[12], data, 48 );\n    GET_ULONG_BE( W[13], data, 52 );\n    GET_ULONG_BE( W[14], data, 56 );\n    GET_ULONG_BE( W[15], data, 60 );\n\n#define  SHR(x,n) ((x & 0xFFFFFFFF) >> n)\n#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))\n\n#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))\n#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))\n\n#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))\n#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))\n\n#define F0(x,y,z) ((x & y) | (z & (x | y)))\n#define F1(x,y,z) (z ^ (x & (y ^ z)))\n\n#define R(t)                                    \\\n(                                               \\\n    W[t] = S1(W[t -  2]) + W[t -  7] +          \\\n           S0(W[t - 15]) + W[t - 16]            \\\n)\n\n#define P(a,b,c,d,e,f,g,h,x,K)                  \\\n{                                               \\\n    temp1 = h + S3(e) + F1(e,f,g) + K + x;      \\\n    temp2 = S2(a) + F0(a,b,c);                  \\\n    d += temp1; h = temp1 + temp2;              \\\n}\n\n\tA = ctx->state[0];\n\tB = ctx->state[1];\n\tC = ctx->state[2];\n\tD = ctx->state[3];\n\tE = ctx->state[4];\n\tF = ctx->state[5];\n\tG = ctx->state[6];\n\tH = ctx->state[7];\n\n    P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );\n    P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );\n    P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );\n    P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );\n    P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );\n    P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );\n    P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );\n    P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );\n    P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );\n    P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );\n    P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );\n    P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );\n    P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );\n    P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );\n    P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );\n    P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );\n    P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );\n    P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );\n    P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );\n    P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );\n    P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );\n    P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );\n    P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );\n    P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );\n    P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );\n    P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );\n    P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );\n    P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );\n    P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );\n    P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );\n    P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );\n    P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );\n    P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );\n    P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );\n    P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );\n    P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );\n    P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );\n    P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );\n    P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );\n    P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );\n    P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );\n    P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );\n    P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );\n    P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );\n    P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );\n    P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );\n    P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );\n    P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );\n    P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );\n    P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );\n    P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );\n    P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );\n    P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );\n    P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );\n    P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );\n    P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );\n    P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );\n    P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );\n    P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );\n    P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );\n    P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );\n    P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );\n    P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );\n    P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );\n\n    ctx->state[0] += A;\n    ctx->state[1] += B;\n    ctx->state[2] += C;\n    ctx->state[3] += D;\n    ctx->state[4] += E;\n    ctx->state[5] += F;\n    ctx->state[6] += G;\n    ctx->state[7] += H;\n}\n\n/*\n * SHA-256 process buffer\n */\nvoid sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )\n{\n    size_t fill;\n    unsigned long left;\n\n    if( ilen <= 0 )\n        return;\n\n    left = ctx->total[0] & 0x3F;\n    fill = 64 - left;\n\n    ctx->total[0] += (unsigned long) ilen;\n    ctx->total[0] &= 0xFFFFFFFF;\n\n    if( ctx->total[0] < (unsigned long) ilen )\n        ctx->total[1]++;\n\n    if( left && ilen >= fill )\n    {\n        memcpy( (void *) (ctx->buffer + left),\n                (void *) input, fill );\n        sha2_process( ctx, ctx->buffer );\n        input += fill;\n        ilen  -= fill;\n        left = 0;\n    }\n\n    while( ilen >= 64 )\n    {\n        sha2_process( ctx, input );\n        input += 64;\n        ilen  -= 64;\n    }\n\n    if( ilen > 0 )\n    {\n        memcpy( (void *) (ctx->buffer + left),\n                (void *) input, ilen );\n    }\n}\n\nstatic const unsigned char sha2_padding[64] =\n{\n 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n};\n\n/*\n * SHA-256 final digest\n */\nvoid sha2_finish( sha2_context *ctx, unsigned char output[32] )\n{\n    unsigned long last, padn;\n    unsigned long high, low;\n    unsigned char msglen[8];\n\n    high = ( ctx->total[0] >> 29 )\n         | ( ctx->total[1] <<  3 );\n    low  = ( ctx->total[0] <<  3 );\n\n    PUT_ULONG_BE( high, msglen, 0 );\n    PUT_ULONG_BE( low,  msglen, 4 );\n\n    last = ctx->total[0] & 0x3F;\n    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );\n\n    sha2_update( ctx, (unsigned char *) sha2_padding, padn );\n    sha2_update( ctx, msglen, 8 );\n\n    PUT_ULONG_BE( ctx->state[0], output,  0 );\n    PUT_ULONG_BE( ctx->state[1], output,  4 );\n    PUT_ULONG_BE( ctx->state[2], output,  8 );\n    PUT_ULONG_BE( ctx->state[3], output, 12 );\n    PUT_ULONG_BE( ctx->state[4], output, 16 );\n    PUT_ULONG_BE( ctx->state[5], output, 20 );\n    PUT_ULONG_BE( ctx->state[6], output, 24 );\n\n    if( ctx->is224 == 0 )\n        PUT_ULONG_BE( ctx->state[7], output, 28 );\n}\n\n/*\n * output = SHA-256( input buffer )\n */\nvoid sha2( const unsigned char *input, size_t ilen,\n           unsigned char output[32], int is224 )\n{\n    sha2_context ctx;\n\n    sha2_starts( &ctx, is224 );\n    sha2_update( &ctx, input, ilen );\n    sha2_finish( &ctx, output );\n\n    memset( &ctx, 0, sizeof( sha2_context ) );\n}\n\n/*\n * SHA-256 HMAC context setup\n */\nvoid sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,\n                       int is224 )\n{\n    size_t i;\n    unsigned char sum[32];\n\n    if( keylen > 64 )\n    {\n        sha2( key, keylen, sum, is224 );\n        keylen = ( is224 ) ? 28 : 32;\n        key = sum;\n    }\n\n    memset( ctx->ipad, 0x36, 64 );\n    memset( ctx->opad, 0x5C, 64 );\n\n    for( i = 0; i < keylen; i++ )\n    {\n        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );\n        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );\n    }\n\n    sha2_starts( ctx, is224 );\n    sha2_update( ctx, ctx->ipad, 64 );\n\n    memset( sum, 0, sizeof( sum ) );\n}\n\n/*\n * SHA-256 HMAC process buffer\n */\nvoid sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen )\n{\n    sha2_update( ctx, input, ilen );\n}\n\n/*\n * SHA-256 HMAC final digest\n */\nvoid sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )\n{\n    int is224, hlen;\n    unsigned char tmpbuf[32];\n\n    is224 = ctx->is224;\n    hlen = ( is224 == 0 ) ? 32 : 28;\n\n    sha2_finish( ctx, tmpbuf );\n    sha2_starts( ctx, is224 );\n    sha2_update( ctx, ctx->opad, 64 );\n    sha2_update( ctx, tmpbuf, hlen );\n    sha2_finish( ctx, output );\n\n    memset( tmpbuf, 0, sizeof( tmpbuf ) );\n}\n\n/*\n * SHA-256 HMAC context reset\n */\nvoid sha2_hmac_reset( sha2_context *ctx )\n{\n    sha2_starts( ctx, ctx->is224 );\n    sha2_update( ctx, ctx->ipad, 64 );\n}\n\n/*\n * output = HMAC-SHA-256( hmac key, input buffer )\n */\nvoid sha2_hmac( const unsigned char *key, size_t keylen,\n                const unsigned char *input, size_t ilen,\n                unsigned char output[32], int is224 )\n{\n    sha2_context ctx;\n\n    sha2_hmac_starts( &ctx, key, keylen, is224 );\n    sha2_hmac_update( &ctx, input, ilen );\n    sha2_hmac_finish( &ctx, output );\n\n    memset( &ctx, 0, sizeof( sha2_context ) );\n}\n\n\n\n\n\n#ifndef min\n#define min( a, b ) ( ((a) < (b)) ? (a) : (b) )\n#endif\n\nvoid PKCS5_PBKDF2_HMAC_SHA256(unsigned char *password, size_t plen,\n    unsigned char *salt, size_t slen,\n    const unsigned long iteration_count, const unsigned long key_length,\n    unsigned char *output)\n{\n\tsha2_context ctx;\n\tsha2_starts(&ctx, 0);\n\n\t// Size of the generated digest\n\tunsigned char md_size = 32;\n\tunsigned char md1[32];\n\tunsigned char work[32];\n\n\tunsigned long counter = 1;\n\tunsigned long generated_key_length = 0;\n\twhile (generated_key_length < key_length) {\n\t\t// U1 ends up in md1 and work\n\t\tunsigned char c[4];\n\t\tc[0] = (counter >> 24) & 0xff;\n\t\tc[1] = (counter >> 16) & 0xff;\n\t\tc[2] = (counter >> 8) & 0xff;\n\t\tc[3] = (counter >> 0) & 0xff;\n\n\t\tsha2_hmac_starts(&ctx, password, plen, 0);\n\t\tsha2_hmac_update(&ctx, salt, slen);\n\t\tsha2_hmac_update(&ctx, c, 4);\n\t\tsha2_hmac_finish(&ctx, md1);\n\t\tmemcpy(work, md1, md_size);\n\n\t\tunsigned long ic = 1;\n\t\tfor (ic = 1; ic < iteration_count; ic++) {\n\t\t\t// U2 ends up in md1\n\t\t\tsha2_hmac_starts(&ctx, password, plen, 0);\n\t\t\tsha2_hmac_update(&ctx, md1, md_size);\n\t\t\tsha2_hmac_finish(&ctx, md1);\n\t\t\t// U1 xor U2\n\t\t\tunsigned long i = 0;\n\t\t\tfor (i = 0; i < md_size; i++) {\n\t\t\t\twork[i] ^= md1[i];\n\t\t\t}\n\t\t\t// and so on until iteration_count\n\t\t}\n\n\t\t// Copy the generated bytes to the key\n\t\tunsigned long bytes_to_write =\n\t\t    min((key_length - generated_key_length), md_size);\n\t\tmemcpy(output + generated_key_length, work, bytes_to_write);\n\t\tgenerated_key_length += bytes_to_write;\n\t\t++counter;\n\t}\n}\n\n\n\n\n\n\n\n\n\n#ifdef TEST\n/*\n * FIPS-180-2 test vectors\n */\nstatic unsigned char sha2_test_buf[3][57] = \n{\n    { \"abc\" },\n    { \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\" },\n    { \"\" }\n};\n\nstatic const int sha2_test_buflen[3] =\n{\n    3, 56, 1000\n};\n\nstatic const unsigned char sha2_test_sum[6][32] =\n{\n    /*\n     * SHA-224 test vectors\n     */\n    { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,\n      0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,\n      0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,\n      0xE3, 0x6C, 0x9D, 0xA7 },\n    { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,\n      0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,\n      0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,\n      0x52, 0x52, 0x25, 0x25 },\n    { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,\n      0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,\n      0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,\n      0x4E, 0xE7, 0xAD, 0x67 },\n\n    /*\n     * SHA-256 test vectors\n     */\n    { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,\n      0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,\n      0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,\n      0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },\n    { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,\n      0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,\n      0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,\n      0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },\n    { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,\n      0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,\n      0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,\n      0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }\n};\n\n/*\n * RFC 4231 test vectors\n */\nstatic unsigned char sha2_hmac_test_key[7][26] = {\n\t{\"\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\"\n\t\t    \"\\x0B\\x0B\\x0B\\x0B\"},\n\t{\"Jefe\"},\n\t{\"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t\t    \"\\xAA\\xAA\\xAA\\xAA\"},\n\t{\"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0A\\x0B\\x0C\\x0D\\x0E\\x0F\\x10\"\n\t\t    \"\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\"},\n\t{\"\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\"\n\t\t    \"\\x0C\\x0C\\x0C\\x0C\"},\n\t{\"\"},\t\t\t/* 0xAA 131 times */\n\t{\"\"}\n};\n\nstatic const int sha2_hmac_test_keylen[7] = {\n\t20, 4, 20, 25, 20, 131, 131\n};\n\nstatic unsigned char sha2_hmac_test_buf[7][153] =\n{\n    { \"Hi There\" },\n    { \"what do ya want for nothing?\" },\n    { \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n      \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n      \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n      \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n      \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\" },\n    { \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n      \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n      \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n      \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n      \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\" },\n    { \"Test With Truncation\" },\n    { \"Test Using Larger Than Block-Size Key - Hash Key First\" },\n    { \"This is a test using a larger than block-size key \"\n      \"and a larger than block-size data. The key needs to \"\n      \"be hashed before being used by the HMAC algorithm.\" }\n};\n\nstatic const int sha2_hmac_test_buflen[7] =\n{\n    8, 28, 50, 50, 20, 54, 152\n};\n\nstatic const unsigned char sha2_hmac_test_sum[14][32] =\n{\n    /*\n     * HMAC-SHA-224 test vectors\n     */\n    { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,\n      0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,\n      0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,\n      0x53, 0x68, 0x4B, 0x22 },\n    { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,\n      0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,\n      0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,\n      0x8F, 0xD0, 0x5E, 0x44 },\n    { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,\n      0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,\n      0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,\n      0xEC, 0x83, 0x33, 0xEA },\n    { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,\n      0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,\n      0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,\n      0xE7, 0xAF, 0xEC, 0x5A },\n    { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,\n      0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },\n    { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,\n      0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,\n      0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,\n      0x3F, 0xA6, 0x87, 0x0E },\n    { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,\n      0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,\n      0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,\n      0xF6, 0xF5, 0x65, 0xD1 },\n\n    /*\n     * HMAC-SHA-256 test vectors\n     */\n    { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,\n      0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,\n      0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,\n      0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },\n    { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,\n      0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,\n      0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,\n      0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },\n    { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,\n      0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,\n      0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,\n      0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },\n    { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,\n      0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,\n      0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,\n      0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },\n    { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,\n      0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },\n    { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,\n      0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,\n      0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,\n      0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },\n    { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,\n      0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,\n      0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,\n      0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }\n};\ntypedef struct {\n\tchar *t;\n\tchar *p;\n\tint plen;\n\tchar *s;\n\tint slen;\n\tint c;\n\tint dkLen;\n\tchar dk[1024];\t\t// Remember to set this to max dkLen\n} testvector;\n\nint do_test(testvector * tv)\n{\n\tprintf(\"Started %s\\n\", tv->t);\n\tfflush(stdout);\n\tchar *key = malloc(tv->dkLen);\n\tif (key == 0) {\n\t\treturn -1;\n\t}\n\n\tPKCS5_PBKDF2_HMAC((unsigned char*)tv->p, tv->plen,\n\t\t\t(unsigned char*)tv->s, tv->slen, tv->c,\n\t\t\ttv->dkLen, (unsigned char*)key);\n\n\tif (memcmp(tv->dk, key, tv->dkLen) != 0) {\n\t\t// Failed\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\n/*\n * Checkup routine\n */\nint main()\n{\n\tint verbose = 1;\n\tint i, j, k, buflen;\n\tunsigned char buf[1024];\n\tunsigned char sha2sum[32];\n\tsha2_context ctx;\n\n\tfor (i = 0; i < 6; i++) {\n\t\tj = i % 3;\n\t\tk = i < 3;\n\n\t\tif (verbose != 0)\n\t\t\tprintf(\"  SHA-%d test #%d: \", 256 - k * 32, j + 1);\n\n\t\tsha2_starts(&ctx, k);\n\n\t\tif (j == 2) {\n\t\t\tmemset(buf, 'a', buflen = 1000);\n\n\t\t\tfor (j = 0; j < 1000; j++)\n\t\t\t\tsha2_update(&ctx, buf, buflen);\n\t\t} else\n\t\t\tsha2_update(&ctx, sha2_test_buf[j],\n\t\t\t    sha2_test_buflen[j]);\n\n\t\tsha2_finish(&ctx, sha2sum);\n\n\t\tif (memcmp(sha2sum, sha2_test_sum[i], 32 - k * 4) != 0) {\n\t\t\tif (verbose != 0)\n\t\t\t\tprintf(\"failed\\n\");\n\n\t\t\treturn (1);\n\t\t}\n\n\t\tif (verbose != 0)\n\t\t\tprintf(\"passed\\n\");\n\t}\n\n\tif (verbose != 0)\n\t\tprintf(\"\\n\");\n\n\tfor (i = 0; i < 14; i++) {\n\t\tj = i % 7;\n\t\tk = i < 7;\n\n\t\tif (verbose != 0)\n\t\t\tprintf(\"  HMAC-SHA-%d test #%d: \", 256 - k * 32,\n\t\t\t    j + 1);\n\n\t\tif (j == 5 || j == 6) {\n\t\t\tmemset(buf, '\\xAA', buflen = 131);\n\t\t\tsha2_hmac_starts(&ctx, buf, buflen, k);\n\t\t} else\n\t\t\tsha2_hmac_starts(&ctx, sha2_hmac_test_key[j],\n\t\t\t    sha2_hmac_test_keylen[j], k);\n\n\t\tsha2_hmac_update(&ctx, sha2_hmac_test_buf[j],\n\t\t    sha2_hmac_test_buflen[j]);\n\n\t\tsha2_hmac_finish(&ctx, sha2sum);\n\n\t\tbuflen = (j == 4) ? 16 : 32 - k * 4;\n\n\t\tif (memcmp(sha2sum, sha2_hmac_test_sum[i], buflen) != 0) {\n\t\t\tif (verbose != 0)\n\t\t\t\tprintf(\"failed\\n\");\n\n\t\t\treturn (1);\n\t\t}\n\n\t\tif (verbose != 0)\n\t\t\tprintf(\"passed\\n\");\n\t}\n\n\tif (verbose != 0)\n\t\tprintf(\"\\n\");\n\n\ttestvector *tv = 0;\n\tint res = 0;\n\n\ttestvector t1 = {\n\t\t\"Test 1\",\n\t\t\"password\", 8, \"salt\", 4, 1, 32,\n\t\t.dk = { 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c,\n\t\t\t0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37,\n\t\t\t0xa8, 0x65, 0x48, 0xc9, 0x2c, 0xcc, 0x35, 0x48,\n\t\t\t0x08, 0x05, 0x98, 0x7c, 0xb7, 0x0b, 0xe1, 0x7b }\n\t};\n\n\ttv = &t1;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n\ttestvector t2 = {\n\t\t\"Test 2\",\n\t\t\"password\", 8, \"salt\", 4, 2, 32, {\n\t\t\t0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,\n\t\t\t0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,\n\t\t\t0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf,\n\t\t\t0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43 }\n\t};\n\n\ttv = &t2;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n\ttestvector t3 = {\n\t\t\"Test 3\",\n\t\t\"password\", 8, \"salt\", 4, 4096, 32, {\n\t\t\t0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41,\n\t\t\t0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d,\n\t\t\t0x96, 0x28, 0x93, 0xa0, 0x01, 0xce, 0x4e, 0x11,\n\t\t\t0xa4, 0x96, 0x38, 0x73, 0xaa, 0x98, 0x13, 0x4a }\n\t};\n\n\ttv = &t3;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n\ttestvector t4 = {\n\t\t\"Test 4\",\n\t\t\"password\", 8, \"salt\", 4, 16777216, 32, {\n\t\t\t0xcf, 0x81, 0xc6, 0x6f, 0xe8, 0xcf, 0xc0, 0x4d,\n\t\t\t0x1f, 0x31, 0xec, 0xb6, 0x5d, 0xab, 0x40, 0x89,\n\t\t\t0xf7, 0xf1, 0x79, 0xe8, 0x9b, 0x3b, 0x0b, 0xcb,\n\t\t\t0x17, 0xad, 0x10, 0xe3, 0xac, 0x6e, 0xba, 0x46 }\n\t};\n\n\ttv = &t4;\n\t// res = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n\ttestvector t5 = {\n\t\t\"Test 5\",\n\t\t\"passwordPASSWORDpassword\", 24,\n\t\t\"saltSALTsaltSALTsaltSALTsaltSALTsalt\", 36, 4096, 40, {\n\t\t\t0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f,\n\t\t\t0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf,\n\t\t\t0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18,\n\t\t\t0x1c, 0x4e, 0x2a, 0x1f, 0xb8, 0xdd, 0x53, 0xe1,\n\t\t\t0xc6, 0x35, 0x51, 0x8c, 0x7d, 0xac, 0x47, 0xe9 }\n\t};\n\n\ttv = &t5;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n\ttestvector t6 = {\n\t\t\"Test 6\",\n\t\t\"pass\\0word\", 9, \"sa\\0lt\", 5, 4096, 16, {\n\t\t\t0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89,\n\t\t\t0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87 }\n\t};\n\n\ttv = &t6;\n\tres = do_test(tv);\n\tif (res != 0) {\n\t\tprintf(\"%s failed\\n\", tv->t);\n\t\treturn res;\n\t}\n\n\treturn (0);\n}\n\n#endif\n\n\n\nconst int sha256_len=32;\n\n#define MBEDTLS_MD_MAX_SIZE  64 \n#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA   -0x5F80\n\nstatic void * (* const volatile memset_func)( void *, int, size_t ) = memset;\n\nvoid mbedtls_platform_zeroize( void *buf, size_t len )\n{\n\t    memset_func( buf, 0, len );\n}\n\nint hkdf_sha256_extract(\n                          const unsigned char *salt, size_t salt_len,\n                          const unsigned char *ikm, size_t ikm_len,\n                          unsigned char *prk )\n{\n    unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\\0' };\n\n    if( salt == NULL )\n    {\n        size_t hash_len;\n\n        hash_len = sha256_len;\n\n        if( hash_len == 0 )\n        {\n            return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;\n        }\n\n        salt = null_salt;\n        salt_len = hash_len;\n    }\n\n    sha2_hmac (salt, salt_len, ikm, ikm_len, prk ,0);\n    return 0;\n}\n\nint hkdf_sha256_expand( const unsigned char *prk,\n                         size_t prk_len, const unsigned char *info,\n                         size_t info_len, unsigned char *okm, size_t okm_len )\n{\n    size_t hash_len;\n    size_t where = 0;\n    size_t n;\n    size_t t_len = 0;\n    size_t i;\n    int ret = 0;\n    sha2_context ctx;\n    unsigned char t[MBEDTLS_MD_MAX_SIZE];\n\n    if( okm == NULL )\n    {\n        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );\n    }\n\n    hash_len = sha256_len;\n\n    if( prk_len < hash_len || hash_len == 0 )\n    {\n        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );\n    }\n\n    if( info == NULL )\n    {\n        info = (const unsigned char *) \"\";\n        info_len = 0;\n    }\n\n    n = okm_len / hash_len;\n\n    if( (okm_len % hash_len) != 0 )\n    {\n        n++;\n    }\n\n    if( n > 255 )\n    {\n        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );\n    }\n\n    //mbedtls_md_init( &ctx );   //old code\n    memset( &ctx, 0, sizeof( ctx) );  //its not necessary\n\n    /*\n    if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 )\n    {\n        goto exit;\n    }*/\n\n\n    /* RFC 5869 Section 2.3. */\n    for( i = 1; i <= n; i++ )\n    {\n        size_t num_to_copy;\n        unsigned char c = i & 0xff;\n\n        sha2_hmac_starts( &ctx, prk, prk_len,0 );\n\n        sha2_hmac_update( &ctx, t, t_len );\n\n        sha2_hmac_update( &ctx, info, info_len );\n\n        /* The constant concatenated to the end of each t(n) is a single octet.\n         * */\n        sha2_hmac_update( &ctx, &c, 1 );\n\n        sha2_hmac_finish( &ctx, t );\n        num_to_copy = i != n ? hash_len : okm_len - where;\n        memcpy( okm + where, t, num_to_copy );\n        where += hash_len;\n        t_len = hash_len;\n    }\n\n//exit:\n    //mbedtls_md_free( &ctx );  //old code\n    mbedtls_platform_zeroize( &ctx, sizeof( ctx ) ); //not necessary too\n\n    mbedtls_platform_zeroize( t, sizeof( t ) );\n\n    return( ret );\n}\n\nint hkdf_sha256( const unsigned char *salt,\n                  size_t salt_len, const unsigned char *ikm, size_t ikm_len,\n                  const unsigned char *info, size_t info_len,\n                  unsigned char *okm, size_t okm_len )\n{\n    int ret;\n    unsigned char prk[MBEDTLS_MD_MAX_SIZE];\n\n    ret = hkdf_sha256_extract( salt, salt_len, ikm, ikm_len, prk );\n\n    if( ret == 0 )\n    {\n        ret = hkdf_sha256_expand( prk, sha256_len,\n                                   info, info_len, okm, okm_len );\n    }\n\n    mbedtls_platform_zeroize( prk, sizeof( prk ) );\n\n    return( ret );\n}\n\n#ifdef HKDF_SHA256_TEST\n\n#include <assert.h>\nint hex_to_number(char a)\n{\n\tif(a>='0' &&a<='9')\n\t\treturn a-'0';\n\tif(a>='a'&& a<='f') return a- 'a' +10;\n\n\tassert(0==1);\n\treturn -1;\n}\nint base16_decode(const char *a,unsigned char *buf)\n{\n\tint len=strlen(a);\n\tassert(len%2==0);\n\n\tfor(int i=0,j=0;i<len;i+=2,j++)\n\t{\n\t\tunsigned char c= hex_to_number(a[i])*16+hex_to_number(a[i+1]);\n\t\tbuf[j]=c;\n\t}\n\treturn len/2;\n}\nint main()\n{\n    const struct {\n    const char *ikm16, *salt16, *info16;\n    int L;\n    const char *okm16;\n  } vecs[] = {\n    { /* from A.1 */\n      \"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\",\n      \"000102030405060708090a0b0c\",\n      \"f0f1f2f3f4f5f6f7f8f9\",\n      42,\n      \"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf\"\n        \"34007208d5b887185865\"\n    },\n    { /* from A.2 */\n      \"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\"\n        \"202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n        \"404142434445464748494a4b4c4d4e4f\",\n      \"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\"\n        \"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f\"\n        \"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf\",\n      \"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf\"\n        \"d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef\"\n        \"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff\",\n      82,\n      \"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c\"\n      \"59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71\"\n      \"cc30c58179ec3e87c14c01d5c1f3434f1d87\"\n    },\n    { /* from A.3 */\n      \"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\",\n      \"\",\n      \"\",\n      42,\n      \"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d\"\n        \"9d201395faa4b61a96c8\",\n    },\n    { NULL, NULL, NULL, -1, NULL }\n  };\n\n    for(int i=0;i<3;i++)\n    {\n\t    unsigned char ikm[200]; int ikm_len;\n\t    unsigned char salt[200];int salt_len;\n\t    unsigned char info[200]; int info_len;\n\t    unsigned char okm[200];\n\n\t    ikm_len=base16_decode(vecs[i].ikm16,ikm);\n\t    salt_len=base16_decode(vecs[i].salt16,salt);\n\t    info_len=base16_decode(vecs[i].info16,info);\n\n\t    base16_decode(vecs[i].okm16,okm);\n\n\t    int outlen=vecs[i].L;\n\t    unsigned char output[200];\n\n\t    int ret=hkdf_sha256(salt,\n\t\t\t    salt_len,ikm, ikm_len,\n\t\t\t    info, info_len,\n\t\t\t    output, outlen );\n\t    assert(ret==0);\n\t    for(int j=0;j<ikm_len;j++)\n\t\t    printf(\"<%02x>\",(int)(ikm[j]));\n\t    printf(\"\\n---------------------------\\n\");\n\t    for(int j=0;j<outlen;j++)\n\t\t    printf(\"<%02x>\",(int)(output[j]));\n\t    printf(\"\\n---------------------------\\n\");\n\t    for(int j=0;j<outlen;j++)\n\t\t    printf(\"<%02x>\",(int)(okm[j]));\n\t    printf(\"\\n===========================\\n\");\n    }\n\n\n}\n\n#endif\n\n\n"
  },
  {
    "path": "lib/pbkdf2-sha256.h",
    "content": "#pragma once\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nvoid PKCS5_PBKDF2_HMAC_SHA256(unsigned char *password, size_t plen,\n    unsigned char *salt, size_t slen,\n    const unsigned long iteration_count, const unsigned long key_length,\n    unsigned char *output);\n\n//void sha2( const unsigned char *input, size_t ilen,unsigned char output[32], int is224 );\n\nint hkdf_sha256_extract(\n                          const unsigned char *salt, size_t salt_len,\n                          const unsigned char *ikm, size_t ikm_len,\n                          unsigned char *prk );\n\nint hkdf_sha256_expand( const unsigned char *prk,\n                         size_t prk_len, const unsigned char *info,\n                         size_t info_len, unsigned char *okm, size_t okm_len );\n\nint hkdf_sha256( const unsigned char *salt,\n                  size_t salt_len, const unsigned char *ikm, size_t ikm_len,\n                  const unsigned char *info, size_t info_len,\n                  unsigned char *okm, size_t okm_len );\n\n\n"
  },
  {
    "path": "libev/CVS/Entries",
    "content": "/Changes/1.315/Wed Jun 21 14:42:30 2017//\n/LICENSE/1.11/Thu Jan 16 11:51:05 2014//\n/Makefile.am/1.9/Wed Dec 21 18:16:08 2011//\n/README/1.21/Fri Mar 30 17:43:55 2012//\n/README.embed/1.29/Sat Nov 24 10:10:26 2007//\n/Symbols.ev/1.14/Tue Jan 11 13:45:28 2011//\n/Symbols.event/1.4/Tue May  8 15:52:13 2012//\n/autogen.sh/1.3/Mon May 30 15:28:54 2011//\n/configure.ac/1.42/Wed Dec 28 04:22:06 2016//\n/ev++.h/1.63/Fri Dec  1 06:37:30 2017//\n/ev.3/1.107/Wed Jun 21 14:42:30 2017//\n/ev.c/1.481/Thu Jun  1 20:25:50 2017//\n/ev.h/1.187/Wed Dec 28 04:22:06 2016//\n/ev.pod/1.441/Thu Jul 13 10:46:52 2017//\n/ev_epoll.c/1.72/Wed Jun 21 14:42:30 2017//\n/ev_kqueue.c/1.56/Thu Feb 18 04:48:05 2016//\n/ev_poll.c/1.40/Thu Feb 18 04:48:05 2016//\n/ev_port.c/1.29/Thu Feb 18 04:48:05 2016//\n/ev_select.c/1.56/Thu Feb 18 04:48:05 2016//\n/ev_vars.h/1.58/Tue Sep  9 21:51:35 2014//\n/ev_win32.c/1.18/Thu Nov 12 07:02:37 2015//\n/ev_wrap.h/1.38/Tue Nov  6 20:56:50 2012//\n/event.c/1.52/Mon Apr  2 23:14:41 2012//\n/event.h/1.26/Mon Apr  2 23:15:27 2012//\n/event_compat.h/1.8/Wed Feb 16 08:02:51 2011//\n/import_libevent/1.29/Tue Apr 15 04:34:07 2008//\n/libev.m4/1.16/Mon Oct 28 12:36:44 2013//\n/update_ev_c/1.2/Wed Jan 18 12:13:14 2012//\n/update_ev_wrap/1.6/Sun May  6 13:09:29 2012//\n/update_symbols/1.1/Wed Dec 19 01:59:29 2007//\nD\n"
  },
  {
    "path": "libev/CVS/Repository",
    "content": "libev\n"
  },
  {
    "path": "libev/CVS/Root",
    "content": ":pserver:anonymous@cvs.schmorp.de/schmorpforge\n"
  },
  {
    "path": "libev/Changes",
    "content": "Revision history for libev, a high-performance and full-featured event loop.\n\n\t- ANDROID => __ANDROID__ (reported by enh@google.com).\n        - disable epoll_create1 on android because it has broken header files\n          and google is unwilling to fix them (reported by enh@google.com).\n\n4.24 Wed Dec 28 05:19:55 CET 2016\n\t- bump version to 4.24, as the release tarball inexplicably\n          didn't have the right version in ev.h, even though the cvs-tagged\n          version did have the right one (reported by Ales Teska).\n\n4.23 Wed Nov 16 18:23:41 CET 2016\n\t- move some declarations at the beginning to help certain retarded\n          microsoft compilers, even though their documentation claims\n          otherwise (reported by Ruslan Osmanov).\n\n4.22 Sun Dec 20 22:11:50 CET 2015\n\t- when epoll detects unremovable fds in the fd set, rebuild\n          only the epoll descriptor, not the signal pipe, to avoid\n          SIGPIPE in ev_async_send. This doesn't solve it on fork,\n          so document what needs to be done in ev_loop_fork\n          (analyzed by Benjamin Mahler).\n\t- remove superfluous sys/timeb.h include on win32\n          (analyzed by Jason Madden).\n        - updated libecb.\n\n4.20 Sat Jun 20 13:01:43 CEST 2015\n\t- prefer noexcept over throw () with C++ 11.\n        - update ecb.h due to incompatibilities with c11.\n        - fix a potential aliasing issue when reading and writing\n          watcher callbacks.\n\n4.19 Thu Sep 25 08:18:25 CEST 2014\n\t- ev.h wasn't valid C++ anymore, which tripped compilers other than\n          clang, msvc or gcc (analyzed by Raphael 'kena' Poss). Unfortunately,\n          C++ doesn't support typedefs for function pointers fully, so the affected\n          declarations have to spell out the types each time.\n\t- when not using autoconf, tighten the check for clock_gettime and related\n          functionality.\n\n4.18 Fri Sep  5 17:55:26 CEST 2014\n\t- events on files were not always generated properly with the\n          epoll backend (testcase by Assaf Inbal).\n\t- mark event pipe fd as cloexec after a fork (analyzed by Sami Farin).\n        - (ecb) support m68k, m88k and sh (patch by Miod Vallat).\n        - use a reasonable fallback for EV_NSIG instead of erroring out\n          when we can't detect the signal set size.\n        - in the absence of autoconf, do not use the clock syscall\n          on glibc >= 2.17 (avoids the syscall AND -lrt on systems\n          doing clock_gettime in userspace).\n        - ensure extern \"C\" function pointers are used for externally-visible\n          loop callbacks (not watcher callbacks yet).\n        - (ecb) work around memory barriers and volatile apparently both being\n          broken in visual studio 2008 and later (analysed and patch by Nicolas Noble).\n\n4.15 Fri Mar  1 12:04:50 CET 2013\n        - destroying a non-default loop would stop the global waitpid\n          watcher (Denis Bilenko).\n\t- queueing pending watchers of higher priority from a watcher now invokes\n          them in a timely fashion (reported by Denis Bilenko).\n\t- add throw() to all libev functions that cannot throw exceptions, for\n          further code size decrease when compiling for C++.\n        - add throw () to callbacks that must not throw exceptions (allocator,\n          syserr, loop acquire/release, periodic reschedule cbs).\n\t- fix event_base_loop return code, add event_get_callback, event_base_new,\n          event_base_get_method calls to improve libevent 1.x emulation and add\n          some libevent 2.x functionality (based on a patch by Jeff Davey).\n        - add more memory fences to fix a bug reported by Jeff Davey. Better\n          be overfenced than underprotected.\n\t- ev_run now returns a boolean status (true meaning watchers are\n          still active).\n\t- ev_once: undef EV_ERROR in ev_kqueue.c, to avoid clashing with\n          libev's EV_ERROR (reported by 191919).\n\t- (ecb) add memory fence support for xlC (Darin McBride).\n\t- (ecb) add memory fence support for gcc-mips (Anton Kirilov).\n\t- (ecb) add memory fence support for gcc-alpha (Christian Weisgerber).\n        - work around some kernels losing file descriptors by leaking\n          the kqueue descriptor in the child.\n        - work around linux inotify not reporting IN_ATTRIB changes for directories\n          in many cases.\n        - include sys/syscall.h instead of plain syscall.h.\n        - check for io watcher loops in ev_verify, check for the most\n          common reported usage bug in ev_io_start.\n        - choose socket vs. WSASocket at compiletime using EV_USE_WSASOCKET.\n        - always use WSASend/WSARecv directly on windows, hoping that this\n          works in all cases (unlike read/write/send/recv...).\n        - try to detect signals around a fork faster (test program by\n          Denis Bilenko).\n        - work around recent glibc versions that leak memory in realloc.\n        - rename ev::embed::set to ev::embed::set_embed to avoid clashing\n          the watcher base set (loop) method.\n        - rewrite the async/signal pipe logic to always keep a valid fd, which\n          simplifies (and hopefully correctifies :) the race checking\n          on fork, at the cost of one extra fd.\n        - add fat, msdos, jffs2, ramfs, ntfs and btrfs to the list of\n          inotify-supporting filesystems.\n        - move orig_CFLAGS assignment to after AC_INIT, as newer autoconf\n          versions ignore it before\n          (https://bugzilla.redhat.com/show_bug.cgi?id=908096).\n        - add some untested android support.\n        - enum expressions must be of type int (reported by Juan Pablo L).\n\n4.11 Sat Feb  4 19:52:39 CET 2012\n\t- INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as\n          was documented already, but not implemented in the repeating case.\n        - new compiletime symbols: EV_NO_SMP and EV_NO_THREADS.\n\t- fix a race where the workaround against the epoll fork bugs\n          caused signals to not be handled anymore.\n\t- correct backend_fudge for most backends, and implement a windows\n          specific workaround to avoid looping because we call both\n          select and Sleep, both with different time resolutions.\n        - document range and guarantees of ev_sleep.\n        - document reasonable ranges for periodics interval and offset.\n        - rename backend_fudge to backend_mintime to avoid future confusion :)\n\t- change the default periodic reschedule function to hopefully be more\n          exact and correct even in corner cases or in the far future.\n        - do not rely on -lm anymore: use it when available but use our\n          own floor () if it is missing. This should make it easier to embed,\n          as no external libraries are required.\n        - strategically import macros from libecb and mark rarely-used functions\n          as cache-cold (saving almost 2k code size on typical amd64 setups).\n        - add Symbols.ev and Symbols.event files, that were missing.\n        - fix backend_mintime value for epoll (was 1/1024, is 1/1000 now).\n        - fix #3 \"be smart about timeouts\" to not \"deadlock\" when\n          timeout == now, also improve the section overall.\n        - avoid \"AVOIDING FINISHING BEFORE RETURNING\" idiom.\n        - support new EV_API_STATIC mode to make all libev symbols\n          static.\n        - supply default CFLAGS of -g -O3 with gcc when original CFLAGS\n          were empty.\n\n4.04 Wed Feb 16 09:01:51 CET 2011\n\t- fix two problems in the native win32 backend, where reuse of fd's\n          with different underlying handles caused handles not to be removed\n          or added to the select set (analyzed and tested by Bert Belder).\n\t- do no rely on ceil() in ev_e?poll.c.\n        - backport libev to HP-UX versions before 11 v3.\n        - configure did not detect nanosleep and clock_gettime properly when\n          they are available in the libc (as opposed to -lrt).\n\n4.03 Tue Jan 11 14:37:25 CET 2011\n\t- officially support polling files with all backends.\n\t- support files, /dev/zero etc. the same way as select in the epoll\n          backend, by generating events on our own.\n        - ports backend: work around solaris bug 6874410 and many related ones\n          (EINTR, maybe more), with no performance loss (note that the solaris\n          bug report is actually wrong, reality is far more bizarre and broken\n          than that).\n\t- define EV_READ/EV_WRITE as macros in event.h, as some programs use\n          #ifdef to test for them.\n        - new (experimental) function: ev_feed_signal.\n        - new (to become default) EVFLAG_NOSIGMASK flag.\n        - new EVBACKEND_MASK symbol.\n        - updated COMMON IDIOMS SECTION.\n\n4.01 Fri Nov  5 21:51:29 CET 2010\n        - automake fucked it up, apparently, --add-missing -f is not quite enough\n          to make it update its files, so 4.00 didn't install ev++.h and\n          event.h on make install. grrr.\n        - ev_loop(count|depth) didn't return anything (Robin Haberkorn).\n        - change EV_UNDEF to 0xffffffff to silence some overzealous compilers.\n        - use \"(libev) \" prefix for all libev error messages now.\n\n4.00 Mon Oct 25 12:32:12 CEST 2010\n\t- \"PORTING FROM LIBEV 3.X TO 4.X\" (in ev.pod) is recommended reading.\n\t- ev_embed_stop did not correctly stop the watcher (very good\n          testcase by Vladimir Timofeev).\n        - ev_run will now always update the current loop time - it erroneously\n          didn't when idle watchers were active, causing timers not to fire.\n        - fix a bug where a timeout of zero caused the timer not to fire\n          in the libevent emulation (testcase by Péter Szabó).\n\t- applied win32 fixes by Michael Lenaghan (also James Mansion).\n\t- replace EV_MINIMAL by EV_FEATURES.\n        - prefer EPOLL_CTL_ADD over EPOLL_CTL_MOD in some more cases, as it\n          seems the former is *much* faster than the latter.\n        - linux kernel version detection (for inotify bug workarounds)\n          did not work properly.\n        - reduce the number of spurious wake-ups with the ports backend.\n        - remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu).\n        - do async init within ev_async_start, not ev_async_set, which avoids\n          an API quirk where the set function must be called in the C++ API\n          even when there is nothing to set.\n        - add (undocumented) EV_ENABLE when adding events with kqueue,\n          this might help with OS X, which seems to need it despite documenting\n          not to need it (helpfully pointed out by Tilghman Lesher).\n        - do not use poll by default on freebsd, it's broken (what isn't\n          on freebsd...).\n        - allow to embed epoll on kernels >= 2.6.32.\n        - configure now prepends -O3, not appends it, so one can still\n          override it.\n        - ev.pod: greatly expanded the portability section, added a porting\n          section, a description of watcher states and made lots of minor fixes.\n        - disable poll backend on AIX, the poll header spams the namespace\n          and it's not worth working around dead platforms (reported\n          and analyzed by Aivars Kalvans).\n        - improve header file compatibility of the standalone eventfd code\n          in an obscure case.\n        - implement EV_AVOID_STDIO option.\n        - do not use sscanf to parse linux version number (smaller, faster,\n          no sscanf dependency).\n        - new EV_CHILD_ENABLE and EV_SIGNAL_ENABLE configurable settings.\n        - update libev.m4 HAVE_CLOCK_SYSCALL test for newer glibcs.\n        - add section on accept() problems to the manpage.\n        - rename EV_TIMEOUT to EV_TIMER.\n        - rename ev_loop_count/depth/verify/loop/unloop.\n        - remove ev_default_destroy and ev_default_fork.\n        - switch to two-digit minor version.\n        - work around an apparent gentoo compiler bug.\n        - define _DARWIN_UNLIMITED_SELECT. just so.\n        - use enum instead of #define for most constants.\n        - improve compatibility to older C++ compilers.\n        - (experimental) ev_run/ev_default_loop/ev_break/ev_loop_new have now\n          default arguments when compiled as C++.\n        - enable automake dependency tracking.\n        - ev_loop_new no longer leaks memory when loop creation failed.\n        - new ev_cleanup watcher type.\n\n3.9  Thu Dec 31 07:59:59 CET 2009\n\t- signalfd is no longer used by default and has to be requested\n          explicitly - this means that easy to catch bugs become hard to\n          catch race conditions, but the users have spoken.\n        - point out the unspecified signal mask in the documentation, and\n          that this is a race condition regardless of EV_SIGNALFD.\n\t- backport inotify code to C89.\n        - inotify file descriptors could leak into child processes.\n        - ev_stat watchers could keep an erroneous extra ref on the loop,\n          preventing exit when unregistering all watchers (testcases\n          provided by ry@tinyclouds.org).\n        - implement EV_WIN32_HANDLE_TO_FD and EV_WIN32_CLOSE_FD configuration\n          symbols to make it easier for apps to do their own fd management.\n        - support EV_IDLE_ENABLE being disabled in ev++.h\n          (patch by Didier Spezia).\n        - take advantage of inotify_init1, if available, to set cloexec/nonblock\n          on fd creation, to avoid races.\n        - the signal handling pipe wasn't always initialised under windows\n          (analysed by lekma).\n        - changed minimum glibc requirement from glibc 2.9 to 2.7, for\n          signalfd.\n        - add missing string.h include (Denis F. Latypoff).\n        - only replace ev_stat.prev when we detect an actual difference,\n          so prev is (almost) always different to attr. this might\n          have caused the problems with 04_stat.t.\n        - add ev::timer->remaining () method to C++ API.\n\n3.8  Sun Aug  9 14:30:45 CEST 2009\n\t- incompatible change: do not necessarily reset signal handler\n          to SIG_DFL when a sighandler is stopped.\n        - ev_default_destroy did not properly free or zero some members,\n          potentially causing crashes and memory corruption on repeated\n          ev_default_destroy/ev_default_loop calls.\n\t- take advantage of signalfd on GNU/Linux systems.\n\t- document that the signal mask might be in an unspecified\n          state when using libev's signal handling.\n        - take advantage of some GNU/Linux calls to set cloexec/nonblock\n          on fd creation, to avoid race conditions.\n\n3.7  Fri Jul 17 16:36:32 CEST 2009\n\t- ev_unloop and ev_loop wrongly used a global variable to exit loops,\n          instead of using a per-loop variable (bug caught by accident...).\n\t- the ev_set_io_collect_interval interpretation has changed.\n        - add new functionality: ev_set_userdata, ev_userdata,\n          ev_set_invoke_pending_cb, ev_set_loop_release_cb,\n          ev_invoke_pending, ev_pending_count, together with a long example\n          about thread locking.\n        - add ev_timer_remaining (as requested by Denis F. Latypoff).\n        - add ev_loop_depth.\n        - calling ev_unloop in fork/prepare watchers will no longer poll\n          for new events.\n\t- Denis F. Latypoff corrected many typos in example code snippets.\n        - honor autoconf detection of EV_USE_CLOCK_SYSCALL, also double-\n          check that the syscall number is available before trying to\n          use it (reported by ry@tinyclouds).\n        - use GetSystemTimeAsFileTime instead of _timeb on windows, for\n          slightly higher accuracy.\n        - properly declare ev_loop_verify and ev_now_update even when\n          !EV_MULTIPLICITY.\n        - do not compile in any priority code when EV_MAXPRI == EV_MINPRI.\n        - support EV_MINIMAL==2 for a reduced API.\n        - actually 0-initialise struct sigaction when installing signals.\n        - add section on hibernate and stopped processes to ev_timer docs.\n\n3.6  Tue Apr 28 02:49:30 CEST 2009\n\t- multiple timers becoming ready within an event loop iteration\n          will be invoked in the \"correct\" order now.\n\t- do not leave the event loop early just because we have no active\n          watchers, fixing a problem when embedding a kqueue loop\n          that has active kernel events but no registered watchers\n          (reported by blacksand blacksand).\n\t- correctly zero the idx values for arrays, so destroying and\n          reinitialising the default loop actually works (patch by\n          Malek Hadj-Ali).\n        - implement ev_suspend and ev_resume.\n        - new EV_CUSTOM revents flag for use by applications.\n        - add documentation section about priorities.\n        - add a glossary to the documentation.\n        - extend the ev_fork description slightly.\n        - optimize a jump out of call_pending.\n\n3.53 Sun Feb 15 02:38:20 CET 2009\n\t- fix a bug in event pipe creation on win32 that would cause a\n          failed assertion on event loop creation (patch by Malek Hadj-Ali).\n\t- probe for CLOCK_REALTIME support at runtime as well and fall\n          back to gettimeofday if there is an error, to support older\n          operating systems with newer header files/libraries.\n        - prefer gettimeofday over clock_gettime with USE_CLOCK_SYSCALL\n          (default most everywhere), otherwise not.\n\n3.52 Wed Jan  7 21:43:02 CET 2009\n\t- fix compilation of select backend in fd_set mode when NFDBITS is\n          missing (to get it to compile on QNX, reported by Rodrigo Campos).\n        - better select-nfds handling when select backend is in fd_set mode.\n        - diagnose fd_set overruns when select backend is in fd_set mode.\n        - due to a thinko, instead of disabling everything but\n          select on the borked OS X platform, everything but select was\n          allowed (reported by Emanuele Giaquinta).\n        - actually verify that local and remote port are matching in\n          libev's socketpair emulation, which makes denial-of-service\n          attacks harder (but not impossible - it's windows). Make sure\n          it even works under vista, which thinks that getpeer/sockname\n          should return fantasy port numbers.\n        - include \"libev\" in all assertion messages for potentially\n          clearer diagnostics.\n        - event_get_version (libevent compatibility) returned\n          a useless string instead of the expected version string\n          (patch by W.C.A. Wijngaards).\n\n3.51 Wed Dec 24 23:00:11 CET 2008\n        - fix a bug where an inotify watcher was added twice, causing\n          freezes on hash collisions (reported and analysed by Graham Leggett).\n\t- new config symbol, EV_USE_CLOCK_SYSCALL, to make libev use\n          a direct syscall - slower, but no dependency on librt et al.\n        - assume negative return values != -1 signals success of port_getn\n          (http://cvs.epicsol.org/cgi/viewcvs.cgi/epic5/source/newio.c?rev=1.52)\n          (no known failure reports, but it doesn't hurt).\n        - fork detection in ev_embed now stops and restarts the watcher\n          automatically.\n        - EXPERIMENTAL: default the method to operator () in ev++.h,\n          to make it nicer to use functors (requested by Benedek László).\n        - fixed const object callbacks in ev++.h.\n        - replaced loop_ref argument of watcher.set (loop) by a direct\n          ev_loop * in ev++.h, to avoid clashes with functor patch.\n        - do not try to watch the empty string via inotify.\n        - inotify watchers could be leaked under certain circumstances.\n        - OS X 10.5 is actually even more broken than earlier versions,\n          so fall back to select on that piece of garbage.\n        - fixed some weirdness in the ev_embed documentation.\n\n3.49 Wed Nov 19 11:26:53 CET 2008\n\t- ev_stat watchers will now use inotify as a mere hint on\n          kernels <2.6.25, or if the filesystem is not in the\n          \"known to be good\" list.\n        - better mingw32 compatibility (it's not as borked as native win32)\n          (analysed by Roger Pack).\n        - include stdio.h in the example program, as too many people are\n          confused by the weird C language otherwise. I guess the next thing\n          I get told is that the \"...\" ellipses in the examples don't compile\n          with their C compiler.\n\n3.48 Thu Oct 30 09:02:37 CET 2008\n\t- further optimise away the EPOLL_CTL_ADD/MOD combo in the epoll\n          backend by assuming the kernel event mask hasn't changed if\n          ADD fails with EEXIST.\n        - work around spurious event notification bugs in epoll by using\n          a 32-bit generation counter. recreate kernel state if we receive\n          spurious notifications or unwanted events. this is very costly,\n          but I didn't come up with this horrible design.\n        - use memset to initialise most arrays now and do away with the\n          init functions.\n        - expand time-out strategies into a \"Be smart about timeouts\" section.\n        - drop the \"struct\" from all ev_watcher declarations in the\n          documentation and did other clarifications (yeah, it was a mistake\n          to have a struct AND a function called ev_loop).\n\t- fix a bug where ev_default would not initialise the default\n          loop again after it was destroyed with ev_default_destroy.\n        - rename syserr to ev_syserr to avoid name clashes when embedding,\n          do similar changes for event.c.\n\n3.45 Tue Oct 21 21:59:26 CEST 2008\n\t- disable inotify usage on linux <2.6.25, as it is broken\n          (reported by Yoann Vandoorselaere).\n        - ev_stat erroneously would try to add inotify watchers\n          even when inotify wasn't available (this should only\n          have a performance impact).\n\t- ev_once now passes both timeout and io to the callback if both\n          occur concurrently, instead of giving timeouts precedence.\n\t- disable EV_USE_INOTIFY when sys/inotify.h is too old.\n\n3.44 Mon Sep 29 05:18:39 CEST 2008\n\t- embed watchers now automatically invoke ev_loop_fork on the\n          embedded loop when the parent loop forks.\n\t- new function: ev_now_update (loop).\n\t- verify_watcher was not marked static.\n        - improve the \"associating...\" manpage section.\n        - documentation tweaks here and there.\n\n3.43 Sun Jul  6 05:34:41 CEST 2008\n\t- include more include files on windows to get struct _stati64\n          (reported by Chris Hulbert, but doesn't quite fix his issue).\n\t- add missing #include <io.h> in ev.c on windows (reported by\n          Matt Tolton).\n\n3.42 Tue Jun 17 12:12:07 CEST 2008\n\t- work around yet another windows bug: FD_SET actually adds fd's\n          multiple times to the fd_*SET*, despite official MSN docs claiming\n          otherwise. Reported and well-analysed by Matt Tolton.\n\t- define NFDBITS to 0 when EV_SELECT_IS_WINSOCKET to make it compile\n          (reported any analysed by Chris Hulbert).\n        - fix a bug in ev_ebadf (this function is only used to catch\n          programming errors in the libev user). reported by Matt Tolton.\n        - fix a bug in fd_intern on win32 (could lead to compile errors\n          under some circumstances, but would work correctly if it compiles).\n          reported by Matt Tolton.\n        - (try to) work around missing lstat on windows.\n\t- pass in the write fd set as except fd set under windows. windows\n          is so uncontrollably lame that it requires this. this means that\n          switching off oobinline is not supported (but tcp/ip doesn't\n          have oob, so that would be stupid anyways.\n        - use posix module symbol to auto-detect monotonic clock presence\n          and some other default values.\n\n3.41 Fri May 23 18:42:54 CEST 2008\n\t- work around an obscure bug in winsocket select: if you\n          provide only empty fd sets then select returns WSAEINVAL. how sucky.\n        - improve timer scheduling stability and reduce use of time_epsilon.\n        - use 1-based 2-heap for EV_MINIMAL, simplifies code, reduces\n          codesize and makes for better cache-efficiency.\n        - use 3-based 4-heap for !EV_MINIMAL. this makes better use\n          of cpu cache lines and gives better growth behaviour than\n          2-based heaps.\n        - cache timestamp within heap for !EV_MINIMAL, to avoid random\n          memory accesses.\n        - document/add EV_USE_4HEAP and EV_HEAP_CACHE_AT.\n        - fix a potential aliasing issue in ev_timer_again.\n        - add/document ev_periodic_at, retract direct access to ->at.\n        - improve ev_stat docs.\n        - add portability requirements section.\n\t- fix manpage headers etc.\n        - normalise WSA error codes to lower range on windows.\n        - add consistency check code that can be called automatically\n          or on demand to check for internal structures (ev_loop_verify).\n\n3.31 Wed Apr 16 20:45:04 CEST 2008\n\t- added last minute fix for ev_poll.c by Brandon Black.\n\n3.3  Wed Apr 16 19:04:10 CEST 2008\n        - event_base_loopexit should return 0 on success\n          (W.C.A. Wijngaards).\n\t- added linux eventfd support.\n        - try to autodetect epoll and inotify support\n          by libc header version if not using autoconf.\n        - new symbols: EV_DEFAULT_UC and EV_DEFAULT_UC_.\n        - declare functions defined in ev.h as inline if\n          C99 or gcc are available.\n        - enable inlining with gcc versions 2 and 3.\n        - work around broken poll implementations potentially\n          not clearing revents field in ev_poll (Brandon Black)\n          (no such systems are known at this time).\n        - work around a bug in realloc on openbsd and darwin,\n          also makes the erroneous valgrind complaints\n          go away (noted by various people).\n        - fix ev_async_pending, add c++ wrapper for ev_async\n          (based on patch sent by Johannes Deisenhofer).\n        - add sensible set method to ev::embed.\n        - made integer constants type int in ev.h.\n\n3.2  Wed Apr  2 17:11:19 CEST 2008\n\t- fix a 64 bit overflow issue in the select backend,\n          by using fd_mask instead of int for the mask.\n        - rename internal sighandler to avoid clash with very old perls.\n        - entering ev_loop will not clear the ONESHOT or NONBLOCKING\n          flags of any outer loops anymore.\n        - add ev_async_pending.\n\n3.1  Thu Mar 13 13:45:22 CET 2008\n\t- implement ev_async watchers.\n        - only initialise signal pipe on demand.\n\t- make use of sig_atomic_t configurable.\n        - improved documentation.\n\n3.0  Mon Jan 28 13:14:47 CET 2008\n\t- API/ABI bump to version 3.0.\n\t- ev++.h includes \"ev.h\" by default now, not <ev.h>.\n\t- slightly improved documentation.\n\t- speed up signal detection after a fork.\n        - only optionally return trace status changed in ev_child\n          watchers.\n        - experimental (and undocumented) loop wrappers for ev++.h.\n\n2.01 Tue Dec 25 08:04:41 CET 2007\n\t- separate Changes file.\n\t- fix ev_path_set => ev_stat_set typo.\n        - remove event_compat.h from the libev tarball.\n        - change how include files are found.\n        - doc updates.\n        - update licenses, explicitly allow for GPL relicensing.\n\n2.0  Sat Dec 22 17:47:03 CET 2007\n        - new ev_sleep, ev_set_(io|timeout)_collect_interval.\n        - removed epoll from embeddable fd set.\n        - fix embed watchers.\n\t- renamed ev_embed.loop to other.\n\t- added exported Symbol tables.\n        - undefine member wrapper macros at the end of ev.c.\n        - respect EV_H in ev++.h.\n\n1.86 Tue Dec 18 02:36:57 CET 2007\n\t- fix memleak on loop destroy (not relevant for perl).\n\n1.85 Fri Dec 14 20:32:40 CET 2007\n        - fix some aliasing issues w.r.t. timers and periodics\n          (not relevant for perl).\n\n(for historic versions refer to EV/Changes, found in the Perl interface)\n\n0.1  Wed Oct 31 21:31:48 CET 2007\n\t- original version; hacked together in <24h.\n\n"
  },
  {
    "path": "libev/LICENSE",
    "content": "All files in libev are\nCopyright (c)2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials provided\n      with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nAlternatively, the contents of this package may be used under the terms\nof the GNU General Public License (\"GPL\") version 2 or any later version,\nin which case the provisions of the GPL are applicable instead of the\nabove. If you wish to allow the use of your version of this package only\nunder the terms of the GPL and not to allow others to use your version of\nthis file under the BSD license, indicate your decision by deleting the\nprovisions above and replace them with the notice and other provisions\nrequired by the GPL in this and the other files of this package. If you do\nnot delete the provisions above, a recipient may use your version of this\nfile under either the BSD or the GPL.\n"
  },
  {
    "path": "libev/Makefile.am",
    "content": "AUTOMAKE_OPTIONS = foreign\n\nVERSION_INFO = 4:0:0\n\nEXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \\\n\t     ev_vars.h ev_wrap.h \\\n\t     ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c \\\n\t     ev.3 ev.pod Symbols.ev Symbols.event\n\nman_MANS = ev.3\n\ninclude_HEADERS = ev.h ev++.h event.h\n\nlib_LTLIBRARIES = libev.la\n\nlibev_la_SOURCES = ev.c event.c\nlibev_la_LDFLAGS = -version-info $(VERSION_INFO)\n\nev.3: ev.pod\n\tpod2man -n LIBEV -r \"libev-$(VERSION)\" -c \"libev - high performance full featured event loop\" -s3 <$< >$@\n"
  },
  {
    "path": "libev/README",
    "content": "libev is a high-performance event loop/event model with lots of features.\n(see benchmark at http://libev.schmorp.de/bench.html)\n\n\nABOUT\n\n   Homepage: http://software.schmorp.de/pkg/libev\n   Mailinglist: libev@lists.schmorp.de\n                http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev\n   Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod\n\n   Libev is modelled (very losely) after libevent and the Event perl\n   module, but is faster, scales better and is more correct, and also more\n   featureful. And also smaller. Yay.\n\n   Some of the specialties of libev not commonly found elsewhere are:\n   \n   - extensive and detailed, readable documentation (not doxygen garbage).\n   - fully supports fork, can detect fork in various ways and automatically\n     re-arms kernel mechanisms that do not support fork.\n   - highly optimised select, poll, epoll, kqueue and event ports backends.\n   - filesystem object (path) watching (with optional linux inotify support).\n   - wallclock-based times (using absolute time, cron-like).\n   - relative timers/timeouts (handle time jumps).\n   - fast intra-thread communication between multiple\n     event loops (with optional fast linux eventfd backend).\n   - extremely easy to embed (fully documented, no dependencies,\n     autoconf supported but optional).\n   - very small codebase, no bloated library, simple code.\n   - fully extensible by being able to plug into the event loop,\n     integrate other event loops, integrate other event loop users.\n   - very little memory use (small watchers, small event loop data).\n   - optional C++ interface allowing method and function callbacks\n     at no extra memory or runtime overhead.\n   - optional Perl interface with similar characteristics (capable\n     of running Glib/Gtk2 on libev).\n   - support for other languages (multiple C++ interfaces, D, Ruby,\n     Python) available from third-parties.\n\n   Examples of programs that embed libev: the EV perl module, node.js,\n   auditd, rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the\n   Deliantra MMORPG server (http://www.deliantra.net/), Rubinius (a\n   next-generation Ruby VM), the Ebb web server, the Rev event toolkit.\n\n\nCONTRIBUTORS\n\n   libev was written and designed by Marc Lehmann and Emanuele Giaquinta.\n\n   The following people sent in patches or made other noteworthy\n   contributions to the design (for minor patches, see the Changes\n   file. If I forgot to include you, please shout at me, it was an\n   accident):\n\n   W.C.A. Wijngaards\n   Christopher Layne\n   Chris Brody\n\n"
  },
  {
    "path": "libev/README.embed",
    "content": "This file is now included in the main libev documentation, see\n\n   http://cvs.schmorp.de/libev/ev.html\n"
  },
  {
    "path": "libev/Symbols.ev",
    "content": "ev_async_send\nev_async_start\nev_async_stop\nev_backend\nev_break\nev_check_start\nev_check_stop\nev_child_start\nev_child_stop\nev_cleanup_start\nev_cleanup_stop\nev_clear_pending\nev_default_loop\nev_default_loop_ptr\nev_depth\nev_embed_start\nev_embed_stop\nev_embed_sweep\nev_embeddable_backends\nev_feed_event\nev_feed_fd_event\nev_feed_signal\nev_feed_signal_event\nev_fork_start\nev_fork_stop\nev_idle_start\nev_idle_stop\nev_invoke\nev_invoke_pending\nev_io_start\nev_io_stop\nev_iteration\nev_loop_destroy\nev_loop_fork\nev_loop_new\nev_now\nev_now_update\nev_once\nev_pending_count\nev_periodic_again\nev_periodic_start\nev_periodic_stop\nev_prepare_start\nev_prepare_stop\nev_recommended_backends\nev_ref\nev_resume\nev_run\nev_set_allocator\nev_set_invoke_pending_cb\nev_set_io_collect_interval\nev_set_loop_release_cb\nev_set_syserr_cb\nev_set_timeout_collect_interval\nev_set_userdata\nev_signal_start\nev_signal_stop\nev_sleep\nev_stat_start\nev_stat_stat\nev_stat_stop\nev_supported_backends\nev_suspend\nev_time\nev_timer_again\nev_timer_remaining\nev_timer_start\nev_timer_stop\nev_unref\nev_userdata\nev_verify\nev_version_major\nev_version_minor\n"
  },
  {
    "path": "libev/Symbols.event",
    "content": "event_active\nevent_add\nevent_base_dispatch\nevent_base_free\nevent_base_get_method\nevent_base_loop\nevent_base_loopexit\nevent_base_new\nevent_base_once\nevent_base_priority_init\nevent_base_set\nevent_del\nevent_dispatch\nevent_get_callback\nevent_get_method\nevent_get_version\nevent_init\nevent_loop\nevent_loopexit\nevent_once\nevent_pending\nevent_priority_init\nevent_priority_set\nevent_set\n"
  },
  {
    "path": "libev/autogen.sh",
    "content": "#!/bin/sh\n\nautoreconf --install --symlink --force\n"
  },
  {
    "path": "libev/configure.ac",
    "content": "AC_INIT\n\norig_CFLAGS=\"$CFLAGS\"\n\nAC_CONFIG_SRCDIR([ev_epoll.c])\n\ndnl also update ev.h!\nAM_INIT_AUTOMAKE(libev,4.24)\nAC_CONFIG_HEADERS([config.h])\nAM_MAINTAINER_MODE\n\nAC_PROG_CC\n\ndnl Supply default CFLAGS, if not specified\nif test -z \"$orig_CFLAGS\"; then\n  if test x$GCC = xyes; then\n    CFLAGS=\"-g -O3\"\n  fi\nfi\n\nAC_PROG_INSTALL\nAC_PROG_LIBTOOL\n\nm4_include([libev.m4])\n\nAC_CONFIG_FILES([Makefile])\nAC_OUTPUT\n"
  },
  {
    "path": "libev/ev++.h",
    "content": "/*\n * libev simple C++ wrapper classes\n *\n * Copyright (c) 2007,2008,2010 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef EVPP_H__\n#define EVPP_H__\n\n#ifdef EV_H\n# include EV_H\n#else\n# include \"ev.h\"\n#endif\n\n#ifndef EV_USE_STDEXCEPT\n# define EV_USE_STDEXCEPT 1\n#endif\n\n#if EV_USE_STDEXCEPT\n# include <stdexcept>\n#endif\n\nnamespace ev {\n\n  typedef ev_tstamp tstamp;\n\n  enum {\n    UNDEF    = EV_UNDEF,\n    NONE     = EV_NONE,\n    READ     = EV_READ,\n    WRITE    = EV_WRITE,\n#if EV_COMPAT3\n    TIMEOUT  = EV_TIMEOUT,\n#endif\n    TIMER    = EV_TIMER,\n    PERIODIC = EV_PERIODIC,\n    SIGNAL   = EV_SIGNAL,\n    CHILD    = EV_CHILD,\n    STAT     = EV_STAT,\n    IDLE     = EV_IDLE,\n    CHECK    = EV_CHECK,\n    PREPARE  = EV_PREPARE,\n    FORK     = EV_FORK,\n    ASYNC    = EV_ASYNC,\n    EMBED    = EV_EMBED,\n#   undef ERROR // some systems stupidly #define ERROR\n    ERROR    = EV_ERROR\n  };\n\n  enum\n  {\n    AUTO      = EVFLAG_AUTO,\n    NOENV     = EVFLAG_NOENV,\n    FORKCHECK = EVFLAG_FORKCHECK,\n\n    SELECT    = EVBACKEND_SELECT,\n    POLL      = EVBACKEND_POLL,\n    EPOLL     = EVBACKEND_EPOLL,\n    KQUEUE    = EVBACKEND_KQUEUE,\n    DEVPOLL   = EVBACKEND_DEVPOLL,\n    PORT      = EVBACKEND_PORT\n  };\n\n  enum\n  {\n#if EV_COMPAT3\n    NONBLOCK = EVLOOP_NONBLOCK,\n    ONESHOT  = EVLOOP_ONESHOT,\n#endif\n    NOWAIT   = EVRUN_NOWAIT,\n    ONCE     = EVRUN_ONCE\n  };\n\n  enum how_t\n  {\n    ONE = EVBREAK_ONE,\n    ALL = EVBREAK_ALL\n  };\n\n  struct bad_loop\n#if EV_USE_STDEXCEPT\n  : std::runtime_error\n#endif\n  {\n#if EV_USE_STDEXCEPT\n    bad_loop ()\n    : std::runtime_error (\"libev event loop cannot be initialized, bad value of LIBEV_FLAGS?\")\n    {\n    }\n#endif\n  };\n\n#ifdef EV_AX\n#  undef EV_AX\n#endif\n\n#ifdef EV_AX_\n#  undef EV_AX_\n#endif\n\n#if EV_MULTIPLICITY\n#  define EV_AX  raw_loop\n#  define EV_AX_ raw_loop,\n#else\n#  define EV_AX\n#  define EV_AX_\n#endif\n\n  struct loop_ref\n  {\n    loop_ref (EV_P) throw ()\n#if EV_MULTIPLICITY\n    : EV_AX (EV_A)\n#endif\n    {\n    }\n\n    bool operator == (const loop_ref &other) const throw ()\n    {\n#if EV_MULTIPLICITY\n      return EV_AX == other.EV_AX;\n#else\n      return true;\n#endif\n    }\n\n    bool operator != (const loop_ref &other) const throw ()\n    {\n#if EV_MULTIPLICITY\n      return ! (*this == other);\n#else\n      return false;\n#endif\n    }\n\n#if EV_MULTIPLICITY\n    bool operator == (const EV_P) const throw ()\n    {\n      return this->EV_AX == EV_A;\n    }\n\n    bool operator != (const EV_P) const throw ()\n    {\n      return ! (*this == EV_A);\n    }\n\n    operator struct ev_loop * () const throw ()\n    {\n      return EV_AX;\n    }\n\n    operator const struct ev_loop * () const throw ()\n    {\n      return EV_AX;\n    }\n\n    bool is_default () const throw ()\n    {\n      return EV_AX == ev_default_loop (0);\n    }\n#endif\n\n#if EV_COMPAT3\n    void loop (int flags = 0)\n    {\n      ev_run (EV_AX_ flags);\n    }\n\n    void unloop (how_t how = ONE) throw ()\n    {\n      ev_break (EV_AX_ how);\n    }\n#endif\n\n    void run (int flags = 0)\n    {\n      ev_run (EV_AX_ flags);\n    }\n\n    void break_loop (how_t how = ONE) throw ()\n    {\n      ev_break (EV_AX_ how);\n    }\n\n    void post_fork () throw ()\n    {\n      ev_loop_fork (EV_AX);\n    }\n\n    unsigned int backend () const throw ()\n    {\n      return ev_backend (EV_AX);\n    }\n\n    tstamp now () const throw ()\n    {\n      return ev_now (EV_AX);\n    }\n\n    void ref () throw ()\n    {\n      ev_ref (EV_AX);\n    }\n\n    void unref () throw ()\n    {\n      ev_unref (EV_AX);\n    }\n\n#if EV_FEATURE_API\n    unsigned int iteration () const throw ()\n    {\n      return ev_iteration (EV_AX);\n    }\n\n    unsigned int depth () const throw ()\n    {\n      return ev_depth (EV_AX);\n    }\n\n    void set_io_collect_interval (tstamp interval) throw ()\n    {\n      ev_set_io_collect_interval (EV_AX_ interval);\n    }\n\n    void set_timeout_collect_interval (tstamp interval) throw ()\n    {\n      ev_set_timeout_collect_interval (EV_AX_ interval);\n    }\n#endif\n\n    // function callback\n    void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw ()\n    {\n      ev_once (EV_AX_ fd, events, timeout, cb, arg);\n    }\n\n    // method callback\n    template<class K, void (K::*method)(int)>\n    void once (int fd, int events, tstamp timeout, K *object) throw ()\n    {\n      once (fd, events, timeout, method_thunk<K, method>, object);\n    }\n\n    // default method == operator ()\n    template<class K>\n    void once (int fd, int events, tstamp timeout, K *object) throw ()\n    {\n      once (fd, events, timeout, method_thunk<K, &K::operator ()>, object);\n    }\n\n    template<class K, void (K::*method)(int)>\n    static void method_thunk (int revents, void *arg)\n    {\n      (static_cast<K *>(arg)->*method)\n        (revents);\n    }\n\n    // no-argument method callback\n    template<class K, void (K::*method)()>\n    void once (int fd, int events, tstamp timeout, K *object) throw ()\n    {\n      once (fd, events, timeout, method_noargs_thunk<K, method>, object);\n    }\n\n    template<class K, void (K::*method)()>\n    static void method_noargs_thunk (int revents, void *arg)\n    {\n      (static_cast<K *>(arg)->*method)\n        ();\n    }\n\n    // simpler function callback\n    template<void (*cb)(int)>\n    void once (int fd, int events, tstamp timeout) throw ()\n    {\n      once (fd, events, timeout, simpler_func_thunk<cb>);\n    }\n\n    template<void (*cb)(int)>\n    static void simpler_func_thunk (int revents, void *arg)\n    {\n      (*cb)\n        (revents);\n    }\n\n    // simplest function callback\n    template<void (*cb)()>\n    void once (int fd, int events, tstamp timeout) throw ()\n    {\n      once (fd, events, timeout, simplest_func_thunk<cb>);\n    }\n\n    template<void (*cb)()>\n    static void simplest_func_thunk (int revents, void *arg)\n    {\n      (*cb)\n        ();\n    }\n\n    void feed_fd_event (int fd, int revents) throw ()\n    {\n      ev_feed_fd_event (EV_AX_ fd, revents);\n    }\n\n    void feed_signal_event (int signum) throw ()\n    {\n      ev_feed_signal_event (EV_AX_ signum);\n    }\n\n#if EV_MULTIPLICITY\n    struct ev_loop* EV_AX;\n#endif\n\n  };\n\n#if EV_MULTIPLICITY\n  struct dynamic_loop : loop_ref\n  {\n\n    dynamic_loop (unsigned int flags = AUTO) throw (bad_loop)\n    : loop_ref (ev_loop_new (flags))\n    {\n      if (!EV_AX)\n        throw bad_loop ();\n    }\n\n    ~dynamic_loop () throw ()\n    {\n      ev_loop_destroy (EV_AX);\n      EV_AX = 0;\n    }\n\n  private:\n\n    dynamic_loop (const dynamic_loop &);\n\n    dynamic_loop & operator= (const dynamic_loop &);\n\n  };\n#endif\n\n  struct default_loop : loop_ref\n  {\n    default_loop (unsigned int flags = AUTO) throw (bad_loop)\n#if EV_MULTIPLICITY\n    : loop_ref (ev_default_loop (flags))\n#endif\n    {\n      if (\n#if EV_MULTIPLICITY\n          !EV_AX\n#else\n          !ev_default_loop (flags)\n#endif\n      )\n        throw bad_loop ();\n    }\n\n  private:\n    default_loop (const default_loop &);\n    default_loop &operator = (const default_loop &);\n  };\n\n  inline loop_ref get_default_loop () throw ()\n  {\n#if EV_MULTIPLICITY\n    return ev_default_loop (0);\n#else\n    return loop_ref ();\n#endif\n  }\n\n#undef EV_AX\n#undef EV_AX_\n\n#undef EV_PX\n#undef EV_PX_\n#if EV_MULTIPLICITY\n#  define EV_PX  loop_ref EV_A\n#  define EV_PX_ loop_ref EV_A_\n#else\n#  define EV_PX\n#  define EV_PX_\n#endif\n\n  template<class ev_watcher, class watcher>\n  struct base : ev_watcher\n  {\n    #if EV_MULTIPLICITY\n      EV_PX;\n\n      // loop set\n      void set (EV_P) throw ()\n      {\n        this->EV_A = EV_A;\n      }\n    #endif\n\n    base (EV_PX) throw ()\n    #if EV_MULTIPLICITY\n      : EV_A (EV_A)\n    #endif\n    {\n      ev_init (this, 0);\n    }\n\n    void set_ (const void *data, void (*cb)(EV_P_ ev_watcher *w, int revents)) throw ()\n    {\n      this->data = (void *)data;\n      ev_set_cb (static_cast<ev_watcher *>(this), cb);\n    }\n\n    // function callback\n    template<void (*function)(watcher &w, int)>\n    void set (void *data = 0) throw ()\n    {\n      set_ (data, function_thunk<function>);\n    }\n\n    template<void (*function)(watcher &w, int)>\n    static void function_thunk (EV_P_ ev_watcher *w, int revents)\n    {\n      function\n        (*static_cast<watcher *>(w), revents);\n    }\n\n    // method callback\n    template<class K, void (K::*method)(watcher &w, int)>\n    void set (K *object) throw ()\n    {\n      set_ (object, method_thunk<K, method>);\n    }\n\n    // default method == operator ()\n    template<class K>\n    void set (K *object) throw ()\n    {\n      set_ (object, method_thunk<K, &K::operator ()>);\n    }\n\n    template<class K, void (K::*method)(watcher &w, int)>\n    static void method_thunk (EV_P_ ev_watcher *w, int revents)\n    {\n      (static_cast<K *>(w->data)->*method)\n        (*static_cast<watcher *>(w), revents);\n    }\n\n    // no-argument callback\n    template<class K, void (K::*method)()>\n    void set (K *object) throw ()\n    {\n      set_ (object, method_noargs_thunk<K, method>);\n    }\n\n    template<class K, void (K::*method)()>\n    static void method_noargs_thunk (EV_P_ ev_watcher *w, int revents)\n    {\n      (static_cast<K *>(w->data)->*method)\n        ();\n    }\n\n    void operator ()(int events = EV_UNDEF)\n    {\n      return\n        ev_cb (static_cast<ev_watcher *>(this))\n          (static_cast<ev_watcher *>(this), events);\n    }\n\n    bool is_active () const throw ()\n    {\n      return ev_is_active (static_cast<const ev_watcher *>(this));\n    }\n\n    bool is_pending () const throw ()\n    {\n      return ev_is_pending (static_cast<const ev_watcher *>(this));\n    }\n\n    void feed_event (int revents) throw ()\n    {\n      ev_feed_event (EV_A_ static_cast<ev_watcher *>(this), revents);\n    }\n  };\n\n  inline tstamp now (EV_P) throw ()\n  {\n    return ev_now (EV_A);\n  }\n\n  inline void delay (tstamp interval) throw ()\n  {\n    ev_sleep (interval);\n  }\n\n  inline int version_major () throw ()\n  {\n    return ev_version_major ();\n  }\n\n  inline int version_minor () throw ()\n  {\n    return ev_version_minor ();\n  }\n\n  inline unsigned int supported_backends () throw ()\n  {\n    return ev_supported_backends ();\n  }\n\n  inline unsigned int recommended_backends () throw ()\n  {\n    return ev_recommended_backends ();\n  }\n\n  inline unsigned int embeddable_backends () throw ()\n  {\n    return ev_embeddable_backends ();\n  }\n\n  inline void set_allocator (void *(*cb)(void *ptr, long size) throw ()) throw ()\n  {\n    ev_set_allocator (cb);\n  }\n\n  inline void set_syserr_cb (void (*cb)(const char *msg) throw ()) throw ()\n  {\n    ev_set_syserr_cb (cb);\n  }\n\n  #if EV_MULTIPLICITY\n    #define EV_CONSTRUCT(cppstem,cstem)\t                                                \\\n      (EV_PX = get_default_loop ()) throw ()                                            \\\n        : base<ev_ ## cstem, cppstem> (EV_A)                                            \\\n      {                                                                                 \\\n      }\n  #else\n    #define EV_CONSTRUCT(cppstem,cstem)                                                 \\\n      () throw ()                                                                       \\\n      {                                                                                 \\\n      }\n  #endif\n\n  /* using a template here would require quite a few more lines,\n   * so a macro solution was chosen */\n  #define EV_BEGIN_WATCHER(cppstem,cstem)\t                                        \\\n                                                                                        \\\n  struct cppstem : base<ev_ ## cstem, cppstem>                                          \\\n  {                                                                                     \\\n    void start () throw ()                                                              \\\n    {                                                                                   \\\n      ev_ ## cstem ## _start (EV_A_ static_cast<ev_ ## cstem *>(this));                 \\\n    }                                                                                   \\\n                                                                                        \\\n    void stop () throw ()                                                               \\\n    {                                                                                   \\\n      ev_ ## cstem ## _stop (EV_A_ static_cast<ev_ ## cstem *>(this));                  \\\n    }                                                                                   \\\n                                                                                        \\\n    cppstem EV_CONSTRUCT(cppstem,cstem)                                                 \\\n                                                                                        \\\n    ~cppstem () throw ()                                                                \\\n    {                                                                                   \\\n      stop ();                                                                          \\\n    }                                                                                   \\\n                                                                                        \\\n    using base<ev_ ## cstem, cppstem>::set;                                             \\\n                                                                                        \\\n  private:                                                                              \\\n                                                                                        \\\n    cppstem (const cppstem &o);                                                         \\\n                                                                                        \\\n    cppstem &operator =(const cppstem &o);                                              \\\n                                                                                        \\\n  public:\n\n  #define EV_END_WATCHER(cppstem,cstem)\t                                                \\\n  };\n\n  EV_BEGIN_WATCHER (io, io)\n    void set (int fd, int events) throw ()\n    {\n      int active = is_active ();\n      if (active) stop ();\n      ev_io_set (static_cast<ev_io *>(this), fd, events);\n      if (active) start ();\n    }\n\n    void set (int events) throw ()\n    {\n      int active = is_active ();\n      if (active) stop ();\n      ev_io_set (static_cast<ev_io *>(this), fd, events);\n      if (active) start ();\n    }\n\n    void start (int fd, int events) throw ()\n    {\n      set (fd, events);\n      start ();\n    }\n  EV_END_WATCHER (io, io)\n\n  EV_BEGIN_WATCHER (timer, timer)\n    void set (ev_tstamp after, ev_tstamp repeat = 0.) throw ()\n    {\n      int active = is_active ();\n      if (active) stop ();\n      ev_timer_set (static_cast<ev_timer *>(this), after, repeat);\n      if (active) start ();\n    }\n\n    void start (ev_tstamp after, ev_tstamp repeat = 0.) throw ()\n    {\n      set (after, repeat);\n      start ();\n    }\n\n    void again () throw ()\n    {\n      ev_timer_again (EV_A_ static_cast<ev_timer *>(this));\n    }\n\n    ev_tstamp remaining ()\n    {\n      return ev_timer_remaining (EV_A_ static_cast<ev_timer *>(this));\n    }\n  EV_END_WATCHER (timer, timer)\n\n  #if EV_PERIODIC_ENABLE\n  EV_BEGIN_WATCHER (periodic, periodic)\n    void set (ev_tstamp at, ev_tstamp interval = 0.) throw ()\n    {\n      int active = is_active ();\n      if (active) stop ();\n      ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);\n      if (active) start ();\n    }\n\n    void start (ev_tstamp at, ev_tstamp interval = 0.) throw ()\n    {\n      set (at, interval);\n      start ();\n    }\n\n    void again () throw ()\n    {\n      ev_periodic_again (EV_A_ static_cast<ev_periodic *>(this));\n    }\n  EV_END_WATCHER (periodic, periodic)\n  #endif\n\n  #if EV_SIGNAL_ENABLE\n  EV_BEGIN_WATCHER (sig, signal)\n    void set (int signum) throw ()\n    {\n      int active = is_active ();\n      if (active) stop ();\n      ev_signal_set (static_cast<ev_signal *>(this), signum);\n      if (active) start ();\n    }\n\n    void start (int signum) throw ()\n    {\n      set (signum);\n      start ();\n    }\n  EV_END_WATCHER (sig, signal)\n  #endif\n\n  #if EV_CHILD_ENABLE\n  EV_BEGIN_WATCHER (child, child)\n    void set (int pid, int trace = 0) throw ()\n    {\n      int active = is_active ();\n      if (active) stop ();\n      ev_child_set (static_cast<ev_child *>(this), pid, trace);\n      if (active) start ();\n    }\n\n    void start (int pid, int trace = 0) throw ()\n    {\n      set (pid, trace);\n      start ();\n    }\n  EV_END_WATCHER (child, child)\n  #endif\n\n  #if EV_STAT_ENABLE\n  EV_BEGIN_WATCHER (stat, stat)\n    void set (const char *path, ev_tstamp interval = 0.) throw ()\n    {\n      int active = is_active ();\n      if (active) stop ();\n      ev_stat_set (static_cast<ev_stat *>(this), path, interval);\n      if (active) start ();\n    }\n\n    void start (const char *path, ev_tstamp interval = 0.) throw ()\n    {\n      stop ();\n      set (path, interval);\n      start ();\n    }\n\n    void update () throw ()\n    {\n      ev_stat_stat (EV_A_ static_cast<ev_stat *>(this));\n    }\n  EV_END_WATCHER (stat, stat)\n  #endif\n\n  #if EV_IDLE_ENABLE\n  EV_BEGIN_WATCHER (idle, idle)\n    void set () throw () { }\n  EV_END_WATCHER (idle, idle)\n  #endif\n\n  #if EV_PREPARE_ENABLE\n  EV_BEGIN_WATCHER (prepare, prepare)\n    void set () throw () { }\n  EV_END_WATCHER (prepare, prepare)\n  #endif\n\n  #if EV_CHECK_ENABLE\n  EV_BEGIN_WATCHER (check, check)\n    void set () throw () { }\n  EV_END_WATCHER (check, check)\n  #endif\n\n  #if EV_EMBED_ENABLE\n  EV_BEGIN_WATCHER (embed, embed)\n    void set_embed (struct ev_loop *embedded_loop) throw ()\n    {\n      int active = is_active ();\n      if (active) stop ();\n      ev_embed_set (static_cast<ev_embed *>(this), embedded_loop);\n      if (active) start ();\n    }\n\n    void start (struct ev_loop *embedded_loop) throw ()\n    {\n      set (embedded_loop);\n      start ();\n    }\n\n    void sweep ()\n    {\n      ev_embed_sweep (EV_A_ static_cast<ev_embed *>(this));\n    }\n  EV_END_WATCHER (embed, embed)\n  #endif\n\n  #if EV_FORK_ENABLE\n  EV_BEGIN_WATCHER (fork, fork)\n    void set () throw () { }\n  EV_END_WATCHER (fork, fork)\n  #endif\n\n  #if EV_ASYNC_ENABLE\n  EV_BEGIN_WATCHER (async, async)\n    void send () throw ()\n    {\n      ev_async_send (EV_A_ static_cast<ev_async *>(this));\n    }\n\n    bool async_pending () throw ()\n    {\n      return ev_async_pending (static_cast<ev_async *>(this));\n    }\n  EV_END_WATCHER (async, async)\n  #endif\n\n  #undef EV_PX\n  #undef EV_PX_\n  #undef EV_CONSTRUCT\n  #undef EV_BEGIN_WATCHER\n  #undef EV_END_WATCHER\n}\n\n#endif\n\n"
  },
  {
    "path": "libev/ev.3",
    "content": ".\\\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29)\n.\\\"\n.\\\" Standard preamble:\n.\\\" ========================================================================\n.de Sp \\\" Vertical space (when we can't use .PP)\n.if t .sp .5v\n.if n .sp\n..\n.de Vb \\\" Begin verbatim text\n.ft CW\n.nf\n.ne \\\\$1\n..\n.de Ve \\\" End verbatim text\n.ft R\n.fi\n..\n.\\\" Set up some character translations and predefined strings.  \\*(-- will\n.\\\" give an unbreakable dash, \\*(PI will give pi, \\*(L\" will give a left\n.\\\" double quote, and \\*(R\" will give a right double quote.  \\*(C+ will\n.\\\" give a nicer C++.  Capital omega is used to do unbreakable dashes and\n.\\\" therefore won't be available.  \\*(C` and \\*(C' expand to `' in nroff,\n.\\\" nothing in troff, for use with C<>.\n.tr \\(*W-\n.ds C+ C\\v'-.1v'\\h'-1p'\\s-2+\\h'-1p'+\\s0\\v'.1v'\\h'-1p'\n.ie n \\{\\\n.    ds -- \\(*W-\n.    ds PI pi\n.    if (\\n(.H=4u)&(1m=24u) .ds -- \\(*W\\h'-12u'\\(*W\\h'-12u'-\\\" diablo 10 pitch\n.    if (\\n(.H=4u)&(1m=20u) .ds -- \\(*W\\h'-12u'\\(*W\\h'-8u'-\\\"  diablo 12 pitch\n.    ds L\" \"\"\n.    ds R\" \"\"\n.    ds C` \"\"\n.    ds C' \"\"\n'br\\}\n.el\\{\\\n.    ds -- \\|\\(em\\|\n.    ds PI \\(*p\n.    ds L\" ``\n.    ds R\" ''\n.    ds C`\n.    ds C'\n'br\\}\n.\\\"\n.\\\" Escape single quotes in literal strings from groff's Unicode transform.\n.ie \\n(.g .ds Aq \\(aq\n.el       .ds Aq '\n.\\\"\n.\\\" If the F register is turned on, we'll generate index entries on stderr for\n.\\\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index\n.\\\" entries marked with X<> in POD.  Of course, you'll have to process the\n.\\\" output yourself in some meaningful fashion.\n.\\\"\n.\\\" Avoid warning from groff about undefined register 'F'.\n.de IX\n..\n.nr rF 0\n.if \\n(.g .if rF .nr rF 1\n.if (\\n(rF:(\\n(.g==0)) \\{\n.    if \\nF \\{\n.        de IX\n.        tm Index:\\\\$1\\t\\\\n%\\t\"\\\\$2\"\n..\n.        if !\\nF==2 \\{\n.            nr % 0\n.            nr F 2\n.        \\}\n.    \\}\n.\\}\n.rr rF\n.\\\"\n.\\\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).\n.\\\" Fear.  Run.  Save yourself.  No user-serviceable parts.\n.    \\\" fudge factors for nroff and troff\n.if n \\{\\\n.    ds #H 0\n.    ds #V .8m\n.    ds #F .3m\n.    ds #[ \\f1\n.    ds #] \\fP\n.\\}\n.if t \\{\\\n.    ds #H ((1u-(\\\\\\\\n(.fu%2u))*.13m)\n.    ds #V .6m\n.    ds #F 0\n.    ds #[ \\&\n.    ds #] \\&\n.\\}\n.    \\\" simple accents for nroff and troff\n.if n \\{\\\n.    ds ' \\&\n.    ds ` \\&\n.    ds ^ \\&\n.    ds , \\&\n.    ds ~ ~\n.    ds /\n.\\}\n.if t \\{\\\n.    ds ' \\\\k:\\h'-(\\\\n(.wu*8/10-\\*(#H)'\\'\\h\"|\\\\n:u\"\n.    ds ` \\\\k:\\h'-(\\\\n(.wu*8/10-\\*(#H)'\\`\\h'|\\\\n:u'\n.    ds ^ \\\\k:\\h'-(\\\\n(.wu*10/11-\\*(#H)'^\\h'|\\\\n:u'\n.    ds , \\\\k:\\h'-(\\\\n(.wu*8/10)',\\h'|\\\\n:u'\n.    ds ~ \\\\k:\\h'-(\\\\n(.wu-\\*(#H-.1m)'~\\h'|\\\\n:u'\n.    ds / \\\\k:\\h'-(\\\\n(.wu*8/10-\\*(#H)'\\z\\(sl\\h'|\\\\n:u'\n.\\}\n.    \\\" troff and (daisy-wheel) nroff accents\n.ds : \\\\k:\\h'-(\\\\n(.wu*8/10-\\*(#H+.1m+\\*(#F)'\\v'-\\*(#V'\\z.\\h'.2m+\\*(#F'.\\h'|\\\\n:u'\\v'\\*(#V'\n.ds 8 \\h'\\*(#H'\\(*b\\h'-\\*(#H'\n.ds o \\\\k:\\h'-(\\\\n(.wu+\\w'\\(de'u-\\*(#H)/2u'\\v'-.3n'\\*(#[\\z\\(de\\v'.3n'\\h'|\\\\n:u'\\*(#]\n.ds d- \\h'\\*(#H'\\(pd\\h'-\\w'~'u'\\v'-.25m'\\f2\\(hy\\fP\\v'.25m'\\h'-\\*(#H'\n.ds D- D\\\\k:\\h'-\\w'D'u'\\v'-.11m'\\z\\(hy\\v'.11m'\\h'|\\\\n:u'\n.ds th \\*(#[\\v'.3m'\\s+1I\\s-1\\v'-.3m'\\h'-(\\w'I'u*2/3)'\\s-1o\\s+1\\*(#]\n.ds Th \\*(#[\\s+2I\\s-2\\h'-\\w'I'u*3/5'\\v'-.3m'o\\v'.3m'\\*(#]\n.ds ae a\\h'-(\\w'a'u*4/10)'e\n.ds Ae A\\h'-(\\w'A'u*4/10)'E\n.    \\\" corrections for vroff\n.if v .ds ~ \\\\k:\\h'-(\\\\n(.wu*9/10-\\*(#H)'\\s-2\\u~\\d\\s+2\\h'|\\\\n:u'\n.if v .ds ^ \\\\k:\\h'-(\\\\n(.wu*10/11-\\*(#H)'\\v'-.4m'^\\v'.4m'\\h'|\\\\n:u'\n.    \\\" for low resolution devices (crt and lpr)\n.if \\n(.H>23 .if \\n(.V>19 \\\n\\{\\\n.    ds : e\n.    ds 8 ss\n.    ds o a\n.    ds d- d\\h'-1'\\(ga\n.    ds D- D\\h'-1'\\(hy\n.    ds th \\o'bp'\n.    ds Th \\o'LP'\n.    ds ae ae\n.    ds Ae AE\n.\\}\n.rm #[ #] #H #V #F C\n.\\\" ========================================================================\n.\\\"\n.IX Title \"LIBEV 3\"\n.TH LIBEV 3 \"2017-06-21\" \"libev-4.24\" \"libev - high performance full featured event loop\"\n.\\\" For nroff, turn off justification.  Always turn off hyphenation; it makes\n.\\\" way too many mistakes in technical documents.\n.if n .ad l\n.nh\n.SH \"NAME\"\nlibev \\- a high performance full\\-featured event loop written in C\n.SH \"SYNOPSIS\"\n.IX Header \"SYNOPSIS\"\n.Vb 1\n\\&   #include <ev.h>\n.Ve\n.SS \"\\s-1EXAMPLE PROGRAM\\s0\"\n.IX Subsection \"EXAMPLE PROGRAM\"\n.Vb 2\n\\&   // a single header file is required\n\\&   #include <ev.h>\n\\&\n\\&   #include <stdio.h> // for puts\n\\&\n\\&   // every watcher type has its own typedef\\*(Aqd struct\n\\&   // with the name ev_TYPE\n\\&   ev_io stdin_watcher;\n\\&   ev_timer timeout_watcher;\n\\&\n\\&   // all watcher callbacks have a similar signature\n\\&   // this callback is called when data is readable on stdin\n\\&   static void\n\\&   stdin_cb (EV_P_ ev_io *w, int revents)\n\\&   {\n\\&     puts (\"stdin ready\");\n\\&     // for one\\-shot events, one must manually stop the watcher\n\\&     // with its corresponding stop function.\n\\&     ev_io_stop (EV_A_ w);\n\\&\n\\&     // this causes all nested ev_run\\*(Aqs to stop iterating\n\\&     ev_break (EV_A_ EVBREAK_ALL);\n\\&   }\n\\&\n\\&   // another callback, this time for a time\\-out\n\\&   static void\n\\&   timeout_cb (EV_P_ ev_timer *w, int revents)\n\\&   {\n\\&     puts (\"timeout\");\n\\&     // this causes the innermost ev_run to stop iterating\n\\&     ev_break (EV_A_ EVBREAK_ONE);\n\\&   }\n\\&\n\\&   int\n\\&   main (void)\n\\&   {\n\\&     // use the default event loop unless you have special needs\n\\&     struct ev_loop *loop = EV_DEFAULT;\n\\&\n\\&     // initialise an io watcher, then start it\n\\&     // this one will watch for stdin to become readable\n\\&     ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);\n\\&     ev_io_start (loop, &stdin_watcher);\n\\&\n\\&     // initialise a timer watcher, then start it\n\\&     // simple non\\-repeating 5.5 second timeout\n\\&     ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);\n\\&     ev_timer_start (loop, &timeout_watcher);\n\\&\n\\&     // now wait for events to arrive\n\\&     ev_run (loop, 0);\n\\&\n\\&     // break was called, so exit\n\\&     return 0;\n\\&   }\n.Ve\n.SH \"ABOUT THIS DOCUMENT\"\n.IX Header \"ABOUT THIS DOCUMENT\"\nThis document documents the libev software package.\n.PP\nThe newest version of this document is also available as an html-formatted\nweb page you might find easier to navigate when reading it for the first\ntime: <http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod>.\n.PP\nWhile this document tries to be as complete as possible in documenting\nlibev, its usage and the rationale behind its design, it is not a tutorial\non event-based programming, nor will it introduce event-based programming\nwith libev.\n.PP\nFamiliarity with event based programming techniques in general is assumed\nthroughout this document.\n.SH \"WHAT TO READ WHEN IN A HURRY\"\n.IX Header \"WHAT TO READ WHEN IN A HURRY\"\nThis manual tries to be very detailed, but unfortunately, this also makes\nit very long. If you just want to know the basics of libev, I suggest\nreading \\*(L\"\\s-1ANATOMY OF A WATCHER\\*(R\"\\s0, then the \\*(L\"\\s-1EXAMPLE PROGRAM\\*(R\"\\s0 above and\nlook up the missing functions in \\*(L\"\\s-1GLOBAL FUNCTIONS\\*(R\"\\s0 and the \\f(CW\\*(C`ev_io\\*(C'\\fR and\n\\&\\f(CW\\*(C`ev_timer\\*(C'\\fR sections in \\*(L\"\\s-1WATCHER TYPES\\*(R\"\\s0.\n.SH \"ABOUT LIBEV\"\n.IX Header \"ABOUT LIBEV\"\nLibev is an event loop: you register interest in certain events (such as a\nfile descriptor being readable or a timeout occurring), and it will manage\nthese event sources and provide your program with events.\n.PP\nTo do this, it must take more or less complete control over your process\n(or thread) by executing the \\fIevent loop\\fR handler, and will then\ncommunicate events via a callback mechanism.\n.PP\nYou register interest in certain events by registering so-called \\fIevent\nwatchers\\fR, which are relatively small C structures you initialise with the\ndetails of the event, and then hand it over to libev by \\fIstarting\\fR the\nwatcher.\n.SS \"\\s-1FEATURES\\s0\"\n.IX Subsection \"FEATURES\"\nLibev supports \\f(CW\\*(C`select\\*(C'\\fR, \\f(CW\\*(C`poll\\*(C'\\fR, the Linux-specific \\f(CW\\*(C`epoll\\*(C'\\fR, the\nBSD-specific \\f(CW\\*(C`kqueue\\*(C'\\fR and the Solaris-specific event port mechanisms\nfor file descriptor events (\\f(CW\\*(C`ev_io\\*(C'\\fR), the Linux \\f(CW\\*(C`inotify\\*(C'\\fR interface\n(for \\f(CW\\*(C`ev_stat\\*(C'\\fR), Linux eventfd/signalfd (for faster and cleaner\ninter-thread wakeup (\\f(CW\\*(C`ev_async\\*(C'\\fR)/signal handling (\\f(CW\\*(C`ev_signal\\*(C'\\fR)) relative\ntimers (\\f(CW\\*(C`ev_timer\\*(C'\\fR), absolute timers with customised rescheduling\n(\\f(CW\\*(C`ev_periodic\\*(C'\\fR), synchronous signals (\\f(CW\\*(C`ev_signal\\*(C'\\fR), process status\nchange events (\\f(CW\\*(C`ev_child\\*(C'\\fR), and event watchers dealing with the event\nloop mechanism itself (\\f(CW\\*(C`ev_idle\\*(C'\\fR, \\f(CW\\*(C`ev_embed\\*(C'\\fR, \\f(CW\\*(C`ev_prepare\\*(C'\\fR and\n\\&\\f(CW\\*(C`ev_check\\*(C'\\fR watchers) as well as file watchers (\\f(CW\\*(C`ev_stat\\*(C'\\fR) and even\nlimited support for fork events (\\f(CW\\*(C`ev_fork\\*(C'\\fR).\n.PP\nIt also is quite fast (see this\nbenchmark <http://libev.schmorp.de/bench.html> comparing it to libevent\nfor example).\n.SS \"\\s-1CONVENTIONS\\s0\"\n.IX Subsection \"CONVENTIONS\"\nLibev is very configurable. In this manual the default (and most common)\nconfiguration will be described, which supports multiple event loops. For\nmore info about various configuration options please have a look at\n\\&\\fB\\s-1EMBED\\s0\\fR section in this manual. If libev was configured without support\nfor multiple event loops, then all functions taking an initial argument of\nname \\f(CW\\*(C`loop\\*(C'\\fR (which is always of type \\f(CW\\*(C`struct ev_loop *\\*(C'\\fR) will not have\nthis argument.\n.SS \"\\s-1TIME REPRESENTATION\\s0\"\n.IX Subsection \"TIME REPRESENTATION\"\nLibev represents time as a single floating point number, representing\nthe (fractional) number of seconds since the (\\s-1POSIX\\s0) epoch (in practice\nsomewhere near the beginning of 1970, details are complicated, don't\nask). This type is called \\f(CW\\*(C`ev_tstamp\\*(C'\\fR, which is what you should use\ntoo. It usually aliases to the \\f(CW\\*(C`double\\*(C'\\fR type in C. When you need to do\nany calculations on it, you should treat it as some floating point value.\n.PP\nUnlike the name component \\f(CW\\*(C`stamp\\*(C'\\fR might indicate, it is also used for\ntime differences (e.g. delays) throughout libev.\n.SH \"ERROR HANDLING\"\n.IX Header \"ERROR HANDLING\"\nLibev knows three classes of errors: operating system errors, usage errors\nand internal errors (bugs).\n.PP\nWhen libev catches an operating system error it cannot handle (for example\na system call indicating a condition libev cannot fix), it calls the callback\nset via \\f(CW\\*(C`ev_set_syserr_cb\\*(C'\\fR, which is supposed to fix the problem or\nabort. The default is to print a diagnostic message and to call \\f(CW\\*(C`abort\n()\\*(C'\\fR.\n.PP\nWhen libev detects a usage error such as a negative timer interval, then\nit will print a diagnostic message and abort (via the \\f(CW\\*(C`assert\\*(C'\\fR mechanism,\nso \\f(CW\\*(C`NDEBUG\\*(C'\\fR will disable this checking): these are programming errors in\nthe libev caller and need to be fixed there.\n.PP\nLibev also has a few internal error-checking \\f(CW\\*(C`assert\\*(C'\\fRions, and also has\nextensive consistency checking code. These do not trigger under normal\ncircumstances, as they indicate either a bug in libev or worse.\n.SH \"GLOBAL FUNCTIONS\"\n.IX Header \"GLOBAL FUNCTIONS\"\nThese functions can be called anytime, even before initialising the\nlibrary in any way.\n.IP \"ev_tstamp ev_time ()\" 4\n.IX Item \"ev_tstamp ev_time ()\"\nReturns the current time as libev would use it. Please note that the\n\\&\\f(CW\\*(C`ev_now\\*(C'\\fR function is usually faster and also often returns the timestamp\nyou actually want to know. Also interesting is the combination of\n\\&\\f(CW\\*(C`ev_now_update\\*(C'\\fR and \\f(CW\\*(C`ev_now\\*(C'\\fR.\n.IP \"ev_sleep (ev_tstamp interval)\" 4\n.IX Item \"ev_sleep (ev_tstamp interval)\"\nSleep for the given interval: The current thread will be blocked\nuntil either it is interrupted or the given time interval has\npassed (approximately \\- it might return a bit earlier even if not\ninterrupted). Returns immediately if \\f(CW\\*(C`interval <= 0\\*(C'\\fR.\n.Sp\nBasically this is a sub-second-resolution \\f(CW\\*(C`sleep ()\\*(C'\\fR.\n.Sp\nThe range of the \\f(CW\\*(C`interval\\*(C'\\fR is limited \\- libev only guarantees to work\nwith sleep times of up to one day (\\f(CW\\*(C`interval <= 86400\\*(C'\\fR).\n.IP \"int ev_version_major ()\" 4\n.IX Item \"int ev_version_major ()\"\n.PD 0\n.IP \"int ev_version_minor ()\" 4\n.IX Item \"int ev_version_minor ()\"\n.PD\nYou can find out the major and minor \\s-1ABI\\s0 version numbers of the library\nyou linked against by calling the functions \\f(CW\\*(C`ev_version_major\\*(C'\\fR and\n\\&\\f(CW\\*(C`ev_version_minor\\*(C'\\fR. If you want, you can compare against the global\nsymbols \\f(CW\\*(C`EV_VERSION_MAJOR\\*(C'\\fR and \\f(CW\\*(C`EV_VERSION_MINOR\\*(C'\\fR, which specify the\nversion of the library your program was compiled against.\n.Sp\nThese version numbers refer to the \\s-1ABI\\s0 version of the library, not the\nrelease version.\n.Sp\nUsually, it's a good idea to terminate if the major versions mismatch,\nas this indicates an incompatible change. Minor versions are usually\ncompatible to older versions, so a larger minor version alone is usually\nnot a problem.\n.Sp\nExample: Make sure we haven't accidentally been linked against the wrong\nversion (note, however, that this will not detect other \\s-1ABI\\s0 mismatches,\nsuch as \\s-1LFS\\s0 or reentrancy).\n.Sp\n.Vb 3\n\\&   assert ((\"libev version mismatch\",\n\\&            ev_version_major () == EV_VERSION_MAJOR\n\\&            && ev_version_minor () >= EV_VERSION_MINOR));\n.Ve\n.IP \"unsigned int ev_supported_backends ()\" 4\n.IX Item \"unsigned int ev_supported_backends ()\"\nReturn the set of all backends (i.e. their corresponding \\f(CW\\*(C`EV_BACKEND_*\\*(C'\\fR\nvalue) compiled into this binary of libev (independent of their\navailability on the system you are running on). See \\f(CW\\*(C`ev_default_loop\\*(C'\\fR for\na description of the set values.\n.Sp\nExample: make sure we have the epoll method, because yeah this is cool and\na must have and can we have a torrent of it please!!!11\n.Sp\n.Vb 2\n\\&   assert ((\"sorry, no epoll, no sex\",\n\\&            ev_supported_backends () & EVBACKEND_EPOLL));\n.Ve\n.IP \"unsigned int ev_recommended_backends ()\" 4\n.IX Item \"unsigned int ev_recommended_backends ()\"\nReturn the set of all backends compiled into this binary of libev and\nalso recommended for this platform, meaning it will work for most file\ndescriptor types. This set is often smaller than the one returned by\n\\&\\f(CW\\*(C`ev_supported_backends\\*(C'\\fR, as for example kqueue is broken on most BSDs\nand will not be auto-detected unless you explicitly request it (assuming\nyou know what you are doing). This is the set of backends that libev will\nprobe for if you specify no backends explicitly.\n.IP \"unsigned int ev_embeddable_backends ()\" 4\n.IX Item \"unsigned int ev_embeddable_backends ()\"\nReturns the set of backends that are embeddable in other event loops. This\nvalue is platform-specific but can include backends not available on the\ncurrent system. To find which embeddable backends might be supported on\nthe current system, you would need to look at \\f(CW\\*(C`ev_embeddable_backends ()\n& ev_supported_backends ()\\*(C'\\fR, likewise for recommended ones.\n.Sp\nSee the description of \\f(CW\\*(C`ev_embed\\*(C'\\fR watchers for more info.\n.IP \"ev_set_allocator (void *(*cb)(void *ptr, long size) throw ())\" 4\n.IX Item \"ev_set_allocator (void *(*cb)(void *ptr, long size) throw ())\"\nSets the allocation function to use (the prototype is similar \\- the\nsemantics are identical to the \\f(CW\\*(C`realloc\\*(C'\\fR C89/SuS/POSIX function). It is\nused to allocate and free memory (no surprises here). If it returns zero\nwhen memory needs to be allocated (\\f(CW\\*(C`size != 0\\*(C'\\fR), the library might abort\nor take some potentially destructive action.\n.Sp\nSince some systems (at least OpenBSD and Darwin) fail to implement\ncorrect \\f(CW\\*(C`realloc\\*(C'\\fR semantics, libev will use a wrapper around the system\n\\&\\f(CW\\*(C`realloc\\*(C'\\fR and \\f(CW\\*(C`free\\*(C'\\fR functions by default.\n.Sp\nYou could override this function in high-availability programs to, say,\nfree some memory if it cannot allocate memory, to use a special allocator,\nor even to sleep a while and retry until some memory is available.\n.Sp\nExample: Replace the libev allocator with one that waits a bit and then\nretries (example requires a standards-compliant \\f(CW\\*(C`realloc\\*(C'\\fR).\n.Sp\n.Vb 6\n\\&   static void *\n\\&   persistent_realloc (void *ptr, size_t size)\n\\&   {\n\\&     for (;;)\n\\&       {\n\\&         void *newptr = realloc (ptr, size);\n\\&\n\\&         if (newptr)\n\\&           return newptr;\n\\&\n\\&         sleep (60);\n\\&       }\n\\&   }\n\\&\n\\&   ...\n\\&   ev_set_allocator (persistent_realloc);\n.Ve\n.IP \"ev_set_syserr_cb (void (*cb)(const char *msg) throw ())\" 4\n.IX Item \"ev_set_syserr_cb (void (*cb)(const char *msg) throw ())\"\nSet the callback function to call on a retryable system call error (such\nas failed select, poll, epoll_wait). The message is a printable string\nindicating the system call or subsystem causing the problem. If this\ncallback is set, then libev will expect it to remedy the situation, no\nmatter what, when it returns. That is, libev will generally retry the\nrequested operation, or, if the condition doesn't go away, do bad stuff\n(such as abort).\n.Sp\nExample: This is basically the same thing that libev does internally, too.\n.Sp\n.Vb 6\n\\&   static void\n\\&   fatal_error (const char *msg)\n\\&   {\n\\&     perror (msg);\n\\&     abort ();\n\\&   }\n\\&\n\\&   ...\n\\&   ev_set_syserr_cb (fatal_error);\n.Ve\n.IP \"ev_feed_signal (int signum)\" 4\n.IX Item \"ev_feed_signal (int signum)\"\nThis function can be used to \\*(L\"simulate\\*(R\" a signal receive. It is completely\nsafe to call this function at any time, from any context, including signal\nhandlers or random threads.\n.Sp\nIts main use is to customise signal handling in your process, especially\nin the presence of threads. For example, you could block signals\nby default in all threads (and specifying \\f(CW\\*(C`EVFLAG_NOSIGMASK\\*(C'\\fR when\ncreating any loops), and in one thread, use \\f(CW\\*(C`sigwait\\*(C'\\fR or any other\nmechanism to wait for signals, then \\*(L\"deliver\\*(R\" them to libev by calling\n\\&\\f(CW\\*(C`ev_feed_signal\\*(C'\\fR.\n.SH \"FUNCTIONS CONTROLLING EVENT LOOPS\"\n.IX Header \"FUNCTIONS CONTROLLING EVENT LOOPS\"\nAn event loop is described by a \\f(CW\\*(C`struct ev_loop *\\*(C'\\fR (the \\f(CW\\*(C`struct\\*(C'\\fR is\n\\&\\fInot\\fR optional in this case unless libev 3 compatibility is disabled, as\nlibev 3 had an \\f(CW\\*(C`ev_loop\\*(C'\\fR function colliding with the struct name).\n.PP\nThe library knows two types of such loops, the \\fIdefault\\fR loop, which\nsupports child process events, and dynamically created event loops which\ndo not.\n.IP \"struct ev_loop *ev_default_loop (unsigned int flags)\" 4\n.IX Item \"struct ev_loop *ev_default_loop (unsigned int flags)\"\nThis returns the \\*(L\"default\\*(R\" event loop object, which is what you should\nnormally use when you just need \\*(L\"the event loop\\*(R\". Event loop objects and\nthe \\f(CW\\*(C`flags\\*(C'\\fR parameter are described in more detail in the entry for\n\\&\\f(CW\\*(C`ev_loop_new\\*(C'\\fR.\n.Sp\nIf the default loop is already initialised then this function simply\nreturns it (and ignores the flags. If that is troubling you, check\n\\&\\f(CW\\*(C`ev_backend ()\\*(C'\\fR afterwards). Otherwise it will create it with the given\nflags, which should almost always be \\f(CW0\\fR, unless the caller is also the\none calling \\f(CW\\*(C`ev_run\\*(C'\\fR or otherwise qualifies as \\*(L\"the main program\\*(R\".\n.Sp\nIf you don't know what event loop to use, use the one returned from this\nfunction (or via the \\f(CW\\*(C`EV_DEFAULT\\*(C'\\fR macro).\n.Sp\nNote that this function is \\fInot\\fR thread-safe, so if you want to use it\nfrom multiple threads, you have to employ some kind of mutex (note also\nthat this case is unlikely, as loops cannot be shared easily between\nthreads anyway).\n.Sp\nThe default loop is the only loop that can handle \\f(CW\\*(C`ev_child\\*(C'\\fR watchers,\nand to do this, it always registers a handler for \\f(CW\\*(C`SIGCHLD\\*(C'\\fR. If this is\na problem for your application you can either create a dynamic loop with\n\\&\\f(CW\\*(C`ev_loop_new\\*(C'\\fR which doesn't do that, or you can simply overwrite the\n\\&\\f(CW\\*(C`SIGCHLD\\*(C'\\fR signal handler \\fIafter\\fR calling \\f(CW\\*(C`ev_default_init\\*(C'\\fR.\n.Sp\nExample: This is the most typical usage.\n.Sp\n.Vb 2\n\\&   if (!ev_default_loop (0))\n\\&     fatal (\"could not initialise libev, bad $LIBEV_FLAGS in environment?\");\n.Ve\n.Sp\nExample: Restrict libev to the select and poll backends, and do not allow\nenvironment settings to be taken into account:\n.Sp\n.Vb 1\n\\&   ev_default_loop (EVBACKEND_POLL | EVBACKEND_SELECT | EVFLAG_NOENV);\n.Ve\n.IP \"struct ev_loop *ev_loop_new (unsigned int flags)\" 4\n.IX Item \"struct ev_loop *ev_loop_new (unsigned int flags)\"\nThis will create and initialise a new event loop object. If the loop\ncould not be initialised, returns false.\n.Sp\nThis function is thread-safe, and one common way to use libev with\nthreads is indeed to create one loop per thread, and using the default\nloop in the \\*(L\"main\\*(R\" or \\*(L\"initial\\*(R\" thread.\n.Sp\nThe flags argument can be used to specify special behaviour or specific\nbackends to use, and is usually specified as \\f(CW0\\fR (or \\f(CW\\*(C`EVFLAG_AUTO\\*(C'\\fR).\n.Sp\nThe following flags are supported:\n.RS 4\n.ie n .IP \"\"\"EVFLAG_AUTO\"\"\" 4\n.el .IP \"\\f(CWEVFLAG_AUTO\\fR\" 4\n.IX Item \"EVFLAG_AUTO\"\nThe default flags value. Use this if you have no clue (it's the right\nthing, believe me).\n.ie n .IP \"\"\"EVFLAG_NOENV\"\"\" 4\n.el .IP \"\\f(CWEVFLAG_NOENV\\fR\" 4\n.IX Item \"EVFLAG_NOENV\"\nIf this flag bit is or'ed into the flag value (or the program runs setuid\nor setgid) then libev will \\fInot\\fR look at the environment variable\n\\&\\f(CW\\*(C`LIBEV_FLAGS\\*(C'\\fR. Otherwise (the default), this environment variable will\noverride the flags completely if it is found in the environment. This is\nuseful to try out specific backends to test their performance, to work\naround bugs, or to make libev threadsafe (accessing environment variables\ncannot be done in a threadsafe way, but usually it works if no other\nthread modifies them).\n.ie n .IP \"\"\"EVFLAG_FORKCHECK\"\"\" 4\n.el .IP \"\\f(CWEVFLAG_FORKCHECK\\fR\" 4\n.IX Item \"EVFLAG_FORKCHECK\"\nInstead of calling \\f(CW\\*(C`ev_loop_fork\\*(C'\\fR manually after a fork, you can also\nmake libev check for a fork in each iteration by enabling this flag.\n.Sp\nThis works by calling \\f(CW\\*(C`getpid ()\\*(C'\\fR on every iteration of the loop,\nand thus this might slow down your event loop if you do a lot of loop\niterations and little real work, but is usually not noticeable (on my\nGNU/Linux system for example, \\f(CW\\*(C`getpid\\*(C'\\fR is actually a simple 5\\-insn sequence\nwithout a system call and thus \\fIvery\\fR fast, but my GNU/Linux system also has\n\\&\\f(CW\\*(C`pthread_atfork\\*(C'\\fR which is even faster).\n.Sp\nThe big advantage of this flag is that you can forget about fork (and\nforget about forgetting to tell libev about forking, although you still\nhave to ignore \\f(CW\\*(C`SIGPIPE\\*(C'\\fR) when you use this flag.\n.Sp\nThis flag setting cannot be overridden or specified in the \\f(CW\\*(C`LIBEV_FLAGS\\*(C'\\fR\nenvironment variable.\n.ie n .IP \"\"\"EVFLAG_NOINOTIFY\"\"\" 4\n.el .IP \"\\f(CWEVFLAG_NOINOTIFY\\fR\" 4\n.IX Item \"EVFLAG_NOINOTIFY\"\nWhen this flag is specified, then libev will not attempt to use the\n\\&\\fIinotify\\fR \\s-1API\\s0 for its \\f(CW\\*(C`ev_stat\\*(C'\\fR watchers. Apart from debugging and\ntesting, this flag can be useful to conserve inotify file descriptors, as\notherwise each loop using \\f(CW\\*(C`ev_stat\\*(C'\\fR watchers consumes one inotify handle.\n.ie n .IP \"\"\"EVFLAG_SIGNALFD\"\"\" 4\n.el .IP \"\\f(CWEVFLAG_SIGNALFD\\fR\" 4\n.IX Item \"EVFLAG_SIGNALFD\"\nWhen this flag is specified, then libev will attempt to use the\n\\&\\fIsignalfd\\fR \\s-1API\\s0 for its \\f(CW\\*(C`ev_signal\\*(C'\\fR (and \\f(CW\\*(C`ev_child\\*(C'\\fR) watchers. This \\s-1API\\s0\ndelivers signals synchronously, which makes it both faster and might make\nit possible to get the queued signal data. It can also simplify signal\nhandling with threads, as long as you properly block signals in your\nthreads that are not interested in handling them.\n.Sp\nSignalfd will not be used by default as this changes your signal mask, and\nthere are a lot of shoddy libraries and programs (glib's threadpool for\nexample) that can't properly initialise their signal masks.\n.ie n .IP \"\"\"EVFLAG_NOSIGMASK\"\"\" 4\n.el .IP \"\\f(CWEVFLAG_NOSIGMASK\\fR\" 4\n.IX Item \"EVFLAG_NOSIGMASK\"\nWhen this flag is specified, then libev will avoid to modify the signal\nmask. Specifically, this means you have to make sure signals are unblocked\nwhen you want to receive them.\n.Sp\nThis behaviour is useful when you want to do your own signal handling, or\nwant to handle signals only in specific threads and want to avoid libev\nunblocking the signals.\n.Sp\nIt's also required by \\s-1POSIX\\s0 in a threaded program, as libev calls\n\\&\\f(CW\\*(C`sigprocmask\\*(C'\\fR, whose behaviour is officially unspecified.\n.Sp\nThis flag's behaviour will become the default in future versions of libev.\n.ie n .IP \"\"\"EVBACKEND_SELECT\"\"  (value 1, portable select backend)\" 4\n.el .IP \"\\f(CWEVBACKEND_SELECT\\fR  (value 1, portable select backend)\" 4\n.IX Item \"EVBACKEND_SELECT (value 1, portable select backend)\"\nThis is your standard \\fIselect\\fR\\|(2) backend. Not \\fIcompletely\\fR standard, as\nlibev tries to roll its own fd_set with no limits on the number of fds,\nbut if that fails, expect a fairly low limit on the number of fds when\nusing this backend. It doesn't scale too well (O(highest_fd)), but its\nusually the fastest backend for a low number of (low-numbered :) fds.\n.Sp\nTo get good performance out of this backend you need a high amount of\nparallelism (most of the file descriptors should be busy). If you are\nwriting a server, you should \\f(CW\\*(C`accept ()\\*(C'\\fR in a loop to accept as many\nconnections as possible during one iteration. You might also want to have\na look at \\f(CW\\*(C`ev_set_io_collect_interval ()\\*(C'\\fR to increase the amount of\nreadiness notifications you get per iteration.\n.Sp\nThis backend maps \\f(CW\\*(C`EV_READ\\*(C'\\fR to the \\f(CW\\*(C`readfds\\*(C'\\fR set and \\f(CW\\*(C`EV_WRITE\\*(C'\\fR to the\n\\&\\f(CW\\*(C`writefds\\*(C'\\fR set (and to work around Microsoft Windows bugs, also onto the\n\\&\\f(CW\\*(C`exceptfds\\*(C'\\fR set on that platform).\n.ie n .IP \"\"\"EVBACKEND_POLL\"\"    (value 2, poll backend, available everywhere except on windows)\" 4\n.el .IP \"\\f(CWEVBACKEND_POLL\\fR    (value 2, poll backend, available everywhere except on windows)\" 4\n.IX Item \"EVBACKEND_POLL (value 2, poll backend, available everywhere except on windows)\"\nAnd this is your standard \\fIpoll\\fR\\|(2) backend. It's more complicated\nthan select, but handles sparse fds better and has no artificial\nlimit on the number of fds you can use (except it will slow down\nconsiderably with a lot of inactive fds). It scales similarly to select,\ni.e. O(total_fds). See the entry for \\f(CW\\*(C`EVBACKEND_SELECT\\*(C'\\fR, above, for\nperformance tips.\n.Sp\nThis backend maps \\f(CW\\*(C`EV_READ\\*(C'\\fR to \\f(CW\\*(C`POLLIN | POLLERR | POLLHUP\\*(C'\\fR, and\n\\&\\f(CW\\*(C`EV_WRITE\\*(C'\\fR to \\f(CW\\*(C`POLLOUT | POLLERR | POLLHUP\\*(C'\\fR.\n.ie n .IP \"\"\"EVBACKEND_EPOLL\"\"   (value 4, Linux)\" 4\n.el .IP \"\\f(CWEVBACKEND_EPOLL\\fR   (value 4, Linux)\" 4\n.IX Item \"EVBACKEND_EPOLL (value 4, Linux)\"\nUse the linux-specific \\fIepoll\\fR\\|(7) interface (for both pre\\- and post\\-2.6.9\nkernels).\n.Sp\nFor few fds, this backend is a bit little slower than poll and select, but\nit scales phenomenally better. While poll and select usually scale like\nO(total_fds) where total_fds is the total number of fds (or the highest\nfd), epoll scales either O(1) or O(active_fds).\n.Sp\nThe epoll mechanism deserves honorable mention as the most misdesigned\nof the more advanced event mechanisms: mere annoyances include silently\ndropping file descriptors, requiring a system call per change per file\ndescriptor (and unnecessary guessing of parameters), problems with dup,\nreturning before the timeout value, resulting in additional iterations\n(and only giving 5ms accuracy while select on the same platform gives\n0.1ms) and so on. The biggest issue is fork races, however \\- if a program\nforks then \\fIboth\\fR parent and child process have to recreate the epoll\nset, which can take considerable time (one syscall per file descriptor)\nand is of course hard to detect.\n.Sp\nEpoll is also notoriously buggy \\- embedding epoll fds \\fIshould\\fR work,\nbut of course \\fIdoesn't\\fR, and epoll just loves to report events for\ntotally \\fIdifferent\\fR file descriptors (even already closed ones, so\none cannot even remove them from the set) than registered in the set\n(especially on \\s-1SMP\\s0 systems). Libev tries to counter these spurious\nnotifications by employing an additional generation counter and comparing\nthat against the events to filter out spurious ones, recreating the set\nwhen required. Epoll also erroneously rounds down timeouts, but gives you\nno way to know when and by how much, so sometimes you have to busy-wait\nbecause epoll returns immediately despite a nonzero timeout. And last\nnot least, it also refuses to work with some file descriptors which work\nperfectly fine with \\f(CW\\*(C`select\\*(C'\\fR (files, many character devices...).\n.Sp\nEpoll is truly the train wreck among event poll mechanisms, a frankenpoll,\ncobbled together in a hurry, no thought to design or interaction with\nothers. Oh, the pain, will it ever stop...\n.Sp\nWhile stopping, setting and starting an I/O watcher in the same iteration\nwill result in some caching, there is still a system call per such\nincident (because the same \\fIfile descriptor\\fR could point to a different\n\\&\\fIfile description\\fR now), so its best to avoid that. Also, \\f(CW\\*(C`dup ()\\*(C'\\fR'ed\nfile descriptors might not work very well if you register events for both\nfile descriptors.\n.Sp\nBest performance from this backend is achieved by not unregistering all\nwatchers for a file descriptor until it has been closed, if possible,\ni.e. keep at least one watcher active per fd at all times. Stopping and\nstarting a watcher (without re-setting it) also usually doesn't cause\nextra overhead. A fork can both result in spurious notifications as well\nas in libev having to destroy and recreate the epoll object, which can\ntake considerable time and thus should be avoided.\n.Sp\nAll this means that, in practice, \\f(CW\\*(C`EVBACKEND_SELECT\\*(C'\\fR can be as fast or\nfaster than epoll for maybe up to a hundred file descriptors, depending on\nthe usage. So sad.\n.Sp\nWhile nominally embeddable in other event loops, this feature is broken in\nall kernel versions tested so far.\n.Sp\nThis backend maps \\f(CW\\*(C`EV_READ\\*(C'\\fR and \\f(CW\\*(C`EV_WRITE\\*(C'\\fR in the same way as\n\\&\\f(CW\\*(C`EVBACKEND_POLL\\*(C'\\fR.\n.ie n .IP \"\"\"EVBACKEND_KQUEUE\"\"  (value 8, most \\s-1BSD\\s0 clones)\" 4\n.el .IP \"\\f(CWEVBACKEND_KQUEUE\\fR  (value 8, most \\s-1BSD\\s0 clones)\" 4\n.IX Item \"EVBACKEND_KQUEUE (value 8, most BSD clones)\"\nKqueue deserves special mention, as at the time of this writing, it\nwas broken on all BSDs except NetBSD (usually it doesn't work reliably\nwith anything but sockets and pipes, except on Darwin, where of course\nit's completely useless). Unlike epoll, however, whose brokenness\nis by design, these kqueue bugs can (and eventually will) be fixed\nwithout \\s-1API\\s0 changes to existing programs. For this reason it's not being\n\\&\\*(L\"auto-detected\\*(R\" unless you explicitly specify it in the flags (i.e. using\n\\&\\f(CW\\*(C`EVBACKEND_KQUEUE\\*(C'\\fR) or libev was compiled on a known-to-be-good (\\-enough)\nsystem like NetBSD.\n.Sp\nYou still can embed kqueue into a normal poll or select backend and use it\nonly for sockets (after having made sure that sockets work with kqueue on\nthe target platform). See \\f(CW\\*(C`ev_embed\\*(C'\\fR watchers for more info.\n.Sp\nIt scales in the same way as the epoll backend, but the interface to the\nkernel is more efficient (which says nothing about its actual speed, of\ncourse). While stopping, setting and starting an I/O watcher does never\ncause an extra system call as with \\f(CW\\*(C`EVBACKEND_EPOLL\\*(C'\\fR, it still adds up to\ntwo event changes per incident. Support for \\f(CW\\*(C`fork ()\\*(C'\\fR is very bad (you\nmight have to leak fd's on fork, but it's more sane than epoll) and it\ndrops fds silently in similarly hard-to-detect cases.\n.Sp\nThis backend usually performs well under most conditions.\n.Sp\nWhile nominally embeddable in other event loops, this doesn't work\neverywhere, so you might need to test for this. And since it is broken\nalmost everywhere, you should only use it when you have a lot of sockets\n(for which it usually works), by embedding it into another event loop\n(e.g. \\f(CW\\*(C`EVBACKEND_SELECT\\*(C'\\fR or \\f(CW\\*(C`EVBACKEND_POLL\\*(C'\\fR (but \\f(CW\\*(C`poll\\*(C'\\fR is of course\nalso broken on \\s-1OS X\\s0)) and, did I mention it, using it only for sockets.\n.Sp\nThis backend maps \\f(CW\\*(C`EV_READ\\*(C'\\fR into an \\f(CW\\*(C`EVFILT_READ\\*(C'\\fR kevent with\n\\&\\f(CW\\*(C`NOTE_EOF\\*(C'\\fR, and \\f(CW\\*(C`EV_WRITE\\*(C'\\fR into an \\f(CW\\*(C`EVFILT_WRITE\\*(C'\\fR kevent with\n\\&\\f(CW\\*(C`NOTE_EOF\\*(C'\\fR.\n.ie n .IP \"\"\"EVBACKEND_DEVPOLL\"\" (value 16, Solaris 8)\" 4\n.el .IP \"\\f(CWEVBACKEND_DEVPOLL\\fR (value 16, Solaris 8)\" 4\n.IX Item \"EVBACKEND_DEVPOLL (value 16, Solaris 8)\"\nThis is not implemented yet (and might never be, unless you send me an\nimplementation). According to reports, \\f(CW\\*(C`/dev/poll\\*(C'\\fR only supports sockets\nand is not embeddable, which would limit the usefulness of this backend\nimmensely.\n.ie n .IP \"\"\"EVBACKEND_PORT\"\"    (value 32, Solaris 10)\" 4\n.el .IP \"\\f(CWEVBACKEND_PORT\\fR    (value 32, Solaris 10)\" 4\n.IX Item \"EVBACKEND_PORT (value 32, Solaris 10)\"\nThis uses the Solaris 10 event port mechanism. As with everything on Solaris,\nit's really slow, but it still scales very well (O(active_fds)).\n.Sp\nWhile this backend scales well, it requires one system call per active\nfile descriptor per loop iteration. For small and medium numbers of file\ndescriptors a \\*(L\"slow\\*(R\" \\f(CW\\*(C`EVBACKEND_SELECT\\*(C'\\fR or \\f(CW\\*(C`EVBACKEND_POLL\\*(C'\\fR backend\nmight perform better.\n.Sp\nOn the positive side, this backend actually performed fully to\nspecification in all tests and is fully embeddable, which is a rare feat\namong the OS-specific backends (I vastly prefer correctness over speed\nhacks).\n.Sp\nOn the negative side, the interface is \\fIbizarre\\fR \\- so bizarre that\neven sun itself gets it wrong in their code examples: The event polling\nfunction sometimes returns events to the caller even though an error\noccurred, but with no indication whether it has done so or not (yes, it's\neven documented that way) \\- deadly for edge-triggered interfaces where you\nabsolutely have to know whether an event occurred or not because you have\nto re-arm the watcher.\n.Sp\nFortunately libev seems to be able to work around these idiocies.\n.Sp\nThis backend maps \\f(CW\\*(C`EV_READ\\*(C'\\fR and \\f(CW\\*(C`EV_WRITE\\*(C'\\fR in the same way as\n\\&\\f(CW\\*(C`EVBACKEND_POLL\\*(C'\\fR.\n.ie n .IP \"\"\"EVBACKEND_ALL\"\"\" 4\n.el .IP \"\\f(CWEVBACKEND_ALL\\fR\" 4\n.IX Item \"EVBACKEND_ALL\"\nTry all backends (even potentially broken ones that wouldn't be tried\nwith \\f(CW\\*(C`EVFLAG_AUTO\\*(C'\\fR). Since this is a mask, you can do stuff such as\n\\&\\f(CW\\*(C`EVBACKEND_ALL & ~EVBACKEND_KQUEUE\\*(C'\\fR.\n.Sp\nIt is definitely not recommended to use this flag, use whatever\n\\&\\f(CW\\*(C`ev_recommended_backends ()\\*(C'\\fR returns, or simply do not specify a backend\nat all.\n.ie n .IP \"\"\"EVBACKEND_MASK\"\"\" 4\n.el .IP \"\\f(CWEVBACKEND_MASK\\fR\" 4\n.IX Item \"EVBACKEND_MASK\"\nNot a backend at all, but a mask to select all backend bits from a\n\\&\\f(CW\\*(C`flags\\*(C'\\fR value, in case you want to mask out any backends from a flags\nvalue (e.g. when modifying the \\f(CW\\*(C`LIBEV_FLAGS\\*(C'\\fR environment variable).\n.RE\n.RS 4\n.Sp\nIf one or more of the backend flags are or'ed into the flags value,\nthen only these backends will be tried (in the reverse order as listed\nhere). If none are specified, all backends in \\f(CW\\*(C`ev_recommended_backends\n()\\*(C'\\fR will be tried.\n.Sp\nExample: Try to create a event loop that uses epoll and nothing else.\n.Sp\n.Vb 3\n\\&   struct ev_loop *epoller = ev_loop_new (EVBACKEND_EPOLL | EVFLAG_NOENV);\n\\&   if (!epoller)\n\\&     fatal (\"no epoll found here, maybe it hides under your chair\");\n.Ve\n.Sp\nExample: Use whatever libev has to offer, but make sure that kqueue is\nused if available.\n.Sp\n.Vb 1\n\\&   struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_KQUEUE);\n.Ve\n.RE\n.IP \"ev_loop_destroy (loop)\" 4\n.IX Item \"ev_loop_destroy (loop)\"\nDestroys an event loop object (frees all memory and kernel state\netc.). None of the active event watchers will be stopped in the normal\nsense, so e.g. \\f(CW\\*(C`ev_is_active\\*(C'\\fR might still return true. It is your\nresponsibility to either stop all watchers cleanly yourself \\fIbefore\\fR\ncalling this function, or cope with the fact afterwards (which is usually\nthe easiest thing, you can just ignore the watchers and/or \\f(CW\\*(C`free ()\\*(C'\\fR them\nfor example).\n.Sp\nNote that certain global state, such as signal state (and installed signal\nhandlers), will not be freed by this function, and related watchers (such\nas signal and child watchers) would need to be stopped manually.\n.Sp\nThis function is normally used on loop objects allocated by\n\\&\\f(CW\\*(C`ev_loop_new\\*(C'\\fR, but it can also be used on the default loop returned by\n\\&\\f(CW\\*(C`ev_default_loop\\*(C'\\fR, in which case it is not thread-safe.\n.Sp\nNote that it is not advisable to call this function on the default loop\nexcept in the rare occasion where you really need to free its resources.\nIf you need dynamically allocated loops it is better to use \\f(CW\\*(C`ev_loop_new\\*(C'\\fR\nand \\f(CW\\*(C`ev_loop_destroy\\*(C'\\fR.\n.IP \"ev_loop_fork (loop)\" 4\n.IX Item \"ev_loop_fork (loop)\"\nThis function sets a flag that causes subsequent \\f(CW\\*(C`ev_run\\*(C'\\fR iterations\nto reinitialise the kernel state for backends that have one. Despite\nthe name, you can call it anytime you are allowed to start or stop\nwatchers (except inside an \\f(CW\\*(C`ev_prepare\\*(C'\\fR callback), but it makes most\nsense after forking, in the child process. You \\fImust\\fR call it (or use\n\\&\\f(CW\\*(C`EVFLAG_FORKCHECK\\*(C'\\fR) in the child before resuming or calling \\f(CW\\*(C`ev_run\\*(C'\\fR.\n.Sp\nIn addition, if you want to reuse a loop (via this function or\n\\&\\f(CW\\*(C`EVFLAG_FORKCHECK\\*(C'\\fR), you \\fIalso\\fR have to ignore \\f(CW\\*(C`SIGPIPE\\*(C'\\fR.\n.Sp\nAgain, you \\fIhave\\fR to call it on \\fIany\\fR loop that you want to re-use after\na fork, \\fIeven if you do not plan to use the loop in the parent\\fR. This is\nbecause some kernel interfaces *cough* \\fIkqueue\\fR *cough* do funny things\nduring fork.\n.Sp\nOn the other hand, you only need to call this function in the child\nprocess if and only if you want to use the event loop in the child. If\nyou just fork+exec or create a new loop in the child, you don't have to\ncall it at all (in fact, \\f(CW\\*(C`epoll\\*(C'\\fR is so badly broken that it makes a\ndifference, but libev will usually detect this case on its own and do a\ncostly reset of the backend).\n.Sp\nThe function itself is quite fast and it's usually not a problem to call\nit just in case after a fork.\n.Sp\nExample: Automate calling \\f(CW\\*(C`ev_loop_fork\\*(C'\\fR on the default loop when\nusing pthreads.\n.Sp\n.Vb 5\n\\&   static void\n\\&   post_fork_child (void)\n\\&   {\n\\&     ev_loop_fork (EV_DEFAULT);\n\\&   }\n\\&\n\\&   ...\n\\&   pthread_atfork (0, 0, post_fork_child);\n.Ve\n.IP \"int ev_is_default_loop (loop)\" 4\n.IX Item \"int ev_is_default_loop (loop)\"\nReturns true when the given loop is, in fact, the default loop, and false\notherwise.\n.IP \"unsigned int ev_iteration (loop)\" 4\n.IX Item \"unsigned int ev_iteration (loop)\"\nReturns the current iteration count for the event loop, which is identical\nto the number of times libev did poll for new events. It starts at \\f(CW0\\fR\nand happily wraps around with enough iterations.\n.Sp\nThis value can sometimes be useful as a generation counter of sorts (it\n\\&\\*(L\"ticks\\*(R\" the number of loop iterations), as it roughly corresponds with\n\\&\\f(CW\\*(C`ev_prepare\\*(C'\\fR and \\f(CW\\*(C`ev_check\\*(C'\\fR calls \\- and is incremented between the\nprepare and check phases.\n.IP \"unsigned int ev_depth (loop)\" 4\n.IX Item \"unsigned int ev_depth (loop)\"\nReturns the number of times \\f(CW\\*(C`ev_run\\*(C'\\fR was entered minus the number of\ntimes \\f(CW\\*(C`ev_run\\*(C'\\fR was exited normally, in other words, the recursion depth.\n.Sp\nOutside \\f(CW\\*(C`ev_run\\*(C'\\fR, this number is zero. In a callback, this number is\n\\&\\f(CW1\\fR, unless \\f(CW\\*(C`ev_run\\*(C'\\fR was invoked recursively (or from another thread),\nin which case it is higher.\n.Sp\nLeaving \\f(CW\\*(C`ev_run\\*(C'\\fR abnormally (setjmp/longjmp, cancelling the thread,\nthrowing an exception etc.), doesn't count as \\*(L\"exit\\*(R\" \\- consider this\nas a hint to avoid such ungentleman-like behaviour unless it's really\nconvenient, in which case it is fully supported.\n.IP \"unsigned int ev_backend (loop)\" 4\n.IX Item \"unsigned int ev_backend (loop)\"\nReturns one of the \\f(CW\\*(C`EVBACKEND_*\\*(C'\\fR flags indicating the event backend in\nuse.\n.IP \"ev_tstamp ev_now (loop)\" 4\n.IX Item \"ev_tstamp ev_now (loop)\"\nReturns the current \\*(L\"event loop time\\*(R\", which is the time the event loop\nreceived events and started processing them. This timestamp does not\nchange as long as callbacks are being processed, and this is also the base\ntime used for relative timers. You can treat it as the timestamp of the\nevent occurring (or more correctly, libev finding out about it).\n.IP \"ev_now_update (loop)\" 4\n.IX Item \"ev_now_update (loop)\"\nEstablishes the current time by querying the kernel, updating the time\nreturned by \\f(CW\\*(C`ev_now ()\\*(C'\\fR in the progress. This is a costly operation and\nis usually done automatically within \\f(CW\\*(C`ev_run ()\\*(C'\\fR.\n.Sp\nThis function is rarely useful, but when some event callback runs for a\nvery long time without entering the event loop, updating libev's idea of\nthe current time is a good idea.\n.Sp\nSee also \\*(L\"The special problem of time updates\\*(R\" in the \\f(CW\\*(C`ev_timer\\*(C'\\fR section.\n.IP \"ev_suspend (loop)\" 4\n.IX Item \"ev_suspend (loop)\"\n.PD 0\n.IP \"ev_resume (loop)\" 4\n.IX Item \"ev_resume (loop)\"\n.PD\nThese two functions suspend and resume an event loop, for use when the\nloop is not used for a while and timeouts should not be processed.\n.Sp\nA typical use case would be an interactive program such as a game:  When\nthe user presses \\f(CW\\*(C`^Z\\*(C'\\fR to suspend the game and resumes it an hour later it\nwould be best to handle timeouts as if no time had actually passed while\nthe program was suspended. This can be achieved by calling \\f(CW\\*(C`ev_suspend\\*(C'\\fR\nin your \\f(CW\\*(C`SIGTSTP\\*(C'\\fR handler, sending yourself a \\f(CW\\*(C`SIGSTOP\\*(C'\\fR and calling\n\\&\\f(CW\\*(C`ev_resume\\*(C'\\fR directly afterwards to resume timer processing.\n.Sp\nEffectively, all \\f(CW\\*(C`ev_timer\\*(C'\\fR watchers will be delayed by the time spend\nbetween \\f(CW\\*(C`ev_suspend\\*(C'\\fR and \\f(CW\\*(C`ev_resume\\*(C'\\fR, and all \\f(CW\\*(C`ev_periodic\\*(C'\\fR watchers\nwill be rescheduled (that is, they will lose any events that would have\noccurred while suspended).\n.Sp\nAfter calling \\f(CW\\*(C`ev_suspend\\*(C'\\fR you \\fBmust not\\fR call \\fIany\\fR function on the\ngiven loop other than \\f(CW\\*(C`ev_resume\\*(C'\\fR, and you \\fBmust not\\fR call \\f(CW\\*(C`ev_resume\\*(C'\\fR\nwithout a previous call to \\f(CW\\*(C`ev_suspend\\*(C'\\fR.\n.Sp\nCalling \\f(CW\\*(C`ev_suspend\\*(C'\\fR/\\f(CW\\*(C`ev_resume\\*(C'\\fR has the side effect of updating the\nevent loop time (see \\f(CW\\*(C`ev_now_update\\*(C'\\fR).\n.IP \"bool ev_run (loop, int flags)\" 4\n.IX Item \"bool ev_run (loop, int flags)\"\nFinally, this is it, the event handler. This function usually is called\nafter you have initialised all your watchers and you want to start\nhandling events. It will ask the operating system for any new events, call\nthe watcher callbacks, and then repeat the whole process indefinitely: This\nis why event loops are called \\fIloops\\fR.\n.Sp\nIf the flags argument is specified as \\f(CW0\\fR, it will keep handling events\nuntil either no event watchers are active anymore or \\f(CW\\*(C`ev_break\\*(C'\\fR was\ncalled.\n.Sp\nThe return value is false if there are no more active watchers (which\nusually means \\*(L\"all jobs done\\*(R\" or \\*(L\"deadlock\\*(R\"), and true in all other cases\n(which usually means \" you should call \\f(CW\\*(C`ev_run\\*(C'\\fR again\").\n.Sp\nPlease note that an explicit \\f(CW\\*(C`ev_break\\*(C'\\fR is usually better than\nrelying on all watchers to be stopped when deciding when a program has\nfinished (especially in interactive programs), but having a program\nthat automatically loops as long as it has to and no longer by virtue\nof relying on its watchers stopping correctly, that is truly a thing of\nbeauty.\n.Sp\nThis function is \\fImostly\\fR exception-safe \\- you can break out of a\n\\&\\f(CW\\*(C`ev_run\\*(C'\\fR call by calling \\f(CW\\*(C`longjmp\\*(C'\\fR in a callback, throwing a \\*(C+\nexception and so on. This does not decrement the \\f(CW\\*(C`ev_depth\\*(C'\\fR value, nor\nwill it clear any outstanding \\f(CW\\*(C`EVBREAK_ONE\\*(C'\\fR breaks.\n.Sp\nA flags value of \\f(CW\\*(C`EVRUN_NOWAIT\\*(C'\\fR will look for new events, will handle\nthose events and any already outstanding ones, but will not wait and\nblock your process in case there are no events and will return after one\niteration of the loop. This is sometimes useful to poll and handle new\nevents while doing lengthy calculations, to keep the program responsive.\n.Sp\nA flags value of \\f(CW\\*(C`EVRUN_ONCE\\*(C'\\fR will look for new events (waiting if\nnecessary) and will handle those and any already outstanding ones. It\nwill block your process until at least one new event arrives (which could\nbe an event internal to libev itself, so there is no guarantee that a\nuser-registered callback will be called), and will return after one\niteration of the loop.\n.Sp\nThis is useful if you are waiting for some external event in conjunction\nwith something not expressible using other libev watchers (i.e. \"roll your\nown \\f(CW\\*(C`ev_run\\*(C'\\fR\"). However, a pair of \\f(CW\\*(C`ev_prepare\\*(C'\\fR/\\f(CW\\*(C`ev_check\\*(C'\\fR watchers is\nusually a better approach for this kind of thing.\n.Sp\nHere are the gory details of what \\f(CW\\*(C`ev_run\\*(C'\\fR does (this is for your\nunderstanding, not a guarantee that things will work exactly like this in\nfuture versions):\n.Sp\n.Vb 10\n\\&   \\- Increment loop depth.\n\\&   \\- Reset the ev_break status.\n\\&   \\- Before the first iteration, call any pending watchers.\n\\&   LOOP:\n\\&   \\- If EVFLAG_FORKCHECK was used, check for a fork.\n\\&   \\- If a fork was detected (by any means), queue and call all fork watchers.\n\\&   \\- Queue and call all prepare watchers.\n\\&   \\- If ev_break was called, goto FINISH.\n\\&   \\- If we have been forked, detach and recreate the kernel state\n\\&     as to not disturb the other process.\n\\&   \\- Update the kernel state with all outstanding changes.\n\\&   \\- Update the \"event loop time\" (ev_now ()).\n\\&   \\- Calculate for how long to sleep or block, if at all\n\\&     (active idle watchers, EVRUN_NOWAIT or not having\n\\&     any active watchers at all will result in not sleeping).\n\\&   \\- Sleep if the I/O and timer collect interval say so.\n\\&   \\- Increment loop iteration counter.\n\\&   \\- Block the process, waiting for any events.\n\\&   \\- Queue all outstanding I/O (fd) events.\n\\&   \\- Update the \"event loop time\" (ev_now ()), and do time jump adjustments.\n\\&   \\- Queue all expired timers.\n\\&   \\- Queue all expired periodics.\n\\&   \\- Queue all idle watchers with priority higher than that of pending events.\n\\&   \\- Queue all check watchers.\n\\&   \\- Call all queued watchers in reverse order (i.e. check watchers first).\n\\&     Signals and child watchers are implemented as I/O watchers, and will\n\\&     be handled here by queueing them when their watcher gets executed.\n\\&   \\- If ev_break has been called, or EVRUN_ONCE or EVRUN_NOWAIT\n\\&     were used, or there are no active watchers, goto FINISH, otherwise\n\\&     continue with step LOOP.\n\\&   FINISH:\n\\&   \\- Reset the ev_break status iff it was EVBREAK_ONE.\n\\&   \\- Decrement the loop depth.\n\\&   \\- Return.\n.Ve\n.Sp\nExample: Queue some jobs and then loop until no events are outstanding\nanymore.\n.Sp\n.Vb 4\n\\&   ... queue jobs here, make sure they register event watchers as long\n\\&   ... as they still have work to do (even an idle watcher will do..)\n\\&   ev_run (my_loop, 0);\n\\&   ... jobs done or somebody called break. yeah!\n.Ve\n.IP \"ev_break (loop, how)\" 4\n.IX Item \"ev_break (loop, how)\"\nCan be used to make a call to \\f(CW\\*(C`ev_run\\*(C'\\fR return early (but only after it\nhas processed all outstanding events). The \\f(CW\\*(C`how\\*(C'\\fR argument must be either\n\\&\\f(CW\\*(C`EVBREAK_ONE\\*(C'\\fR, which will make the innermost \\f(CW\\*(C`ev_run\\*(C'\\fR call return, or\n\\&\\f(CW\\*(C`EVBREAK_ALL\\*(C'\\fR, which will make all nested \\f(CW\\*(C`ev_run\\*(C'\\fR calls return.\n.Sp\nThis \\*(L\"break state\\*(R\" will be cleared on the next call to \\f(CW\\*(C`ev_run\\*(C'\\fR.\n.Sp\nIt is safe to call \\f(CW\\*(C`ev_break\\*(C'\\fR from outside any \\f(CW\\*(C`ev_run\\*(C'\\fR calls, too, in\nwhich case it will have no effect.\n.IP \"ev_ref (loop)\" 4\n.IX Item \"ev_ref (loop)\"\n.PD 0\n.IP \"ev_unref (loop)\" 4\n.IX Item \"ev_unref (loop)\"\n.PD\nRef/unref can be used to add or remove a reference count on the event\nloop: Every watcher keeps one reference, and as long as the reference\ncount is nonzero, \\f(CW\\*(C`ev_run\\*(C'\\fR will not return on its own.\n.Sp\nThis is useful when you have a watcher that you never intend to\nunregister, but that nevertheless should not keep \\f(CW\\*(C`ev_run\\*(C'\\fR from\nreturning. In such a case, call \\f(CW\\*(C`ev_unref\\*(C'\\fR after starting, and \\f(CW\\*(C`ev_ref\\*(C'\\fR\nbefore stopping it.\n.Sp\nAs an example, libev itself uses this for its internal signal pipe: It\nis not visible to the libev user and should not keep \\f(CW\\*(C`ev_run\\*(C'\\fR from\nexiting if no event watchers registered by it are active. It is also an\nexcellent way to do this for generic recurring timers or from within\nthird-party libraries. Just remember to \\fIunref after start\\fR and \\fIref\nbefore stop\\fR (but only if the watcher wasn't active before, or was active\nbefore, respectively. Note also that libev might stop watchers itself\n(e.g. non-repeating timers) in which case you have to \\f(CW\\*(C`ev_ref\\*(C'\\fR\nin the callback).\n.Sp\nExample: Create a signal watcher, but keep it from keeping \\f(CW\\*(C`ev_run\\*(C'\\fR\nrunning when nothing else is active.\n.Sp\n.Vb 4\n\\&   ev_signal exitsig;\n\\&   ev_signal_init (&exitsig, sig_cb, SIGINT);\n\\&   ev_signal_start (loop, &exitsig);\n\\&   ev_unref (loop);\n.Ve\n.Sp\nExample: For some weird reason, unregister the above signal handler again.\n.Sp\n.Vb 2\n\\&   ev_ref (loop);\n\\&   ev_signal_stop (loop, &exitsig);\n.Ve\n.IP \"ev_set_io_collect_interval (loop, ev_tstamp interval)\" 4\n.IX Item \"ev_set_io_collect_interval (loop, ev_tstamp interval)\"\n.PD 0\n.IP \"ev_set_timeout_collect_interval (loop, ev_tstamp interval)\" 4\n.IX Item \"ev_set_timeout_collect_interval (loop, ev_tstamp interval)\"\n.PD\nThese advanced functions influence the time that libev will spend waiting\nfor events. Both time intervals are by default \\f(CW0\\fR, meaning that libev\nwill try to invoke timer/periodic callbacks and I/O callbacks with minimum\nlatency.\n.Sp\nSetting these to a higher value (the \\f(CW\\*(C`interval\\*(C'\\fR \\fImust\\fR be >= \\f(CW0\\fR)\nallows libev to delay invocation of I/O and timer/periodic callbacks\nto increase efficiency of loop iterations (or to increase power-saving\nopportunities).\n.Sp\nThe idea is that sometimes your program runs just fast enough to handle\none (or very few) event(s) per loop iteration. While this makes the\nprogram responsive, it also wastes a lot of \\s-1CPU\\s0 time to poll for new\nevents, especially with backends like \\f(CW\\*(C`select ()\\*(C'\\fR which have a high\noverhead for the actual polling but can deliver many events at once.\n.Sp\nBy setting a higher \\fIio collect interval\\fR you allow libev to spend more\ntime collecting I/O events, so you can handle more events per iteration,\nat the cost of increasing latency. Timeouts (both \\f(CW\\*(C`ev_periodic\\*(C'\\fR and\n\\&\\f(CW\\*(C`ev_timer\\*(C'\\fR) will not be affected. Setting this to a non-null value will\nintroduce an additional \\f(CW\\*(C`ev_sleep ()\\*(C'\\fR call into most loop iterations. The\nsleep time ensures that libev will not poll for I/O events more often then\nonce per this interval, on average (as long as the host time resolution is\ngood enough).\n.Sp\nLikewise, by setting a higher \\fItimeout collect interval\\fR you allow libev\nto spend more time collecting timeouts, at the expense of increased\nlatency/jitter/inexactness (the watcher callback will be called\nlater). \\f(CW\\*(C`ev_io\\*(C'\\fR watchers will not be affected. Setting this to a non-null\nvalue will not introduce any overhead in libev.\n.Sp\nMany (busy) programs can usually benefit by setting the I/O collect\ninterval to a value near \\f(CW0.1\\fR or so, which is often enough for\ninteractive servers (of course not for games), likewise for timeouts. It\nusually doesn't make much sense to set it to a lower value than \\f(CW0.01\\fR,\nas this approaches the timing granularity of most systems. Note that if\nyou do transactions with the outside world and you can't increase the\nparallelity, then this setting will limit your transaction rate (if you\nneed to poll once per transaction and the I/O collect interval is 0.01,\nthen you can't do more than 100 transactions per second).\n.Sp\nSetting the \\fItimeout collect interval\\fR can improve the opportunity for\nsaving power, as the program will \\*(L\"bundle\\*(R\" timer callback invocations that\nare \\*(L\"near\\*(R\" in time together, by delaying some, thus reducing the number of\ntimes the process sleeps and wakes up again. Another useful technique to\nreduce iterations/wake\\-ups is to use \\f(CW\\*(C`ev_periodic\\*(C'\\fR watchers and make sure\nthey fire on, say, one-second boundaries only.\n.Sp\nExample: we only need 0.1s timeout granularity, and we wish not to poll\nmore often than 100 times per second:\n.Sp\n.Vb 2\n\\&   ev_set_timeout_collect_interval (EV_DEFAULT_UC_ 0.1);\n\\&   ev_set_io_collect_interval (EV_DEFAULT_UC_ 0.01);\n.Ve\n.IP \"ev_invoke_pending (loop)\" 4\n.IX Item \"ev_invoke_pending (loop)\"\nThis call will simply invoke all pending watchers while resetting their\npending state. Normally, \\f(CW\\*(C`ev_run\\*(C'\\fR does this automatically when required,\nbut when overriding the invoke callback this call comes handy. This\nfunction can be invoked from a watcher \\- this can be useful for example\nwhen you want to do some lengthy calculation and want to pass further\nevent handling to another thread (you still have to make sure only one\nthread executes within \\f(CW\\*(C`ev_invoke_pending\\*(C'\\fR or \\f(CW\\*(C`ev_run\\*(C'\\fR of course).\n.IP \"int ev_pending_count (loop)\" 4\n.IX Item \"int ev_pending_count (loop)\"\nReturns the number of pending watchers \\- zero indicates that no watchers\nare pending.\n.IP \"ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(\\s-1EV_P\\s0))\" 4\n.IX Item \"ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(EV_P))\"\nThis overrides the invoke pending functionality of the loop: Instead of\ninvoking all pending watchers when there are any, \\f(CW\\*(C`ev_run\\*(C'\\fR will call\nthis callback instead. This is useful, for example, when you want to\ninvoke the actual watchers inside another context (another thread etc.).\n.Sp\nIf you want to reset the callback, use \\f(CW\\*(C`ev_invoke_pending\\*(C'\\fR as new\ncallback.\n.IP \"ev_set_loop_release_cb (loop, void (*release)(\\s-1EV_P\\s0) throw (), void (*acquire)(\\s-1EV_P\\s0) throw ())\" 4\n.IX Item \"ev_set_loop_release_cb (loop, void (*release)(EV_P) throw (), void (*acquire)(EV_P) throw ())\"\nSometimes you want to share the same loop between multiple threads. This\ncan be done relatively simply by putting mutex_lock/unlock calls around\neach call to a libev function.\n.Sp\nHowever, \\f(CW\\*(C`ev_run\\*(C'\\fR can run an indefinite time, so it is not feasible\nto wait for it to return. One way around this is to wake up the event\nloop via \\f(CW\\*(C`ev_break\\*(C'\\fR and \\f(CW\\*(C`ev_async_send\\*(C'\\fR, another way is to set these\n\\&\\fIrelease\\fR and \\fIacquire\\fR callbacks on the loop.\n.Sp\nWhen set, then \\f(CW\\*(C`release\\*(C'\\fR will be called just before the thread is\nsuspended waiting for new events, and \\f(CW\\*(C`acquire\\*(C'\\fR is called just\nafterwards.\n.Sp\nIdeally, \\f(CW\\*(C`release\\*(C'\\fR will just call your mutex_unlock function, and\n\\&\\f(CW\\*(C`acquire\\*(C'\\fR will just call the mutex_lock function again.\n.Sp\nWhile event loop modifications are allowed between invocations of\n\\&\\f(CW\\*(C`release\\*(C'\\fR and \\f(CW\\*(C`acquire\\*(C'\\fR (that's their only purpose after all), no\nmodifications done will affect the event loop, i.e. adding watchers will\nhave no effect on the set of file descriptors being watched, or the time\nwaited. Use an \\f(CW\\*(C`ev_async\\*(C'\\fR watcher to wake up \\f(CW\\*(C`ev_run\\*(C'\\fR when you want it\nto take note of any changes you made.\n.Sp\nIn theory, threads executing \\f(CW\\*(C`ev_run\\*(C'\\fR will be async-cancel safe between\ninvocations of \\f(CW\\*(C`release\\*(C'\\fR and \\f(CW\\*(C`acquire\\*(C'\\fR.\n.Sp\nSee also the locking example in the \\f(CW\\*(C`THREADS\\*(C'\\fR section later in this\ndocument.\n.IP \"ev_set_userdata (loop, void *data)\" 4\n.IX Item \"ev_set_userdata (loop, void *data)\"\n.PD 0\n.IP \"void *ev_userdata (loop)\" 4\n.IX Item \"void *ev_userdata (loop)\"\n.PD\nSet and retrieve a single \\f(CW\\*(C`void *\\*(C'\\fR associated with a loop. When\n\\&\\f(CW\\*(C`ev_set_userdata\\*(C'\\fR has never been called, then \\f(CW\\*(C`ev_userdata\\*(C'\\fR returns\n\\&\\f(CW0\\fR.\n.Sp\nThese two functions can be used to associate arbitrary data with a loop,\nand are intended solely for the \\f(CW\\*(C`invoke_pending_cb\\*(C'\\fR, \\f(CW\\*(C`release\\*(C'\\fR and\n\\&\\f(CW\\*(C`acquire\\*(C'\\fR callbacks described above, but of course can be (ab\\-)used for\nany other purpose as well.\n.IP \"ev_verify (loop)\" 4\n.IX Item \"ev_verify (loop)\"\nThis function only does something when \\f(CW\\*(C`EV_VERIFY\\*(C'\\fR support has been\ncompiled in, which is the default for non-minimal builds. It tries to go\nthrough all internal structures and checks them for validity. If anything\nis found to be inconsistent, it will print an error message to standard\nerror and call \\f(CW\\*(C`abort ()\\*(C'\\fR.\n.Sp\nThis can be used to catch bugs inside libev itself: under normal\ncircumstances, this function will never abort as of course libev keeps its\ndata structures consistent.\n.SH \"ANATOMY OF A WATCHER\"\n.IX Header \"ANATOMY OF A WATCHER\"\nIn the following description, uppercase \\f(CW\\*(C`TYPE\\*(C'\\fR in names stands for the\nwatcher type, e.g. \\f(CW\\*(C`ev_TYPE_start\\*(C'\\fR can mean \\f(CW\\*(C`ev_timer_start\\*(C'\\fR for timer\nwatchers and \\f(CW\\*(C`ev_io_start\\*(C'\\fR for I/O watchers.\n.PP\nA watcher is an opaque structure that you allocate and register to record\nyour interest in some event. To make a concrete example, imagine you want\nto wait for \\s-1STDIN\\s0 to become readable, you would create an \\f(CW\\*(C`ev_io\\*(C'\\fR watcher\nfor that:\n.PP\n.Vb 5\n\\&   static void my_cb (struct ev_loop *loop, ev_io *w, int revents)\n\\&   {\n\\&     ev_io_stop (w);\n\\&     ev_break (loop, EVBREAK_ALL);\n\\&   }\n\\&\n\\&   struct ev_loop *loop = ev_default_loop (0);\n\\&\n\\&   ev_io stdin_watcher;\n\\&\n\\&   ev_init (&stdin_watcher, my_cb);\n\\&   ev_io_set (&stdin_watcher, STDIN_FILENO, EV_READ);\n\\&   ev_io_start (loop, &stdin_watcher);\n\\&\n\\&   ev_run (loop, 0);\n.Ve\n.PP\nAs you can see, you are responsible for allocating the memory for your\nwatcher structures (and it is \\fIusually\\fR a bad idea to do this on the\nstack).\n.PP\nEach watcher has an associated watcher structure (called \\f(CW\\*(C`struct ev_TYPE\\*(C'\\fR\nor simply \\f(CW\\*(C`ev_TYPE\\*(C'\\fR, as typedefs are provided for all watcher structs).\n.PP\nEach watcher structure must be initialised by a call to \\f(CW\\*(C`ev_init (watcher\n*, callback)\\*(C'\\fR, which expects a callback to be provided. This callback is\ninvoked each time the event occurs (or, in the case of I/O watchers, each\ntime the event loop detects that the file descriptor given is readable\nand/or writable).\n.PP\nEach watcher type further has its own \\f(CW\\*(C`ev_TYPE_set (watcher *, ...)\\*(C'\\fR\nmacro to configure it, with arguments specific to the watcher type. There\nis also a macro to combine initialisation and setting in one call: \\f(CW\\*(C`ev_TYPE_init (watcher *, callback, ...)\\*(C'\\fR.\n.PP\nTo make the watcher actually watch out for events, you have to start it\nwith a watcher-specific start function (\\f(CW\\*(C`ev_TYPE_start (loop, watcher\n*)\\*(C'\\fR), and you can stop watching for events at any time by calling the\ncorresponding stop function (\\f(CW\\*(C`ev_TYPE_stop (loop, watcher *)\\*(C'\\fR.\n.PP\nAs long as your watcher is active (has been started but not stopped) you\nmust not touch the values stored in it. Most specifically you must never\nreinitialise it or call its \\f(CW\\*(C`ev_TYPE_set\\*(C'\\fR macro.\n.PP\nEach and every callback receives the event loop pointer as first, the\nregistered watcher structure as second, and a bitset of received events as\nthird argument.\n.PP\nThe received events usually include a single bit per event type received\n(you can receive multiple events at the same time). The possible bit masks\nare:\n.ie n .IP \"\"\"EV_READ\"\"\" 4\n.el .IP \"\\f(CWEV_READ\\fR\" 4\n.IX Item \"EV_READ\"\n.PD 0\n.ie n .IP \"\"\"EV_WRITE\"\"\" 4\n.el .IP \"\\f(CWEV_WRITE\\fR\" 4\n.IX Item \"EV_WRITE\"\n.PD\nThe file descriptor in the \\f(CW\\*(C`ev_io\\*(C'\\fR watcher has become readable and/or\nwritable.\n.ie n .IP \"\"\"EV_TIMER\"\"\" 4\n.el .IP \"\\f(CWEV_TIMER\\fR\" 4\n.IX Item \"EV_TIMER\"\nThe \\f(CW\\*(C`ev_timer\\*(C'\\fR watcher has timed out.\n.ie n .IP \"\"\"EV_PERIODIC\"\"\" 4\n.el .IP \"\\f(CWEV_PERIODIC\\fR\" 4\n.IX Item \"EV_PERIODIC\"\nThe \\f(CW\\*(C`ev_periodic\\*(C'\\fR watcher has timed out.\n.ie n .IP \"\"\"EV_SIGNAL\"\"\" 4\n.el .IP \"\\f(CWEV_SIGNAL\\fR\" 4\n.IX Item \"EV_SIGNAL\"\nThe signal specified in the \\f(CW\\*(C`ev_signal\\*(C'\\fR watcher has been received by a thread.\n.ie n .IP \"\"\"EV_CHILD\"\"\" 4\n.el .IP \"\\f(CWEV_CHILD\\fR\" 4\n.IX Item \"EV_CHILD\"\nThe pid specified in the \\f(CW\\*(C`ev_child\\*(C'\\fR watcher has received a status change.\n.ie n .IP \"\"\"EV_STAT\"\"\" 4\n.el .IP \"\\f(CWEV_STAT\\fR\" 4\n.IX Item \"EV_STAT\"\nThe path specified in the \\f(CW\\*(C`ev_stat\\*(C'\\fR watcher changed its attributes somehow.\n.ie n .IP \"\"\"EV_IDLE\"\"\" 4\n.el .IP \"\\f(CWEV_IDLE\\fR\" 4\n.IX Item \"EV_IDLE\"\nThe \\f(CW\\*(C`ev_idle\\*(C'\\fR watcher has determined that you have nothing better to do.\n.ie n .IP \"\"\"EV_PREPARE\"\"\" 4\n.el .IP \"\\f(CWEV_PREPARE\\fR\" 4\n.IX Item \"EV_PREPARE\"\n.PD 0\n.ie n .IP \"\"\"EV_CHECK\"\"\" 4\n.el .IP \"\\f(CWEV_CHECK\\fR\" 4\n.IX Item \"EV_CHECK\"\n.PD\nAll \\f(CW\\*(C`ev_prepare\\*(C'\\fR watchers are invoked just \\fIbefore\\fR \\f(CW\\*(C`ev_run\\*(C'\\fR starts to\ngather new events, and all \\f(CW\\*(C`ev_check\\*(C'\\fR watchers are queued (not invoked)\njust after \\f(CW\\*(C`ev_run\\*(C'\\fR has gathered them, but before it queues any callbacks\nfor any received events. That means \\f(CW\\*(C`ev_prepare\\*(C'\\fR watchers are the last\nwatchers invoked before the event loop sleeps or polls for new events, and\n\\&\\f(CW\\*(C`ev_check\\*(C'\\fR watchers will be invoked before any other watchers of the same\nor lower priority within an event loop iteration.\n.Sp\nCallbacks of both watcher types can start and stop as many watchers as\nthey want, and all of them will be taken into account (for example, a\n\\&\\f(CW\\*(C`ev_prepare\\*(C'\\fR watcher might start an idle watcher to keep \\f(CW\\*(C`ev_run\\*(C'\\fR from\nblocking).\n.ie n .IP \"\"\"EV_EMBED\"\"\" 4\n.el .IP \"\\f(CWEV_EMBED\\fR\" 4\n.IX Item \"EV_EMBED\"\nThe embedded event loop specified in the \\f(CW\\*(C`ev_embed\\*(C'\\fR watcher needs attention.\n.ie n .IP \"\"\"EV_FORK\"\"\" 4\n.el .IP \"\\f(CWEV_FORK\\fR\" 4\n.IX Item \"EV_FORK\"\nThe event loop has been resumed in the child process after fork (see\n\\&\\f(CW\\*(C`ev_fork\\*(C'\\fR).\n.ie n .IP \"\"\"EV_CLEANUP\"\"\" 4\n.el .IP \"\\f(CWEV_CLEANUP\\fR\" 4\n.IX Item \"EV_CLEANUP\"\nThe event loop is about to be destroyed (see \\f(CW\\*(C`ev_cleanup\\*(C'\\fR).\n.ie n .IP \"\"\"EV_ASYNC\"\"\" 4\n.el .IP \"\\f(CWEV_ASYNC\\fR\" 4\n.IX Item \"EV_ASYNC\"\nThe given async watcher has been asynchronously notified (see \\f(CW\\*(C`ev_async\\*(C'\\fR).\n.ie n .IP \"\"\"EV_CUSTOM\"\"\" 4\n.el .IP \"\\f(CWEV_CUSTOM\\fR\" 4\n.IX Item \"EV_CUSTOM\"\nNot ever sent (or otherwise used) by libev itself, but can be freely used\nby libev users to signal watchers (e.g. via \\f(CW\\*(C`ev_feed_event\\*(C'\\fR).\n.ie n .IP \"\"\"EV_ERROR\"\"\" 4\n.el .IP \"\\f(CWEV_ERROR\\fR\" 4\n.IX Item \"EV_ERROR\"\nAn unspecified error has occurred, the watcher has been stopped. This might\nhappen because the watcher could not be properly started because libev\nran out of memory, a file descriptor was found to be closed or any other\nproblem. Libev considers these application bugs.\n.Sp\nYou best act on it by reporting the problem and somehow coping with the\nwatcher being stopped. Note that well-written programs should not receive\nan error ever, so when your watcher receives it, this usually indicates a\nbug in your program.\n.Sp\nLibev will usually signal a few \\*(L\"dummy\\*(R\" events together with an error, for\nexample it might indicate that a fd is readable or writable, and if your\ncallbacks is well-written it can just attempt the operation and cope with\nthe error from \\fIread()\\fR or \\fIwrite()\\fR. This will not work in multi-threaded\nprograms, though, as the fd could already be closed and reused for another\nthing, so beware.\n.SS \"\\s-1GENERIC WATCHER FUNCTIONS\\s0\"\n.IX Subsection \"GENERIC WATCHER FUNCTIONS\"\n.ie n .IP \"\"\"ev_init\"\" (ev_TYPE *watcher, callback)\" 4\n.el .IP \"\\f(CWev_init\\fR (ev_TYPE *watcher, callback)\" 4\n.IX Item \"ev_init (ev_TYPE *watcher, callback)\"\nThis macro initialises the generic portion of a watcher. The contents\nof the watcher object can be arbitrary (so \\f(CW\\*(C`malloc\\*(C'\\fR will do). Only\nthe generic parts of the watcher are initialised, you \\fIneed\\fR to call\nthe type-specific \\f(CW\\*(C`ev_TYPE_set\\*(C'\\fR macro afterwards to initialise the\ntype-specific parts. For each type there is also a \\f(CW\\*(C`ev_TYPE_init\\*(C'\\fR macro\nwhich rolls both calls into one.\n.Sp\nYou can reinitialise a watcher at any time as long as it has been stopped\n(or never started) and there are no pending events outstanding.\n.Sp\nThe callback is always of type \\f(CW\\*(C`void (*)(struct ev_loop *loop, ev_TYPE *watcher,\nint revents)\\*(C'\\fR.\n.Sp\nExample: Initialise an \\f(CW\\*(C`ev_io\\*(C'\\fR watcher in two steps.\n.Sp\n.Vb 3\n\\&   ev_io w;\n\\&   ev_init (&w, my_cb);\n\\&   ev_io_set (&w, STDIN_FILENO, EV_READ);\n.Ve\n.ie n .IP \"\"\"ev_TYPE_set\"\" (ev_TYPE *watcher, [args])\" 4\n.el .IP \"\\f(CWev_TYPE_set\\fR (ev_TYPE *watcher, [args])\" 4\n.IX Item \"ev_TYPE_set (ev_TYPE *watcher, [args])\"\nThis macro initialises the type-specific parts of a watcher. You need to\ncall \\f(CW\\*(C`ev_init\\*(C'\\fR at least once before you call this macro, but you can\ncall \\f(CW\\*(C`ev_TYPE_set\\*(C'\\fR any number of times. You must not, however, call this\nmacro on a watcher that is active (it can be pending, however, which is a\ndifference to the \\f(CW\\*(C`ev_init\\*(C'\\fR macro).\n.Sp\nAlthough some watcher types do not have type-specific arguments\n(e.g. \\f(CW\\*(C`ev_prepare\\*(C'\\fR) you still need to call its \\f(CW\\*(C`set\\*(C'\\fR macro.\n.Sp\nSee \\f(CW\\*(C`ev_init\\*(C'\\fR, above, for an example.\n.ie n .IP \"\"\"ev_TYPE_init\"\" (ev_TYPE *watcher, callback, [args])\" 4\n.el .IP \"\\f(CWev_TYPE_init\\fR (ev_TYPE *watcher, callback, [args])\" 4\n.IX Item \"ev_TYPE_init (ev_TYPE *watcher, callback, [args])\"\nThis convenience macro rolls both \\f(CW\\*(C`ev_init\\*(C'\\fR and \\f(CW\\*(C`ev_TYPE_set\\*(C'\\fR macro\ncalls into a single call. This is the most convenient method to initialise\na watcher. The same limitations apply, of course.\n.Sp\nExample: Initialise and set an \\f(CW\\*(C`ev_io\\*(C'\\fR watcher in one step.\n.Sp\n.Vb 1\n\\&   ev_io_init (&w, my_cb, STDIN_FILENO, EV_READ);\n.Ve\n.ie n .IP \"\"\"ev_TYPE_start\"\" (loop, ev_TYPE *watcher)\" 4\n.el .IP \"\\f(CWev_TYPE_start\\fR (loop, ev_TYPE *watcher)\" 4\n.IX Item \"ev_TYPE_start (loop, ev_TYPE *watcher)\"\nStarts (activates) the given watcher. Only active watchers will receive\nevents. If the watcher is already active nothing will happen.\n.Sp\nExample: Start the \\f(CW\\*(C`ev_io\\*(C'\\fR watcher that is being abused as example in this\nwhole section.\n.Sp\n.Vb 1\n\\&   ev_io_start (EV_DEFAULT_UC, &w);\n.Ve\n.ie n .IP \"\"\"ev_TYPE_stop\"\" (loop, ev_TYPE *watcher)\" 4\n.el .IP \"\\f(CWev_TYPE_stop\\fR (loop, ev_TYPE *watcher)\" 4\n.IX Item \"ev_TYPE_stop (loop, ev_TYPE *watcher)\"\nStops the given watcher if active, and clears the pending status (whether\nthe watcher was active or not).\n.Sp\nIt is possible that stopped watchers are pending \\- for example,\nnon-repeating timers are being stopped when they become pending \\- but\ncalling \\f(CW\\*(C`ev_TYPE_stop\\*(C'\\fR ensures that the watcher is neither active nor\npending. If you want to free or reuse the memory used by the watcher it is\ntherefore a good idea to always call its \\f(CW\\*(C`ev_TYPE_stop\\*(C'\\fR function.\n.IP \"bool ev_is_active (ev_TYPE *watcher)\" 4\n.IX Item \"bool ev_is_active (ev_TYPE *watcher)\"\nReturns a true value iff the watcher is active (i.e. it has been started\nand not yet been stopped). As long as a watcher is active you must not modify\nit.\n.IP \"bool ev_is_pending (ev_TYPE *watcher)\" 4\n.IX Item \"bool ev_is_pending (ev_TYPE *watcher)\"\nReturns a true value iff the watcher is pending, (i.e. it has outstanding\nevents but its callback has not yet been invoked). As long as a watcher\nis pending (but not active) you must not call an init function on it (but\n\\&\\f(CW\\*(C`ev_TYPE_set\\*(C'\\fR is safe), you must not change its priority, and you must\nmake sure the watcher is available to libev (e.g. you cannot \\f(CW\\*(C`free ()\\*(C'\\fR\nit).\n.IP \"callback ev_cb (ev_TYPE *watcher)\" 4\n.IX Item \"callback ev_cb (ev_TYPE *watcher)\"\nReturns the callback currently set on the watcher.\n.IP \"ev_set_cb (ev_TYPE *watcher, callback)\" 4\n.IX Item \"ev_set_cb (ev_TYPE *watcher, callback)\"\nChange the callback. You can change the callback at virtually any time\n(modulo threads).\n.IP \"ev_set_priority (ev_TYPE *watcher, int priority)\" 4\n.IX Item \"ev_set_priority (ev_TYPE *watcher, int priority)\"\n.PD 0\n.IP \"int ev_priority (ev_TYPE *watcher)\" 4\n.IX Item \"int ev_priority (ev_TYPE *watcher)\"\n.PD\nSet and query the priority of the watcher. The priority is a small\ninteger between \\f(CW\\*(C`EV_MAXPRI\\*(C'\\fR (default: \\f(CW2\\fR) and \\f(CW\\*(C`EV_MINPRI\\*(C'\\fR\n(default: \\f(CW\\*(C`\\-2\\*(C'\\fR). Pending watchers with higher priority will be invoked\nbefore watchers with lower priority, but priority will not keep watchers\nfrom being executed (except for \\f(CW\\*(C`ev_idle\\*(C'\\fR watchers).\n.Sp\nIf you need to suppress invocation when higher priority events are pending\nyou need to look at \\f(CW\\*(C`ev_idle\\*(C'\\fR watchers, which provide this functionality.\n.Sp\nYou \\fImust not\\fR change the priority of a watcher as long as it is active or\npending.\n.Sp\nSetting a priority outside the range of \\f(CW\\*(C`EV_MINPRI\\*(C'\\fR to \\f(CW\\*(C`EV_MAXPRI\\*(C'\\fR is\nfine, as long as you do not mind that the priority value you query might\nor might not have been clamped to the valid range.\n.Sp\nThe default priority used by watchers when no priority has been set is\nalways \\f(CW0\\fR, which is supposed to not be too high and not be too low :).\n.Sp\nSee \\*(L\"\\s-1WATCHER PRIORITY MODELS\\*(R\"\\s0, below, for a more thorough treatment of\npriorities.\n.IP \"ev_invoke (loop, ev_TYPE *watcher, int revents)\" 4\n.IX Item \"ev_invoke (loop, ev_TYPE *watcher, int revents)\"\nInvoke the \\f(CW\\*(C`watcher\\*(C'\\fR with the given \\f(CW\\*(C`loop\\*(C'\\fR and \\f(CW\\*(C`revents\\*(C'\\fR. Neither\n\\&\\f(CW\\*(C`loop\\*(C'\\fR nor \\f(CW\\*(C`revents\\*(C'\\fR need to be valid as long as the watcher callback\ncan deal with that fact, as both are simply passed through to the\ncallback.\n.IP \"int ev_clear_pending (loop, ev_TYPE *watcher)\" 4\n.IX Item \"int ev_clear_pending (loop, ev_TYPE *watcher)\"\nIf the watcher is pending, this function clears its pending status and\nreturns its \\f(CW\\*(C`revents\\*(C'\\fR bitset (as if its callback was invoked). If the\nwatcher isn't pending it does nothing and returns \\f(CW0\\fR.\n.Sp\nSometimes it can be useful to \\*(L\"poll\\*(R\" a watcher instead of waiting for its\ncallback to be invoked, which can be accomplished with this function.\n.IP \"ev_feed_event (loop, ev_TYPE *watcher, int revents)\" 4\n.IX Item \"ev_feed_event (loop, ev_TYPE *watcher, int revents)\"\nFeeds the given event set into the event loop, as if the specified event\nhad happened for the specified watcher (which must be a pointer to an\ninitialised but not necessarily started event watcher). Obviously you must\nnot free the watcher as long as it has pending events.\n.Sp\nStopping the watcher, letting libev invoke it, or calling\n\\&\\f(CW\\*(C`ev_clear_pending\\*(C'\\fR will clear the pending event, even if the watcher was\nnot started in the first place.\n.Sp\nSee also \\f(CW\\*(C`ev_feed_fd_event\\*(C'\\fR and \\f(CW\\*(C`ev_feed_signal_event\\*(C'\\fR for related\nfunctions that do not need a watcher.\n.PP\nSee also the \\*(L\"\\s-1ASSOCIATING CUSTOM DATA WITH A WATCHER\\*(R\"\\s0 and \\*(L\"\\s-1BUILDING YOUR\nOWN COMPOSITE WATCHERS\\*(R\"\\s0 idioms.\n.SS \"\\s-1WATCHER STATES\\s0\"\n.IX Subsection \"WATCHER STATES\"\nThere are various watcher states mentioned throughout this manual \\-\nactive, pending and so on. In this section these states and the rules to\ntransition between them will be described in more detail \\- and while these\nrules might look complicated, they usually do \\*(L\"the right thing\\*(R\".\n.IP \"initialised\" 4\n.IX Item \"initialised\"\nBefore a watcher can be registered with the event loop it has to be\ninitialised. This can be done with a call to \\f(CW\\*(C`ev_TYPE_init\\*(C'\\fR, or calls to\n\\&\\f(CW\\*(C`ev_init\\*(C'\\fR followed by the watcher-specific \\f(CW\\*(C`ev_TYPE_set\\*(C'\\fR function.\n.Sp\nIn this state it is simply some block of memory that is suitable for\nuse in an event loop. It can be moved around, freed, reused etc. at\nwill \\- as long as you either keep the memory contents intact, or call\n\\&\\f(CW\\*(C`ev_TYPE_init\\*(C'\\fR again.\n.IP \"started/running/active\" 4\n.IX Item \"started/running/active\"\nOnce a watcher has been started with a call to \\f(CW\\*(C`ev_TYPE_start\\*(C'\\fR it becomes\nproperty of the event loop, and is actively waiting for events. While in\nthis state it cannot be accessed (except in a few documented ways), moved,\nfreed or anything else \\- the only legal thing is to keep a pointer to it,\nand call libev functions on it that are documented to work on active watchers.\n.IP \"pending\" 4\n.IX Item \"pending\"\nIf a watcher is active and libev determines that an event it is interested\nin has occurred (such as a timer expiring), it will become pending. It will\nstay in this pending state until either it is stopped or its callback is\nabout to be invoked, so it is not normally pending inside the watcher\ncallback.\n.Sp\nThe watcher might or might not be active while it is pending (for example,\nan expired non-repeating timer can be pending but no longer active). If it\nis stopped, it can be freely accessed (e.g. by calling \\f(CW\\*(C`ev_TYPE_set\\*(C'\\fR),\nbut it is still property of the event loop at this time, so cannot be\nmoved, freed or reused. And if it is active the rules described in the\nprevious item still apply.\n.Sp\nIt is also possible to feed an event on a watcher that is not active (e.g.\nvia \\f(CW\\*(C`ev_feed_event\\*(C'\\fR), in which case it becomes pending without being\nactive.\n.IP \"stopped\" 4\n.IX Item \"stopped\"\nA watcher can be stopped implicitly by libev (in which case it might still\nbe pending), or explicitly by calling its \\f(CW\\*(C`ev_TYPE_stop\\*(C'\\fR function. The\nlatter will clear any pending state the watcher might be in, regardless\nof whether it was active or not, so stopping a watcher explicitly before\nfreeing it is often a good idea.\n.Sp\nWhile stopped (and not pending) the watcher is essentially in the\ninitialised state, that is, it can be reused, moved, modified in any way\nyou wish (but when you trash the memory block, you need to \\f(CW\\*(C`ev_TYPE_init\\*(C'\\fR\nit again).\n.SS \"\\s-1WATCHER PRIORITY MODELS\\s0\"\n.IX Subsection \"WATCHER PRIORITY MODELS\"\nMany event loops support \\fIwatcher priorities\\fR, which are usually small\nintegers that influence the ordering of event callback invocation\nbetween watchers in some way, all else being equal.\n.PP\nIn libev, Watcher priorities can be set using \\f(CW\\*(C`ev_set_priority\\*(C'\\fR. See its\ndescription for the more technical details such as the actual priority\nrange.\n.PP\nThere are two common ways how these these priorities are being interpreted\nby event loops:\n.PP\nIn the more common lock-out model, higher priorities \\*(L\"lock out\\*(R\" invocation\nof lower priority watchers, which means as long as higher priority\nwatchers receive events, lower priority watchers are not being invoked.\n.PP\nThe less common only-for-ordering model uses priorities solely to order\ncallback invocation within a single event loop iteration: Higher priority\nwatchers are invoked before lower priority ones, but they all get invoked\nbefore polling for new events.\n.PP\nLibev uses the second (only-for-ordering) model for all its watchers\nexcept for idle watchers (which use the lock-out model).\n.PP\nThe rationale behind this is that implementing the lock-out model for\nwatchers is not well supported by most kernel interfaces, and most event\nlibraries will just poll for the same events again and again as long as\ntheir callbacks have not been executed, which is very inefficient in the\ncommon case of one high-priority watcher locking out a mass of lower\npriority ones.\n.PP\nStatic (ordering) priorities are most useful when you have two or more\nwatchers handling the same resource: a typical usage example is having an\n\\&\\f(CW\\*(C`ev_io\\*(C'\\fR watcher to receive data, and an associated \\f(CW\\*(C`ev_timer\\*(C'\\fR to handle\ntimeouts. Under load, data might be received while the program handles\nother jobs, but since timers normally get invoked first, the timeout\nhandler will be executed before checking for data. In that case, giving\nthe timer a lower priority than the I/O watcher ensures that I/O will be\nhandled first even under adverse conditions (which is usually, but not\nalways, what you want).\n.PP\nSince idle watchers use the \\*(L\"lock-out\\*(R\" model, meaning that idle watchers\nwill only be executed when no same or higher priority watchers have\nreceived events, they can be used to implement the \\*(L\"lock-out\\*(R\" model when\nrequired.\n.PP\nFor example, to emulate how many other event libraries handle priorities,\nyou can associate an \\f(CW\\*(C`ev_idle\\*(C'\\fR watcher to each such watcher, and in\nthe normal watcher callback, you just start the idle watcher. The real\nprocessing is done in the idle watcher callback. This causes libev to\ncontinuously poll and process kernel event data for the watcher, but when\nthe lock-out case is known to be rare (which in turn is rare :), this is\nworkable.\n.PP\nUsually, however, the lock-out model implemented that way will perform\nmiserably under the type of load it was designed to handle. In that case,\nit might be preferable to stop the real watcher before starting the\nidle watcher, so the kernel will not have to process the event in case\nthe actual processing will be delayed for considerable time.\n.PP\nHere is an example of an I/O watcher that should run at a strictly lower\npriority than the default, and which should only process data when no\nother events are pending:\n.PP\n.Vb 2\n\\&   ev_idle idle; // actual processing watcher\n\\&   ev_io io;     // actual event watcher\n\\&\n\\&   static void\n\\&   io_cb (EV_P_ ev_io *w, int revents)\n\\&   {\n\\&     // stop the I/O watcher, we received the event, but\n\\&     // are not yet ready to handle it.\n\\&     ev_io_stop (EV_A_ w);\n\\&\n\\&     // start the idle watcher to handle the actual event.\n\\&     // it will not be executed as long as other watchers\n\\&     // with the default priority are receiving events.\n\\&     ev_idle_start (EV_A_ &idle);\n\\&   }\n\\&\n\\&   static void\n\\&   idle_cb (EV_P_ ev_idle *w, int revents)\n\\&   {\n\\&     // actual processing\n\\&     read (STDIN_FILENO, ...);\n\\&\n\\&     // have to start the I/O watcher again, as\n\\&     // we have handled the event\n\\&     ev_io_start (EV_P_ &io);\n\\&   }\n\\&\n\\&   // initialisation\n\\&   ev_idle_init (&idle, idle_cb);\n\\&   ev_io_init (&io, io_cb, STDIN_FILENO, EV_READ);\n\\&   ev_io_start (EV_DEFAULT_ &io);\n.Ve\n.PP\nIn the \\*(L\"real\\*(R\" world, it might also be beneficial to start a timer, so that\nlow-priority connections can not be locked out forever under load. This\nenables your program to keep a lower latency for important connections\nduring short periods of high load, while not completely locking out less\nimportant ones.\n.SH \"WATCHER TYPES\"\n.IX Header \"WATCHER TYPES\"\nThis section describes each watcher in detail, but will not repeat\ninformation given in the last section. Any initialisation/set macros,\nfunctions and members specific to the watcher type are explained.\n.PP\nMembers are additionally marked with either \\fI[read\\-only]\\fR, meaning that,\nwhile the watcher is active, you can look at the member and expect some\nsensible content, but you must not modify it (you can modify it while the\nwatcher is stopped to your hearts content), or \\fI[read\\-write]\\fR, which\nmeans you can expect it to have some sensible content while the watcher\nis active, but you can also modify it. Modifying it may not do something\nsensible or take immediate effect (or do anything at all), but libev will\nnot crash or malfunction in any way.\n.ie n .SS \"\"\"ev_io\"\" \\- is this file descriptor readable or writable?\"\n.el .SS \"\\f(CWev_io\\fP \\- is this file descriptor readable or writable?\"\n.IX Subsection \"ev_io - is this file descriptor readable or writable?\"\nI/O watchers check whether a file descriptor is readable or writable\nin each iteration of the event loop, or, more precisely, when reading\nwould not block the process and writing would at least be able to write\nsome data. This behaviour is called level-triggering because you keep\nreceiving events as long as the condition persists. Remember you can stop\nthe watcher if you don't want to act on the event and neither want to\nreceive future events.\n.PP\nIn general you can register as many read and/or write event watchers per\nfd as you want (as long as you don't confuse yourself). Setting all file\ndescriptors to non-blocking mode is also usually a good idea (but not\nrequired if you know what you are doing).\n.PP\nAnother thing you have to watch out for is that it is quite easy to\nreceive \\*(L\"spurious\\*(R\" readiness notifications, that is, your callback might\nbe called with \\f(CW\\*(C`EV_READ\\*(C'\\fR but a subsequent \\f(CW\\*(C`read\\*(C'\\fR(2) will actually block\nbecause there is no data. It is very easy to get into this situation even\nwith a relatively standard program structure. Thus it is best to always\nuse non-blocking I/O: An extra \\f(CW\\*(C`read\\*(C'\\fR(2) returning \\f(CW\\*(C`EAGAIN\\*(C'\\fR is far\npreferable to a program hanging until some data arrives.\n.PP\nIf you cannot run the fd in non-blocking mode (for example you should\nnot play around with an Xlib connection), then you have to separately\nre-test whether a file descriptor is really ready with a known-to-be good\ninterface such as poll (fortunately in the case of Xlib, it already does\nthis on its own, so its quite safe to use). Some people additionally\nuse \\f(CW\\*(C`SIGALRM\\*(C'\\fR and an interval timer, just to be sure you won't block\nindefinitely.\n.PP\nBut really, best use non-blocking mode.\n.PP\n\\fIThe special problem of disappearing file descriptors\\fR\n.IX Subsection \"The special problem of disappearing file descriptors\"\n.PP\nSome backends (e.g. kqueue, epoll) need to be told about closing a file\ndescriptor (either due to calling \\f(CW\\*(C`close\\*(C'\\fR explicitly or any other means,\nsuch as \\f(CW\\*(C`dup2\\*(C'\\fR). The reason is that you register interest in some file\ndescriptor, but when it goes away, the operating system will silently drop\nthis interest. If another file descriptor with the same number then is\nregistered with libev, there is no efficient way to see that this is, in\nfact, a different file descriptor.\n.PP\nTo avoid having to explicitly tell libev about such cases, libev follows\nthe following policy:  Each time \\f(CW\\*(C`ev_io_set\\*(C'\\fR is being called, libev\nwill assume that this is potentially a new file descriptor, otherwise\nit is assumed that the file descriptor stays the same. That means that\nyou \\fIhave\\fR to call \\f(CW\\*(C`ev_io_set\\*(C'\\fR (or \\f(CW\\*(C`ev_io_init\\*(C'\\fR) when you change the\ndescriptor even if the file descriptor number itself did not change.\n.PP\nThis is how one would do it normally anyway, the important point is that\nthe libev application should not optimise around libev but should leave\noptimisations to libev.\n.PP\n\\fIThe special problem of dup'ed file descriptors\\fR\n.IX Subsection \"The special problem of dup'ed file descriptors\"\n.PP\nSome backends (e.g. epoll), cannot register events for file descriptors,\nbut only events for the underlying file descriptions. That means when you\nhave \\f(CW\\*(C`dup ()\\*(C'\\fR'ed file descriptors or weirder constellations, and register\nevents for them, only one file descriptor might actually receive events.\n.PP\nThere is no workaround possible except not registering events\nfor potentially \\f(CW\\*(C`dup ()\\*(C'\\fR'ed file descriptors, or to resort to\n\\&\\f(CW\\*(C`EVBACKEND_SELECT\\*(C'\\fR or \\f(CW\\*(C`EVBACKEND_POLL\\*(C'\\fR.\n.PP\n\\fIThe special problem of files\\fR\n.IX Subsection \"The special problem of files\"\n.PP\nMany people try to use \\f(CW\\*(C`select\\*(C'\\fR (or libev) on file descriptors\nrepresenting files, and expect it to become ready when their program\ndoesn't block on disk accesses (which can take a long time on their own).\n.PP\nHowever, this cannot ever work in the \\*(L\"expected\\*(R\" way \\- you get a readiness\nnotification as soon as the kernel knows whether and how much data is\nthere, and in the case of open files, that's always the case, so you\nalways get a readiness notification instantly, and your read (or possibly\nwrite) will still block on the disk I/O.\n.PP\nAnother way to view it is that in the case of sockets, pipes, character\ndevices and so on, there is another party (the sender) that delivers data\non its own, but in the case of files, there is no such thing: the disk\nwill not send data on its own, simply because it doesn't know what you\nwish to read \\- you would first have to request some data.\n.PP\nSince files are typically not-so-well supported by advanced notification\nmechanism, libev tries hard to emulate \\s-1POSIX\\s0 behaviour with respect\nto files, even though you should not use it. The reason for this is\nconvenience: sometimes you want to watch \\s-1STDIN\\s0 or \\s-1STDOUT,\\s0 which is\nusually a tty, often a pipe, but also sometimes files or special devices\n(for example, \\f(CW\\*(C`epoll\\*(C'\\fR on Linux works with \\fI/dev/random\\fR but not with\n\\&\\fI/dev/urandom\\fR), and even though the file might better be served with\nasynchronous I/O instead of with non-blocking I/O, it is still useful when\nit \\*(L\"just works\\*(R\" instead of freezing.\n.PP\nSo avoid file descriptors pointing to files when you know it (e.g. use\nlibeio), but use them when it is convenient, e.g. for \\s-1STDIN/STDOUT,\\s0 or\nwhen you rarely read from a file instead of from a socket, and want to\nreuse the same code path.\n.PP\n\\fIThe special problem of fork\\fR\n.IX Subsection \"The special problem of fork\"\n.PP\nSome backends (epoll, kqueue) do not support \\f(CW\\*(C`fork ()\\*(C'\\fR at all or exhibit\nuseless behaviour. Libev fully supports fork, but needs to be told about\nit in the child if you want to continue to use it in the child.\n.PP\nTo support fork in your child processes, you have to call \\f(CW\\*(C`ev_loop_fork\n()\\*(C'\\fR after a fork in the child, enable \\f(CW\\*(C`EVFLAG_FORKCHECK\\*(C'\\fR, or resort to\n\\&\\f(CW\\*(C`EVBACKEND_SELECT\\*(C'\\fR or \\f(CW\\*(C`EVBACKEND_POLL\\*(C'\\fR.\n.PP\n\\fIThe special problem of \\s-1SIGPIPE\\s0\\fR\n.IX Subsection \"The special problem of SIGPIPE\"\n.PP\nWhile not really specific to libev, it is easy to forget about \\f(CW\\*(C`SIGPIPE\\*(C'\\fR:\nwhen writing to a pipe whose other end has been closed, your program gets\nsent a \\s-1SIGPIPE,\\s0 which, by default, aborts your program. For most programs\nthis is sensible behaviour, for daemons, this is usually undesirable.\n.PP\nSo when you encounter spurious, unexplained daemon exits, make sure you\nignore \\s-1SIGPIPE \\s0(and maybe make sure you log the exit status of your daemon\nsomewhere, as that would have given you a big clue).\n.PP\n\\fIThe special problem of \\fIaccept()\\fIing when you can't\\fR\n.IX Subsection \"The special problem of accept()ing when you can't\"\n.PP\nMany implementations of the \\s-1POSIX \\s0\\f(CW\\*(C`accept\\*(C'\\fR function (for example,\nfound in post\\-2004 Linux) have the peculiar behaviour of not removing a\nconnection from the pending queue in all error cases.\n.PP\nFor example, larger servers often run out of file descriptors (because\nof resource limits), causing \\f(CW\\*(C`accept\\*(C'\\fR to fail with \\f(CW\\*(C`ENFILE\\*(C'\\fR but not\nrejecting the connection, leading to libev signalling readiness on\nthe next iteration again (the connection still exists after all), and\ntypically causing the program to loop at 100% \\s-1CPU\\s0 usage.\n.PP\nUnfortunately, the set of errors that cause this issue differs between\noperating systems, there is usually little the app can do to remedy the\nsituation, and no known thread-safe method of removing the connection to\ncope with overload is known (to me).\n.PP\nOne of the easiest ways to handle this situation is to just ignore it\n\\&\\- when the program encounters an overload, it will just loop until the\nsituation is over. While this is a form of busy waiting, no \\s-1OS\\s0 offers an\nevent-based way to handle this situation, so it's the best one can do.\n.PP\nA better way to handle the situation is to log any errors other than\n\\&\\f(CW\\*(C`EAGAIN\\*(C'\\fR and \\f(CW\\*(C`EWOULDBLOCK\\*(C'\\fR, making sure not to flood the log with such\nmessages, and continue as usual, which at least gives the user an idea of\nwhat could be wrong (\\*(L\"raise the ulimit!\\*(R\"). For extra points one could stop\nthe \\f(CW\\*(C`ev_io\\*(C'\\fR watcher on the listening fd \\*(L\"for a while\\*(R\", which reduces \\s-1CPU\\s0\nusage.\n.PP\nIf your program is single-threaded, then you could also keep a dummy file\ndescriptor for overload situations (e.g. by opening \\fI/dev/null\\fR), and\nwhen you run into \\f(CW\\*(C`ENFILE\\*(C'\\fR or \\f(CW\\*(C`EMFILE\\*(C'\\fR, close it, run \\f(CW\\*(C`accept\\*(C'\\fR,\nclose that fd, and create a new dummy fd. This will gracefully refuse\nclients under typical overload conditions.\n.PP\nThe last way to handle it is to simply log the error and \\f(CW\\*(C`exit\\*(C'\\fR, as\nis often done with \\f(CW\\*(C`malloc\\*(C'\\fR failures, but this results in an easy\nopportunity for a DoS attack.\n.PP\n\\fIWatcher-Specific Functions\\fR\n.IX Subsection \"Watcher-Specific Functions\"\n.IP \"ev_io_init (ev_io *, callback, int fd, int events)\" 4\n.IX Item \"ev_io_init (ev_io *, callback, int fd, int events)\"\n.PD 0\n.IP \"ev_io_set (ev_io *, int fd, int events)\" 4\n.IX Item \"ev_io_set (ev_io *, int fd, int events)\"\n.PD\nConfigures an \\f(CW\\*(C`ev_io\\*(C'\\fR watcher. The \\f(CW\\*(C`fd\\*(C'\\fR is the file descriptor to\nreceive events for and \\f(CW\\*(C`events\\*(C'\\fR is either \\f(CW\\*(C`EV_READ\\*(C'\\fR, \\f(CW\\*(C`EV_WRITE\\*(C'\\fR or\n\\&\\f(CW\\*(C`EV_READ | EV_WRITE\\*(C'\\fR, to express the desire to receive the given events.\n.IP \"int fd [read\\-only]\" 4\n.IX Item \"int fd [read-only]\"\nThe file descriptor being watched.\n.IP \"int events [read\\-only]\" 4\n.IX Item \"int events [read-only]\"\nThe events being watched.\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nExample: Call \\f(CW\\*(C`stdin_readable_cb\\*(C'\\fR when \\s-1STDIN_FILENO\\s0 has become, well\nreadable, but only once. Since it is likely line-buffered, you could\nattempt to read a whole line in the callback.\n.PP\n.Vb 6\n\\&   static void\n\\&   stdin_readable_cb (struct ev_loop *loop, ev_io *w, int revents)\n\\&   {\n\\&      ev_io_stop (loop, w);\n\\&     .. read from stdin here (or from w\\->fd) and handle any I/O errors\n\\&   }\n\\&\n\\&   ...\n\\&   struct ev_loop *loop = ev_default_init (0);\n\\&   ev_io stdin_readable;\n\\&   ev_io_init (&stdin_readable, stdin_readable_cb, STDIN_FILENO, EV_READ);\n\\&   ev_io_start (loop, &stdin_readable);\n\\&   ev_run (loop, 0);\n.Ve\n.ie n .SS \"\"\"ev_timer\"\" \\- relative and optionally repeating timeouts\"\n.el .SS \"\\f(CWev_timer\\fP \\- relative and optionally repeating timeouts\"\n.IX Subsection \"ev_timer - relative and optionally repeating timeouts\"\nTimer watchers are simple relative timers that generate an event after a\ngiven time, and optionally repeating in regular intervals after that.\n.PP\nThe timers are based on real time, that is, if you register an event that\ntimes out after an hour and you reset your system clock to January last\nyear, it will still time out after (roughly) one hour. \\*(L\"Roughly\\*(R\" because\ndetecting time jumps is hard, and some inaccuracies are unavoidable (the\nmonotonic clock option helps a lot here).\n.PP\nThe callback is guaranteed to be invoked only \\fIafter\\fR its timeout has\npassed (not \\fIat\\fR, so on systems with very low-resolution clocks this\nmight introduce a small delay, see \\*(L\"the special problem of being too\nearly\\*(R\", below). If multiple timers become ready during the same loop\niteration then the ones with earlier time-out values are invoked before\nones of the same priority with later time-out values (but this is no\nlonger true when a callback calls \\f(CW\\*(C`ev_run\\*(C'\\fR recursively).\n.PP\n\\fIBe smart about timeouts\\fR\n.IX Subsection \"Be smart about timeouts\"\n.PP\nMany real-world problems involve some kind of timeout, usually for error\nrecovery. A typical example is an \\s-1HTTP\\s0 request \\- if the other side hangs,\nyou want to raise some error after a while.\n.PP\nWhat follows are some ways to handle this problem, from obvious and\ninefficient to smart and efficient.\n.PP\nIn the following, a 60 second activity timeout is assumed \\- a timeout that\ngets reset to 60 seconds each time there is activity (e.g. each time some\ndata or other life sign was received).\n.IP \"1. Use a timer and stop, reinitialise and start it on activity.\" 4\n.IX Item \"1. Use a timer and stop, reinitialise and start it on activity.\"\nThis is the most obvious, but not the most simple way: In the beginning,\nstart the watcher:\n.Sp\n.Vb 2\n\\&   ev_timer_init (timer, callback, 60., 0.);\n\\&   ev_timer_start (loop, timer);\n.Ve\n.Sp\nThen, each time there is some activity, \\f(CW\\*(C`ev_timer_stop\\*(C'\\fR it, initialise it\nand start it again:\n.Sp\n.Vb 3\n\\&   ev_timer_stop (loop, timer);\n\\&   ev_timer_set (timer, 60., 0.);\n\\&   ev_timer_start (loop, timer);\n.Ve\n.Sp\nThis is relatively simple to implement, but means that each time there is\nsome activity, libev will first have to remove the timer from its internal\ndata structure and then add it again. Libev tries to be fast, but it's\nstill not a constant-time operation.\n.ie n .IP \"2. Use a timer and re-start it with \"\"ev_timer_again\"\" inactivity.\" 4\n.el .IP \"2. Use a timer and re-start it with \\f(CWev_timer_again\\fR inactivity.\" 4\n.IX Item \"2. Use a timer and re-start it with ev_timer_again inactivity.\"\nThis is the easiest way, and involves using \\f(CW\\*(C`ev_timer_again\\*(C'\\fR instead of\n\\&\\f(CW\\*(C`ev_timer_start\\*(C'\\fR.\n.Sp\nTo implement this, configure an \\f(CW\\*(C`ev_timer\\*(C'\\fR with a \\f(CW\\*(C`repeat\\*(C'\\fR value\nof \\f(CW60\\fR and then call \\f(CW\\*(C`ev_timer_again\\*(C'\\fR at start and each time you\nsuccessfully read or write some data. If you go into an idle state where\nyou do not expect data to travel on the socket, you can \\f(CW\\*(C`ev_timer_stop\\*(C'\\fR\nthe timer, and \\f(CW\\*(C`ev_timer_again\\*(C'\\fR will automatically restart it if need be.\n.Sp\nThat means you can ignore both the \\f(CW\\*(C`ev_timer_start\\*(C'\\fR function and the\n\\&\\f(CW\\*(C`after\\*(C'\\fR argument to \\f(CW\\*(C`ev_timer_set\\*(C'\\fR, and only ever use the \\f(CW\\*(C`repeat\\*(C'\\fR\nmember and \\f(CW\\*(C`ev_timer_again\\*(C'\\fR.\n.Sp\nAt start:\n.Sp\n.Vb 3\n\\&   ev_init (timer, callback);\n\\&   timer\\->repeat = 60.;\n\\&   ev_timer_again (loop, timer);\n.Ve\n.Sp\nEach time there is some activity:\n.Sp\n.Vb 1\n\\&   ev_timer_again (loop, timer);\n.Ve\n.Sp\nIt is even possible to change the time-out on the fly, regardless of\nwhether the watcher is active or not:\n.Sp\n.Vb 2\n\\&   timer\\->repeat = 30.;\n\\&   ev_timer_again (loop, timer);\n.Ve\n.Sp\nThis is slightly more efficient then stopping/starting the timer each time\nyou want to modify its timeout value, as libev does not have to completely\nremove and re-insert the timer from/into its internal data structure.\n.Sp\nIt is, however, even simpler than the \\*(L\"obvious\\*(R\" way to do it.\n.IP \"3. Let the timer time out, but then re-arm it as required.\" 4\n.IX Item \"3. Let the timer time out, but then re-arm it as required.\"\nThis method is more tricky, but usually most efficient: Most timeouts are\nrelatively long compared to the intervals between other activity \\- in\nour example, within 60 seconds, there are usually many I/O events with\nassociated activity resets.\n.Sp\nIn this case, it would be more efficient to leave the \\f(CW\\*(C`ev_timer\\*(C'\\fR alone,\nbut remember the time of last activity, and check for a real timeout only\nwithin the callback:\n.Sp\n.Vb 3\n\\&   ev_tstamp timeout = 60.;\n\\&   ev_tstamp last_activity; // time of last activity\n\\&   ev_timer timer;\n\\&\n\\&   static void\n\\&   callback (EV_P_ ev_timer *w, int revents)\n\\&   {\n\\&     // calculate when the timeout would happen\n\\&     ev_tstamp after = last_activity \\- ev_now (EV_A) + timeout;\n\\&\n\\&     // if negative, it means we the timeout already occurred\n\\&     if (after < 0.)\n\\&       {\n\\&         // timeout occurred, take action\n\\&       }\n\\&     else\n\\&       {\n\\&         // callback was invoked, but there was some recent \n\\&         // activity. simply restart the timer to time out\n\\&         // after \"after\" seconds, which is the earliest time\n\\&         // the timeout can occur.\n\\&         ev_timer_set (w, after, 0.);\n\\&         ev_timer_start (EV_A_ w);\n\\&       }\n\\&   }\n.Ve\n.Sp\nTo summarise the callback: first calculate in how many seconds the\ntimeout will occur (by calculating the absolute time when it would occur,\n\\&\\f(CW\\*(C`last_activity + timeout\\*(C'\\fR, and subtracting the current time, \\f(CW\\*(C`ev_now\n(EV_A)\\*(C'\\fR from that).\n.Sp\nIf this value is negative, then we are already past the timeout, i.e. we\ntimed out, and need to do whatever is needed in this case.\n.Sp\nOtherwise, we now the earliest time at which the timeout would trigger,\nand simply start the timer with this timeout value.\n.Sp\nIn other words, each time the callback is invoked it will check whether\nthe timeout occurred. If not, it will simply reschedule itself to check\nagain at the earliest time it could time out. Rinse. Repeat.\n.Sp\nThis scheme causes more callback invocations (about one every 60 seconds\nminus half the average time between activity), but virtually no calls to\nlibev to change the timeout.\n.Sp\nTo start the machinery, simply initialise the watcher and set\n\\&\\f(CW\\*(C`last_activity\\*(C'\\fR to the current time (meaning there was some activity just\nnow), then call the callback, which will \\*(L\"do the right thing\\*(R\" and start\nthe timer:\n.Sp\n.Vb 3\n\\&   last_activity = ev_now (EV_A);\n\\&   ev_init (&timer, callback);\n\\&   callback (EV_A_ &timer, 0);\n.Ve\n.Sp\nWhen there is some activity, simply store the current time in\n\\&\\f(CW\\*(C`last_activity\\*(C'\\fR, no libev calls at all:\n.Sp\n.Vb 2\n\\&   if (activity detected)\n\\&     last_activity = ev_now (EV_A);\n.Ve\n.Sp\nWhen your timeout value changes, then the timeout can be changed by simply\nproviding a new value, stopping the timer and calling the callback, which\nwill again do the right thing (for example, time out immediately :).\n.Sp\n.Vb 3\n\\&   timeout = new_value;\n\\&   ev_timer_stop (EV_A_ &timer);\n\\&   callback (EV_A_ &timer, 0);\n.Ve\n.Sp\nThis technique is slightly more complex, but in most cases where the\ntime-out is unlikely to be triggered, much more efficient.\n.IP \"4. Wee, just use a double-linked list for your timeouts.\" 4\n.IX Item \"4. Wee, just use a double-linked list for your timeouts.\"\nIf there is not one request, but many thousands (millions...), all\nemploying some kind of timeout with the same timeout value, then one can\ndo even better:\n.Sp\nWhen starting the timeout, calculate the timeout value and put the timeout\nat the \\fIend\\fR of the list.\n.Sp\nThen use an \\f(CW\\*(C`ev_timer\\*(C'\\fR to fire when the timeout at the \\fIbeginning\\fR of\nthe list is expected to fire (for example, using the technique #3).\n.Sp\nWhen there is some activity, remove the timer from the list, recalculate\nthe timeout, append it to the end of the list again, and make sure to\nupdate the \\f(CW\\*(C`ev_timer\\*(C'\\fR if it was taken from the beginning of the list.\n.Sp\nThis way, one can manage an unlimited number of timeouts in O(1) time for\nstarting, stopping and updating the timers, at the expense of a major\ncomplication, and having to use a constant timeout. The constant timeout\nensures that the list stays sorted.\n.PP\nSo which method the best?\n.PP\nMethod #2 is a simple no-brain-required solution that is adequate in most\nsituations. Method #3 requires a bit more thinking, but handles many cases\nbetter, and isn't very complicated either. In most case, choosing either\none is fine, with #3 being better in typical situations.\n.PP\nMethod #1 is almost always a bad idea, and buys you nothing. Method #4 is\nrather complicated, but extremely efficient, something that really pays\noff after the first million or so of active timers, i.e. it's usually\noverkill :)\n.PP\n\\fIThe special problem of being too early\\fR\n.IX Subsection \"The special problem of being too early\"\n.PP\nIf you ask a timer to call your callback after three seconds, then\nyou expect it to be invoked after three seconds \\- but of course, this\ncannot be guaranteed to infinite precision. Less obviously, it cannot be\nguaranteed to any precision by libev \\- imagine somebody suspending the\nprocess with a \\s-1STOP\\s0 signal for a few hours for example.\n.PP\nSo, libev tries to invoke your callback as soon as possible \\fIafter\\fR the\ndelay has occurred, but cannot guarantee this.\n.PP\nA less obvious failure mode is calling your callback too early: many event\nloops compare timestamps with a \\*(L\"elapsed delay >= requested delay\\*(R\", but\nthis can cause your callback to be invoked much earlier than you would\nexpect.\n.PP\nTo see why, imagine a system with a clock that only offers full second\nresolution (think windows if you can't come up with a broken enough \\s-1OS\\s0\nyourself). If you schedule a one-second timer at the time 500.9, then the\nevent loop will schedule your timeout to elapse at a system time of 500\n(500.9 truncated to the resolution) + 1, or 501.\n.PP\nIf an event library looks at the timeout 0.1s later, it will see \\*(L\"501 >=\n501\\*(R\" and invoke the callback 0.1s after it was started, even though a\none-second delay was requested \\- this is being \\*(L\"too early\\*(R\", despite best\nintentions.\n.PP\nThis is the reason why libev will never invoke the callback if the elapsed\ndelay equals the requested delay, but only when the elapsed delay is\nlarger than the requested delay. In the example above, libev would only invoke\nthe callback at system time 502, or 1.1s after the timer was started.\n.PP\nSo, while libev cannot guarantee that your callback will be invoked\nexactly when requested, it \\fIcan\\fR and \\fIdoes\\fR guarantee that the requested\ndelay has actually elapsed, or in other words, it always errs on the \\*(L\"too\nlate\\*(R\" side of things.\n.PP\n\\fIThe special problem of time updates\\fR\n.IX Subsection \"The special problem of time updates\"\n.PP\nEstablishing the current time is a costly operation (it usually takes\nat least one system call): \\s-1EV\\s0 therefore updates its idea of the current\ntime only before and after \\f(CW\\*(C`ev_run\\*(C'\\fR collects new events, which causes a\ngrowing difference between \\f(CW\\*(C`ev_now ()\\*(C'\\fR and \\f(CW\\*(C`ev_time ()\\*(C'\\fR when handling\nlots of events in one iteration.\n.PP\nThe relative timeouts are calculated relative to the \\f(CW\\*(C`ev_now ()\\*(C'\\fR\ntime. This is usually the right thing as this timestamp refers to the time\nof the event triggering whatever timeout you are modifying/starting. If\nyou suspect event processing to be delayed and you \\fIneed\\fR to base the\ntimeout on the current time, use something like the following to adjust\nfor it:\n.PP\n.Vb 1\n\\&   ev_timer_set (&timer, after + (ev_time () \\- ev_now ()), 0.);\n.Ve\n.PP\nIf the event loop is suspended for a long time, you can also force an\nupdate of the time returned by \\f(CW\\*(C`ev_now ()\\*(C'\\fR by calling \\f(CW\\*(C`ev_now_update\n()\\*(C'\\fR, although that will push the event time of all outstanding events\nfurther into the future.\n.PP\n\\fIThe special problem of unsynchronised clocks\\fR\n.IX Subsection \"The special problem of unsynchronised clocks\"\n.PP\nModern systems have a variety of clocks \\- libev itself uses the normal\n\\&\\*(L\"wall clock\\*(R\" clock and, if available, the monotonic clock (to avoid time\njumps).\n.PP\nNeither of these clocks is synchronised with each other or any other clock\non the system, so \\f(CW\\*(C`ev_time ()\\*(C'\\fR might return a considerably different time\nthan \\f(CW\\*(C`gettimeofday ()\\*(C'\\fR or \\f(CW\\*(C`time ()\\*(C'\\fR. On a GNU/Linux system, for example,\na call to \\f(CW\\*(C`gettimeofday\\*(C'\\fR might return a second count that is one higher\nthan a directly following call to \\f(CW\\*(C`time\\*(C'\\fR.\n.PP\nThe moral of this is to only compare libev-related timestamps with\n\\&\\f(CW\\*(C`ev_time ()\\*(C'\\fR and \\f(CW\\*(C`ev_now ()\\*(C'\\fR, at least if you want better precision than\na second or so.\n.PP\nOne more problem arises due to this lack of synchronisation: if libev uses\nthe system monotonic clock and you compare timestamps from \\f(CW\\*(C`ev_time\\*(C'\\fR\nor \\f(CW\\*(C`ev_now\\*(C'\\fR from when you started your timer and when your callback is\ninvoked, you will find that sometimes the callback is a bit \\*(L\"early\\*(R\".\n.PP\nThis is because \\f(CW\\*(C`ev_timer\\*(C'\\fRs work in real time, not wall clock time, so\nlibev makes sure your callback is not invoked before the delay happened,\n\\&\\fImeasured according to the real time\\fR, not the system clock.\n.PP\nIf your timeouts are based on a physical timescale (e.g. \\*(L\"time out this\nconnection after 100 seconds\\*(R\") then this shouldn't bother you as it is\nexactly the right behaviour.\n.PP\nIf you want to compare wall clock/system timestamps to your timers, then\nyou need to use \\f(CW\\*(C`ev_periodic\\*(C'\\fRs, as these are based on the wall clock\ntime, where your comparisons will always generate correct results.\n.PP\n\\fIThe special problems of suspended animation\\fR\n.IX Subsection \"The special problems of suspended animation\"\n.PP\nWhen you leave the server world it is quite customary to hit machines that\ncan suspend/hibernate \\- what happens to the clocks during such a suspend?\n.PP\nSome quick tests made with a Linux 2.6.28 indicate that a suspend freezes\nall processes, while the clocks (\\f(CW\\*(C`times\\*(C'\\fR, \\f(CW\\*(C`CLOCK_MONOTONIC\\*(C'\\fR) continue\nto run until the system is suspended, but they will not advance while the\nsystem is suspended. That means, on resume, it will be as if the program\nwas frozen for a few seconds, but the suspend time will not be counted\ntowards \\f(CW\\*(C`ev_timer\\*(C'\\fR when a monotonic clock source is used. The real time\nclock advanced as expected, but if it is used as sole clocksource, then a\nlong suspend would be detected as a time jump by libev, and timers would\nbe adjusted accordingly.\n.PP\nI would not be surprised to see different behaviour in different between\noperating systems, \\s-1OS\\s0 versions or even different hardware.\n.PP\nThe other form of suspend (job control, or sending a \\s-1SIGSTOP\\s0) will see a\ntime jump in the monotonic clocks and the realtime clock. If the program\nis suspended for a very long time, and monotonic clock sources are in use,\nthen you can expect \\f(CW\\*(C`ev_timer\\*(C'\\fRs to expire as the full suspension time\nwill be counted towards the timers. When no monotonic clock source is in\nuse, then libev will again assume a timejump and adjust accordingly.\n.PP\nIt might be beneficial for this latter case to call \\f(CW\\*(C`ev_suspend\\*(C'\\fR\nand \\f(CW\\*(C`ev_resume\\*(C'\\fR in code that handles \\f(CW\\*(C`SIGTSTP\\*(C'\\fR, to at least get\ndeterministic behaviour in this case (you can do nothing against\n\\&\\f(CW\\*(C`SIGSTOP\\*(C'\\fR).\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_timer_init (ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)\" 4\n.IX Item \"ev_timer_init (ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)\"\n.PD 0\n.IP \"ev_timer_set (ev_timer *, ev_tstamp after, ev_tstamp repeat)\" 4\n.IX Item \"ev_timer_set (ev_timer *, ev_tstamp after, ev_tstamp repeat)\"\n.PD\nConfigure the timer to trigger after \\f(CW\\*(C`after\\*(C'\\fR seconds. If \\f(CW\\*(C`repeat\\*(C'\\fR\nis \\f(CW0.\\fR, then it will automatically be stopped once the timeout is\nreached. If it is positive, then the timer will automatically be\nconfigured to trigger again \\f(CW\\*(C`repeat\\*(C'\\fR seconds later, again, and again,\nuntil stopped manually.\n.Sp\nThe timer itself will do a best-effort at avoiding drift, that is, if\nyou configure a timer to trigger every 10 seconds, then it will normally\ntrigger at exactly 10 second intervals. If, however, your program cannot\nkeep up with the timer (because it takes longer than those 10 seconds to\ndo stuff) the timer will not fire more than once per event loop iteration.\n.IP \"ev_timer_again (loop, ev_timer *)\" 4\n.IX Item \"ev_timer_again (loop, ev_timer *)\"\nThis will act as if the timer timed out, and restarts it again if it is\nrepeating. It basically works like calling \\f(CW\\*(C`ev_timer_stop\\*(C'\\fR, updating the\ntimeout to the \\f(CW\\*(C`repeat\\*(C'\\fR value and calling \\f(CW\\*(C`ev_timer_start\\*(C'\\fR.\n.Sp\nThe exact semantics are as in the following rules, all of which will be\napplied to the watcher:\n.RS 4\n.IP \"If the timer is pending, the pending status is always cleared.\" 4\n.IX Item \"If the timer is pending, the pending status is always cleared.\"\n.PD 0\n.IP \"If the timer is started but non-repeating, stop it (as if it timed out, without invoking it).\" 4\n.IX Item \"If the timer is started but non-repeating, stop it (as if it timed out, without invoking it).\"\n.ie n .IP \"If the timer is repeating, make the \"\"repeat\"\" value the new timeout and start the timer, if necessary.\" 4\n.el .IP \"If the timer is repeating, make the \\f(CWrepeat\\fR value the new timeout and start the timer, if necessary.\" 4\n.IX Item \"If the timer is repeating, make the repeat value the new timeout and start the timer, if necessary.\"\n.RE\n.RS 4\n.PD\n.Sp\nThis sounds a bit complicated, see \\*(L\"Be smart about timeouts\\*(R\", above, for a\nusage example.\n.RE\n.IP \"ev_tstamp ev_timer_remaining (loop, ev_timer *)\" 4\n.IX Item \"ev_tstamp ev_timer_remaining (loop, ev_timer *)\"\nReturns the remaining time until a timer fires. If the timer is active,\nthen this time is relative to the current event loop time, otherwise it's\nthe timeout value currently configured.\n.Sp\nThat is, after an \\f(CW\\*(C`ev_timer_set (w, 5, 7)\\*(C'\\fR, \\f(CW\\*(C`ev_timer_remaining\\*(C'\\fR returns\n\\&\\f(CW5\\fR. When the timer is started and one second passes, \\f(CW\\*(C`ev_timer_remaining\\*(C'\\fR\nwill return \\f(CW4\\fR. When the timer expires and is restarted, it will return\nroughly \\f(CW7\\fR (likely slightly less as callback invocation takes some time,\ntoo), and so on.\n.IP \"ev_tstamp repeat [read\\-write]\" 4\n.IX Item \"ev_tstamp repeat [read-write]\"\nThe current \\f(CW\\*(C`repeat\\*(C'\\fR value. Will be used each time the watcher times out\nor \\f(CW\\*(C`ev_timer_again\\*(C'\\fR is called, and determines the next timeout (if any),\nwhich is also when any modifications are taken into account.\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nExample: Create a timer that fires after 60 seconds.\n.PP\n.Vb 5\n\\&   static void\n\\&   one_minute_cb (struct ev_loop *loop, ev_timer *w, int revents)\n\\&   {\n\\&     .. one minute over, w is actually stopped right here\n\\&   }\n\\&\n\\&   ev_timer mytimer;\n\\&   ev_timer_init (&mytimer, one_minute_cb, 60., 0.);\n\\&   ev_timer_start (loop, &mytimer);\n.Ve\n.PP\nExample: Create a timeout timer that times out after 10 seconds of\ninactivity.\n.PP\n.Vb 5\n\\&   static void\n\\&   timeout_cb (struct ev_loop *loop, ev_timer *w, int revents)\n\\&   {\n\\&     .. ten seconds without any activity\n\\&   }\n\\&\n\\&   ev_timer mytimer;\n\\&   ev_timer_init (&mytimer, timeout_cb, 0., 10.); /* note, only repeat used */\n\\&   ev_timer_again (&mytimer); /* start timer */\n\\&   ev_run (loop, 0);\n\\&\n\\&   // and in some piece of code that gets executed on any \"activity\":\n\\&   // reset the timeout to start ticking again at 10 seconds\n\\&   ev_timer_again (&mytimer);\n.Ve\n.ie n .SS \"\"\"ev_periodic\"\" \\- to cron or not to cron?\"\n.el .SS \"\\f(CWev_periodic\\fP \\- to cron or not to cron?\"\n.IX Subsection \"ev_periodic - to cron or not to cron?\"\nPeriodic watchers are also timers of a kind, but they are very versatile\n(and unfortunately a bit complex).\n.PP\nUnlike \\f(CW\\*(C`ev_timer\\*(C'\\fR, periodic watchers are not based on real time (or\nrelative time, the physical time that passes) but on wall clock time\n(absolute time, the thing you can read on your calendar or clock). The\ndifference is that wall clock time can run faster or slower than real\ntime, and time jumps are not uncommon (e.g. when you adjust your\nwrist-watch).\n.PP\nYou can tell a periodic watcher to trigger after some specific point\nin time: for example, if you tell a periodic watcher to trigger \\*(L\"in 10\nseconds\\*(R\" (by specifying e.g. \\f(CW\\*(C`ev_now () + 10.\\*(C'\\fR, that is, an absolute time\nnot a delay) and then reset your system clock to January of the previous\nyear, then it will take a year or more to trigger the event (unlike an\n\\&\\f(CW\\*(C`ev_timer\\*(C'\\fR, which would still trigger roughly 10 seconds after starting\nit, as it uses a relative timeout).\n.PP\n\\&\\f(CW\\*(C`ev_periodic\\*(C'\\fR watchers can also be used to implement vastly more complex\ntimers, such as triggering an event on each \\*(L\"midnight, local time\\*(R\", or\nother complicated rules. This cannot be done with \\f(CW\\*(C`ev_timer\\*(C'\\fR watchers, as\nthose cannot react to time jumps.\n.PP\nAs with timers, the callback is guaranteed to be invoked only when the\npoint in time where it is supposed to trigger has passed. If multiple\ntimers become ready during the same loop iteration then the ones with\nearlier time-out values are invoked before ones with later time-out values\n(but this is no longer true when a callback calls \\f(CW\\*(C`ev_run\\*(C'\\fR recursively).\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_periodic_init (ev_periodic *, callback, ev_tstamp offset, ev_tstamp interval, reschedule_cb)\" 4\n.IX Item \"ev_periodic_init (ev_periodic *, callback, ev_tstamp offset, ev_tstamp interval, reschedule_cb)\"\n.PD 0\n.IP \"ev_periodic_set (ev_periodic *, ev_tstamp offset, ev_tstamp interval, reschedule_cb)\" 4\n.IX Item \"ev_periodic_set (ev_periodic *, ev_tstamp offset, ev_tstamp interval, reschedule_cb)\"\n.PD\nLots of arguments, let's sort it out... There are basically three modes of\noperation, and we will explain them from simplest to most complex:\n.RS 4\n.IP \"\\(bu\" 4\nabsolute timer (offset = absolute time, interval = 0, reschedule_cb = 0)\n.Sp\nIn this configuration the watcher triggers an event after the wall clock\ntime \\f(CW\\*(C`offset\\*(C'\\fR has passed. It will not repeat and will not adjust when a\ntime jump occurs, that is, if it is to be run at January 1st 2011 then it\nwill be stopped and invoked when the system clock reaches or surpasses\nthis point in time.\n.IP \"\\(bu\" 4\nrepeating interval timer (offset = offset within interval, interval > 0, reschedule_cb = 0)\n.Sp\nIn this mode the watcher will always be scheduled to time out at the next\n\\&\\f(CW\\*(C`offset + N * interval\\*(C'\\fR time (for some integer N, which can also be\nnegative) and then repeat, regardless of any time jumps. The \\f(CW\\*(C`offset\\*(C'\\fR\nargument is merely an offset into the \\f(CW\\*(C`interval\\*(C'\\fR periods.\n.Sp\nThis can be used to create timers that do not drift with respect to the\nsystem clock, for example, here is an \\f(CW\\*(C`ev_periodic\\*(C'\\fR that triggers each\nhour, on the hour (with respect to \\s-1UTC\\s0):\n.Sp\n.Vb 1\n\\&   ev_periodic_set (&periodic, 0., 3600., 0);\n.Ve\n.Sp\nThis doesn't mean there will always be 3600 seconds in between triggers,\nbut only that the callback will be called when the system time shows a\nfull hour (\\s-1UTC\\s0), or more correctly, when the system time is evenly divisible\nby 3600.\n.Sp\nAnother way to think about it (for the mathematically inclined) is that\n\\&\\f(CW\\*(C`ev_periodic\\*(C'\\fR will try to run the callback in this mode at the next possible\ntime where \\f(CW\\*(C`time = offset (mod interval)\\*(C'\\fR, regardless of any time jumps.\n.Sp\nThe \\f(CW\\*(C`interval\\*(C'\\fR \\fI\\s-1MUST\\s0\\fR be positive, and for numerical stability, the\ninterval value should be higher than \\f(CW\\*(C`1/8192\\*(C'\\fR (which is around 100\nmicroseconds) and \\f(CW\\*(C`offset\\*(C'\\fR should be higher than \\f(CW0\\fR and should have\nat most a similar magnitude as the current time (say, within a factor of\nten). Typical values for offset are, in fact, \\f(CW0\\fR or something between\n\\&\\f(CW0\\fR and \\f(CW\\*(C`interval\\*(C'\\fR, which is also the recommended range.\n.Sp\nNote also that there is an upper limit to how often a timer can fire (\\s-1CPU\\s0\nspeed for example), so if \\f(CW\\*(C`interval\\*(C'\\fR is very small then timing stability\nwill of course deteriorate. Libev itself tries to be exact to be about one\nmillisecond (if the \\s-1OS\\s0 supports it and the machine is fast enough).\n.IP \"\\(bu\" 4\nmanual reschedule mode (offset ignored, interval ignored, reschedule_cb = callback)\n.Sp\nIn this mode the values for \\f(CW\\*(C`interval\\*(C'\\fR and \\f(CW\\*(C`offset\\*(C'\\fR are both being\nignored. Instead, each time the periodic watcher gets scheduled, the\nreschedule callback will be called with the watcher as first, and the\ncurrent time as second argument.\n.Sp\n\\&\\s-1NOTE: \\s0\\fIThis callback \\s-1MUST NOT\\s0 stop or destroy any periodic watcher, ever,\nor make \\s-1ANY\\s0 other event loop modifications whatsoever, unless explicitly\nallowed by documentation here\\fR.\n.Sp\nIf you need to stop it, return \\f(CW\\*(C`now + 1e30\\*(C'\\fR (or so, fudge fudge) and stop\nit afterwards (e.g. by starting an \\f(CW\\*(C`ev_prepare\\*(C'\\fR watcher, which is the\nonly event loop modification you are allowed to do).\n.Sp\nThe callback prototype is \\f(CW\\*(C`ev_tstamp (*reschedule_cb)(ev_periodic\n*w, ev_tstamp now)\\*(C'\\fR, e.g.:\n.Sp\n.Vb 5\n\\&   static ev_tstamp\n\\&   my_rescheduler (ev_periodic *w, ev_tstamp now)\n\\&   {\n\\&     return now + 60.;\n\\&   }\n.Ve\n.Sp\nIt must return the next time to trigger, based on the passed time value\n(that is, the lowest time value larger than to the second argument). It\nwill usually be called just before the callback will be triggered, but\nmight be called at other times, too.\n.Sp\n\\&\\s-1NOTE: \\s0\\fIThis callback must always return a time that is higher than or\nequal to the passed \\f(CI\\*(C`now\\*(C'\\fI value\\fR.\n.Sp\nThis can be used to create very complex timers, such as a timer that\ntriggers on \\*(L\"next midnight, local time\\*(R\". To do this, you would calculate the\nnext midnight after \\f(CW\\*(C`now\\*(C'\\fR and return the timestamp value for this. How\nyou do this is, again, up to you (but it is not trivial, which is the main\nreason I omitted it as an example).\n.RE\n.RS 4\n.RE\n.IP \"ev_periodic_again (loop, ev_periodic *)\" 4\n.IX Item \"ev_periodic_again (loop, ev_periodic *)\"\nSimply stops and restarts the periodic watcher again. This is only useful\nwhen you changed some parameters or the reschedule callback would return\na different time than the last time it was called (e.g. in a crond like\nprogram when the crontabs have changed).\n.IP \"ev_tstamp ev_periodic_at (ev_periodic *)\" 4\n.IX Item \"ev_tstamp ev_periodic_at (ev_periodic *)\"\nWhen active, returns the absolute time that the watcher is supposed\nto trigger next. This is not the same as the \\f(CW\\*(C`offset\\*(C'\\fR argument to\n\\&\\f(CW\\*(C`ev_periodic_set\\*(C'\\fR, but indeed works even in interval and manual\nrescheduling modes.\n.IP \"ev_tstamp offset [read\\-write]\" 4\n.IX Item \"ev_tstamp offset [read-write]\"\nWhen repeating, this contains the offset value, otherwise this is the\nabsolute point in time (the \\f(CW\\*(C`offset\\*(C'\\fR value passed to \\f(CW\\*(C`ev_periodic_set\\*(C'\\fR,\nalthough libev might modify this value for better numerical stability).\n.Sp\nCan be modified any time, but changes only take effect when the periodic\ntimer fires or \\f(CW\\*(C`ev_periodic_again\\*(C'\\fR is being called.\n.IP \"ev_tstamp interval [read\\-write]\" 4\n.IX Item \"ev_tstamp interval [read-write]\"\nThe current interval value. Can be modified any time, but changes only\ntake effect when the periodic timer fires or \\f(CW\\*(C`ev_periodic_again\\*(C'\\fR is being\ncalled.\n.IP \"ev_tstamp (*reschedule_cb)(ev_periodic *w, ev_tstamp now) [read\\-write]\" 4\n.IX Item \"ev_tstamp (*reschedule_cb)(ev_periodic *w, ev_tstamp now) [read-write]\"\nThe current reschedule callback, or \\f(CW0\\fR, if this functionality is\nswitched off. Can be changed any time, but changes only take effect when\nthe periodic timer fires or \\f(CW\\*(C`ev_periodic_again\\*(C'\\fR is being called.\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nExample: Call a callback every hour, or, more precisely, whenever the\nsystem time is divisible by 3600. The callback invocation times have\npotentially a lot of jitter, but good long-term stability.\n.PP\n.Vb 5\n\\&   static void\n\\&   clock_cb (struct ev_loop *loop, ev_periodic *w, int revents)\n\\&   {\n\\&     ... its now a full hour (UTC, or TAI or whatever your clock follows)\n\\&   }\n\\&\n\\&   ev_periodic hourly_tick;\n\\&   ev_periodic_init (&hourly_tick, clock_cb, 0., 3600., 0);\n\\&   ev_periodic_start (loop, &hourly_tick);\n.Ve\n.PP\nExample: The same as above, but use a reschedule callback to do it:\n.PP\n.Vb 1\n\\&   #include <math.h>\n\\&\n\\&   static ev_tstamp\n\\&   my_scheduler_cb (ev_periodic *w, ev_tstamp now)\n\\&   {\n\\&     return now + (3600. \\- fmod (now, 3600.));\n\\&   }\n\\&\n\\&   ev_periodic_init (&hourly_tick, clock_cb, 0., 0., my_scheduler_cb);\n.Ve\n.PP\nExample: Call a callback every hour, starting now:\n.PP\n.Vb 4\n\\&   ev_periodic hourly_tick;\n\\&   ev_periodic_init (&hourly_tick, clock_cb,\n\\&                     fmod (ev_now (loop), 3600.), 3600., 0);\n\\&   ev_periodic_start (loop, &hourly_tick);\n.Ve\n.ie n .SS \"\"\"ev_signal\"\" \\- signal me when a signal gets signalled!\"\n.el .SS \"\\f(CWev_signal\\fP \\- signal me when a signal gets signalled!\"\n.IX Subsection \"ev_signal - signal me when a signal gets signalled!\"\nSignal watchers will trigger an event when the process receives a specific\nsignal one or more times. Even though signals are very asynchronous, libev\nwill try its best to deliver signals synchronously, i.e. as part of the\nnormal event processing, like any other event.\n.PP\nIf you want signals to be delivered truly asynchronously, just use\n\\&\\f(CW\\*(C`sigaction\\*(C'\\fR as you would do without libev and forget about sharing\nthe signal. You can even use \\f(CW\\*(C`ev_async\\*(C'\\fR from a signal handler to\nsynchronously wake up an event loop.\n.PP\nYou can configure as many watchers as you like for the same signal, but\nonly within the same loop, i.e. you can watch for \\f(CW\\*(C`SIGINT\\*(C'\\fR in your\ndefault loop and for \\f(CW\\*(C`SIGIO\\*(C'\\fR in another loop, but you cannot watch for\n\\&\\f(CW\\*(C`SIGINT\\*(C'\\fR in both the default loop and another loop at the same time. At\nthe moment, \\f(CW\\*(C`SIGCHLD\\*(C'\\fR is permanently tied to the default loop.\n.PP\nOnly after the first watcher for a signal is started will libev actually\nregister something with the kernel. It thus coexists with your own signal\nhandlers as long as you don't register any with libev for the same signal.\n.PP\nIf possible and supported, libev will install its handlers with\n\\&\\f(CW\\*(C`SA_RESTART\\*(C'\\fR (or equivalent) behaviour enabled, so system calls should\nnot be unduly interrupted. If you have a problem with system calls getting\ninterrupted by signals you can block all signals in an \\f(CW\\*(C`ev_check\\*(C'\\fR watcher\nand unblock them in an \\f(CW\\*(C`ev_prepare\\*(C'\\fR watcher.\n.PP\n\\fIThe special problem of inheritance over fork/execve/pthread_create\\fR\n.IX Subsection \"The special problem of inheritance over fork/execve/pthread_create\"\n.PP\nBoth the signal mask (\\f(CW\\*(C`sigprocmask\\*(C'\\fR) and the signal disposition\n(\\f(CW\\*(C`sigaction\\*(C'\\fR) are unspecified after starting a signal watcher (and after\nstopping it again), that is, libev might or might not block the signal,\nand might or might not set or restore the installed signal handler (but\nsee \\f(CW\\*(C`EVFLAG_NOSIGMASK\\*(C'\\fR).\n.PP\nWhile this does not matter for the signal disposition (libev never\nsets signals to \\f(CW\\*(C`SIG_IGN\\*(C'\\fR, so handlers will be reset to \\f(CW\\*(C`SIG_DFL\\*(C'\\fR on\n\\&\\f(CW\\*(C`execve\\*(C'\\fR), this matters for the signal mask: many programs do not expect\ncertain signals to be blocked.\n.PP\nThis means that before calling \\f(CW\\*(C`exec\\*(C'\\fR (from the child) you should reset\nthe signal mask to whatever \\*(L\"default\\*(R\" you expect (all clear is a good\nchoice usually).\n.PP\nThe simplest way to ensure that the signal mask is reset in the child is\nto install a fork handler with \\f(CW\\*(C`pthread_atfork\\*(C'\\fR that resets it. That will\ncatch fork calls done by libraries (such as the libc) as well.\n.PP\nIn current versions of libev, the signal will not be blocked indefinitely\nunless you use the \\f(CW\\*(C`signalfd\\*(C'\\fR \\s-1API \\s0(\\f(CW\\*(C`EV_SIGNALFD\\*(C'\\fR). While this reduces\nthe window of opportunity for problems, it will not go away, as libev\n\\&\\fIhas\\fR to modify the signal mask, at least temporarily.\n.PP\nSo I can't stress this enough: \\fIIf you do not reset your signal mask when\nyou expect it to be empty, you have a race condition in your code\\fR. This\nis not a libev-specific thing, this is true for most event libraries.\n.PP\n\\fIThe special problem of threads signal handling\\fR\n.IX Subsection \"The special problem of threads signal handling\"\n.PP\n\\&\\s-1POSIX\\s0 threads has problematic signal handling semantics, specifically,\na lot of functionality (sigfd, sigwait etc.) only really works if all\nthreads in a process block signals, which is hard to achieve.\n.PP\nWhen you want to use sigwait (or mix libev signal handling with your own\nfor the same signals), you can tackle this problem by globally blocking\nall signals before creating any threads (or creating them with a fully set\nsigprocmask) and also specifying the \\f(CW\\*(C`EVFLAG_NOSIGMASK\\*(C'\\fR when creating\nloops. Then designate one thread as \\*(L\"signal receiver thread\\*(R\" which handles\nthese signals. You can pass on any signals that libev might be interested\nin by calling \\f(CW\\*(C`ev_feed_signal\\*(C'\\fR.\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_signal_init (ev_signal *, callback, int signum)\" 4\n.IX Item \"ev_signal_init (ev_signal *, callback, int signum)\"\n.PD 0\n.IP \"ev_signal_set (ev_signal *, int signum)\" 4\n.IX Item \"ev_signal_set (ev_signal *, int signum)\"\n.PD\nConfigures the watcher to trigger on the given signal number (usually one\nof the \\f(CW\\*(C`SIGxxx\\*(C'\\fR constants).\n.IP \"int signum [read\\-only]\" 4\n.IX Item \"int signum [read-only]\"\nThe signal the watcher watches out for.\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nExample: Try to exit cleanly on \\s-1SIGINT.\\s0\n.PP\n.Vb 5\n\\&   static void\n\\&   sigint_cb (struct ev_loop *loop, ev_signal *w, int revents)\n\\&   {\n\\&     ev_break (loop, EVBREAK_ALL);\n\\&   }\n\\&\n\\&   ev_signal signal_watcher;\n\\&   ev_signal_init (&signal_watcher, sigint_cb, SIGINT);\n\\&   ev_signal_start (loop, &signal_watcher);\n.Ve\n.ie n .SS \"\"\"ev_child\"\" \\- watch out for process status changes\"\n.el .SS \"\\f(CWev_child\\fP \\- watch out for process status changes\"\n.IX Subsection \"ev_child - watch out for process status changes\"\nChild watchers trigger when your process receives a \\s-1SIGCHLD\\s0 in response to\nsome child status changes (most typically when a child of yours dies or\nexits). It is permissible to install a child watcher \\fIafter\\fR the child\nhas been forked (which implies it might have already exited), as long\nas the event loop isn't entered (or is continued from a watcher), i.e.,\nforking and then immediately registering a watcher for the child is fine,\nbut forking and registering a watcher a few event loop iterations later or\nin the next callback invocation is not.\n.PP\nOnly the default event loop is capable of handling signals, and therefore\nyou can only register child watchers in the default event loop.\n.PP\nDue to some design glitches inside libev, child watchers will always be\nhandled at maximum priority (their priority is set to \\f(CW\\*(C`EV_MAXPRI\\*(C'\\fR by\nlibev)\n.PP\n\\fIProcess Interaction\\fR\n.IX Subsection \"Process Interaction\"\n.PP\nLibev grabs \\f(CW\\*(C`SIGCHLD\\*(C'\\fR as soon as the default event loop is\ninitialised. This is necessary to guarantee proper behaviour even if the\nfirst child watcher is started after the child exits. The occurrence\nof \\f(CW\\*(C`SIGCHLD\\*(C'\\fR is recorded asynchronously, but child reaping is done\nsynchronously as part of the event loop processing. Libev always reaps all\nchildren, even ones not watched.\n.PP\n\\fIOverriding the Built-In Processing\\fR\n.IX Subsection \"Overriding the Built-In Processing\"\n.PP\nLibev offers no special support for overriding the built-in child\nprocessing, but if your application collides with libev's default child\nhandler, you can override it easily by installing your own handler for\n\\&\\f(CW\\*(C`SIGCHLD\\*(C'\\fR after initialising the default loop, and making sure the\ndefault loop never gets destroyed. You are encouraged, however, to use an\nevent-based approach to child reaping and thus use libev's support for\nthat, so other libev users can use \\f(CW\\*(C`ev_child\\*(C'\\fR watchers freely.\n.PP\n\\fIStopping the Child Watcher\\fR\n.IX Subsection \"Stopping the Child Watcher\"\n.PP\nCurrently, the child watcher never gets stopped, even when the\nchild terminates, so normally one needs to stop the watcher in the\ncallback. Future versions of libev might stop the watcher automatically\nwhen a child exit is detected (calling \\f(CW\\*(C`ev_child_stop\\*(C'\\fR twice is not a\nproblem).\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_child_init (ev_child *, callback, int pid, int trace)\" 4\n.IX Item \"ev_child_init (ev_child *, callback, int pid, int trace)\"\n.PD 0\n.IP \"ev_child_set (ev_child *, int pid, int trace)\" 4\n.IX Item \"ev_child_set (ev_child *, int pid, int trace)\"\n.PD\nConfigures the watcher to wait for status changes of process \\f(CW\\*(C`pid\\*(C'\\fR (or\n\\&\\fIany\\fR process if \\f(CW\\*(C`pid\\*(C'\\fR is specified as \\f(CW0\\fR). The callback can look\nat the \\f(CW\\*(C`rstatus\\*(C'\\fR member of the \\f(CW\\*(C`ev_child\\*(C'\\fR watcher structure to see\nthe status word (use the macros from \\f(CW\\*(C`sys/wait.h\\*(C'\\fR and see your systems\n\\&\\f(CW\\*(C`waitpid\\*(C'\\fR documentation). The \\f(CW\\*(C`rpid\\*(C'\\fR member contains the pid of the\nprocess causing the status change. \\f(CW\\*(C`trace\\*(C'\\fR must be either \\f(CW0\\fR (only\nactivate the watcher when the process terminates) or \\f(CW1\\fR (additionally\nactivate the watcher when the process is stopped or continued).\n.IP \"int pid [read\\-only]\" 4\n.IX Item \"int pid [read-only]\"\nThe process id this watcher watches out for, or \\f(CW0\\fR, meaning any process id.\n.IP \"int rpid [read\\-write]\" 4\n.IX Item \"int rpid [read-write]\"\nThe process id that detected a status change.\n.IP \"int rstatus [read\\-write]\" 4\n.IX Item \"int rstatus [read-write]\"\nThe process exit/trace status caused by \\f(CW\\*(C`rpid\\*(C'\\fR (see your systems\n\\&\\f(CW\\*(C`waitpid\\*(C'\\fR and \\f(CW\\*(C`sys/wait.h\\*(C'\\fR documentation for details).\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nExample: \\f(CW\\*(C`fork()\\*(C'\\fR a new process and install a child handler to wait for\nits completion.\n.PP\n.Vb 1\n\\&   ev_child cw;\n\\&\n\\&   static void\n\\&   child_cb (EV_P_ ev_child *w, int revents)\n\\&   {\n\\&     ev_child_stop (EV_A_ w);\n\\&     printf (\"process %d exited with status %x\\en\", w\\->rpid, w\\->rstatus);\n\\&   }\n\\&\n\\&   pid_t pid = fork ();\n\\&\n\\&   if (pid < 0)\n\\&     // error\n\\&   else if (pid == 0)\n\\&     {\n\\&       // the forked child executes here\n\\&       exit (1);\n\\&     }\n\\&   else\n\\&     {\n\\&       ev_child_init (&cw, child_cb, pid, 0);\n\\&       ev_child_start (EV_DEFAULT_ &cw);\n\\&     }\n.Ve\n.ie n .SS \"\"\"ev_stat\"\" \\- did the file attributes just change?\"\n.el .SS \"\\f(CWev_stat\\fP \\- did the file attributes just change?\"\n.IX Subsection \"ev_stat - did the file attributes just change?\"\nThis watches a file system path for attribute changes. That is, it calls\n\\&\\f(CW\\*(C`stat\\*(C'\\fR on that path in regular intervals (or when the \\s-1OS\\s0 says it changed)\nand sees if it changed compared to the last time, invoking the callback\nif it did. Starting the watcher \\f(CW\\*(C`stat\\*(C'\\fR's the file, so only changes that\nhappen after the watcher has been started will be reported.\n.PP\nThe path does not need to exist: changing from \\*(L\"path exists\\*(R\" to \\*(L\"path does\nnot exist\\*(R\" is a status change like any other. The condition \\*(L\"path does not\nexist\\*(R\" (or more correctly \\*(L\"path cannot be stat'ed\\*(R\") is signified by the\n\\&\\f(CW\\*(C`st_nlink\\*(C'\\fR field being zero (which is otherwise always forced to be at\nleast one) and all the other fields of the stat buffer having unspecified\ncontents.\n.PP\nThe path \\fImust not\\fR end in a slash or contain special components such as\n\\&\\f(CW\\*(C`.\\*(C'\\fR or \\f(CW\\*(C`..\\*(C'\\fR. The path \\fIshould\\fR be absolute: If it is relative and\nyour working directory changes, then the behaviour is undefined.\n.PP\nSince there is no portable change notification interface available, the\nportable implementation simply calls \\f(CWstat(2)\\fR regularly on the path\nto see if it changed somehow. You can specify a recommended polling\ninterval for this case. If you specify a polling interval of \\f(CW0\\fR (highly\nrecommended!) then a \\fIsuitable, unspecified default\\fR value will be used\n(which you can expect to be around five seconds, although this might\nchange dynamically). Libev will also impose a minimum interval which is\ncurrently around \\f(CW0.1\\fR, but that's usually overkill.\n.PP\nThis watcher type is not meant for massive numbers of stat watchers,\nas even with OS-supported change notifications, this can be\nresource-intensive.\n.PP\nAt the time of this writing, the only OS-specific interface implemented\nis the Linux inotify interface (implementing kqueue support is left as an\nexercise for the reader. Note, however, that the author sees no way of\nimplementing \\f(CW\\*(C`ev_stat\\*(C'\\fR semantics with kqueue, except as a hint).\n.PP\n\\fI\\s-1ABI\\s0 Issues (Largefile Support)\\fR\n.IX Subsection \"ABI Issues (Largefile Support)\"\n.PP\nLibev by default (unless the user overrides this) uses the default\ncompilation environment, which means that on systems with large file\nsupport disabled by default, you get the 32 bit version of the stat\nstructure. When using the library from programs that change the \\s-1ABI\\s0 to\nuse 64 bit file offsets the programs will fail. In that case you have to\ncompile libev with the same flags to get binary compatibility. This is\nobviously the case with any flags that change the \\s-1ABI,\\s0 but the problem is\nmost noticeably displayed with ev_stat and large file support.\n.PP\nThe solution for this is to lobby your distribution maker to make large\nfile interfaces available by default (as e.g. FreeBSD does) and not\noptional. Libev cannot simply switch on large file support because it has\nto exchange stat structures with application programs compiled using the\ndefault compilation environment.\n.PP\n\\fIInotify and Kqueue\\fR\n.IX Subsection \"Inotify and Kqueue\"\n.PP\nWhen \\f(CW\\*(C`inotify (7)\\*(C'\\fR support has been compiled into libev and present at\nruntime, it will be used to speed up change detection where possible. The\ninotify descriptor will be created lazily when the first \\f(CW\\*(C`ev_stat\\*(C'\\fR\nwatcher is being started.\n.PP\nInotify presence does not change the semantics of \\f(CW\\*(C`ev_stat\\*(C'\\fR watchers\nexcept that changes might be detected earlier, and in some cases, to avoid\nmaking regular \\f(CW\\*(C`stat\\*(C'\\fR calls. Even in the presence of inotify support\nthere are many cases where libev has to resort to regular \\f(CW\\*(C`stat\\*(C'\\fR polling,\nbut as long as kernel 2.6.25 or newer is used (2.6.24 and older have too\nmany bugs), the path exists (i.e. stat succeeds), and the path resides on\na local filesystem (libev currently assumes only ext2/3, jfs, reiserfs and\nxfs are fully working) libev usually gets away without polling.\n.PP\nThere is no support for kqueue, as apparently it cannot be used to\nimplement this functionality, due to the requirement of having a file\ndescriptor open on the object at all times, and detecting renames, unlinks\netc. is difficult.\n.PP\n\\fI\\f(CI\\*(C`stat ()\\*(C'\\fI is a synchronous operation\\fR\n.IX Subsection \"stat () is a synchronous operation\"\n.PP\nLibev doesn't normally do any kind of I/O itself, and so is not blocking\nthe process. The exception are \\f(CW\\*(C`ev_stat\\*(C'\\fR watchers \\- those call \\f(CW\\*(C`stat\n()\\*(C'\\fR, which is a synchronous operation.\n.PP\nFor local paths, this usually doesn't matter: unless the system is very\nbusy or the intervals between stat's are large, a stat call will be fast,\nas the path data is usually in memory already (except when starting the\nwatcher).\n.PP\nFor networked file systems, calling \\f(CW\\*(C`stat ()\\*(C'\\fR can block an indefinite\ntime due to network issues, and even under good conditions, a stat call\noften takes multiple milliseconds.\n.PP\nTherefore, it is best to avoid using \\f(CW\\*(C`ev_stat\\*(C'\\fR watchers on networked\npaths, although this is fully supported by libev.\n.PP\n\\fIThe special problem of stat time resolution\\fR\n.IX Subsection \"The special problem of stat time resolution\"\n.PP\nThe \\f(CW\\*(C`stat ()\\*(C'\\fR system call only supports full-second resolution portably,\nand even on systems where the resolution is higher, most file systems\nstill only support whole seconds.\n.PP\nThat means that, if the time is the only thing that changes, you can\neasily miss updates: on the first update, \\f(CW\\*(C`ev_stat\\*(C'\\fR detects a change and\ncalls your callback, which does something. When there is another update\nwithin the same second, \\f(CW\\*(C`ev_stat\\*(C'\\fR will be unable to detect unless the\nstat data does change in other ways (e.g. file size).\n.PP\nThe solution to this is to delay acting on a change for slightly more\nthan a second (or till slightly after the next full second boundary), using\na roughly one-second-delay \\f(CW\\*(C`ev_timer\\*(C'\\fR (e.g. \\f(CW\\*(C`ev_timer_set (w, 0., 1.02);\nev_timer_again (loop, w)\\*(C'\\fR).\n.PP\nThe \\f(CW.02\\fR offset is added to work around small timing inconsistencies\nof some operating systems (where the second counter of the current time\nmight be be delayed. One such system is the Linux kernel, where a call to\n\\&\\f(CW\\*(C`gettimeofday\\*(C'\\fR might return a timestamp with a full second later than\na subsequent \\f(CW\\*(C`time\\*(C'\\fR call \\- if the equivalent of \\f(CW\\*(C`time ()\\*(C'\\fR is used to\nupdate file times then there will be a small window where the kernel uses\nthe previous second to update file times but libev might already execute\nthe timer callback).\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_stat_init (ev_stat *, callback, const char *path, ev_tstamp interval)\" 4\n.IX Item \"ev_stat_init (ev_stat *, callback, const char *path, ev_tstamp interval)\"\n.PD 0\n.IP \"ev_stat_set (ev_stat *, const char *path, ev_tstamp interval)\" 4\n.IX Item \"ev_stat_set (ev_stat *, const char *path, ev_tstamp interval)\"\n.PD\nConfigures the watcher to wait for status changes of the given\n\\&\\f(CW\\*(C`path\\*(C'\\fR. The \\f(CW\\*(C`interval\\*(C'\\fR is a hint on how quickly a change is expected to\nbe detected and should normally be specified as \\f(CW0\\fR to let libev choose\na suitable value. The memory pointed to by \\f(CW\\*(C`path\\*(C'\\fR must point to the same\npath for as long as the watcher is active.\n.Sp\nThe callback will receive an \\f(CW\\*(C`EV_STAT\\*(C'\\fR event when a change was detected,\nrelative to the attributes at the time the watcher was started (or the\nlast change was detected).\n.IP \"ev_stat_stat (loop, ev_stat *)\" 4\n.IX Item \"ev_stat_stat (loop, ev_stat *)\"\nUpdates the stat buffer immediately with new values. If you change the\nwatched path in your callback, you could call this function to avoid\ndetecting this change (while introducing a race condition if you are not\nthe only one changing the path). Can also be useful simply to find out the\nnew values.\n.IP \"ev_statdata attr [read\\-only]\" 4\n.IX Item \"ev_statdata attr [read-only]\"\nThe most-recently detected attributes of the file. Although the type is\n\\&\\f(CW\\*(C`ev_statdata\\*(C'\\fR, this is usually the (or one of the) \\f(CW\\*(C`struct stat\\*(C'\\fR types\nsuitable for your system, but you can only rely on the POSIX-standardised\nmembers to be present. If the \\f(CW\\*(C`st_nlink\\*(C'\\fR member is \\f(CW0\\fR, then there was\nsome error while \\f(CW\\*(C`stat\\*(C'\\fRing the file.\n.IP \"ev_statdata prev [read\\-only]\" 4\n.IX Item \"ev_statdata prev [read-only]\"\nThe previous attributes of the file. The callback gets invoked whenever\n\\&\\f(CW\\*(C`prev\\*(C'\\fR != \\f(CW\\*(C`attr\\*(C'\\fR, or, more precisely, one or more of these members\ndiffer: \\f(CW\\*(C`st_dev\\*(C'\\fR, \\f(CW\\*(C`st_ino\\*(C'\\fR, \\f(CW\\*(C`st_mode\\*(C'\\fR, \\f(CW\\*(C`st_nlink\\*(C'\\fR, \\f(CW\\*(C`st_uid\\*(C'\\fR,\n\\&\\f(CW\\*(C`st_gid\\*(C'\\fR, \\f(CW\\*(C`st_rdev\\*(C'\\fR, \\f(CW\\*(C`st_size\\*(C'\\fR, \\f(CW\\*(C`st_atime\\*(C'\\fR, \\f(CW\\*(C`st_mtime\\*(C'\\fR, \\f(CW\\*(C`st_ctime\\*(C'\\fR.\n.IP \"ev_tstamp interval [read\\-only]\" 4\n.IX Item \"ev_tstamp interval [read-only]\"\nThe specified interval.\n.IP \"const char *path [read\\-only]\" 4\n.IX Item \"const char *path [read-only]\"\nThe file system path that is being watched.\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nExample: Watch \\f(CW\\*(C`/etc/passwd\\*(C'\\fR for attribute changes.\n.PP\n.Vb 10\n\\&   static void\n\\&   passwd_cb (struct ev_loop *loop, ev_stat *w, int revents)\n\\&   {\n\\&     /* /etc/passwd changed in some way */\n\\&     if (w\\->attr.st_nlink)\n\\&       {\n\\&         printf (\"passwd current size  %ld\\en\", (long)w\\->attr.st_size);\n\\&         printf (\"passwd current atime %ld\\en\", (long)w\\->attr.st_mtime);\n\\&         printf (\"passwd current mtime %ld\\en\", (long)w\\->attr.st_mtime);\n\\&       }\n\\&     else\n\\&       /* you shalt not abuse printf for puts */\n\\&       puts (\"wow, /etc/passwd is not there, expect problems. \"\n\\&             \"if this is windows, they already arrived\\en\");\n\\&   }\n\\&\n\\&   ...\n\\&   ev_stat passwd;\n\\&\n\\&   ev_stat_init (&passwd, passwd_cb, \"/etc/passwd\", 0.);\n\\&   ev_stat_start (loop, &passwd);\n.Ve\n.PP\nExample: Like above, but additionally use a one-second delay so we do not\nmiss updates (however, frequent updates will delay processing, too, so\none might do the work both on \\f(CW\\*(C`ev_stat\\*(C'\\fR callback invocation \\fIand\\fR on\n\\&\\f(CW\\*(C`ev_timer\\*(C'\\fR callback invocation).\n.PP\n.Vb 2\n\\&   static ev_stat passwd;\n\\&   static ev_timer timer;\n\\&\n\\&   static void\n\\&   timer_cb (EV_P_ ev_timer *w, int revents)\n\\&   {\n\\&     ev_timer_stop (EV_A_ w);\n\\&\n\\&     /* now it\\*(Aqs one second after the most recent passwd change */\n\\&   }\n\\&\n\\&   static void\n\\&   stat_cb (EV_P_ ev_stat *w, int revents)\n\\&   {\n\\&     /* reset the one\\-second timer */\n\\&     ev_timer_again (EV_A_ &timer);\n\\&   }\n\\&\n\\&   ...\n\\&   ev_stat_init (&passwd, stat_cb, \"/etc/passwd\", 0.);\n\\&   ev_stat_start (loop, &passwd);\n\\&   ev_timer_init (&timer, timer_cb, 0., 1.02);\n.Ve\n.ie n .SS \"\"\"ev_idle\"\" \\- when you've got nothing better to do...\"\n.el .SS \"\\f(CWev_idle\\fP \\- when you've got nothing better to do...\"\n.IX Subsection \"ev_idle - when you've got nothing better to do...\"\nIdle watchers trigger events when no other events of the same or higher\npriority are pending (prepare, check and other idle watchers do not count\nas receiving \\*(L\"events\\*(R\").\n.PP\nThat is, as long as your process is busy handling sockets or timeouts\n(or even signals, imagine) of the same or higher priority it will not be\ntriggered. But when your process is idle (or only lower-priority watchers\nare pending), the idle watchers are being called once per event loop\niteration \\- until stopped, that is, or your process receives more events\nand becomes busy again with higher priority stuff.\n.PP\nThe most noteworthy effect is that as long as any idle watchers are\nactive, the process will not block when waiting for new events.\n.PP\nApart from keeping your process non-blocking (which is a useful\neffect on its own sometimes), idle watchers are a good place to do\n\\&\\*(L\"pseudo-background processing\\*(R\", or delay processing stuff to after the\nevent loop has handled all outstanding events.\n.PP\n\\fIAbusing an \\f(CI\\*(C`ev_idle\\*(C'\\fI watcher for its side-effect\\fR\n.IX Subsection \"Abusing an ev_idle watcher for its side-effect\"\n.PP\nAs long as there is at least one active idle watcher, libev will never\nsleep unnecessarily. Or in other words, it will loop as fast as possible.\nFor this to work, the idle watcher doesn't need to be invoked at all \\- the\nlowest priority will do.\n.PP\nThis mode of operation can be useful together with an \\f(CW\\*(C`ev_check\\*(C'\\fR watcher,\nto do something on each event loop iteration \\- for example to balance load\nbetween different connections.\n.PP\nSee \\*(L\"Abusing an ev_check watcher for its side-effect\\*(R\" for a longer\nexample.\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_idle_init (ev_idle *, callback)\" 4\n.IX Item \"ev_idle_init (ev_idle *, callback)\"\nInitialises and configures the idle watcher \\- it has no parameters of any\nkind. There is a \\f(CW\\*(C`ev_idle_set\\*(C'\\fR macro, but using it is utterly pointless,\nbelieve me.\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nExample: Dynamically allocate an \\f(CW\\*(C`ev_idle\\*(C'\\fR watcher, start it, and in the\ncallback, free it. Also, use no error checking, as usual.\n.PP\n.Vb 5\n\\&   static void\n\\&   idle_cb (struct ev_loop *loop, ev_idle *w, int revents)\n\\&   {\n\\&     // stop the watcher\n\\&     ev_idle_stop (loop, w);\n\\&\n\\&     // now we can free it\n\\&     free (w);\n\\&\n\\&     // now do something you wanted to do when the program has\n\\&     // no longer anything immediate to do.\n\\&   }\n\\&\n\\&   ev_idle *idle_watcher = malloc (sizeof (ev_idle));\n\\&   ev_idle_init (idle_watcher, idle_cb);\n\\&   ev_idle_start (loop, idle_watcher);\n.Ve\n.ie n .SS \"\"\"ev_prepare\"\" and \"\"ev_check\"\" \\- customise your event loop!\"\n.el .SS \"\\f(CWev_prepare\\fP and \\f(CWev_check\\fP \\- customise your event loop!\"\n.IX Subsection \"ev_prepare and ev_check - customise your event loop!\"\nPrepare and check watchers are often (but not always) used in pairs:\nprepare watchers get invoked before the process blocks and check watchers\nafterwards.\n.PP\nYou \\fImust not\\fR call \\f(CW\\*(C`ev_run\\*(C'\\fR (or similar functions that enter the\ncurrent event loop) or \\f(CW\\*(C`ev_loop_fork\\*(C'\\fR from either \\f(CW\\*(C`ev_prepare\\*(C'\\fR or\n\\&\\f(CW\\*(C`ev_check\\*(C'\\fR watchers. Other loops than the current one are fine,\nhowever. The rationale behind this is that you do not need to check\nfor recursion in those watchers, i.e. the sequence will always be\n\\&\\f(CW\\*(C`ev_prepare\\*(C'\\fR, blocking, \\f(CW\\*(C`ev_check\\*(C'\\fR so if you have one watcher of each\nkind they will always be called in pairs bracketing the blocking call.\n.PP\nTheir main purpose is to integrate other event mechanisms into libev and\ntheir use is somewhat advanced. They could be used, for example, to track\nvariable changes, implement your own watchers, integrate net-snmp or a\ncoroutine library and lots more. They are also occasionally useful if\nyou cache some data and want to flush it before blocking (for example,\nin X programs you might want to do an \\f(CW\\*(C`XFlush ()\\*(C'\\fR in an \\f(CW\\*(C`ev_prepare\\*(C'\\fR\nwatcher).\n.PP\nThis is done by examining in each prepare call which file descriptors\nneed to be watched by the other library, registering \\f(CW\\*(C`ev_io\\*(C'\\fR watchers\nfor them and starting an \\f(CW\\*(C`ev_timer\\*(C'\\fR watcher for any timeouts (many\nlibraries provide exactly this functionality). Then, in the check watcher,\nyou check for any events that occurred (by checking the pending status\nof all watchers and stopping them) and call back into the library. The\nI/O and timer callbacks will never actually be called (but must be valid\nnevertheless, because you never know, you know?).\n.PP\nAs another example, the Perl Coro module uses these hooks to integrate\ncoroutines into libev programs, by yielding to other active coroutines\nduring each prepare and only letting the process block if no coroutines\nare ready to run (it's actually more complicated: it only runs coroutines\nwith priority higher than or equal to the event loop and one coroutine\nof lower priority, but only once, using idle watchers to keep the event\nloop from blocking if lower-priority coroutines are active, thus mapping\nlow-priority coroutines to idle/background tasks).\n.PP\nWhen used for this purpose, it is recommended to give \\f(CW\\*(C`ev_check\\*(C'\\fR watchers\nhighest (\\f(CW\\*(C`EV_MAXPRI\\*(C'\\fR) priority, to ensure that they are being run before\nany other watchers after the poll (this doesn't matter for \\f(CW\\*(C`ev_prepare\\*(C'\\fR\nwatchers).\n.PP\nAlso, \\f(CW\\*(C`ev_check\\*(C'\\fR watchers (and \\f(CW\\*(C`ev_prepare\\*(C'\\fR watchers, too) should not\nactivate (\\*(L\"feed\\*(R\") events into libev. While libev fully supports this, they\nmight get executed before other \\f(CW\\*(C`ev_check\\*(C'\\fR watchers did their job. As\n\\&\\f(CW\\*(C`ev_check\\*(C'\\fR watchers are often used to embed other (non-libev) event\nloops those other event loops might be in an unusable state until their\n\\&\\f(CW\\*(C`ev_check\\*(C'\\fR watcher ran (always remind yourself to coexist peacefully with\nothers).\n.PP\n\\fIAbusing an \\f(CI\\*(C`ev_check\\*(C'\\fI watcher for its side-effect\\fR\n.IX Subsection \"Abusing an ev_check watcher for its side-effect\"\n.PP\n\\&\\f(CW\\*(C`ev_check\\*(C'\\fR (and less often also \\f(CW\\*(C`ev_prepare\\*(C'\\fR) watchers can also be\nuseful because they are called once per event loop iteration. For\nexample, if you want to handle a large number of connections fairly, you\nnormally only do a bit of work for each active connection, and if there\nis more work to do, you wait for the next event loop iteration, so other\nconnections have a chance of making progress.\n.PP\nUsing an \\f(CW\\*(C`ev_check\\*(C'\\fR watcher is almost enough: it will be called on the\nnext event loop iteration. However, that isn't as soon as possible \\-\nwithout external events, your \\f(CW\\*(C`ev_check\\*(C'\\fR watcher will not be invoked.\n.PP\nThis is where \\f(CW\\*(C`ev_idle\\*(C'\\fR watchers come in handy \\- all you need is a\nsingle global idle watcher that is active as long as you have one active\n\\&\\f(CW\\*(C`ev_check\\*(C'\\fR watcher. The \\f(CW\\*(C`ev_idle\\*(C'\\fR watcher makes sure the event loop\nwill not sleep, and the \\f(CW\\*(C`ev_check\\*(C'\\fR watcher makes sure a callback gets\ninvoked. Neither watcher alone can do that.\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_prepare_init (ev_prepare *, callback)\" 4\n.IX Item \"ev_prepare_init (ev_prepare *, callback)\"\n.PD 0\n.IP \"ev_check_init (ev_check *, callback)\" 4\n.IX Item \"ev_check_init (ev_check *, callback)\"\n.PD\nInitialises and configures the prepare or check watcher \\- they have no\nparameters of any kind. There are \\f(CW\\*(C`ev_prepare_set\\*(C'\\fR and \\f(CW\\*(C`ev_check_set\\*(C'\\fR\nmacros, but using them is utterly, utterly, utterly and completely\npointless.\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nThere are a number of principal ways to embed other event loops or modules\ninto libev. Here are some ideas on how to include libadns into libev\n(there is a Perl module named \\f(CW\\*(C`EV::ADNS\\*(C'\\fR that does this, which you could\nuse as a working example. Another Perl module named \\f(CW\\*(C`EV::Glib\\*(C'\\fR embeds a\nGlib main context into libev, and finally, \\f(CW\\*(C`Glib::EV\\*(C'\\fR embeds \\s-1EV\\s0 into the\nGlib event loop).\n.PP\nMethod 1: Add \\s-1IO\\s0 watchers and a timeout watcher in a prepare handler,\nand in a check watcher, destroy them and call into libadns. What follows\nis pseudo-code only of course. This requires you to either use a low\npriority for the check watcher or use \\f(CW\\*(C`ev_clear_pending\\*(C'\\fR explicitly, as\nthe callbacks for the IO/timeout watchers might not have been called yet.\n.PP\n.Vb 2\n\\&   static ev_io iow [nfd];\n\\&   static ev_timer tw;\n\\&\n\\&   static void\n\\&   io_cb (struct ev_loop *loop, ev_io *w, int revents)\n\\&   {\n\\&   }\n\\&\n\\&   // create io watchers for each fd and a timer before blocking\n\\&   static void\n\\&   adns_prepare_cb (struct ev_loop *loop, ev_prepare *w, int revents)\n\\&   {\n\\&     int timeout = 3600000;\n\\&     struct pollfd fds [nfd];\n\\&     // actual code will need to loop here and realloc etc.\n\\&     adns_beforepoll (ads, fds, &nfd, &timeout, timeval_from (ev_time ()));\n\\&\n\\&     /* the callback is illegal, but won\\*(Aqt be called as we stop during check */\n\\&     ev_timer_init (&tw, 0, timeout * 1e\\-3, 0.);\n\\&     ev_timer_start (loop, &tw);\n\\&\n\\&     // create one ev_io per pollfd\n\\&     for (int i = 0; i < nfd; ++i)\n\\&       {\n\\&         ev_io_init (iow + i, io_cb, fds [i].fd,\n\\&           ((fds [i].events & POLLIN ? EV_READ : 0)\n\\&            | (fds [i].events & POLLOUT ? EV_WRITE : 0)));\n\\&\n\\&         fds [i].revents = 0;\n\\&         ev_io_start (loop, iow + i);\n\\&       }\n\\&   }\n\\&\n\\&   // stop all watchers after blocking\n\\&   static void\n\\&   adns_check_cb (struct ev_loop *loop, ev_check *w, int revents)\n\\&   {\n\\&     ev_timer_stop (loop, &tw);\n\\&\n\\&     for (int i = 0; i < nfd; ++i)\n\\&       {\n\\&         // set the relevant poll flags\n\\&         // could also call adns_processreadable etc. here\n\\&         struct pollfd *fd = fds + i;\n\\&         int revents = ev_clear_pending (iow + i);\n\\&         if (revents & EV_READ ) fd\\->revents |= fd\\->events & POLLIN;\n\\&         if (revents & EV_WRITE) fd\\->revents |= fd\\->events & POLLOUT;\n\\&\n\\&         // now stop the watcher\n\\&         ev_io_stop (loop, iow + i);\n\\&       }\n\\&\n\\&     adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop));\n\\&   }\n.Ve\n.PP\nMethod 2: This would be just like method 1, but you run \\f(CW\\*(C`adns_afterpoll\\*(C'\\fR\nin the prepare watcher and would dispose of the check watcher.\n.PP\nMethod 3: If the module to be embedded supports explicit event\nnotification (libadns does), you can also make use of the actual watcher\ncallbacks, and only destroy/create the watchers in the prepare watcher.\n.PP\n.Vb 5\n\\&   static void\n\\&   timer_cb (EV_P_ ev_timer *w, int revents)\n\\&   {\n\\&     adns_state ads = (adns_state)w\\->data;\n\\&     update_now (EV_A);\n\\&\n\\&     adns_processtimeouts (ads, &tv_now);\n\\&   }\n\\&\n\\&   static void\n\\&   io_cb (EV_P_ ev_io *w, int revents)\n\\&   {\n\\&     adns_state ads = (adns_state)w\\->data;\n\\&     update_now (EV_A);\n\\&\n\\&     if (revents & EV_READ ) adns_processreadable  (ads, w\\->fd, &tv_now);\n\\&     if (revents & EV_WRITE) adns_processwriteable (ads, w\\->fd, &tv_now);\n\\&   }\n\\&\n\\&   // do not ever call adns_afterpoll\n.Ve\n.PP\nMethod 4: Do not use a prepare or check watcher because the module you\nwant to embed is not flexible enough to support it. Instead, you can\noverride their poll function. The drawback with this solution is that the\nmain loop is now no longer controllable by \\s-1EV.\\s0 The \\f(CW\\*(C`Glib::EV\\*(C'\\fR module uses\nthis approach, effectively embedding \\s-1EV\\s0 as a client into the horrible\nlibglib event loop.\n.PP\n.Vb 4\n\\&   static gint\n\\&   event_poll_func (GPollFD *fds, guint nfds, gint timeout)\n\\&   {\n\\&     int got_events = 0;\n\\&\n\\&     for (n = 0; n < nfds; ++n)\n\\&       // create/start io watcher that sets the relevant bits in fds[n] and increment got_events\n\\&\n\\&     if (timeout >= 0)\n\\&       // create/start timer\n\\&\n\\&     // poll\n\\&     ev_run (EV_A_ 0);\n\\&\n\\&     // stop timer again\n\\&     if (timeout >= 0)\n\\&       ev_timer_stop (EV_A_ &to);\n\\&\n\\&     // stop io watchers again \\- their callbacks should have set\n\\&     for (n = 0; n < nfds; ++n)\n\\&       ev_io_stop (EV_A_ iow [n]);\n\\&\n\\&     return got_events;\n\\&   }\n.Ve\n.ie n .SS \"\"\"ev_embed\"\" \\- when one backend isn't enough...\"\n.el .SS \"\\f(CWev_embed\\fP \\- when one backend isn't enough...\"\n.IX Subsection \"ev_embed - when one backend isn't enough...\"\nThis is a rather advanced watcher type that lets you embed one event loop\ninto another (currently only \\f(CW\\*(C`ev_io\\*(C'\\fR events are supported in the embedded\nloop, other types of watchers might be handled in a delayed or incorrect\nfashion and must not be used).\n.PP\nThere are primarily two reasons you would want that: work around bugs and\nprioritise I/O.\n.PP\nAs an example for a bug workaround, the kqueue backend might only support\nsockets on some platform, so it is unusable as generic backend, but you\nstill want to make use of it because you have many sockets and it scales\nso nicely. In this case, you would create a kqueue-based loop and embed\nit into your default loop (which might use e.g. poll). Overall operation\nwill be a bit slower because first libev has to call \\f(CW\\*(C`poll\\*(C'\\fR and then\n\\&\\f(CW\\*(C`kevent\\*(C'\\fR, but at least you can use both mechanisms for what they are\nbest: \\f(CW\\*(C`kqueue\\*(C'\\fR for scalable sockets and \\f(CW\\*(C`poll\\*(C'\\fR if you want it to work :)\n.PP\nAs for prioritising I/O: under rare circumstances you have the case where\nsome fds have to be watched and handled very quickly (with low latency),\nand even priorities and idle watchers might have too much overhead. In\nthis case you would put all the high priority stuff in one loop and all\nthe rest in a second one, and embed the second one in the first.\n.PP\nAs long as the watcher is active, the callback will be invoked every\ntime there might be events pending in the embedded loop. The callback\nmust then call \\f(CW\\*(C`ev_embed_sweep (mainloop, watcher)\\*(C'\\fR to make a single\nsweep and invoke their callbacks (the callback doesn't need to invoke the\n\\&\\f(CW\\*(C`ev_embed_sweep\\*(C'\\fR function directly, it could also start an idle watcher\nto give the embedded loop strictly lower priority for example).\n.PP\nYou can also set the callback to \\f(CW0\\fR, in which case the embed watcher\nwill automatically execute the embedded loop sweep whenever necessary.\n.PP\nFork detection will be handled transparently while the \\f(CW\\*(C`ev_embed\\*(C'\\fR watcher\nis active, i.e., the embedded loop will automatically be forked when the\nembedding loop forks. In other cases, the user is responsible for calling\n\\&\\f(CW\\*(C`ev_loop_fork\\*(C'\\fR on the embedded loop.\n.PP\nUnfortunately, not all backends are embeddable: only the ones returned by\n\\&\\f(CW\\*(C`ev_embeddable_backends\\*(C'\\fR are, which, unfortunately, does not include any\nportable one.\n.PP\nSo when you want to use this feature you will always have to be prepared\nthat you cannot get an embeddable loop. The recommended way to get around\nthis is to have a separate variables for your embeddable loop, try to\ncreate it, and if that fails, use the normal loop for everything.\n.PP\n\\fI\\f(CI\\*(C`ev_embed\\*(C'\\fI and fork\\fR\n.IX Subsection \"ev_embed and fork\"\n.PP\nWhile the \\f(CW\\*(C`ev_embed\\*(C'\\fR watcher is running, forks in the embedding loop will\nautomatically be applied to the embedded loop as well, so no special\nfork handling is required in that case. When the watcher is not running,\nhowever, it is still the task of the libev user to call \\f(CW\\*(C`ev_loop_fork ()\\*(C'\\fR\nas applicable.\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_embed_init (ev_embed *, callback, struct ev_loop *embedded_loop)\" 4\n.IX Item \"ev_embed_init (ev_embed *, callback, struct ev_loop *embedded_loop)\"\n.PD 0\n.IP \"ev_embed_set (ev_embed *, struct ev_loop *embedded_loop)\" 4\n.IX Item \"ev_embed_set (ev_embed *, struct ev_loop *embedded_loop)\"\n.PD\nConfigures the watcher to embed the given loop, which must be\nembeddable. If the callback is \\f(CW0\\fR, then \\f(CW\\*(C`ev_embed_sweep\\*(C'\\fR will be\ninvoked automatically, otherwise it is the responsibility of the callback\nto invoke it (it will continue to be called until the sweep has been done,\nif you do not want that, you need to temporarily stop the embed watcher).\n.IP \"ev_embed_sweep (loop, ev_embed *)\" 4\n.IX Item \"ev_embed_sweep (loop, ev_embed *)\"\nMake a single, non-blocking sweep over the embedded loop. This works\nsimilarly to \\f(CW\\*(C`ev_run (embedded_loop, EVRUN_NOWAIT)\\*(C'\\fR, but in the most\nappropriate way for embedded loops.\n.IP \"struct ev_loop *other [read\\-only]\" 4\n.IX Item \"struct ev_loop *other [read-only]\"\nThe embedded event loop.\n.PP\n\\fIExamples\\fR\n.IX Subsection \"Examples\"\n.PP\nExample: Try to get an embeddable event loop and embed it into the default\nevent loop. If that is not possible, use the default loop. The default\nloop is stored in \\f(CW\\*(C`loop_hi\\*(C'\\fR, while the embeddable loop is stored in\n\\&\\f(CW\\*(C`loop_lo\\*(C'\\fR (which is \\f(CW\\*(C`loop_hi\\*(C'\\fR in the case no embeddable loop can be\nused).\n.PP\n.Vb 3\n\\&   struct ev_loop *loop_hi = ev_default_init (0);\n\\&   struct ev_loop *loop_lo = 0;\n\\&   ev_embed embed;\n\\&\n\\&   // see if there is a chance of getting one that works\n\\&   // (remember that a flags value of 0 means autodetection)\n\\&   loop_lo = ev_embeddable_backends () & ev_recommended_backends ()\n\\&     ? ev_loop_new (ev_embeddable_backends () & ev_recommended_backends ())\n\\&     : 0;\n\\&\n\\&   // if we got one, then embed it, otherwise default to loop_hi\n\\&   if (loop_lo)\n\\&     {\n\\&       ev_embed_init (&embed, 0, loop_lo);\n\\&       ev_embed_start (loop_hi, &embed);\n\\&     }\n\\&   else\n\\&     loop_lo = loop_hi;\n.Ve\n.PP\nExample: Check if kqueue is available but not recommended and create\na kqueue backend for use with sockets (which usually work with any\nkqueue implementation). Store the kqueue/socket\\-only event loop in\n\\&\\f(CW\\*(C`loop_socket\\*(C'\\fR. (One might optionally use \\f(CW\\*(C`EVFLAG_NOENV\\*(C'\\fR, too).\n.PP\n.Vb 3\n\\&   struct ev_loop *loop = ev_default_init (0);\n\\&   struct ev_loop *loop_socket = 0;\n\\&   ev_embed embed;\n\\&\n\\&   if (ev_supported_backends () & ~ev_recommended_backends () & EVBACKEND_KQUEUE)\n\\&     if ((loop_socket = ev_loop_new (EVBACKEND_KQUEUE))\n\\&       {\n\\&         ev_embed_init (&embed, 0, loop_socket);\n\\&         ev_embed_start (loop, &embed);\n\\&       }\n\\&\n\\&   if (!loop_socket)\n\\&     loop_socket = loop;\n\\&\n\\&   // now use loop_socket for all sockets, and loop for everything else\n.Ve\n.ie n .SS \"\"\"ev_fork\"\" \\- the audacity to resume the event loop after a fork\"\n.el .SS \"\\f(CWev_fork\\fP \\- the audacity to resume the event loop after a fork\"\n.IX Subsection \"ev_fork - the audacity to resume the event loop after a fork\"\nFork watchers are called when a \\f(CW\\*(C`fork ()\\*(C'\\fR was detected (usually because\nwhoever is a good citizen cared to tell libev about it by calling\n\\&\\f(CW\\*(C`ev_loop_fork\\*(C'\\fR). The invocation is done before the event loop blocks next\nand before \\f(CW\\*(C`ev_check\\*(C'\\fR watchers are being called, and only in the child\nafter the fork. If whoever good citizen calling \\f(CW\\*(C`ev_default_fork\\*(C'\\fR cheats\nand calls it in the wrong process, the fork handlers will be invoked, too,\nof course.\n.PP\n\\fIThe special problem of life after fork \\- how is it possible?\\fR\n.IX Subsection \"The special problem of life after fork - how is it possible?\"\n.PP\nMost uses of \\f(CW\\*(C`fork ()\\*(C'\\fR consist of forking, then some simple calls to set\nup/change the process environment, followed by a call to \\f(CW\\*(C`exec()\\*(C'\\fR. This\nsequence should be handled by libev without any problems.\n.PP\nThis changes when the application actually wants to do event handling\nin the child, or both parent in child, in effect \\*(L\"continuing\\*(R\" after the\nfork.\n.PP\nThe default mode of operation (for libev, with application help to detect\nforks) is to duplicate all the state in the child, as would be expected\nwhen \\fIeither\\fR the parent \\fIor\\fR the child process continues.\n.PP\nWhen both processes want to continue using libev, then this is usually the\nwrong result. In that case, usually one process (typically the parent) is\nsupposed to continue with all watchers in place as before, while the other\nprocess typically wants to start fresh, i.e. without any active watchers.\n.PP\nThe cleanest and most efficient way to achieve that with libev is to\nsimply create a new event loop, which of course will be \\*(L\"empty\\*(R\", and\nuse that for new watchers. This has the advantage of not touching more\nmemory than necessary, and thus avoiding the copy-on-write, and the\ndisadvantage of having to use multiple event loops (which do not support\nsignal watchers).\n.PP\nWhen this is not possible, or you want to use the default loop for\nother reasons, then in the process that wants to start \\*(L\"fresh\\*(R\", call\n\\&\\f(CW\\*(C`ev_loop_destroy (EV_DEFAULT)\\*(C'\\fR followed by \\f(CW\\*(C`ev_default_loop (...)\\*(C'\\fR.\nDestroying the default loop will \\*(L\"orphan\\*(R\" (not stop) all registered\nwatchers, so you have to be careful not to execute code that modifies\nthose watchers. Note also that in that case, you have to re-register any\nsignal watchers.\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_fork_init (ev_fork *, callback)\" 4\n.IX Item \"ev_fork_init (ev_fork *, callback)\"\nInitialises and configures the fork watcher \\- it has no parameters of any\nkind. There is a \\f(CW\\*(C`ev_fork_set\\*(C'\\fR macro, but using it is utterly pointless,\nreally.\n.ie n .SS \"\"\"ev_cleanup\"\" \\- even the best things end\"\n.el .SS \"\\f(CWev_cleanup\\fP \\- even the best things end\"\n.IX Subsection \"ev_cleanup - even the best things end\"\nCleanup watchers are called just before the event loop is being destroyed\nby a call to \\f(CW\\*(C`ev_loop_destroy\\*(C'\\fR.\n.PP\nWhile there is no guarantee that the event loop gets destroyed, cleanup\nwatchers provide a convenient method to install cleanup hooks for your\nprogram, worker threads and so on \\- you just to make sure to destroy the\nloop when you want them to be invoked.\n.PP\nCleanup watchers are invoked in the same way as any other watcher. Unlike\nall other watchers, they do not keep a reference to the event loop (which\nmakes a lot of sense if you think about it). Like all other watchers, you\ncan call libev functions in the callback, except \\f(CW\\*(C`ev_cleanup_start\\*(C'\\fR.\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_cleanup_init (ev_cleanup *, callback)\" 4\n.IX Item \"ev_cleanup_init (ev_cleanup *, callback)\"\nInitialises and configures the cleanup watcher \\- it has no parameters of\nany kind. There is a \\f(CW\\*(C`ev_cleanup_set\\*(C'\\fR macro, but using it is utterly\npointless, I assure you.\n.PP\nExample: Register an atexit handler to destroy the default loop, so any\ncleanup functions are called.\n.PP\n.Vb 5\n\\&   static void\n\\&   program_exits (void)\n\\&   {\n\\&     ev_loop_destroy (EV_DEFAULT_UC);\n\\&   }\n\\&\n\\&   ...\n\\&   atexit (program_exits);\n.Ve\n.ie n .SS \"\"\"ev_async\"\" \\- how to wake up an event loop\"\n.el .SS \"\\f(CWev_async\\fP \\- how to wake up an event loop\"\n.IX Subsection \"ev_async - how to wake up an event loop\"\nIn general, you cannot use an \\f(CW\\*(C`ev_loop\\*(C'\\fR from multiple threads or other\nasynchronous sources such as signal handlers (as opposed to multiple event\nloops \\- those are of course safe to use in different threads).\n.PP\nSometimes, however, you need to wake up an event loop you do not control,\nfor example because it belongs to another thread. This is what \\f(CW\\*(C`ev_async\\*(C'\\fR\nwatchers do: as long as the \\f(CW\\*(C`ev_async\\*(C'\\fR watcher is active, you can signal\nit by calling \\f(CW\\*(C`ev_async_send\\*(C'\\fR, which is thread\\- and signal safe.\n.PP\nThis functionality is very similar to \\f(CW\\*(C`ev_signal\\*(C'\\fR watchers, as signals,\ntoo, are asynchronous in nature, and signals, too, will be compressed\n(i.e. the number of callback invocations may be less than the number of\n\\&\\f(CW\\*(C`ev_async_send\\*(C'\\fR calls). In fact, you could use signal watchers as a kind\nof \\*(L\"global async watchers\\*(R\" by using a watcher on an otherwise unused\nsignal, and \\f(CW\\*(C`ev_feed_signal\\*(C'\\fR to signal this watcher from another thread,\neven without knowing which loop owns the signal.\n.PP\n\\fIQueueing\\fR\n.IX Subsection \"Queueing\"\n.PP\n\\&\\f(CW\\*(C`ev_async\\*(C'\\fR does not support queueing of data in any way. The reason\nis that the author does not know of a simple (or any) algorithm for a\nmultiple-writer-single-reader queue that works in all cases and doesn't\nneed elaborate support such as pthreads or unportable memory access\nsemantics.\n.PP\nThat means that if you want to queue data, you have to provide your own\nqueue. But at least I can tell you how to implement locking around your\nqueue:\n.IP \"queueing from a signal handler context\" 4\n.IX Item \"queueing from a signal handler context\"\nTo implement race-free queueing, you simply add to the queue in the signal\nhandler but you block the signal handler in the watcher callback. Here is\nan example that does that for some fictitious \\s-1SIGUSR1\\s0 handler:\n.Sp\n.Vb 1\n\\&   static ev_async mysig;\n\\&\n\\&   static void\n\\&   sigusr1_handler (void)\n\\&   {\n\\&     sometype data;\n\\&\n\\&     // no locking etc.\n\\&     queue_put (data);\n\\&     ev_async_send (EV_DEFAULT_ &mysig);\n\\&   }\n\\&\n\\&   static void\n\\&   mysig_cb (EV_P_ ev_async *w, int revents)\n\\&   {\n\\&     sometype data;\n\\&     sigset_t block, prev;\n\\&\n\\&     sigemptyset (&block);\n\\&     sigaddset (&block, SIGUSR1);\n\\&     sigprocmask (SIG_BLOCK, &block, &prev);\n\\&\n\\&     while (queue_get (&data))\n\\&       process (data);\n\\&\n\\&     if (sigismember (&prev, SIGUSR1)\n\\&       sigprocmask (SIG_UNBLOCK, &block, 0);\n\\&   }\n.Ve\n.Sp\n(Note: pthreads in theory requires you to use \\f(CW\\*(C`pthread_setmask\\*(C'\\fR\ninstead of \\f(CW\\*(C`sigprocmask\\*(C'\\fR when you use threads, but libev doesn't do it\neither...).\n.IP \"queueing from a thread context\" 4\n.IX Item \"queueing from a thread context\"\nThe strategy for threads is different, as you cannot (easily) block\nthreads but you can easily preempt them, so to queue safely you need to\nemploy a traditional mutex lock, such as in this pthread example:\n.Sp\n.Vb 2\n\\&   static ev_async mysig;\n\\&   static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;\n\\&\n\\&   static void\n\\&   otherthread (void)\n\\&   {\n\\&     // only need to lock the actual queueing operation\n\\&     pthread_mutex_lock (&mymutex);\n\\&     queue_put (data);\n\\&     pthread_mutex_unlock (&mymutex);\n\\&\n\\&     ev_async_send (EV_DEFAULT_ &mysig);\n\\&   }\n\\&\n\\&   static void\n\\&   mysig_cb (EV_P_ ev_async *w, int revents)\n\\&   {\n\\&     pthread_mutex_lock (&mymutex);\n\\&\n\\&     while (queue_get (&data))\n\\&       process (data);\n\\&\n\\&     pthread_mutex_unlock (&mymutex);\n\\&   }\n.Ve\n.PP\n\\fIWatcher-Specific Functions and Data Members\\fR\n.IX Subsection \"Watcher-Specific Functions and Data Members\"\n.IP \"ev_async_init (ev_async *, callback)\" 4\n.IX Item \"ev_async_init (ev_async *, callback)\"\nInitialises and configures the async watcher \\- it has no parameters of any\nkind. There is a \\f(CW\\*(C`ev_async_set\\*(C'\\fR macro, but using it is utterly pointless,\ntrust me.\n.IP \"ev_async_send (loop, ev_async *)\" 4\n.IX Item \"ev_async_send (loop, ev_async *)\"\nSends/signals/activates the given \\f(CW\\*(C`ev_async\\*(C'\\fR watcher, that is, feeds\nan \\f(CW\\*(C`EV_ASYNC\\*(C'\\fR event on the watcher into the event loop, and instantly\nreturns.\n.Sp\nUnlike \\f(CW\\*(C`ev_feed_event\\*(C'\\fR, this call is safe to do from other threads,\nsignal or similar contexts (see the discussion of \\f(CW\\*(C`EV_ATOMIC_T\\*(C'\\fR in the\nembedding section below on what exactly this means).\n.Sp\nNote that, as with other watchers in libev, multiple events might get\ncompressed into a single callback invocation (another way to look at\nthis is that \\f(CW\\*(C`ev_async\\*(C'\\fR watchers are level-triggered: they are set on\n\\&\\f(CW\\*(C`ev_async_send\\*(C'\\fR, reset when the event loop detects that).\n.Sp\nThis call incurs the overhead of at most one extra system call per event\nloop iteration, if the event loop is blocked, and no syscall at all if\nthe event loop (or your program) is processing events. That means that\nrepeated calls are basically free (there is no need to avoid calls for\nperformance reasons) and that the overhead becomes smaller (typically\nzero) under load.\n.IP \"bool = ev_async_pending (ev_async *)\" 4\n.IX Item \"bool = ev_async_pending (ev_async *)\"\nReturns a non-zero value when \\f(CW\\*(C`ev_async_send\\*(C'\\fR has been called on the\nwatcher but the event has not yet been processed (or even noted) by the\nevent loop.\n.Sp\n\\&\\f(CW\\*(C`ev_async_send\\*(C'\\fR sets a flag in the watcher and wakes up the loop. When\nthe loop iterates next and checks for the watcher to have become active,\nit will reset the flag again. \\f(CW\\*(C`ev_async_pending\\*(C'\\fR can be used to very\nquickly check whether invoking the loop might be a good idea.\n.Sp\nNot that this does \\fInot\\fR check whether the watcher itself is pending,\nonly whether it has been requested to make this watcher pending: there\nis a time window between the event loop checking and resetting the async\nnotification, and the callback being invoked.\n.SH \"OTHER FUNCTIONS\"\n.IX Header \"OTHER FUNCTIONS\"\nThere are some other functions of possible interest. Described. Here. Now.\n.IP \"ev_once (loop, int fd, int events, ev_tstamp timeout, callback)\" 4\n.IX Item \"ev_once (loop, int fd, int events, ev_tstamp timeout, callback)\"\nThis function combines a simple timer and an I/O watcher, calls your\ncallback on whichever event happens first and automatically stops both\nwatchers. This is useful if you want to wait for a single event on an fd\nor timeout without having to allocate/configure/start/stop/free one or\nmore watchers yourself.\n.Sp\nIf \\f(CW\\*(C`fd\\*(C'\\fR is less than 0, then no I/O watcher will be started and the\n\\&\\f(CW\\*(C`events\\*(C'\\fR argument is being ignored. Otherwise, an \\f(CW\\*(C`ev_io\\*(C'\\fR watcher for\nthe given \\f(CW\\*(C`fd\\*(C'\\fR and \\f(CW\\*(C`events\\*(C'\\fR set will be created and started.\n.Sp\nIf \\f(CW\\*(C`timeout\\*(C'\\fR is less than 0, then no timeout watcher will be\nstarted. Otherwise an \\f(CW\\*(C`ev_timer\\*(C'\\fR watcher with after = \\f(CW\\*(C`timeout\\*(C'\\fR (and\nrepeat = 0) will be started. \\f(CW0\\fR is a valid timeout.\n.Sp\nThe callback has the type \\f(CW\\*(C`void (*cb)(int revents, void *arg)\\*(C'\\fR and is\npassed an \\f(CW\\*(C`revents\\*(C'\\fR set like normal event callbacks (a combination of\n\\&\\f(CW\\*(C`EV_ERROR\\*(C'\\fR, \\f(CW\\*(C`EV_READ\\*(C'\\fR, \\f(CW\\*(C`EV_WRITE\\*(C'\\fR or \\f(CW\\*(C`EV_TIMER\\*(C'\\fR) and the \\f(CW\\*(C`arg\\*(C'\\fR\nvalue passed to \\f(CW\\*(C`ev_once\\*(C'\\fR. Note that it is possible to receive \\fIboth\\fR\na timeout and an io event at the same time \\- you probably should give io\nevents precedence.\n.Sp\nExample: wait up to ten seconds for data to appear on \\s-1STDIN_FILENO.\\s0\n.Sp\n.Vb 7\n\\&   static void stdin_ready (int revents, void *arg)\n\\&   {\n\\&     if (revents & EV_READ)\n\\&       /* stdin might have data for us, joy! */;\n\\&     else if (revents & EV_TIMER)\n\\&       /* doh, nothing entered */;\n\\&   }\n\\&\n\\&   ev_once (STDIN_FILENO, EV_READ, 10., stdin_ready, 0);\n.Ve\n.IP \"ev_feed_fd_event (loop, int fd, int revents)\" 4\n.IX Item \"ev_feed_fd_event (loop, int fd, int revents)\"\nFeed an event on the given fd, as if a file descriptor backend detected\nthe given events.\n.IP \"ev_feed_signal_event (loop, int signum)\" 4\n.IX Item \"ev_feed_signal_event (loop, int signum)\"\nFeed an event as if the given signal occurred. See also \\f(CW\\*(C`ev_feed_signal\\*(C'\\fR,\nwhich is async-safe.\n.SH \"COMMON OR USEFUL IDIOMS (OR BOTH)\"\n.IX Header \"COMMON OR USEFUL IDIOMS (OR BOTH)\"\nThis section explains some common idioms that are not immediately\nobvious. Note that examples are sprinkled over the whole manual, and this\nsection only contains stuff that wouldn't fit anywhere else.\n.SS \"\\s-1ASSOCIATING CUSTOM DATA WITH A WATCHER\\s0\"\n.IX Subsection \"ASSOCIATING CUSTOM DATA WITH A WATCHER\"\nEach watcher has, by default, a \\f(CW\\*(C`void *data\\*(C'\\fR member that you can read\nor modify at any time: libev will completely ignore it. This can be used\nto associate arbitrary data with your watcher. If you need more data and\ndon't want to allocate memory separately and store a pointer to it in that\ndata member, you can also \\*(L\"subclass\\*(R\" the watcher type and provide your own\ndata:\n.PP\n.Vb 7\n\\&   struct my_io\n\\&   {\n\\&     ev_io io;\n\\&     int otherfd;\n\\&     void *somedata;\n\\&     struct whatever *mostinteresting;\n\\&   };\n\\&\n\\&   ...\n\\&   struct my_io w;\n\\&   ev_io_init (&w.io, my_cb, fd, EV_READ);\n.Ve\n.PP\nAnd since your callback will be called with a pointer to the watcher, you\ncan cast it back to your own type:\n.PP\n.Vb 5\n\\&   static void my_cb (struct ev_loop *loop, ev_io *w_, int revents)\n\\&   {\n\\&     struct my_io *w = (struct my_io *)w_;\n\\&     ...\n\\&   }\n.Ve\n.PP\nMore interesting and less C\\-conformant ways of casting your callback\nfunction type instead have been omitted.\n.SS \"\\s-1BUILDING YOUR OWN COMPOSITE WATCHERS\\s0\"\n.IX Subsection \"BUILDING YOUR OWN COMPOSITE WATCHERS\"\nAnother common scenario is to use some data structure with multiple\nembedded watchers, in effect creating your own watcher that combines\nmultiple libev event sources into one \\*(L\"super-watcher\\*(R\":\n.PP\n.Vb 6\n\\&   struct my_biggy\n\\&   {\n\\&     int some_data;\n\\&     ev_timer t1;\n\\&     ev_timer t2;\n\\&   }\n.Ve\n.PP\nIn this case getting the pointer to \\f(CW\\*(C`my_biggy\\*(C'\\fR is a bit more\ncomplicated: Either you store the address of your \\f(CW\\*(C`my_biggy\\*(C'\\fR struct in\nthe \\f(CW\\*(C`data\\*(C'\\fR member of the watcher (for woozies or \\*(C+ coders), or you need\nto use some pointer arithmetic using \\f(CW\\*(C`offsetof\\*(C'\\fR inside your watchers (for\nreal programmers):\n.PP\n.Vb 1\n\\&   #include <stddef.h>\n\\&\n\\&   static void\n\\&   t1_cb (EV_P_ ev_timer *w, int revents)\n\\&   {\n\\&     struct my_biggy big = (struct my_biggy *)\n\\&       (((char *)w) \\- offsetof (struct my_biggy, t1));\n\\&   }\n\\&\n\\&   static void\n\\&   t2_cb (EV_P_ ev_timer *w, int revents)\n\\&   {\n\\&     struct my_biggy big = (struct my_biggy *)\n\\&       (((char *)w) \\- offsetof (struct my_biggy, t2));\n\\&   }\n.Ve\n.SS \"\\s-1AVOIDING FINISHING BEFORE RETURNING\\s0\"\n.IX Subsection \"AVOIDING FINISHING BEFORE RETURNING\"\nOften you have structures like this in event-based programs:\n.PP\n.Vb 4\n\\&  callback ()\n\\&  {\n\\&    free (request);\n\\&  }\n\\&\n\\&  request = start_new_request (..., callback);\n.Ve\n.PP\nThe intent is to start some \\*(L\"lengthy\\*(R\" operation. The \\f(CW\\*(C`request\\*(C'\\fR could be\nused to cancel the operation, or do other things with it.\n.PP\nIt's not uncommon to have code paths in \\f(CW\\*(C`start_new_request\\*(C'\\fR that\nimmediately invoke the callback, for example, to report errors. Or you add\nsome caching layer that finds that it can skip the lengthy aspects of the\noperation and simply invoke the callback with the result.\n.PP\nThe problem here is that this will happen \\fIbefore\\fR \\f(CW\\*(C`start_new_request\\*(C'\\fR\nhas returned, so \\f(CW\\*(C`request\\*(C'\\fR is not set.\n.PP\nEven if you pass the request by some safer means to the callback, you\nmight want to do something to the request after starting it, such as\ncanceling it, which probably isn't working so well when the callback has\nalready been invoked.\n.PP\nA common way around all these issues is to make sure that\n\\&\\f(CW\\*(C`start_new_request\\*(C'\\fR \\fIalways\\fR returns before the callback is invoked. If\n\\&\\f(CW\\*(C`start_new_request\\*(C'\\fR immediately knows the result, it can artificially\ndelay invoking the callback by using a \\f(CW\\*(C`prepare\\*(C'\\fR or \\f(CW\\*(C`idle\\*(C'\\fR watcher for\nexample, or more sneakily, by reusing an existing (stopped) watcher and\npushing it into the pending queue:\n.PP\n.Vb 2\n\\&   ev_set_cb (watcher, callback);\n\\&   ev_feed_event (EV_A_ watcher, 0);\n.Ve\n.PP\nThis way, \\f(CW\\*(C`start_new_request\\*(C'\\fR can safely return before the callback is\ninvoked, while not delaying callback invocation too much.\n.SS \"\\s-1MODEL/NESTED EVENT LOOP INVOCATIONS AND EXIT CONDITIONS\\s0\"\n.IX Subsection \"MODEL/NESTED EVENT LOOP INVOCATIONS AND EXIT CONDITIONS\"\nOften (especially in \\s-1GUI\\s0 toolkits) there are places where you have\n\\&\\fImodal\\fR interaction, which is most easily implemented by recursively\ninvoking \\f(CW\\*(C`ev_run\\*(C'\\fR.\n.PP\nThis brings the problem of exiting \\- a callback might want to finish the\nmain \\f(CW\\*(C`ev_run\\*(C'\\fR call, but not the nested one (e.g. user clicked \\*(L\"Quit\\*(R\", but\na modal \\*(L\"Are you sure?\\*(R\" dialog is still waiting), or just the nested one\nand not the main one (e.g. user clocked \\*(L\"Ok\\*(R\" in a modal dialog), or some\nother combination: In these cases, a simple \\f(CW\\*(C`ev_break\\*(C'\\fR will not work.\n.PP\nThe solution is to maintain \\*(L\"break this loop\\*(R\" variable for each \\f(CW\\*(C`ev_run\\*(C'\\fR\ninvocation, and use a loop around \\f(CW\\*(C`ev_run\\*(C'\\fR until the condition is\ntriggered, using \\f(CW\\*(C`EVRUN_ONCE\\*(C'\\fR:\n.PP\n.Vb 2\n\\&   // main loop\n\\&   int exit_main_loop = 0;\n\\&\n\\&   while (!exit_main_loop)\n\\&     ev_run (EV_DEFAULT_ EVRUN_ONCE);\n\\&\n\\&   // in a modal watcher\n\\&   int exit_nested_loop = 0;\n\\&\n\\&   while (!exit_nested_loop)\n\\&     ev_run (EV_A_ EVRUN_ONCE);\n.Ve\n.PP\nTo exit from any of these loops, just set the corresponding exit variable:\n.PP\n.Vb 2\n\\&   // exit modal loop\n\\&   exit_nested_loop = 1;\n\\&\n\\&   // exit main program, after modal loop is finished\n\\&   exit_main_loop = 1;\n\\&\n\\&   // exit both\n\\&   exit_main_loop = exit_nested_loop = 1;\n.Ve\n.SS \"\\s-1THREAD LOCKING EXAMPLE\\s0\"\n.IX Subsection \"THREAD LOCKING EXAMPLE\"\nHere is a fictitious example of how to run an event loop in a different\nthread from where callbacks are being invoked and watchers are\ncreated/added/removed.\n.PP\nFor a real-world example, see the \\f(CW\\*(C`EV::Loop::Async\\*(C'\\fR perl module,\nwhich uses exactly this technique (which is suited for many high-level\nlanguages).\n.PP\nThe example uses a pthread mutex to protect the loop data, a condition\nvariable to wait for callback invocations, an async watcher to notify the\nevent loop thread and an unspecified mechanism to wake up the main thread.\n.PP\nFirst, you need to associate some data with the event loop:\n.PP\n.Vb 6\n\\&   typedef struct {\n\\&     mutex_t lock; /* global loop lock */\n\\&     ev_async async_w;\n\\&     thread_t tid;\n\\&     cond_t invoke_cv;\n\\&   } userdata;\n\\&\n\\&   void prepare_loop (EV_P)\n\\&   {\n\\&      // for simplicity, we use a static userdata struct.\n\\&      static userdata u;\n\\&\n\\&      ev_async_init (&u\\->async_w, async_cb);\n\\&      ev_async_start (EV_A_ &u\\->async_w);\n\\&\n\\&      pthread_mutex_init (&u\\->lock, 0);\n\\&      pthread_cond_init (&u\\->invoke_cv, 0);\n\\&\n\\&      // now associate this with the loop\n\\&      ev_set_userdata (EV_A_ u);\n\\&      ev_set_invoke_pending_cb (EV_A_ l_invoke);\n\\&      ev_set_loop_release_cb (EV_A_ l_release, l_acquire);\n\\&\n\\&      // then create the thread running ev_run\n\\&      pthread_create (&u\\->tid, 0, l_run, EV_A);\n\\&   }\n.Ve\n.PP\nThe callback for the \\f(CW\\*(C`ev_async\\*(C'\\fR watcher does nothing: the watcher is used\nsolely to wake up the event loop so it takes notice of any new watchers\nthat might have been added:\n.PP\n.Vb 5\n\\&   static void\n\\&   async_cb (EV_P_ ev_async *w, int revents)\n\\&   {\n\\&      // just used for the side effects\n\\&   }\n.Ve\n.PP\nThe \\f(CW\\*(C`l_release\\*(C'\\fR and \\f(CW\\*(C`l_acquire\\*(C'\\fR callbacks simply unlock/lock the mutex\nprotecting the loop data, respectively.\n.PP\n.Vb 6\n\\&   static void\n\\&   l_release (EV_P)\n\\&   {\n\\&     userdata *u = ev_userdata (EV_A);\n\\&     pthread_mutex_unlock (&u\\->lock);\n\\&   }\n\\&\n\\&   static void\n\\&   l_acquire (EV_P)\n\\&   {\n\\&     userdata *u = ev_userdata (EV_A);\n\\&     pthread_mutex_lock (&u\\->lock);\n\\&   }\n.Ve\n.PP\nThe event loop thread first acquires the mutex, and then jumps straight\ninto \\f(CW\\*(C`ev_run\\*(C'\\fR:\n.PP\n.Vb 4\n\\&   void *\n\\&   l_run (void *thr_arg)\n\\&   {\n\\&     struct ev_loop *loop = (struct ev_loop *)thr_arg;\n\\&\n\\&     l_acquire (EV_A);\n\\&     pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);\n\\&     ev_run (EV_A_ 0);\n\\&     l_release (EV_A);\n\\&\n\\&     return 0;\n\\&   }\n.Ve\n.PP\nInstead of invoking all pending watchers, the \\f(CW\\*(C`l_invoke\\*(C'\\fR callback will\nsignal the main thread via some unspecified mechanism (signals? pipe\nwrites? \\f(CW\\*(C`Async::Interrupt\\*(C'\\fR?) and then waits until all pending watchers\nhave been called (in a while loop because a) spurious wakeups are possible\nand b) skipping inter-thread-communication when there are no pending\nwatchers is very beneficial):\n.PP\n.Vb 4\n\\&   static void\n\\&   l_invoke (EV_P)\n\\&   {\n\\&     userdata *u = ev_userdata (EV_A);\n\\&\n\\&     while (ev_pending_count (EV_A))\n\\&       {\n\\&         wake_up_other_thread_in_some_magic_or_not_so_magic_way ();\n\\&         pthread_cond_wait (&u\\->invoke_cv, &u\\->lock);\n\\&       }\n\\&   }\n.Ve\n.PP\nNow, whenever the main thread gets told to invoke pending watchers, it\nwill grab the lock, call \\f(CW\\*(C`ev_invoke_pending\\*(C'\\fR and then signal the loop\nthread to continue:\n.PP\n.Vb 4\n\\&   static void\n\\&   real_invoke_pending (EV_P)\n\\&   {\n\\&     userdata *u = ev_userdata (EV_A);\n\\&\n\\&     pthread_mutex_lock (&u\\->lock);\n\\&     ev_invoke_pending (EV_A);\n\\&     pthread_cond_signal (&u\\->invoke_cv);\n\\&     pthread_mutex_unlock (&u\\->lock);\n\\&   }\n.Ve\n.PP\nWhenever you want to start/stop a watcher or do other modifications to an\nevent loop, you will now have to lock:\n.PP\n.Vb 2\n\\&   ev_timer timeout_watcher;\n\\&   userdata *u = ev_userdata (EV_A);\n\\&\n\\&   ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);\n\\&\n\\&   pthread_mutex_lock (&u\\->lock);\n\\&   ev_timer_start (EV_A_ &timeout_watcher);\n\\&   ev_async_send (EV_A_ &u\\->async_w);\n\\&   pthread_mutex_unlock (&u\\->lock);\n.Ve\n.PP\nNote that sending the \\f(CW\\*(C`ev_async\\*(C'\\fR watcher is required because otherwise\nan event loop currently blocking in the kernel will have no knowledge\nabout the newly added timer. By waking up the loop it will pick up any new\nwatchers in the next event loop iteration.\n.SS \"\\s-1THREADS, COROUTINES, CONTINUATIONS, QUEUES... INSTEAD OF CALLBACKS\\s0\"\n.IX Subsection \"THREADS, COROUTINES, CONTINUATIONS, QUEUES... INSTEAD OF CALLBACKS\"\nWhile the overhead of a callback that e.g. schedules a thread is small, it\nis still an overhead. If you embed libev, and your main usage is with some\nkind of threads or coroutines, you might want to customise libev so that\ndoesn't need callbacks anymore.\n.PP\nImagine you have coroutines that you can switch to using a function\n\\&\\f(CW\\*(C`switch_to (coro)\\*(C'\\fR, that libev runs in a coroutine called \\f(CW\\*(C`libev_coro\\*(C'\\fR\nand that due to some magic, the currently active coroutine is stored in a\nglobal called \\f(CW\\*(C`current_coro\\*(C'\\fR. Then you can build your own \\*(L\"wait for libev\nevent\\*(R\" primitive by changing \\f(CW\\*(C`EV_CB_DECLARE\\*(C'\\fR and \\f(CW\\*(C`EV_CB_INVOKE\\*(C'\\fR (note\nthe differing \\f(CW\\*(C`;\\*(C'\\fR conventions):\n.PP\n.Vb 2\n\\&   #define EV_CB_DECLARE(type)   struct my_coro *cb;\n\\&   #define EV_CB_INVOKE(watcher) switch_to ((watcher)\\->cb)\n.Ve\n.PP\nThat means instead of having a C callback function, you store the\ncoroutine to switch to in each watcher, and instead of having libev call\nyour callback, you instead have it switch to that coroutine.\n.PP\nA coroutine might now wait for an event with a function called\n\\&\\f(CW\\*(C`wait_for_event\\*(C'\\fR. (the watcher needs to be started, as always, but it doesn't\nmatter when, or whether the watcher is active or not when this function is\ncalled):\n.PP\n.Vb 6\n\\&   void\n\\&   wait_for_event (ev_watcher *w)\n\\&   {\n\\&     ev_set_cb (w, current_coro);\n\\&     switch_to (libev_coro);\n\\&   }\n.Ve\n.PP\nThat basically suspends the coroutine inside \\f(CW\\*(C`wait_for_event\\*(C'\\fR and\ncontinues the libev coroutine, which, when appropriate, switches back to\nthis or any other coroutine.\n.PP\nYou can do similar tricks if you have, say, threads with an event queue \\-\ninstead of storing a coroutine, you store the queue object and instead of\nswitching to a coroutine, you push the watcher onto the queue and notify\nany waiters.\n.PP\nTo embed libev, see \\*(L\"\\s-1EMBEDDING\\*(R\"\\s0, but in short, it's easiest to create two\nfiles, \\fImy_ev.h\\fR and \\fImy_ev.c\\fR that include the respective libev files:\n.PP\n.Vb 4\n\\&   // my_ev.h\n\\&   #define EV_CB_DECLARE(type)   struct my_coro *cb;\n\\&   #define EV_CB_INVOKE(watcher) switch_to ((watcher)\\->cb)\n\\&   #include \"../libev/ev.h\"\n\\&\n\\&   // my_ev.c\n\\&   #define EV_H \"my_ev.h\"\n\\&   #include \"../libev/ev.c\"\n.Ve\n.PP\nAnd then use \\fImy_ev.h\\fR when you would normally use \\fIev.h\\fR, and compile\n\\&\\fImy_ev.c\\fR into your project. When properly specifying include paths, you\ncan even use \\fIev.h\\fR as header file name directly.\n.SH \"LIBEVENT EMULATION\"\n.IX Header \"LIBEVENT EMULATION\"\nLibev offers a compatibility emulation layer for libevent. It cannot\nemulate the internals of libevent, so here are some usage hints:\n.IP \"\\(bu\" 4\nOnly the libevent\\-1.4.1\\-beta \\s-1API\\s0 is being emulated.\n.Sp\nThis was the newest libevent version available when libev was implemented,\nand is still mostly unchanged in 2010.\n.IP \"\\(bu\" 4\nUse it by including <event.h>, as usual.\n.IP \"\\(bu\" 4\nThe following members are fully supported: ev_base, ev_callback,\nev_arg, ev_fd, ev_res, ev_events.\n.IP \"\\(bu\" 4\nAvoid using ev_flags and the EVLIST_*\\-macros, while it is\nmaintained by libev, it does not work exactly the same way as in libevent (consider\nit a private \\s-1API\\s0).\n.IP \"\\(bu\" 4\nPriorities are not currently supported. Initialising priorities\nwill fail and all watchers will have the same priority, even though there\nis an ev_pri field.\n.IP \"\\(bu\" 4\nIn libevent, the last base created gets the signals, in libev, the\nbase that registered the signal gets the signals.\n.IP \"\\(bu\" 4\nOther members are not supported.\n.IP \"\\(bu\" 4\nThe libev emulation is \\fInot\\fR \\s-1ABI\\s0 compatible to libevent, you need\nto use the libev header file and library.\n.SH \"\\*(C+ SUPPORT\"\n.IX Header \" SUPPORT\"\n.SS \"C \\s-1API\\s0\"\n.IX Subsection \"C API\"\nThe normal C \\s-1API\\s0 should work fine when used from \\*(C+: both ev.h and the\nlibev sources can be compiled as \\*(C+. Therefore, code that uses the C \\s-1API\\s0\nwill work fine.\n.PP\nProper exception specifications might have to be added to callbacks passed\nto libev: exceptions may be thrown only from watcher callbacks, all\nother callbacks (allocator, syserr, loop acquire/release and periodic\nreschedule callbacks) must not throw exceptions, and might need a \\f(CW\\*(C`throw\n()\\*(C'\\fR specification. If you have code that needs to be compiled as both C\nand \\*(C+ you can use the \\f(CW\\*(C`EV_THROW\\*(C'\\fR macro for this:\n.PP\n.Vb 6\n\\&   static void\n\\&   fatal_error (const char *msg) EV_THROW\n\\&   {\n\\&     perror (msg);\n\\&     abort ();\n\\&   }\n\\&\n\\&   ...\n\\&   ev_set_syserr_cb (fatal_error);\n.Ve\n.PP\nThe only \\s-1API\\s0 functions that can currently throw exceptions are \\f(CW\\*(C`ev_run\\*(C'\\fR,\n\\&\\f(CW\\*(C`ev_invoke\\*(C'\\fR, \\f(CW\\*(C`ev_invoke_pending\\*(C'\\fR and \\f(CW\\*(C`ev_loop_destroy\\*(C'\\fR (the latter\nbecause it runs cleanup watchers).\n.PP\nThrowing exceptions in watcher callbacks is only supported if libev itself\nis compiled with a \\*(C+ compiler or your C and \\*(C+ environments allow\nthrowing exceptions through C libraries (most do).\n.SS \"\\*(C+ \\s-1API\\s0\"\n.IX Subsection \" API\"\nLibev comes with some simplistic wrapper classes for \\*(C+ that mainly allow\nyou to use some convenience methods to start/stop watchers and also change\nthe callback model to a model using method callbacks on objects.\n.PP\nTo use it,\n.PP\n.Vb 1\n\\&   #include <ev++.h>\n.Ve\n.PP\nThis automatically includes \\fIev.h\\fR and puts all of its definitions (many\nof them macros) into the global namespace. All \\*(C+ specific things are\nput into the \\f(CW\\*(C`ev\\*(C'\\fR namespace. It should support all the same embedding\noptions as \\fIev.h\\fR, most notably \\f(CW\\*(C`EV_MULTIPLICITY\\*(C'\\fR.\n.PP\nCare has been taken to keep the overhead low. The only data member the \\*(C+\nclasses add (compared to plain C\\-style watchers) is the event loop pointer\nthat the watcher is associated with (or no additional members at all if\nyou disable \\f(CW\\*(C`EV_MULTIPLICITY\\*(C'\\fR when embedding libev).\n.PP\nCurrently, functions, static and non-static member functions and classes\nwith \\f(CW\\*(C`operator ()\\*(C'\\fR can be used as callbacks. Other types should be easy\nto add as long as they only need one additional pointer for context. If\nyou need support for other types of functors please contact the author\n(preferably after implementing it).\n.PP\nFor all this to work, your \\*(C+ compiler either has to use the same calling\nconventions as your C compiler (for static member functions), or you have\nto embed libev and compile libev itself as \\*(C+.\n.PP\nHere is a list of things available in the \\f(CW\\*(C`ev\\*(C'\\fR namespace:\n.ie n .IP \"\"\"ev::READ\"\", \"\"ev::WRITE\"\" etc.\" 4\n.el .IP \"\\f(CWev::READ\\fR, \\f(CWev::WRITE\\fR etc.\" 4\n.IX Item \"ev::READ, ev::WRITE etc.\"\nThese are just enum values with the same values as the \\f(CW\\*(C`EV_READ\\*(C'\\fR etc.\nmacros from \\fIev.h\\fR.\n.ie n .IP \"\"\"ev::tstamp\"\", \"\"ev::now\"\"\" 4\n.el .IP \"\\f(CWev::tstamp\\fR, \\f(CWev::now\\fR\" 4\n.IX Item \"ev::tstamp, ev::now\"\nAliases to the same types/functions as with the \\f(CW\\*(C`ev_\\*(C'\\fR prefix.\n.ie n .IP \"\"\"ev::io\"\", \"\"ev::timer\"\", \"\"ev::periodic\"\", \"\"ev::idle\"\", \"\"ev::sig\"\" etc.\" 4\n.el .IP \"\\f(CWev::io\\fR, \\f(CWev::timer\\fR, \\f(CWev::periodic\\fR, \\f(CWev::idle\\fR, \\f(CWev::sig\\fR etc.\" 4\n.IX Item \"ev::io, ev::timer, ev::periodic, ev::idle, ev::sig etc.\"\nFor each \\f(CW\\*(C`ev_TYPE\\*(C'\\fR watcher in \\fIev.h\\fR there is a corresponding class of\nthe same name in the \\f(CW\\*(C`ev\\*(C'\\fR namespace, with the exception of \\f(CW\\*(C`ev_signal\\*(C'\\fR\nwhich is called \\f(CW\\*(C`ev::sig\\*(C'\\fR to avoid clashes with the \\f(CW\\*(C`signal\\*(C'\\fR macro\ndefined by many implementations.\n.Sp\nAll of those classes have these methods:\n.RS 4\n.IP \"ev::TYPE::TYPE ()\" 4\n.IX Item \"ev::TYPE::TYPE ()\"\n.PD 0\n.IP \"ev::TYPE::TYPE (loop)\" 4\n.IX Item \"ev::TYPE::TYPE (loop)\"\n.IP \"ev::TYPE::~TYPE\" 4\n.IX Item \"ev::TYPE::~TYPE\"\n.PD\nThe constructor (optionally) takes an event loop to associate the watcher\nwith. If it is omitted, it will use \\f(CW\\*(C`EV_DEFAULT\\*(C'\\fR.\n.Sp\nThe constructor calls \\f(CW\\*(C`ev_init\\*(C'\\fR for you, which means you have to call the\n\\&\\f(CW\\*(C`set\\*(C'\\fR method before starting it.\n.Sp\nIt will not set a callback, however: You have to call the templated \\f(CW\\*(C`set\\*(C'\\fR\nmethod to set a callback before you can start the watcher.\n.Sp\n(The reason why you have to use a method is a limitation in \\*(C+ which does\nnot allow explicit template arguments for constructors).\n.Sp\nThe destructor automatically stops the watcher if it is active.\n.IP \"w\\->set<class, &class::method> (object *)\" 4\n.IX Item \"w->set<class, &class::method> (object *)\"\nThis method sets the callback method to call. The method has to have a\nsignature of \\f(CW\\*(C`void (*)(ev_TYPE &, int)\\*(C'\\fR, it receives the watcher as\nfirst argument and the \\f(CW\\*(C`revents\\*(C'\\fR as second. The object must be given as\nparameter and is stored in the \\f(CW\\*(C`data\\*(C'\\fR member of the watcher.\n.Sp\nThis method synthesizes efficient thunking code to call your method from\nthe C callback that libev requires. If your compiler can inline your\ncallback (i.e. it is visible to it at the place of the \\f(CW\\*(C`set\\*(C'\\fR call and\nyour compiler is good :), then the method will be fully inlined into the\nthunking function, making it as fast as a direct C callback.\n.Sp\nExample: simple class declaration and watcher initialisation\n.Sp\n.Vb 4\n\\&   struct myclass\n\\&   {\n\\&     void io_cb (ev::io &w, int revents) { }\n\\&   }\n\\&\n\\&   myclass obj;\n\\&   ev::io iow;\n\\&   iow.set <myclass, &myclass::io_cb> (&obj);\n.Ve\n.IP \"w\\->set (object *)\" 4\n.IX Item \"w->set (object *)\"\nThis is a variation of a method callback \\- leaving out the method to call\nwill default the method to \\f(CW\\*(C`operator ()\\*(C'\\fR, which makes it possible to use\nfunctor objects without having to manually specify the \\f(CW\\*(C`operator ()\\*(C'\\fR all\nthe time. Incidentally, you can then also leave out the template argument\nlist.\n.Sp\nThe \\f(CW\\*(C`operator ()\\*(C'\\fR method prototype must be \\f(CW\\*(C`void operator ()(watcher &w,\nint revents)\\*(C'\\fR.\n.Sp\nSee the method\\-\\f(CW\\*(C`set\\*(C'\\fR above for more details.\n.Sp\nExample: use a functor object as callback.\n.Sp\n.Vb 7\n\\&   struct myfunctor\n\\&   {\n\\&     void operator() (ev::io &w, int revents)\n\\&     {\n\\&       ...\n\\&     }\n\\&   }\n\\&\n\\&   myfunctor f;\n\\&\n\\&   ev::io w;\n\\&   w.set (&f);\n.Ve\n.IP \"w\\->set<function> (void *data = 0)\" 4\n.IX Item \"w->set<function> (void *data = 0)\"\nAlso sets a callback, but uses a static method or plain function as\ncallback. The optional \\f(CW\\*(C`data\\*(C'\\fR argument will be stored in the watcher's\n\\&\\f(CW\\*(C`data\\*(C'\\fR member and is free for you to use.\n.Sp\nThe prototype of the \\f(CW\\*(C`function\\*(C'\\fR must be \\f(CW\\*(C`void (*)(ev::TYPE &w, int)\\*(C'\\fR.\n.Sp\nSee the method\\-\\f(CW\\*(C`set\\*(C'\\fR above for more details.\n.Sp\nExample: Use a plain function as callback.\n.Sp\n.Vb 2\n\\&   static void io_cb (ev::io &w, int revents) { }\n\\&   iow.set <io_cb> ();\n.Ve\n.IP \"w\\->set (loop)\" 4\n.IX Item \"w->set (loop)\"\nAssociates a different \\f(CW\\*(C`struct ev_loop\\*(C'\\fR with this watcher. You can only\ndo this when the watcher is inactive (and not pending either).\n.IP \"w\\->set ([arguments])\" 4\n.IX Item \"w->set ([arguments])\"\nBasically the same as \\f(CW\\*(C`ev_TYPE_set\\*(C'\\fR (except for \\f(CW\\*(C`ev::embed\\*(C'\\fR watchers>),\nwith the same arguments. Either this method or a suitable start method\nmust be called at least once. Unlike the C counterpart, an active watcher\ngets automatically stopped and restarted when reconfiguring it with this\nmethod.\n.Sp\nFor \\f(CW\\*(C`ev::embed\\*(C'\\fR watchers this method is called \\f(CW\\*(C`set_embed\\*(C'\\fR, to avoid\nclashing with the \\f(CW\\*(C`set (loop)\\*(C'\\fR method.\n.IP \"w\\->start ()\" 4\n.IX Item \"w->start ()\"\nStarts the watcher. Note that there is no \\f(CW\\*(C`loop\\*(C'\\fR argument, as the\nconstructor already stores the event loop.\n.IP \"w\\->start ([arguments])\" 4\n.IX Item \"w->start ([arguments])\"\nInstead of calling \\f(CW\\*(C`set\\*(C'\\fR and \\f(CW\\*(C`start\\*(C'\\fR methods separately, it is often\nconvenient to wrap them in one call. Uses the same type of arguments as\nthe configure \\f(CW\\*(C`set\\*(C'\\fR method of the watcher.\n.IP \"w\\->stop ()\" 4\n.IX Item \"w->stop ()\"\nStops the watcher if it is active. Again, no \\f(CW\\*(C`loop\\*(C'\\fR argument.\n.ie n .IP \"w\\->again () (\"\"ev::timer\"\", \"\"ev::periodic\"\" only)\" 4\n.el .IP \"w\\->again () (\\f(CWev::timer\\fR, \\f(CWev::periodic\\fR only)\" 4\n.IX Item \"w->again () (ev::timer, ev::periodic only)\"\nFor \\f(CW\\*(C`ev::timer\\*(C'\\fR and \\f(CW\\*(C`ev::periodic\\*(C'\\fR, this invokes the corresponding\n\\&\\f(CW\\*(C`ev_TYPE_again\\*(C'\\fR function.\n.ie n .IP \"w\\->sweep () (\"\"ev::embed\"\" only)\" 4\n.el .IP \"w\\->sweep () (\\f(CWev::embed\\fR only)\" 4\n.IX Item \"w->sweep () (ev::embed only)\"\nInvokes \\f(CW\\*(C`ev_embed_sweep\\*(C'\\fR.\n.ie n .IP \"w\\->update () (\"\"ev::stat\"\" only)\" 4\n.el .IP \"w\\->update () (\\f(CWev::stat\\fR only)\" 4\n.IX Item \"w->update () (ev::stat only)\"\nInvokes \\f(CW\\*(C`ev_stat_stat\\*(C'\\fR.\n.RE\n.RS 4\n.RE\n.PP\nExample: Define a class with two I/O and idle watchers, start the I/O\nwatchers in the constructor.\n.PP\n.Vb 5\n\\&   class myclass\n\\&   {\n\\&     ev::io   io  ; void io_cb   (ev::io   &w, int revents);\n\\&     ev::io   io2 ; void io2_cb  (ev::io   &w, int revents);\n\\&     ev::idle idle; void idle_cb (ev::idle &w, int revents);\n\\&\n\\&     myclass (int fd)\n\\&     {\n\\&       io  .set <myclass, &myclass::io_cb  > (this);\n\\&       io2 .set <myclass, &myclass::io2_cb > (this);\n\\&       idle.set <myclass, &myclass::idle_cb> (this);\n\\&\n\\&       io.set (fd, ev::WRITE); // configure the watcher\n\\&       io.start ();            // start it whenever convenient\n\\&\n\\&       io2.start (fd, ev::READ); // set + start in one call\n\\&     }\n\\&   };\n.Ve\n.SH \"OTHER LANGUAGE BINDINGS\"\n.IX Header \"OTHER LANGUAGE BINDINGS\"\nLibev does not offer other language bindings itself, but bindings for a\nnumber of languages exist in the form of third-party packages. If you know\nany interesting language binding in addition to the ones listed here, drop\nme a note.\n.IP \"Perl\" 4\n.IX Item \"Perl\"\nThe \\s-1EV\\s0 module implements the full libev \\s-1API\\s0 and is actually used to test\nlibev. \\s-1EV\\s0 is developed together with libev. Apart from the \\s-1EV\\s0 core module,\nthere are additional modules that implement libev-compatible interfaces\nto \\f(CW\\*(C`libadns\\*(C'\\fR (\\f(CW\\*(C`EV::ADNS\\*(C'\\fR, but \\f(CW\\*(C`AnyEvent::DNS\\*(C'\\fR is preferred nowadays),\n\\&\\f(CW\\*(C`Net::SNMP\\*(C'\\fR (\\f(CW\\*(C`Net::SNMP::EV\\*(C'\\fR) and the \\f(CW\\*(C`libglib\\*(C'\\fR event core (\\f(CW\\*(C`Glib::EV\\*(C'\\fR\nand \\f(CW\\*(C`EV::Glib\\*(C'\\fR).\n.Sp\nIt can be found and installed via \\s-1CPAN,\\s0 its homepage is at\n<http://software.schmorp.de/pkg/EV>.\n.IP \"Python\" 4\n.IX Item \"Python\"\nPython bindings can be found at <http://code.google.com/p/pyev/>. It\nseems to be quite complete and well-documented.\n.IP \"Ruby\" 4\n.IX Item \"Ruby\"\nTony Arcieri has written a ruby extension that offers access to a subset\nof the libev \\s-1API\\s0 and adds file handle abstractions, asynchronous \\s-1DNS\\s0 and\nmore on top of it. It can be found via gem servers. Its homepage is at\n<http://rev.rubyforge.org/>.\n.Sp\nRoger Pack reports that using the link order \\f(CW\\*(C`\\-lws2_32 \\-lmsvcrt\\-ruby\\-190\\*(C'\\fR\nmakes rev work even on mingw.\n.IP \"Haskell\" 4\n.IX Item \"Haskell\"\nA haskell binding to libev is available at\n<http://hackage.haskell.org/cgi\\-bin/hackage\\-scripts/package/hlibev>.\n.IP \"D\" 4\n.IX Item \"D\"\nLeandro Lucarella has written a D language binding (\\fIev.d\\fR) for libev, to\nbe found at <http://www.llucax.com.ar/proj/ev.d/index.html>.\n.IP \"Ocaml\" 4\n.IX Item \"Ocaml\"\nErkki Seppala has written Ocaml bindings for libev, to be found at\n<http://modeemi.cs.tut.fi/~flux/software/ocaml\\-ev/>.\n.IP \"Lua\" 4\n.IX Item \"Lua\"\nBrian Maher has written a partial interface to libev for lua (at the\ntime of this writing, only \\f(CW\\*(C`ev_io\\*(C'\\fR and \\f(CW\\*(C`ev_timer\\*(C'\\fR), to be found at\n<http://github.com/brimworks/lua\\-ev>.\n.IP \"Javascript\" 4\n.IX Item \"Javascript\"\nNode.js (<http://nodejs.org>) uses libev as the underlying event library.\n.IP \"Others\" 4\n.IX Item \"Others\"\nThere are others, and I stopped counting.\n.SH \"MACRO MAGIC\"\n.IX Header \"MACRO MAGIC\"\nLibev can be compiled with a variety of options, the most fundamental\nof which is \\f(CW\\*(C`EV_MULTIPLICITY\\*(C'\\fR. This option determines whether (most)\nfunctions and callbacks have an initial \\f(CW\\*(C`struct ev_loop *\\*(C'\\fR argument.\n.PP\nTo make it easier to write programs that cope with either variant, the\nfollowing macros are defined:\n.ie n .IP \"\"\"EV_A\"\", \"\"EV_A_\"\"\" 4\n.el .IP \"\\f(CWEV_A\\fR, \\f(CWEV_A_\\fR\" 4\n.IX Item \"EV_A, EV_A_\"\nThis provides the loop \\fIargument\\fR for functions, if one is required (\\*(L\"ev\nloop argument\\*(R\"). The \\f(CW\\*(C`EV_A\\*(C'\\fR form is used when this is the sole argument,\n\\&\\f(CW\\*(C`EV_A_\\*(C'\\fR is used when other arguments are following. Example:\n.Sp\n.Vb 3\n\\&   ev_unref (EV_A);\n\\&   ev_timer_add (EV_A_ watcher);\n\\&   ev_run (EV_A_ 0);\n.Ve\n.Sp\nIt assumes the variable \\f(CW\\*(C`loop\\*(C'\\fR of type \\f(CW\\*(C`struct ev_loop *\\*(C'\\fR is in scope,\nwhich is often provided by the following macro.\n.ie n .IP \"\"\"EV_P\"\", \"\"EV_P_\"\"\" 4\n.el .IP \"\\f(CWEV_P\\fR, \\f(CWEV_P_\\fR\" 4\n.IX Item \"EV_P, EV_P_\"\nThis provides the loop \\fIparameter\\fR for functions, if one is required (\\*(L\"ev\nloop parameter\\*(R\"). The \\f(CW\\*(C`EV_P\\*(C'\\fR form is used when this is the sole parameter,\n\\&\\f(CW\\*(C`EV_P_\\*(C'\\fR is used when other parameters are following. Example:\n.Sp\n.Vb 2\n\\&   // this is how ev_unref is being declared\n\\&   static void ev_unref (EV_P);\n\\&\n\\&   // this is how you can declare your typical callback\n\\&   static void cb (EV_P_ ev_timer *w, int revents)\n.Ve\n.Sp\nIt declares a parameter \\f(CW\\*(C`loop\\*(C'\\fR of type \\f(CW\\*(C`struct ev_loop *\\*(C'\\fR, quite\nsuitable for use with \\f(CW\\*(C`EV_A\\*(C'\\fR.\n.ie n .IP \"\"\"EV_DEFAULT\"\", \"\"EV_DEFAULT_\"\"\" 4\n.el .IP \"\\f(CWEV_DEFAULT\\fR, \\f(CWEV_DEFAULT_\\fR\" 4\n.IX Item \"EV_DEFAULT, EV_DEFAULT_\"\nSimilar to the other two macros, this gives you the value of the default\nloop, if multiple loops are supported (\\*(L\"ev loop default\\*(R\"). The default loop\nwill be initialised if it isn't already initialised.\n.Sp\nFor non-multiplicity builds, these macros do nothing, so you always have\nto initialise the loop somewhere.\n.ie n .IP \"\"\"EV_DEFAULT_UC\"\", \"\"EV_DEFAULT_UC_\"\"\" 4\n.el .IP \"\\f(CWEV_DEFAULT_UC\\fR, \\f(CWEV_DEFAULT_UC_\\fR\" 4\n.IX Item \"EV_DEFAULT_UC, EV_DEFAULT_UC_\"\nUsage identical to \\f(CW\\*(C`EV_DEFAULT\\*(C'\\fR and \\f(CW\\*(C`EV_DEFAULT_\\*(C'\\fR, but requires that the\ndefault loop has been initialised (\\f(CW\\*(C`UC\\*(C'\\fR == unchecked). Their behaviour\nis undefined when the default loop has not been initialised by a previous\nexecution of \\f(CW\\*(C`EV_DEFAULT\\*(C'\\fR, \\f(CW\\*(C`EV_DEFAULT_\\*(C'\\fR or \\f(CW\\*(C`ev_default_init (...)\\*(C'\\fR.\n.Sp\nIt is often prudent to use \\f(CW\\*(C`EV_DEFAULT\\*(C'\\fR when initialising the first\nwatcher in a function but use \\f(CW\\*(C`EV_DEFAULT_UC\\*(C'\\fR afterwards.\n.PP\nExample: Declare and initialise a check watcher, utilising the above\nmacros so it will work regardless of whether multiple loops are supported\nor not.\n.PP\n.Vb 5\n\\&   static void\n\\&   check_cb (EV_P_ ev_timer *w, int revents)\n\\&   {\n\\&     ev_check_stop (EV_A_ w);\n\\&   }\n\\&\n\\&   ev_check check;\n\\&   ev_check_init (&check, check_cb);\n\\&   ev_check_start (EV_DEFAULT_ &check);\n\\&   ev_run (EV_DEFAULT_ 0);\n.Ve\n.SH \"EMBEDDING\"\n.IX Header \"EMBEDDING\"\nLibev can (and often is) directly embedded into host\napplications. Examples of applications that embed it include the Deliantra\nGame Server, the \\s-1EV\\s0 perl module, the \\s-1GNU\\s0 Virtual Private Ethernet (gvpe)\nand rxvt-unicode.\n.PP\nThe goal is to enable you to just copy the necessary files into your\nsource directory without having to change even a single line in them, so\nyou can easily upgrade by simply copying (or having a checked-out copy of\nlibev somewhere in your source tree).\n.SS \"\\s-1FILESETS\\s0\"\n.IX Subsection \"FILESETS\"\nDepending on what features you need you need to include one or more sets of files\nin your application.\n.PP\n\\fI\\s-1CORE EVENT LOOP\\s0\\fR\n.IX Subsection \"CORE EVENT LOOP\"\n.PP\nTo include only the libev core (all the \\f(CW\\*(C`ev_*\\*(C'\\fR functions), with manual\nconfiguration (no autoconf):\n.PP\n.Vb 2\n\\&   #define EV_STANDALONE 1\n\\&   #include \"ev.c\"\n.Ve\n.PP\nThis will automatically include \\fIev.h\\fR, too, and should be done in a\nsingle C source file only to provide the function implementations. To use\nit, do the same for \\fIev.h\\fR in all files wishing to use this \\s-1API \\s0(best\ndone by writing a wrapper around \\fIev.h\\fR that you can include instead and\nwhere you can put other configuration options):\n.PP\n.Vb 2\n\\&   #define EV_STANDALONE 1\n\\&   #include \"ev.h\"\n.Ve\n.PP\nBoth header files and implementation files can be compiled with a \\*(C+\ncompiler (at least, that's a stated goal, and breakage will be treated\nas a bug).\n.PP\nYou need the following files in your source tree, or in a directory\nin your include path (e.g. in libev/ when using \\-Ilibev):\n.PP\n.Vb 4\n\\&   ev.h\n\\&   ev.c\n\\&   ev_vars.h\n\\&   ev_wrap.h\n\\&\n\\&   ev_win32.c      required on win32 platforms only\n\\&\n\\&   ev_select.c     only when select backend is enabled\n\\&   ev_poll.c       only when poll backend is enabled\n\\&   ev_epoll.c      only when the epoll backend is enabled\n\\&   ev_kqueue.c     only when the kqueue backend is enabled\n\\&   ev_port.c       only when the solaris port backend is enabled\n.Ve\n.PP\n\\&\\fIev.c\\fR includes the backend files directly when enabled, so you only need\nto compile this single file.\n.PP\n\\fI\\s-1LIBEVENT COMPATIBILITY API\\s0\\fR\n.IX Subsection \"LIBEVENT COMPATIBILITY API\"\n.PP\nTo include the libevent compatibility \\s-1API,\\s0 also include:\n.PP\n.Vb 1\n\\&   #include \"event.c\"\n.Ve\n.PP\nin the file including \\fIev.c\\fR, and:\n.PP\n.Vb 1\n\\&   #include \"event.h\"\n.Ve\n.PP\nin the files that want to use the libevent \\s-1API.\\s0 This also includes \\fIev.h\\fR.\n.PP\nYou need the following additional files for this:\n.PP\n.Vb 2\n\\&   event.h\n\\&   event.c\n.Ve\n.PP\n\\fI\\s-1AUTOCONF SUPPORT\\s0\\fR\n.IX Subsection \"AUTOCONF SUPPORT\"\n.PP\nInstead of using \\f(CW\\*(C`EV_STANDALONE=1\\*(C'\\fR and providing your configuration in\nwhatever way you want, you can also \\f(CW\\*(C`m4_include([libev.m4])\\*(C'\\fR in your\n\\&\\fIconfigure.ac\\fR and leave \\f(CW\\*(C`EV_STANDALONE\\*(C'\\fR undefined. \\fIev.c\\fR will then\ninclude \\fIconfig.h\\fR and configure itself accordingly.\n.PP\nFor this of course you need the m4 file:\n.PP\n.Vb 1\n\\&   libev.m4\n.Ve\n.SS \"\\s-1PREPROCESSOR SYMBOLS/MACROS\\s0\"\n.IX Subsection \"PREPROCESSOR SYMBOLS/MACROS\"\nLibev can be configured via a variety of preprocessor symbols you have to\ndefine before including (or compiling) any of its files. The default in\nthe absence of autoconf is documented for every option.\n.PP\nSymbols marked with \\*(L\"(h)\\*(R\" do not change the \\s-1ABI,\\s0 and can have different\nvalues when compiling libev vs. including \\fIev.h\\fR, so it is permissible\nto redefine them before including \\fIev.h\\fR without breaking compatibility\nto a compiled library. All other symbols change the \\s-1ABI,\\s0 which means all\nusers of libev and the libev code itself must be compiled with compatible\nsettings.\n.IP \"\\s-1EV_COMPAT3 \\s0(h)\" 4\n.IX Item \"EV_COMPAT3 (h)\"\nBackwards compatibility is a major concern for libev. This is why this\nrelease of libev comes with wrappers for the functions and symbols that\nhave been renamed between libev version 3 and 4.\n.Sp\nYou can disable these wrappers (to test compatibility with future\nversions) by defining \\f(CW\\*(C`EV_COMPAT3\\*(C'\\fR to \\f(CW0\\fR when compiling your\nsources. This has the additional advantage that you can drop the \\f(CW\\*(C`struct\\*(C'\\fR\nfrom \\f(CW\\*(C`struct ev_loop\\*(C'\\fR declarations, as libev will provide an \\f(CW\\*(C`ev_loop\\*(C'\\fR\ntypedef in that case.\n.Sp\nIn some future version, the default for \\f(CW\\*(C`EV_COMPAT3\\*(C'\\fR will become \\f(CW0\\fR,\nand in some even more future version the compatibility code will be\nremoved completely.\n.IP \"\\s-1EV_STANDALONE \\s0(h)\" 4\n.IX Item \"EV_STANDALONE (h)\"\nMust always be \\f(CW1\\fR if you do not use autoconf configuration, which\nkeeps libev from including \\fIconfig.h\\fR, and it also defines dummy\nimplementations for some libevent functions (such as logging, which is not\nsupported). It will also not define any of the structs usually found in\n\\&\\fIevent.h\\fR that are not directly supported by the libev core alone.\n.Sp\nIn standalone mode, libev will still try to automatically deduce the\nconfiguration, but has to be more conservative.\n.IP \"\\s-1EV_USE_FLOOR\\s0\" 4\n.IX Item \"EV_USE_FLOOR\"\nIf defined to be \\f(CW1\\fR, libev will use the \\f(CW\\*(C`floor ()\\*(C'\\fR function for its\nperiodic reschedule calculations, otherwise libev will fall back on a\nportable (slower) implementation. If you enable this, you usually have to\nlink against libm or something equivalent. Enabling this when the \\f(CW\\*(C`floor\\*(C'\\fR\nfunction is not available will fail, so the safe default is to not enable\nthis.\n.IP \"\\s-1EV_USE_MONOTONIC\\s0\" 4\n.IX Item \"EV_USE_MONOTONIC\"\nIf defined to be \\f(CW1\\fR, libev will try to detect the availability of the\nmonotonic clock option at both compile time and runtime. Otherwise no\nuse of the monotonic clock option will be attempted. If you enable this,\nyou usually have to link against librt or something similar. Enabling it\nwhen the functionality isn't available is safe, though, although you have\nto make sure you link against any libraries where the \\f(CW\\*(C`clock_gettime\\*(C'\\fR\nfunction is hiding in (often \\fI\\-lrt\\fR). See also \\f(CW\\*(C`EV_USE_CLOCK_SYSCALL\\*(C'\\fR.\n.IP \"\\s-1EV_USE_REALTIME\\s0\" 4\n.IX Item \"EV_USE_REALTIME\"\nIf defined to be \\f(CW1\\fR, libev will try to detect the availability of the\nreal-time clock option at compile time (and assume its availability\nat runtime if successful). Otherwise no use of the real-time clock\noption will be attempted. This effectively replaces \\f(CW\\*(C`gettimeofday\\*(C'\\fR\nby \\f(CW\\*(C`clock_get (CLOCK_REALTIME, ...)\\*(C'\\fR and will not normally affect\ncorrectness. See the note about libraries in the description of\n\\&\\f(CW\\*(C`EV_USE_MONOTONIC\\*(C'\\fR, though. Defaults to the opposite value of\n\\&\\f(CW\\*(C`EV_USE_CLOCK_SYSCALL\\*(C'\\fR.\n.IP \"\\s-1EV_USE_CLOCK_SYSCALL\\s0\" 4\n.IX Item \"EV_USE_CLOCK_SYSCALL\"\nIf defined to be \\f(CW1\\fR, libev will try to use a direct syscall instead\nof calling the system-provided \\f(CW\\*(C`clock_gettime\\*(C'\\fR function. This option\nexists because on GNU/Linux, \\f(CW\\*(C`clock_gettime\\*(C'\\fR is in \\f(CW\\*(C`librt\\*(C'\\fR, but \\f(CW\\*(C`librt\\*(C'\\fR\nunconditionally pulls in \\f(CW\\*(C`libpthread\\*(C'\\fR, slowing down single-threaded\nprograms needlessly. Using a direct syscall is slightly slower (in\ntheory), because no optimised vdso implementation can be used, but avoids\nthe pthread dependency. Defaults to \\f(CW1\\fR on GNU/Linux with glibc 2.x or\nhigher, as it simplifies linking (no need for \\f(CW\\*(C`\\-lrt\\*(C'\\fR).\n.IP \"\\s-1EV_USE_NANOSLEEP\\s0\" 4\n.IX Item \"EV_USE_NANOSLEEP\"\nIf defined to be \\f(CW1\\fR, libev will assume that \\f(CW\\*(C`nanosleep ()\\*(C'\\fR is available\nand will use it for delays. Otherwise it will use \\f(CW\\*(C`select ()\\*(C'\\fR.\n.IP \"\\s-1EV_USE_EVENTFD\\s0\" 4\n.IX Item \"EV_USE_EVENTFD\"\nIf defined to be \\f(CW1\\fR, then libev will assume that \\f(CW\\*(C`eventfd ()\\*(C'\\fR is\navailable and will probe for kernel support at runtime. This will improve\n\\&\\f(CW\\*(C`ev_signal\\*(C'\\fR and \\f(CW\\*(C`ev_async\\*(C'\\fR performance and reduce resource consumption.\nIf undefined, it will be enabled if the headers indicate GNU/Linux + Glibc\n2.7 or newer, otherwise disabled.\n.IP \"\\s-1EV_USE_SELECT\\s0\" 4\n.IX Item \"EV_USE_SELECT\"\nIf undefined or defined to be \\f(CW1\\fR, libev will compile in support for the\n\\&\\f(CW\\*(C`select\\*(C'\\fR(2) backend. No attempt at auto-detection will be done: if no\nother method takes over, select will be it. Otherwise the select backend\nwill not be compiled in.\n.IP \"\\s-1EV_SELECT_USE_FD_SET\\s0\" 4\n.IX Item \"EV_SELECT_USE_FD_SET\"\nIf defined to \\f(CW1\\fR, then the select backend will use the system \\f(CW\\*(C`fd_set\\*(C'\\fR\nstructure. This is useful if libev doesn't compile due to a missing\n\\&\\f(CW\\*(C`NFDBITS\\*(C'\\fR or \\f(CW\\*(C`fd_mask\\*(C'\\fR definition or it mis-guesses the bitset layout\non exotic systems. This usually limits the range of file descriptors to\nsome low limit such as 1024 or might have other limitations (winsocket\nonly allows 64 sockets). The \\f(CW\\*(C`FD_SETSIZE\\*(C'\\fR macro, set before compilation,\nconfigures the maximum size of the \\f(CW\\*(C`fd_set\\*(C'\\fR.\n.IP \"\\s-1EV_SELECT_IS_WINSOCKET\\s0\" 4\n.IX Item \"EV_SELECT_IS_WINSOCKET\"\nWhen defined to \\f(CW1\\fR, the select backend will assume that\nselect/socket/connect etc. don't understand file descriptors but\nwants osf handles on win32 (this is the case when the select to\nbe used is the winsock select). This means that it will call\n\\&\\f(CW\\*(C`_get_osfhandle\\*(C'\\fR on the fd to convert it to an \\s-1OS\\s0 handle. Otherwise,\nit is assumed that all these functions actually work on fds, even\non win32. Should not be defined on non\\-win32 platforms.\n.IP \"\\s-1EV_FD_TO_WIN32_HANDLE\\s0(fd)\" 4\n.IX Item \"EV_FD_TO_WIN32_HANDLE(fd)\"\nIf \\f(CW\\*(C`EV_SELECT_IS_WINSOCKET\\*(C'\\fR is enabled, then libev needs a way to map\nfile descriptors to socket handles. When not defining this symbol (the\ndefault), then libev will call \\f(CW\\*(C`_get_osfhandle\\*(C'\\fR, which is usually\ncorrect. In some cases, programs use their own file descriptor management,\nin which case they can provide this function to map fds to socket handles.\n.IP \"\\s-1EV_WIN32_HANDLE_TO_FD\\s0(handle)\" 4\n.IX Item \"EV_WIN32_HANDLE_TO_FD(handle)\"\nIf \\f(CW\\*(C`EV_SELECT_IS_WINSOCKET\\*(C'\\fR then libev maps handles to file descriptors\nusing the standard \\f(CW\\*(C`_open_osfhandle\\*(C'\\fR function. For programs implementing\ntheir own fd to handle mapping, overwriting this function makes it easier\nto do so. This can be done by defining this macro to an appropriate value.\n.IP \"\\s-1EV_WIN32_CLOSE_FD\\s0(fd)\" 4\n.IX Item \"EV_WIN32_CLOSE_FD(fd)\"\nIf programs implement their own fd to handle mapping on win32, then this\nmacro can be used to override the \\f(CW\\*(C`close\\*(C'\\fR function, useful to unregister\nfile descriptors again. Note that the replacement function has to close\nthe underlying \\s-1OS\\s0 handle.\n.IP \"\\s-1EV_USE_WSASOCKET\\s0\" 4\n.IX Item \"EV_USE_WSASOCKET\"\nIf defined to be \\f(CW1\\fR, libev will use \\f(CW\\*(C`WSASocket\\*(C'\\fR to create its internal\ncommunication socket, which works better in some environments. Otherwise,\nthe normal \\f(CW\\*(C`socket\\*(C'\\fR function will be used, which works better in other\nenvironments.\n.IP \"\\s-1EV_USE_POLL\\s0\" 4\n.IX Item \"EV_USE_POLL\"\nIf defined to be \\f(CW1\\fR, libev will compile in support for the \\f(CW\\*(C`poll\\*(C'\\fR(2)\nbackend. Otherwise it will be enabled on non\\-win32 platforms. It\ntakes precedence over select.\n.IP \"\\s-1EV_USE_EPOLL\\s0\" 4\n.IX Item \"EV_USE_EPOLL\"\nIf defined to be \\f(CW1\\fR, libev will compile in support for the Linux\n\\&\\f(CW\\*(C`epoll\\*(C'\\fR(7) backend. Its availability will be detected at runtime,\notherwise another method will be used as fallback. This is the preferred\nbackend for GNU/Linux systems. If undefined, it will be enabled if the\nheaders indicate GNU/Linux + Glibc 2.4 or newer, otherwise disabled.\n.IP \"\\s-1EV_USE_KQUEUE\\s0\" 4\n.IX Item \"EV_USE_KQUEUE\"\nIf defined to be \\f(CW1\\fR, libev will compile in support for the \\s-1BSD\\s0 style\n\\&\\f(CW\\*(C`kqueue\\*(C'\\fR(2) backend. Its actual availability will be detected at runtime,\notherwise another method will be used as fallback. This is the preferred\nbackend for \\s-1BSD\\s0 and BSD-like systems, although on most BSDs kqueue only\nsupports some types of fds correctly (the only platform we found that\nsupports ptys for example was NetBSD), so kqueue might be compiled in, but\nnot be used unless explicitly requested. The best way to use it is to find\nout whether kqueue supports your type of fd properly and use an embedded\nkqueue loop.\n.IP \"\\s-1EV_USE_PORT\\s0\" 4\n.IX Item \"EV_USE_PORT\"\nIf defined to be \\f(CW1\\fR, libev will compile in support for the Solaris\n10 port style backend. Its availability will be detected at runtime,\notherwise another method will be used as fallback. This is the preferred\nbackend for Solaris 10 systems.\n.IP \"\\s-1EV_USE_DEVPOLL\\s0\" 4\n.IX Item \"EV_USE_DEVPOLL\"\nReserved for future expansion, works like the \\s-1USE\\s0 symbols above.\n.IP \"\\s-1EV_USE_INOTIFY\\s0\" 4\n.IX Item \"EV_USE_INOTIFY\"\nIf defined to be \\f(CW1\\fR, libev will compile in support for the Linux inotify\ninterface to speed up \\f(CW\\*(C`ev_stat\\*(C'\\fR watchers. Its actual availability will\nbe detected at runtime. If undefined, it will be enabled if the headers\nindicate GNU/Linux + Glibc 2.4 or newer, otherwise disabled.\n.IP \"\\s-1EV_NO_SMP\\s0\" 4\n.IX Item \"EV_NO_SMP\"\nIf defined to be \\f(CW1\\fR, libev will assume that memory is always coherent\nbetween threads, that is, threads can be used, but threads never run on\ndifferent cpus (or different cpu cores). This reduces dependencies\nand makes libev faster.\n.IP \"\\s-1EV_NO_THREADS\\s0\" 4\n.IX Item \"EV_NO_THREADS\"\nIf defined to be \\f(CW1\\fR, libev will assume that it will never be called from\ndifferent threads (that includes signal handlers), which is a stronger\nassumption than \\f(CW\\*(C`EV_NO_SMP\\*(C'\\fR, above. This reduces dependencies and makes\nlibev faster.\n.IP \"\\s-1EV_ATOMIC_T\\s0\" 4\n.IX Item \"EV_ATOMIC_T\"\nLibev requires an integer type (suitable for storing \\f(CW0\\fR or \\f(CW1\\fR) whose\naccess is atomic with respect to other threads or signal contexts. No\nsuch type is easily found in the C language, so you can provide your own\ntype that you know is safe for your purposes. It is used both for signal\nhandler \\*(L\"locking\\*(R\" as well as for signal and thread safety in \\f(CW\\*(C`ev_async\\*(C'\\fR\nwatchers.\n.Sp\nIn the absence of this define, libev will use \\f(CW\\*(C`sig_atomic_t volatile\\*(C'\\fR\n(from \\fIsignal.h\\fR), which is usually good enough on most platforms.\n.IP \"\\s-1EV_H \\s0(h)\" 4\n.IX Item \"EV_H (h)\"\nThe name of the \\fIev.h\\fR header file used to include it. The default if\nundefined is \\f(CW\"ev.h\"\\fR in \\fIevent.h\\fR, \\fIev.c\\fR and \\fIev++.h\\fR. This can be\nused to virtually rename the \\fIev.h\\fR header file in case of conflicts.\n.IP \"\\s-1EV_CONFIG_H \\s0(h)\" 4\n.IX Item \"EV_CONFIG_H (h)\"\nIf \\f(CW\\*(C`EV_STANDALONE\\*(C'\\fR isn't \\f(CW1\\fR, this variable can be used to override\n\\&\\fIev.c\\fR's idea of where to find the \\fIconfig.h\\fR file, similarly to\n\\&\\f(CW\\*(C`EV_H\\*(C'\\fR, above.\n.IP \"\\s-1EV_EVENT_H \\s0(h)\" 4\n.IX Item \"EV_EVENT_H (h)\"\nSimilarly to \\f(CW\\*(C`EV_H\\*(C'\\fR, this macro can be used to override \\fIevent.c\\fR's idea\nof how the \\fIevent.h\\fR header can be found, the default is \\f(CW\"event.h\"\\fR.\n.IP \"\\s-1EV_PROTOTYPES \\s0(h)\" 4\n.IX Item \"EV_PROTOTYPES (h)\"\nIf defined to be \\f(CW0\\fR, then \\fIev.h\\fR will not define any function\nprototypes, but still define all the structs and other symbols. This is\noccasionally useful if you want to provide your own wrapper functions\naround libev functions.\n.IP \"\\s-1EV_MULTIPLICITY\\s0\" 4\n.IX Item \"EV_MULTIPLICITY\"\nIf undefined or defined to \\f(CW1\\fR, then all event-loop-specific functions\nwill have the \\f(CW\\*(C`struct ev_loop *\\*(C'\\fR as first argument, and you can create\nadditional independent event loops. Otherwise there will be no support\nfor multiple event loops and there is no first event loop pointer\nargument. Instead, all functions act on the single default loop.\n.Sp\nNote that \\f(CW\\*(C`EV_DEFAULT\\*(C'\\fR and \\f(CW\\*(C`EV_DEFAULT_\\*(C'\\fR will no longer provide a\ndefault loop when multiplicity is switched off \\- you always have to\ninitialise the loop manually in this case.\n.IP \"\\s-1EV_MINPRI\\s0\" 4\n.IX Item \"EV_MINPRI\"\n.PD 0\n.IP \"\\s-1EV_MAXPRI\\s0\" 4\n.IX Item \"EV_MAXPRI\"\n.PD\nThe range of allowed priorities. \\f(CW\\*(C`EV_MINPRI\\*(C'\\fR must be smaller or equal to\n\\&\\f(CW\\*(C`EV_MAXPRI\\*(C'\\fR, but otherwise there are no non-obvious limitations. You can\nprovide for more priorities by overriding those symbols (usually defined\nto be \\f(CW\\*(C`\\-2\\*(C'\\fR and \\f(CW2\\fR, respectively).\n.Sp\nWhen doing priority-based operations, libev usually has to linearly search\nall the priorities, so having many of them (hundreds) uses a lot of space\nand time, so using the defaults of five priorities (\\-2 .. +2) is usually\nfine.\n.Sp\nIf your embedding application does not need any priorities, defining these\nboth to \\f(CW0\\fR will save some memory and \\s-1CPU.\\s0\n.IP \"\\s-1EV_PERIODIC_ENABLE, EV_IDLE_ENABLE, EV_EMBED_ENABLE, EV_STAT_ENABLE, EV_PREPARE_ENABLE, EV_CHECK_ENABLE, EV_FORK_ENABLE, EV_SIGNAL_ENABLE, EV_ASYNC_ENABLE, EV_CHILD_ENABLE.\\s0\" 4\n.IX Item \"EV_PERIODIC_ENABLE, EV_IDLE_ENABLE, EV_EMBED_ENABLE, EV_STAT_ENABLE, EV_PREPARE_ENABLE, EV_CHECK_ENABLE, EV_FORK_ENABLE, EV_SIGNAL_ENABLE, EV_ASYNC_ENABLE, EV_CHILD_ENABLE.\"\nIf undefined or defined to be \\f(CW1\\fR (and the platform supports it), then\nthe respective watcher type is supported. If defined to be \\f(CW0\\fR, then it\nis not. Disabling watcher types mainly saves code size.\n.IP \"\\s-1EV_FEATURES\\s0\" 4\n.IX Item \"EV_FEATURES\"\nIf you need to shave off some kilobytes of code at the expense of some\nspeed (but with the full \\s-1API\\s0), you can define this symbol to request\ncertain subsets of functionality. The default is to enable all features\nthat can be enabled on the platform.\n.Sp\nA typical way to use this symbol is to define it to \\f(CW0\\fR (or to a bitset\nwith some broad features you want) and then selectively re-enable\nadditional parts you want, for example if you want everything minimal,\nbut multiple event loop support, async and child watchers and the poll\nbackend, use this:\n.Sp\n.Vb 5\n\\&   #define EV_FEATURES 0\n\\&   #define EV_MULTIPLICITY 1\n\\&   #define EV_USE_POLL 1\n\\&   #define EV_CHILD_ENABLE 1\n\\&   #define EV_ASYNC_ENABLE 1\n.Ve\n.Sp\nThe actual value is a bitset, it can be a combination of the following\nvalues (by default, all of these are enabled):\n.RS 4\n.ie n .IP \"1 \\- faster/larger code\" 4\n.el .IP \"\\f(CW1\\fR \\- faster/larger code\" 4\n.IX Item \"1 - faster/larger code\"\nUse larger code to speed up some operations.\n.Sp\nCurrently this is used to override some inlining decisions (enlarging the\ncode size by roughly 30% on amd64).\n.Sp\nWhen optimising for size, use of compiler flags such as \\f(CW\\*(C`\\-Os\\*(C'\\fR with\ngcc is recommended, as well as \\f(CW\\*(C`\\-DNDEBUG\\*(C'\\fR, as libev contains a number of\nassertions.\n.Sp\nThe default is off when \\f(CW\\*(C`_\\|_OPTIMIZE_SIZE_\\|_\\*(C'\\fR is defined by your compiler\n(e.g. gcc with \\f(CW\\*(C`\\-Os\\*(C'\\fR).\n.ie n .IP \"2 \\- faster/larger data structures\" 4\n.el .IP \"\\f(CW2\\fR \\- faster/larger data structures\" 4\n.IX Item \"2 - faster/larger data structures\"\nReplaces the small 2\\-heap for timer management by a faster 4\\-heap, larger\nhash table sizes and so on. This will usually further increase code size\nand can additionally have an effect on the size of data structures at\nruntime.\n.Sp\nThe default is off when \\f(CW\\*(C`_\\|_OPTIMIZE_SIZE_\\|_\\*(C'\\fR is defined by your compiler\n(e.g. gcc with \\f(CW\\*(C`\\-Os\\*(C'\\fR).\n.ie n .IP \"4 \\- full \\s-1API\\s0 configuration\" 4\n.el .IP \"\\f(CW4\\fR \\- full \\s-1API\\s0 configuration\" 4\n.IX Item \"4 - full API configuration\"\nThis enables priorities (sets \\f(CW\\*(C`EV_MAXPRI\\*(C'\\fR=2 and \\f(CW\\*(C`EV_MINPRI\\*(C'\\fR=\\-2), and\nenables multiplicity (\\f(CW\\*(C`EV_MULTIPLICITY\\*(C'\\fR=1).\n.ie n .IP \"8 \\- full \\s-1API\\s0\" 4\n.el .IP \"\\f(CW8\\fR \\- full \\s-1API\\s0\" 4\n.IX Item \"8 - full API\"\nThis enables a lot of the \\*(L\"lesser used\\*(R\" \\s-1API\\s0 functions. See \\f(CW\\*(C`ev.h\\*(C'\\fR for\ndetails on which parts of the \\s-1API\\s0 are still available without this\nfeature, and do not complain if this subset changes over time.\n.ie n .IP \"16 \\- enable all optional watcher types\" 4\n.el .IP \"\\f(CW16\\fR \\- enable all optional watcher types\" 4\n.IX Item \"16 - enable all optional watcher types\"\nEnables all optional watcher types.  If you want to selectively enable\nonly some watcher types other than I/O and timers (e.g. prepare,\nembed, async, child...) you can enable them manually by defining\n\\&\\f(CW\\*(C`EV_watchertype_ENABLE\\*(C'\\fR to \\f(CW1\\fR instead.\n.ie n .IP \"32 \\- enable all backends\" 4\n.el .IP \"\\f(CW32\\fR \\- enable all backends\" 4\n.IX Item \"32 - enable all backends\"\nThis enables all backends \\- without this feature, you need to enable at\nleast one backend manually (\\f(CW\\*(C`EV_USE_SELECT\\*(C'\\fR is a good choice).\n.ie n .IP \"64 \\- enable OS-specific \"\"helper\"\" APIs\" 4\n.el .IP \"\\f(CW64\\fR \\- enable OS-specific ``helper'' APIs\" 4\n.IX Item \"64 - enable OS-specific helper APIs\"\nEnable inotify, eventfd, signalfd and similar OS-specific helper APIs by\ndefault.\n.RE\n.RS 4\n.Sp\nCompiling with \\f(CW\\*(C`gcc \\-Os \\-DEV_STANDALONE \\-DEV_USE_EPOLL=1 \\-DEV_FEATURES=0\\*(C'\\fR\nreduces the compiled size of libev from 24.7Kb code/2.8Kb data to 6.5Kb\ncode/0.3Kb data on my GNU/Linux amd64 system, while still giving you I/O\nwatchers, timers and monotonic clock support.\n.Sp\nWith an intelligent-enough linker (gcc+binutils are intelligent enough\nwhen you use \\f(CW\\*(C`\\-Wl,\\-\\-gc\\-sections \\-ffunction\\-sections\\*(C'\\fR) functions unused by\nyour program might be left out as well \\- a binary starting a timer and an\nI/O watcher then might come out at only 5Kb.\n.RE\n.IP \"\\s-1EV_API_STATIC\\s0\" 4\n.IX Item \"EV_API_STATIC\"\nIf this symbol is defined (by default it is not), then all identifiers\nwill have static linkage. This means that libev will not export any\nidentifiers, and you cannot link against libev anymore. This can be useful\nwhen you embed libev, only want to use libev functions in a single file,\nand do not want its identifiers to be visible.\n.Sp\nTo use this, define \\f(CW\\*(C`EV_API_STATIC\\*(C'\\fR and include \\fIev.c\\fR in the file that\nwants to use libev.\n.Sp\nThis option only works when libev is compiled with a C compiler, as \\*(C+\ndoesn't support the required declaration syntax.\n.IP \"\\s-1EV_AVOID_STDIO\\s0\" 4\n.IX Item \"EV_AVOID_STDIO\"\nIf this is set to \\f(CW1\\fR at compiletime, then libev will avoid using stdio\nfunctions (printf, scanf, perror etc.). This will increase the code size\nsomewhat, but if your program doesn't otherwise depend on stdio and your\nlibc allows it, this avoids linking in the stdio library which is quite\nbig.\n.Sp\nNote that error messages might become less precise when this option is\nenabled.\n.IP \"\\s-1EV_NSIG\\s0\" 4\n.IX Item \"EV_NSIG\"\nThe highest supported signal number, +1 (or, the number of\nsignals): Normally, libev tries to deduce the maximum number of signals\nautomatically, but sometimes this fails, in which case it can be\nspecified. Also, using a lower number than detected (\\f(CW32\\fR should be\ngood for about any system in existence) can save some memory, as libev\nstatically allocates some 12\\-24 bytes per signal number.\n.IP \"\\s-1EV_PID_HASHSIZE\\s0\" 4\n.IX Item \"EV_PID_HASHSIZE\"\n\\&\\f(CW\\*(C`ev_child\\*(C'\\fR watchers use a small hash table to distribute workload by\npid. The default size is \\f(CW16\\fR (or \\f(CW1\\fR with \\f(CW\\*(C`EV_FEATURES\\*(C'\\fR disabled),\nusually more than enough. If you need to manage thousands of children you\nmight want to increase this value (\\fImust\\fR be a power of two).\n.IP \"\\s-1EV_INOTIFY_HASHSIZE\\s0\" 4\n.IX Item \"EV_INOTIFY_HASHSIZE\"\n\\&\\f(CW\\*(C`ev_stat\\*(C'\\fR watchers use a small hash table to distribute workload by\ninotify watch id. The default size is \\f(CW16\\fR (or \\f(CW1\\fR with \\f(CW\\*(C`EV_FEATURES\\*(C'\\fR\ndisabled), usually more than enough. If you need to manage thousands of\n\\&\\f(CW\\*(C`ev_stat\\*(C'\\fR watchers you might want to increase this value (\\fImust\\fR be a\npower of two).\n.IP \"\\s-1EV_USE_4HEAP\\s0\" 4\n.IX Item \"EV_USE_4HEAP\"\nHeaps are not very cache-efficient. To improve the cache-efficiency of the\ntimer and periodics heaps, libev uses a 4\\-heap when this symbol is defined\nto \\f(CW1\\fR. The 4\\-heap uses more complicated (longer) code but has noticeably\nfaster performance with many (thousands) of watchers.\n.Sp\nThe default is \\f(CW1\\fR, unless \\f(CW\\*(C`EV_FEATURES\\*(C'\\fR overrides it, in which case it\nwill be \\f(CW0\\fR.\n.IP \"\\s-1EV_HEAP_CACHE_AT\\s0\" 4\n.IX Item \"EV_HEAP_CACHE_AT\"\nHeaps are not very cache-efficient. To improve the cache-efficiency of the\ntimer and periodics heaps, libev can cache the timestamp (\\fIat\\fR) within\nthe heap structure (selected by defining \\f(CW\\*(C`EV_HEAP_CACHE_AT\\*(C'\\fR to \\f(CW1\\fR),\nwhich uses 8\\-12 bytes more per watcher and a few hundred bytes more code,\nbut avoids random read accesses on heap changes. This improves performance\nnoticeably with many (hundreds) of watchers.\n.Sp\nThe default is \\f(CW1\\fR, unless \\f(CW\\*(C`EV_FEATURES\\*(C'\\fR overrides it, in which case it\nwill be \\f(CW0\\fR.\n.IP \"\\s-1EV_VERIFY\\s0\" 4\n.IX Item \"EV_VERIFY\"\nControls how much internal verification (see \\f(CW\\*(C`ev_verify ()\\*(C'\\fR) will\nbe done: If set to \\f(CW0\\fR, no internal verification code will be compiled\nin. If set to \\f(CW1\\fR, then verification code will be compiled in, but not\ncalled. If set to \\f(CW2\\fR, then the internal verification code will be\ncalled once per loop, which can slow down libev. If set to \\f(CW3\\fR, then the\nverification code will be called very frequently, which will slow down\nlibev considerably.\n.Sp\nThe default is \\f(CW1\\fR, unless \\f(CW\\*(C`EV_FEATURES\\*(C'\\fR overrides it, in which case it\nwill be \\f(CW0\\fR.\n.IP \"\\s-1EV_COMMON\\s0\" 4\n.IX Item \"EV_COMMON\"\nBy default, all watchers have a \\f(CW\\*(C`void *data\\*(C'\\fR member. By redefining\nthis macro to something else you can include more and other types of\nmembers. You have to define it each time you include one of the files,\nthough, and it must be identical each time.\n.Sp\nFor example, the perl \\s-1EV\\s0 module uses something like this:\n.Sp\n.Vb 3\n\\&   #define EV_COMMON                       \\e\n\\&     SV *self; /* contains this struct */  \\e\n\\&     SV *cb_sv, *fh /* note no trailing \";\" */\n.Ve\n.IP \"\\s-1EV_CB_DECLARE \\s0(type)\" 4\n.IX Item \"EV_CB_DECLARE (type)\"\n.PD 0\n.IP \"\\s-1EV_CB_INVOKE \\s0(watcher, revents)\" 4\n.IX Item \"EV_CB_INVOKE (watcher, revents)\"\n.IP \"ev_set_cb (ev, cb)\" 4\n.IX Item \"ev_set_cb (ev, cb)\"\n.PD\nCan be used to change the callback member declaration in each watcher,\nand the way callbacks are invoked and set. Must expand to a struct member\ndefinition and a statement, respectively. See the \\fIev.h\\fR header file for\ntheir default definitions. One possible use for overriding these is to\navoid the \\f(CW\\*(C`struct ev_loop *\\*(C'\\fR as first argument in all cases, or to use\nmethod calls instead of plain function calls in \\*(C+.\n.SS \"\\s-1EXPORTED API SYMBOLS\\s0\"\n.IX Subsection \"EXPORTED API SYMBOLS\"\nIf you need to re-export the \\s-1API \\s0(e.g. via a \\s-1DLL\\s0) and you need a list of\nexported symbols, you can use the provided \\fISymbol.*\\fR files which list\nall public symbols, one per line:\n.PP\n.Vb 2\n\\&   Symbols.ev      for libev proper\n\\&   Symbols.event   for the libevent emulation\n.Ve\n.PP\nThis can also be used to rename all public symbols to avoid clashes with\nmultiple versions of libev linked together (which is obviously bad in\nitself, but sometimes it is inconvenient to avoid this).\n.PP\nA sed command like this will create wrapper \\f(CW\\*(C`#define\\*(C'\\fR's that you need to\ninclude before including \\fIev.h\\fR:\n.PP\n.Vb 1\n\\&   <Symbols.ev sed \\-e \"s/.*/#define & myprefix_&/\" >wrap.h\n.Ve\n.PP\nThis would create a file \\fIwrap.h\\fR which essentially looks like this:\n.PP\n.Vb 4\n\\&   #define ev_backend     myprefix_ev_backend\n\\&   #define ev_check_start myprefix_ev_check_start\n\\&   #define ev_check_stop  myprefix_ev_check_stop\n\\&   ...\n.Ve\n.SS \"\\s-1EXAMPLES\\s0\"\n.IX Subsection \"EXAMPLES\"\nFor a real-world example of a program the includes libev\nverbatim, you can have a look at the \\s-1EV\\s0 perl module\n(<http://software.schmorp.de/pkg/EV.html>). It has the libev files in\nthe \\fIlibev/\\fR subdirectory and includes them in the \\fI\\s-1EV/EVAPI\\s0.h\\fR (public\ninterface) and \\fI\\s-1EV\\s0.xs\\fR (implementation) files. Only the \\fI\\s-1EV\\s0.xs\\fR file\nwill be compiled. It is pretty complex because it provides its own header\nfile.\n.PP\nThe usage in rxvt-unicode is simpler. It has a \\fIev_cpp.h\\fR header file\nthat everybody includes and which overrides some configure choices:\n.PP\n.Vb 8\n\\&   #define EV_FEATURES 8\n\\&   #define EV_USE_SELECT 1\n\\&   #define EV_PREPARE_ENABLE 1\n\\&   #define EV_IDLE_ENABLE 1\n\\&   #define EV_SIGNAL_ENABLE 1\n\\&   #define EV_CHILD_ENABLE 1\n\\&   #define EV_USE_STDEXCEPT 0\n\\&   #define EV_CONFIG_H <config.h>\n\\&\n\\&   #include \"ev++.h\"\n.Ve\n.PP\nAnd a \\fIev_cpp.C\\fR implementation file that contains libev proper and is compiled:\n.PP\n.Vb 2\n\\&   #include \"ev_cpp.h\"\n\\&   #include \"ev.c\"\n.Ve\n.SH \"INTERACTION WITH OTHER PROGRAMS, LIBRARIES OR THE ENVIRONMENT\"\n.IX Header \"INTERACTION WITH OTHER PROGRAMS, LIBRARIES OR THE ENVIRONMENT\"\n.SS \"\\s-1THREADS AND COROUTINES\\s0\"\n.IX Subsection \"THREADS AND COROUTINES\"\n\\fI\\s-1THREADS\\s0\\fR\n.IX Subsection \"THREADS\"\n.PP\nAll libev functions are reentrant and thread-safe unless explicitly\ndocumented otherwise, but libev implements no locking itself. This means\nthat you can use as many loops as you want in parallel, as long as there\nare no concurrent calls into any libev function with the same loop\nparameter (\\f(CW\\*(C`ev_default_*\\*(C'\\fR calls have an implicit default loop parameter,\nof course): libev guarantees that different event loops share no data\nstructures that need any locking.\n.PP\nOr to put it differently: calls with different loop parameters can be done\nconcurrently from multiple threads, calls with the same loop parameter\nmust be done serially (but can be done from different threads, as long as\nonly one thread ever is inside a call at any point in time, e.g. by using\na mutex per loop).\n.PP\nSpecifically to support threads (and signal handlers), libev implements\nso-called \\f(CW\\*(C`ev_async\\*(C'\\fR watchers, which allow some limited form of\nconcurrency on the same event loop, namely waking it up \\*(L\"from the\noutside\\*(R\".\n.PP\nIf you want to know which design (one loop, locking, or multiple loops\nwithout or something else still) is best for your problem, then I cannot\nhelp you, but here is some generic advice:\n.IP \"\\(bu\" 4\nmost applications have a main thread: use the default libev loop\nin that thread, or create a separate thread running only the default loop.\n.Sp\nThis helps integrating other libraries or software modules that use libev\nthemselves and don't care/know about threading.\n.IP \"\\(bu\" 4\none loop per thread is usually a good model.\n.Sp\nDoing this is almost never wrong, sometimes a better-performance model\nexists, but it is always a good start.\n.IP \"\\(bu\" 4\nother models exist, such as the leader/follower pattern, where one\nloop is handed through multiple threads in a kind of round-robin fashion.\n.Sp\nChoosing a model is hard \\- look around, learn, know that usually you can do\nbetter than you currently do :\\-)\n.IP \"\\(bu\" 4\noften you need to talk to some other thread which blocks in the\nevent loop.\n.Sp\n\\&\\f(CW\\*(C`ev_async\\*(C'\\fR watchers can be used to wake them up from other threads safely\n(or from signal contexts...).\n.Sp\nAn example use would be to communicate signals or other events that only\nwork in the default loop by registering the signal watcher with the\ndefault loop and triggering an \\f(CW\\*(C`ev_async\\*(C'\\fR watcher from the default loop\nwatcher callback into the event loop interested in the signal.\n.PP\nSee also \\*(L\"\\s-1THREAD LOCKING EXAMPLE\\*(R\"\\s0.\n.PP\n\\fI\\s-1COROUTINES\\s0\\fR\n.IX Subsection \"COROUTINES\"\n.PP\nLibev is very accommodating to coroutines (\\*(L\"cooperative threads\\*(R\"):\nlibev fully supports nesting calls to its functions from different\ncoroutines (e.g. you can call \\f(CW\\*(C`ev_run\\*(C'\\fR on the same loop from two\ndifferent coroutines, and switch freely between both coroutines running\nthe loop, as long as you don't confuse yourself). The only exception is\nthat you must not do this from \\f(CW\\*(C`ev_periodic\\*(C'\\fR reschedule callbacks.\n.PP\nCare has been taken to ensure that libev does not keep local state inside\n\\&\\f(CW\\*(C`ev_run\\*(C'\\fR, and other calls do not usually allow for coroutine switches as\nthey do not call any callbacks.\n.SS \"\\s-1COMPILER WARNINGS\\s0\"\n.IX Subsection \"COMPILER WARNINGS\"\nDepending on your compiler and compiler settings, you might get no or a\nlot of warnings when compiling libev code. Some people are apparently\nscared by this.\n.PP\nHowever, these are unavoidable for many reasons. For one, each compiler\nhas different warnings, and each user has different tastes regarding\nwarning options. \\*(L\"Warn-free\\*(R\" code therefore cannot be a goal except when\ntargeting a specific compiler and compiler-version.\n.PP\nAnother reason is that some compiler warnings require elaborate\nworkarounds, or other changes to the code that make it less clear and less\nmaintainable.\n.PP\nAnd of course, some compiler warnings are just plain stupid, or simply\nwrong (because they don't actually warn about the condition their message\nseems to warn about). For example, certain older gcc versions had some\nwarnings that resulted in an extreme number of false positives. These have\nbeen fixed, but some people still insist on making code warn-free with\nsuch buggy versions.\n.PP\nWhile libev is written to generate as few warnings as possible,\n\\&\\*(L\"warn-free\\*(R\" code is not a goal, and it is recommended not to build libev\nwith any compiler warnings enabled unless you are prepared to cope with\nthem (e.g. by ignoring them). Remember that warnings are just that:\nwarnings, not errors, or proof of bugs.\n.SS \"\\s-1VALGRIND\\s0\"\n.IX Subsection \"VALGRIND\"\nValgrind has a special section here because it is a popular tool that is\nhighly useful. Unfortunately, valgrind reports are very hard to interpret.\n.PP\nIf you think you found a bug (memory leak, uninitialised data access etc.)\nin libev, then check twice: If valgrind reports something like:\n.PP\n.Vb 3\n\\&   ==2274==    definitely lost: 0 bytes in 0 blocks.\n\\&   ==2274==      possibly lost: 0 bytes in 0 blocks.\n\\&   ==2274==    still reachable: 256 bytes in 1 blocks.\n.Ve\n.PP\nThen there is no memory leak, just as memory accounted to global variables\nis not a memleak \\- the memory is still being referenced, and didn't leak.\n.PP\nSimilarly, under some circumstances, valgrind might report kernel bugs\nas if it were a bug in libev (e.g. in realloc or in the poll backend,\nalthough an acceptable workaround has been found here), or it might be\nconfused.\n.PP\nKeep in mind that valgrind is a very good tool, but only a tool. Don't\nmake it into some kind of religion.\n.PP\nIf you are unsure about something, feel free to contact the mailing list\nwith the full valgrind report and an explanation on why you think this\nis a bug in libev (best check the archives, too :). However, don't be\nannoyed when you get a brisk \\*(L\"this is no bug\\*(R\" answer and take the chance\nof learning how to interpret valgrind properly.\n.PP\nIf you need, for some reason, empty reports from valgrind for your project\nI suggest using suppression lists.\n.SH \"PORTABILITY NOTES\"\n.IX Header \"PORTABILITY NOTES\"\n.SS \"\\s-1GNU/LINUX 32 BIT LIMITATIONS\\s0\"\n.IX Subsection \"GNU/LINUX 32 BIT LIMITATIONS\"\nGNU/Linux is the only common platform that supports 64 bit file/large file\ninterfaces but \\fIdisables\\fR them by default.\n.PP\nThat means that libev compiled in the default environment doesn't support\nfiles larger than 2GiB or so, which mainly affects \\f(CW\\*(C`ev_stat\\*(C'\\fR watchers.\n.PP\nUnfortunately, many programs try to work around this GNU/Linux issue\nby enabling the large file \\s-1API,\\s0 which makes them incompatible with the\nstandard libev compiled for their system.\n.PP\nLikewise, libev cannot enable the large file \\s-1API\\s0 itself as this would\nsuddenly make it incompatible to the default compile time environment,\ni.e. all programs not using special compile switches.\n.SS \"\\s-1OS/X AND DARWIN BUGS\\s0\"\n.IX Subsection \"OS/X AND DARWIN BUGS\"\nThe whole thing is a bug if you ask me \\- basically any system interface\nyou touch is broken, whether it is locales, poll, kqueue or even the\nOpenGL drivers.\n.PP\n\\fI\\f(CI\\*(C`kqueue\\*(C'\\fI is buggy\\fR\n.IX Subsection \"kqueue is buggy\"\n.PP\nThe kqueue syscall is broken in all known versions \\- most versions support\nonly sockets, many support pipes.\n.PP\nLibev tries to work around this by not using \\f(CW\\*(C`kqueue\\*(C'\\fR by default on this\nrotten platform, but of course you can still ask for it when creating a\nloop \\- embedding a socket-only kqueue loop into a select-based one is\nprobably going to work well.\n.PP\n\\fI\\f(CI\\*(C`poll\\*(C'\\fI is buggy\\fR\n.IX Subsection \"poll is buggy\"\n.PP\nInstead of fixing \\f(CW\\*(C`kqueue\\*(C'\\fR, Apple replaced their (working) \\f(CW\\*(C`poll\\*(C'\\fR\nimplementation by something calling \\f(CW\\*(C`kqueue\\*(C'\\fR internally around the 10.5.6\nrelease, so now \\f(CW\\*(C`kqueue\\*(C'\\fR \\fIand\\fR \\f(CW\\*(C`poll\\*(C'\\fR are broken.\n.PP\nLibev tries to work around this by not using \\f(CW\\*(C`poll\\*(C'\\fR by default on\nthis rotten platform, but of course you can still ask for it when creating\na loop.\n.PP\n\\fI\\f(CI\\*(C`select\\*(C'\\fI is buggy\\fR\n.IX Subsection \"select is buggy\"\n.PP\nAll that's left is \\f(CW\\*(C`select\\*(C'\\fR, and of course Apple found a way to fuck this\none up as well: On \\s-1OS/X, \\s0\\f(CW\\*(C`select\\*(C'\\fR actively limits the number of file\ndescriptors you can pass in to 1024 \\- your program suddenly crashes when\nyou use more.\n.PP\nThere is an undocumented \\*(L\"workaround\\*(R\" for this \\- defining\n\\&\\f(CW\\*(C`_DARWIN_UNLIMITED_SELECT\\*(C'\\fR, which libev tries to use, so select \\fIshould\\fR\nwork on \\s-1OS/X.\\s0\n.SS \"\\s-1SOLARIS PROBLEMS AND WORKAROUNDS\\s0\"\n.IX Subsection \"SOLARIS PROBLEMS AND WORKAROUNDS\"\n\\fI\\f(CI\\*(C`errno\\*(C'\\fI reentrancy\\fR\n.IX Subsection \"errno reentrancy\"\n.PP\nThe default compile environment on Solaris is unfortunately so\nthread-unsafe that you can't even use components/libraries compiled\nwithout \\f(CW\\*(C`\\-D_REENTRANT\\*(C'\\fR in a threaded program, which, of course, isn't\ndefined by default. A valid, if stupid, implementation choice.\n.PP\nIf you want to use libev in threaded environments you have to make sure\nit's compiled with \\f(CW\\*(C`_REENTRANT\\*(C'\\fR defined.\n.PP\n\\fIEvent port backend\\fR\n.IX Subsection \"Event port backend\"\n.PP\nThe scalable event interface for Solaris is called \\*(L\"event\nports\\*(R\". Unfortunately, this mechanism is very buggy in all major\nreleases. If you run into high \\s-1CPU\\s0 usage, your program freezes or you get\na large number of spurious wakeups, make sure you have all the relevant\nand latest kernel patches applied. No, I don't know which ones, but there\nare multiple ones to apply, and afterwards, event ports actually work\ngreat.\n.PP\nIf you can't get it to work, you can try running the program by setting\nthe environment variable \\f(CW\\*(C`LIBEV_FLAGS=3\\*(C'\\fR to only allow \\f(CW\\*(C`poll\\*(C'\\fR and\n\\&\\f(CW\\*(C`select\\*(C'\\fR backends.\n.SS \"\\s-1AIX POLL BUG\\s0\"\n.IX Subsection \"AIX POLL BUG\"\n\\&\\s-1AIX\\s0 unfortunately has a broken \\f(CW\\*(C`poll.h\\*(C'\\fR header. Libev works around\nthis by trying to avoid the poll backend altogether (i.e. it's not even\ncompiled in), which normally isn't a big problem as \\f(CW\\*(C`select\\*(C'\\fR works fine\nwith large bitsets on \\s-1AIX,\\s0 and \\s-1AIX\\s0 is dead anyway.\n.SS \"\\s-1WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS\\s0\"\n.IX Subsection \"WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS\"\n\\fIGeneral issues\\fR\n.IX Subsection \"General issues\"\n.PP\nWin32 doesn't support any of the standards (e.g. \\s-1POSIX\\s0) that libev\nrequires, and its I/O model is fundamentally incompatible with the \\s-1POSIX\\s0\nmodel. Libev still offers limited functionality on this platform in\nthe form of the \\f(CW\\*(C`EVBACKEND_SELECT\\*(C'\\fR backend, and only supports socket\ndescriptors. This only applies when using Win32 natively, not when using\ne.g. cygwin. Actually, it only applies to the microsofts own compilers,\nas every compiler comes with a slightly differently broken/incompatible\nenvironment.\n.PP\nLifting these limitations would basically require the full\nre-implementation of the I/O system. If you are into this kind of thing,\nthen note that glib does exactly that for you in a very portable way (note\nalso that glib is the slowest event library known to man).\n.PP\nThere is no supported compilation method available on windows except\nembedding it into other applications.\n.PP\nSensible signal handling is officially unsupported by Microsoft \\- libev\ntries its best, but under most conditions, signals will simply not work.\n.PP\nNot a libev limitation but worth mentioning: windows apparently doesn't\naccept large writes: instead of resulting in a partial write, windows will\neither accept everything or return \\f(CW\\*(C`ENOBUFS\\*(C'\\fR if the buffer is too large,\nso make sure you only write small amounts into your sockets (less than a\nmegabyte seems safe, but this apparently depends on the amount of memory\navailable).\n.PP\nDue to the many, low, and arbitrary limits on the win32 platform and\nthe abysmal performance of winsockets, using a large number of sockets\nis not recommended (and not reasonable). If your program needs to use\nmore than a hundred or so sockets, then likely it needs to use a totally\ndifferent implementation for windows, as libev offers the \\s-1POSIX\\s0 readiness\nnotification model, which cannot be implemented efficiently on windows\n(due to Microsoft monopoly games).\n.PP\nA typical way to use libev under windows is to embed it (see the embedding\nsection for details) and use the following \\fIevwrap.h\\fR header file instead\nof \\fIev.h\\fR:\n.PP\n.Vb 2\n\\&   #define EV_STANDALONE              /* keeps ev from requiring config.h */\n\\&   #define EV_SELECT_IS_WINSOCKET 1   /* configure libev for windows select */\n\\&\n\\&   #include \"ev.h\"\n.Ve\n.PP\nAnd compile the following \\fIevwrap.c\\fR file into your project (make sure\nyou do \\fInot\\fR compile the \\fIev.c\\fR or any other embedded source files!):\n.PP\n.Vb 2\n\\&   #include \"evwrap.h\"\n\\&   #include \"ev.c\"\n.Ve\n.PP\n\\fIThe winsocket \\f(CI\\*(C`select\\*(C'\\fI function\\fR\n.IX Subsection \"The winsocket select function\"\n.PP\nThe winsocket \\f(CW\\*(C`select\\*(C'\\fR function doesn't follow \\s-1POSIX\\s0 in that it\nrequires socket \\fIhandles\\fR and not socket \\fIfile descriptors\\fR (it is\nalso extremely buggy). This makes select very inefficient, and also\nrequires a mapping from file descriptors to socket handles (the Microsoft\nC runtime provides the function \\f(CW\\*(C`_open_osfhandle\\*(C'\\fR for this). See the\ndiscussion of the \\f(CW\\*(C`EV_SELECT_USE_FD_SET\\*(C'\\fR, \\f(CW\\*(C`EV_SELECT_IS_WINSOCKET\\*(C'\\fR and\n\\&\\f(CW\\*(C`EV_FD_TO_WIN32_HANDLE\\*(C'\\fR preprocessor symbols for more info.\n.PP\nThe configuration for a \\*(L\"naked\\*(R\" win32 using the Microsoft runtime\nlibraries and raw winsocket select is:\n.PP\n.Vb 2\n\\&   #define EV_USE_SELECT 1\n\\&   #define EV_SELECT_IS_WINSOCKET 1   /* forces EV_SELECT_USE_FD_SET, too */\n.Ve\n.PP\nNote that winsockets handling of fd sets is O(n), so you can easily get a\ncomplexity in the O(nX) range when using win32.\n.PP\n\\fILimited number of file descriptors\\fR\n.IX Subsection \"Limited number of file descriptors\"\n.PP\nWindows has numerous arbitrary (and low) limits on things.\n.PP\nEarly versions of winsocket's select only supported waiting for a maximum\nof \\f(CW64\\fR handles (probably owning to the fact that all windows kernels\ncan only wait for \\f(CW64\\fR things at the same time internally; Microsoft\nrecommends spawning a chain of threads and wait for 63 handles and the\nprevious thread in each. Sounds great!).\n.PP\nNewer versions support more handles, but you need to define \\f(CW\\*(C`FD_SETSIZE\\*(C'\\fR\nto some high number (e.g. \\f(CW2048\\fR) before compiling the winsocket select\ncall (which might be in libev or elsewhere, for example, perl and many\nother interpreters do their own select emulation on windows).\n.PP\nAnother limit is the number of file descriptors in the Microsoft runtime\nlibraries, which by default is \\f(CW64\\fR (there must be a hidden \\fI64\\fR\nfetish or something like this inside Microsoft). You can increase this\nby calling \\f(CW\\*(C`_setmaxstdio\\*(C'\\fR, which can increase this limit to \\f(CW2048\\fR\n(another arbitrary limit), but is broken in many versions of the Microsoft\nruntime libraries. This might get you to about \\f(CW512\\fR or \\f(CW2048\\fR sockets\n(depending on windows version and/or the phase of the moon). To get more,\nyou need to wrap all I/O functions and provide your own fd management, but\nthe cost of calling select (O(nX)) will likely make this unworkable.\n.SS \"\\s-1PORTABILITY REQUIREMENTS\\s0\"\n.IX Subsection \"PORTABILITY REQUIREMENTS\"\nIn addition to a working ISO-C implementation and of course the\nbackend-specific APIs, libev relies on a few additional extensions:\n.ie n .IP \"\"\"void (*)(ev_watcher_type *, int revents)\"\" must have compatible calling conventions regardless of \"\"ev_watcher_type *\"\".\" 4\n.el .IP \"\\f(CWvoid (*)(ev_watcher_type *, int revents)\\fR must have compatible calling conventions regardless of \\f(CWev_watcher_type *\\fR.\" 4\n.IX Item \"void (*)(ev_watcher_type *, int revents) must have compatible calling conventions regardless of ev_watcher_type *.\"\nLibev assumes not only that all watcher pointers have the same internal\nstructure (guaranteed by \\s-1POSIX\\s0 but not by \\s-1ISO C\\s0 for example), but it also\nassumes that the same (machine) code can be used to call any watcher\ncallback: The watcher callbacks have different type signatures, but libev\ncalls them using an \\f(CW\\*(C`ev_watcher *\\*(C'\\fR internally.\n.IP \"null pointers and integer zero are represented by 0 bytes\" 4\n.IX Item \"null pointers and integer zero are represented by 0 bytes\"\nLibev uses \\f(CW\\*(C`memset\\*(C'\\fR to initialise structs and arrays to \\f(CW0\\fR bytes, and\nrelies on this setting pointers and integers to null.\n.IP \"pointer accesses must be thread-atomic\" 4\n.IX Item \"pointer accesses must be thread-atomic\"\nAccessing a pointer value must be atomic, it must both be readable and\nwritable in one piece \\- this is the case on all current architectures.\n.ie n .IP \"\"\"sig_atomic_t volatile\"\" must be thread-atomic as well\" 4\n.el .IP \"\\f(CWsig_atomic_t volatile\\fR must be thread-atomic as well\" 4\n.IX Item \"sig_atomic_t volatile must be thread-atomic as well\"\nThe type \\f(CW\\*(C`sig_atomic_t volatile\\*(C'\\fR (or whatever is defined as\n\\&\\f(CW\\*(C`EV_ATOMIC_T\\*(C'\\fR) must be atomic with respect to accesses from different\nthreads. This is not part of the specification for \\f(CW\\*(C`sig_atomic_t\\*(C'\\fR, but is\nbelieved to be sufficiently portable.\n.ie n .IP \"\"\"sigprocmask\"\" must work in a threaded environment\" 4\n.el .IP \"\\f(CWsigprocmask\\fR must work in a threaded environment\" 4\n.IX Item \"sigprocmask must work in a threaded environment\"\nLibev uses \\f(CW\\*(C`sigprocmask\\*(C'\\fR to temporarily block signals. This is not\nallowed in a threaded program (\\f(CW\\*(C`pthread_sigmask\\*(C'\\fR has to be used). Typical\npthread implementations will either allow \\f(CW\\*(C`sigprocmask\\*(C'\\fR in the \\*(L\"main\nthread\\*(R\" or will block signals process-wide, both behaviours would\nbe compatible with libev. Interaction between \\f(CW\\*(C`sigprocmask\\*(C'\\fR and\n\\&\\f(CW\\*(C`pthread_sigmask\\*(C'\\fR could complicate things, however.\n.Sp\nThe most portable way to handle signals is to block signals in all threads\nexcept the initial one, and run the signal handling loop in the initial\nthread as well.\n.ie n .IP \"\"\"long\"\" must be large enough for common memory allocation sizes\" 4\n.el .IP \"\\f(CWlong\\fR must be large enough for common memory allocation sizes\" 4\n.IX Item \"long must be large enough for common memory allocation sizes\"\nTo improve portability and simplify its \\s-1API,\\s0 libev uses \\f(CW\\*(C`long\\*(C'\\fR internally\ninstead of \\f(CW\\*(C`size_t\\*(C'\\fR when allocating its data structures. On non-POSIX\nsystems (Microsoft...) this might be unexpectedly low, but is still at\nleast 31 bits everywhere, which is enough for hundreds of millions of\nwatchers.\n.ie n .IP \"\"\"double\"\" must hold a time value in seconds with enough accuracy\" 4\n.el .IP \"\\f(CWdouble\\fR must hold a time value in seconds with enough accuracy\" 4\n.IX Item \"double must hold a time value in seconds with enough accuracy\"\nThe type \\f(CW\\*(C`double\\*(C'\\fR is used to represent timestamps. It is required to\nhave at least 51 bits of mantissa (and 9 bits of exponent), which is\ngood enough for at least into the year 4000 with millisecond accuracy\n(the design goal for libev). This requirement is overfulfilled by\nimplementations using \\s-1IEEE 754,\\s0 which is basically all existing ones.\n.Sp\nWith \\s-1IEEE 754\\s0 doubles, you get microsecond accuracy until at least the\nyear 2255 (and millisecond accuracy till the year 287396 \\- by then, libev\nis either obsolete or somebody patched it to use \\f(CW\\*(C`long double\\*(C'\\fR or\nsomething like that, just kidding).\n.PP\nIf you know of other additional requirements drop me a note.\n.SH \"ALGORITHMIC COMPLEXITIES\"\n.IX Header \"ALGORITHMIC COMPLEXITIES\"\nIn this section the complexities of (many of) the algorithms used inside\nlibev will be documented. For complexity discussions about backends see\nthe documentation for \\f(CW\\*(C`ev_default_init\\*(C'\\fR.\n.PP\nAll of the following are about amortised time: If an array needs to be\nextended, libev needs to realloc and move the whole array, but this\nhappens asymptotically rarer with higher number of elements, so O(1) might\nmean that libev does a lengthy realloc operation in rare cases, but on\naverage it is much faster and asymptotically approaches constant time.\n.IP \"Starting and stopping timer/periodic watchers: O(log skipped_other_timers)\" 4\n.IX Item \"Starting and stopping timer/periodic watchers: O(log skipped_other_timers)\"\nThis means that, when you have a watcher that triggers in one hour and\nthere are 100 watchers that would trigger before that, then inserting will\nhave to skip roughly seven (\\f(CW\\*(C`ld 100\\*(C'\\fR) of these watchers.\n.IP \"Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers)\" 4\n.IX Item \"Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers)\"\nThat means that changing a timer costs less than removing/adding them,\nas only the relative motion in the event queue has to be paid for.\n.IP \"Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1)\" 4\n.IX Item \"Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1)\"\nThese just add the watcher into an array or at the head of a list.\n.IP \"Stopping check/prepare/idle/fork/async watchers: O(1)\" 4\n.IX Item \"Stopping check/prepare/idle/fork/async watchers: O(1)\"\n.PD 0\n.IP \"Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % \\s-1EV_PID_HASHSIZE\\s0))\" 4\n.IX Item \"Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE))\"\n.PD\nThese watchers are stored in lists, so they need to be walked to find the\ncorrect watcher to remove. The lists are usually short (you don't usually\nhave many watchers waiting for the same fd or signal: one is typical, two\nis rare).\n.IP \"Finding the next timer in each loop iteration: O(1)\" 4\n.IX Item \"Finding the next timer in each loop iteration: O(1)\"\nBy virtue of using a binary or 4\\-heap, the next timer is always found at a\nfixed position in the storage array.\n.IP \"Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd)\" 4\n.IX Item \"Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd)\"\nA change means an I/O watcher gets started or stopped, which requires\nlibev to recalculate its status (and possibly tell the kernel, depending\non backend and whether \\f(CW\\*(C`ev_io_set\\*(C'\\fR was used).\n.IP \"Activating one watcher (putting it into the pending state): O(1)\" 4\n.IX Item \"Activating one watcher (putting it into the pending state): O(1)\"\n.PD 0\n.IP \"Priority handling: O(number_of_priorities)\" 4\n.IX Item \"Priority handling: O(number_of_priorities)\"\n.PD\nPriorities are implemented by allocating some space for each\npriority. When doing priority-based operations, libev usually has to\nlinearly search all the priorities, but starting/stopping and activating\nwatchers becomes O(1) with respect to priority handling.\n.IP \"Sending an ev_async: O(1)\" 4\n.IX Item \"Sending an ev_async: O(1)\"\n.PD 0\n.IP \"Processing ev_async_send: O(number_of_async_watchers)\" 4\n.IX Item \"Processing ev_async_send: O(number_of_async_watchers)\"\n.IP \"Processing signals: O(max_signal_number)\" 4\n.IX Item \"Processing signals: O(max_signal_number)\"\n.PD\nSending involves a system call \\fIiff\\fR there were no other \\f(CW\\*(C`ev_async_send\\*(C'\\fR\ncalls in the current loop iteration and the loop is currently\nblocked. Checking for async and signal events involves iterating over all\nrunning async watchers or all signal numbers.\n.SH \"PORTING FROM LIBEV 3.X TO 4.X\"\n.IX Header \"PORTING FROM LIBEV 3.X TO 4.X\"\nThe major version 4 introduced some incompatible changes to the \\s-1API.\\s0\n.PP\nAt the moment, the \\f(CW\\*(C`ev.h\\*(C'\\fR header file provides compatibility definitions\nfor all changes, so most programs should still compile. The compatibility\nlayer might be removed in later versions of libev, so better update to the\nnew \\s-1API\\s0 early than late.\n.ie n .IP \"\"\"EV_COMPAT3\"\" backwards compatibility mechanism\" 4\n.el .IP \"\\f(CWEV_COMPAT3\\fR backwards compatibility mechanism\" 4\n.IX Item \"EV_COMPAT3 backwards compatibility mechanism\"\nThe backward compatibility mechanism can be controlled by\n\\&\\f(CW\\*(C`EV_COMPAT3\\*(C'\\fR. See \\*(L\"\\s-1PREPROCESSOR SYMBOLS/MACROS\\*(R\"\\s0 in the \\*(L\"\\s-1EMBEDDING\\*(R\"\\s0\nsection.\n.ie n .IP \"\"\"ev_default_destroy\"\" and \"\"ev_default_fork\"\" have been removed\" 4\n.el .IP \"\\f(CWev_default_destroy\\fR and \\f(CWev_default_fork\\fR have been removed\" 4\n.IX Item \"ev_default_destroy and ev_default_fork have been removed\"\nThese calls can be replaced easily by their \\f(CW\\*(C`ev_loop_xxx\\*(C'\\fR counterparts:\n.Sp\n.Vb 2\n\\&   ev_loop_destroy (EV_DEFAULT_UC);\n\\&   ev_loop_fork (EV_DEFAULT);\n.Ve\n.IP \"function/symbol renames\" 4\n.IX Item \"function/symbol renames\"\nA number of functions and symbols have been renamed:\n.Sp\n.Vb 3\n\\&  ev_loop         => ev_run\n\\&  EVLOOP_NONBLOCK => EVRUN_NOWAIT\n\\&  EVLOOP_ONESHOT  => EVRUN_ONCE\n\\&\n\\&  ev_unloop       => ev_break\n\\&  EVUNLOOP_CANCEL => EVBREAK_CANCEL\n\\&  EVUNLOOP_ONE    => EVBREAK_ONE\n\\&  EVUNLOOP_ALL    => EVBREAK_ALL\n\\&\n\\&  EV_TIMEOUT      => EV_TIMER\n\\&\n\\&  ev_loop_count   => ev_iteration\n\\&  ev_loop_depth   => ev_depth\n\\&  ev_loop_verify  => ev_verify\n.Ve\n.Sp\nMost functions working on \\f(CW\\*(C`struct ev_loop\\*(C'\\fR objects don't have an\n\\&\\f(CW\\*(C`ev_loop_\\*(C'\\fR prefix, so it was removed; \\f(CW\\*(C`ev_loop\\*(C'\\fR, \\f(CW\\*(C`ev_unloop\\*(C'\\fR and\nassociated constants have been renamed to not collide with the \\f(CW\\*(C`struct\nev_loop\\*(C'\\fR anymore and \\f(CW\\*(C`EV_TIMER\\*(C'\\fR now follows the same naming scheme\nas all other watcher types. Note that \\f(CW\\*(C`ev_loop_fork\\*(C'\\fR is still called\n\\&\\f(CW\\*(C`ev_loop_fork\\*(C'\\fR because it would otherwise clash with the \\f(CW\\*(C`ev_fork\\*(C'\\fR\ntypedef.\n.ie n .IP \"\"\"EV_MINIMAL\"\" mechanism replaced by \"\"EV_FEATURES\"\"\" 4\n.el .IP \"\\f(CWEV_MINIMAL\\fR mechanism replaced by \\f(CWEV_FEATURES\\fR\" 4\n.IX Item \"EV_MINIMAL mechanism replaced by EV_FEATURES\"\nThe preprocessor symbol \\f(CW\\*(C`EV_MINIMAL\\*(C'\\fR has been replaced by a different\nmechanism, \\f(CW\\*(C`EV_FEATURES\\*(C'\\fR. Programs using \\f(CW\\*(C`EV_MINIMAL\\*(C'\\fR usually compile\nand work, but the library code will of course be larger.\n.SH \"GLOSSARY\"\n.IX Header \"GLOSSARY\"\n.IP \"active\" 4\n.IX Item \"active\"\nA watcher is active as long as it has been started and not yet stopped.\nSee \\*(L\"\\s-1WATCHER STATES\\*(R\"\\s0 for details.\n.IP \"application\" 4\n.IX Item \"application\"\nIn this document, an application is whatever is using libev.\n.IP \"backend\" 4\n.IX Item \"backend\"\nThe part of the code dealing with the operating system interfaces.\n.IP \"callback\" 4\n.IX Item \"callback\"\nThe address of a function that is called when some event has been\ndetected. Callbacks are being passed the event loop, the watcher that\nreceived the event, and the actual event bitset.\n.IP \"callback/watcher invocation\" 4\n.IX Item \"callback/watcher invocation\"\nThe act of calling the callback associated with a watcher.\n.IP \"event\" 4\n.IX Item \"event\"\nA change of state of some external event, such as data now being available\nfor reading on a file descriptor, time having passed or simply not having\nany other events happening anymore.\n.Sp\nIn libev, events are represented as single bits (such as \\f(CW\\*(C`EV_READ\\*(C'\\fR or\n\\&\\f(CW\\*(C`EV_TIMER\\*(C'\\fR).\n.IP \"event library\" 4\n.IX Item \"event library\"\nA software package implementing an event model and loop.\n.IP \"event loop\" 4\n.IX Item \"event loop\"\nAn entity that handles and processes external events and converts them\ninto callback invocations.\n.IP \"event model\" 4\n.IX Item \"event model\"\nThe model used to describe how an event loop handles and processes\nwatchers and events.\n.IP \"pending\" 4\n.IX Item \"pending\"\nA watcher is pending as soon as the corresponding event has been\ndetected. See \\*(L\"\\s-1WATCHER STATES\\*(R\"\\s0 for details.\n.IP \"real time\" 4\n.IX Item \"real time\"\nThe physical time that is observed. It is apparently strictly monotonic :)\n.IP \"wall-clock time\" 4\n.IX Item \"wall-clock time\"\nThe time and date as shown on clocks. Unlike real time, it can actually\nbe wrong and jump forwards and backwards, e.g. when you adjust your\nclock.\n.IP \"watcher\" 4\n.IX Item \"watcher\"\nA data structure that describes interest in certain events. Watchers need\nto be started (attached to an event loop) before they can receive events.\n.SH \"AUTHOR\"\n.IX Header \"AUTHOR\"\nMarc Lehmann <libev@schmorp.de>, with repeated corrections by Mikael\nMagnusson and Emanuele Giaquinta, and minor corrections by many others.\n"
  },
  {
    "path": "libev/ev.c",
    "content": "/*\n * libev event processing core, watcher management\n *\n * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n/* this big block deduces configuration from config.h */\n#ifndef EV_STANDALONE\n# ifdef EV_CONFIG_H\n#  include EV_CONFIG_H\n# else\n#  include \"config.h\"\n# endif\n\n# if HAVE_FLOOR\n#  ifndef EV_USE_FLOOR\n#   define EV_USE_FLOOR 1\n#  endif\n# endif\n\n# if HAVE_CLOCK_SYSCALL\n#  ifndef EV_USE_CLOCK_SYSCALL\n#   define EV_USE_CLOCK_SYSCALL 1\n#   ifndef EV_USE_REALTIME\n#    define EV_USE_REALTIME  0\n#   endif\n#   ifndef EV_USE_MONOTONIC\n#    define EV_USE_MONOTONIC 1\n#   endif\n#  endif\n# elif !defined EV_USE_CLOCK_SYSCALL\n#  define EV_USE_CLOCK_SYSCALL 0\n# endif\n\n# if HAVE_CLOCK_GETTIME\n#  ifndef EV_USE_MONOTONIC\n#   define EV_USE_MONOTONIC 1\n#  endif\n#  ifndef EV_USE_REALTIME\n#   define EV_USE_REALTIME  0\n#  endif\n# else\n#  ifndef EV_USE_MONOTONIC\n#   define EV_USE_MONOTONIC 0\n#  endif\n#  ifndef EV_USE_REALTIME\n#   define EV_USE_REALTIME  0\n#  endif\n# endif\n\n# if HAVE_NANOSLEEP\n#  ifndef EV_USE_NANOSLEEP\n#    define EV_USE_NANOSLEEP EV_FEATURE_OS\n#  endif\n# else\n#   undef EV_USE_NANOSLEEP\n#   define EV_USE_NANOSLEEP 0\n# endif\n\n# if HAVE_SELECT && HAVE_SYS_SELECT_H\n#  ifndef EV_USE_SELECT\n#   define EV_USE_SELECT EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_SELECT\n#  define EV_USE_SELECT 0\n# endif\n\n# if HAVE_POLL && HAVE_POLL_H\n#  ifndef EV_USE_POLL\n#   define EV_USE_POLL EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_POLL\n#  define EV_USE_POLL 0\n# endif\n   \n# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H\n#  ifndef EV_USE_EPOLL\n#   define EV_USE_EPOLL EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_EPOLL\n#  define EV_USE_EPOLL 0\n# endif\n   \n# if HAVE_KQUEUE && HAVE_SYS_EVENT_H\n#  ifndef EV_USE_KQUEUE\n#   define EV_USE_KQUEUE EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_KQUEUE\n#  define EV_USE_KQUEUE 0\n# endif\n   \n# if HAVE_PORT_H && HAVE_PORT_CREATE\n#  ifndef EV_USE_PORT\n#   define EV_USE_PORT EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_PORT\n#  define EV_USE_PORT 0\n# endif\n\n# if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H\n#  ifndef EV_USE_INOTIFY\n#   define EV_USE_INOTIFY EV_FEATURE_OS\n#  endif\n# else\n#  undef EV_USE_INOTIFY\n#  define EV_USE_INOTIFY 0\n# endif\n\n# if HAVE_SIGNALFD && HAVE_SYS_SIGNALFD_H\n#  ifndef EV_USE_SIGNALFD\n#   define EV_USE_SIGNALFD EV_FEATURE_OS\n#  endif\n# else\n#  undef EV_USE_SIGNALFD\n#  define EV_USE_SIGNALFD 0\n# endif\n\n# if HAVE_EVENTFD\n#  ifndef EV_USE_EVENTFD\n#   define EV_USE_EVENTFD EV_FEATURE_OS\n#  endif\n# else\n#  undef EV_USE_EVENTFD\n#  define EV_USE_EVENTFD 0\n# endif\n \n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <fcntl.h>\n#include <stddef.h>\n\n#include <stdio.h>\n\n#include <assert.h>\n#include <errno.h>\n#include <sys/types.h>\n#include <time.h>\n#include <limits.h>\n\n#include <signal.h>\n\n#ifdef EV_H\n# include EV_H\n#else\n# include \"ev.h\"\n#endif\n\n#if EV_NO_THREADS\n# undef EV_NO_SMP\n# define EV_NO_SMP 1\n# undef ECB_NO_THREADS\n# define ECB_NO_THREADS 1\n#endif\n#if EV_NO_SMP\n# undef EV_NO_SMP\n# define ECB_NO_SMP 1\n#endif\n\n#ifndef _WIN32\n# include <sys/time.h>\n# include <sys/wait.h>\n# include <unistd.h>\n#else\n# include <io.h>\n# define WIN32_LEAN_AND_MEAN\n# include <winsock2.h>\n# include <windows.h>\n# ifndef EV_SELECT_IS_WINSOCKET\n#  define EV_SELECT_IS_WINSOCKET 1\n# endif\n# undef EV_AVOID_STDIO\n#endif\n\n/* OS X, in its infinite idiocy, actually HARDCODES\n * a limit of 1024 into their select. Where people have brains,\n * OS X engineers apparently have a vacuum. Or maybe they were\n * ordered to have a vacuum, or they do anything for money.\n * This might help. Or not.\n */\n#define _DARWIN_UNLIMITED_SELECT 1\n\n/* this block tries to deduce configuration from header-defined symbols and defaults */\n\n/* try to deduce the maximum number of signals on this platform */\n#if defined EV_NSIG\n/* use what's provided */\n#elif defined NSIG\n# define EV_NSIG (NSIG)\n#elif defined _NSIG\n# define EV_NSIG (_NSIG)\n#elif defined SIGMAX\n# define EV_NSIG (SIGMAX+1)\n#elif defined SIG_MAX\n# define EV_NSIG (SIG_MAX+1)\n#elif defined _SIG_MAX\n# define EV_NSIG (_SIG_MAX+1)\n#elif defined MAXSIG\n# define EV_NSIG (MAXSIG+1)\n#elif defined MAX_SIG\n# define EV_NSIG (MAX_SIG+1)\n#elif defined SIGARRAYSIZE\n# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */\n#elif defined _sys_nsig\n# define EV_NSIG (_sys_nsig) /* Solaris 2.5 */\n#else\n# define EV_NSIG (8 * sizeof (sigset_t) + 1)\n#endif\n\n#ifndef EV_USE_FLOOR\n# define EV_USE_FLOOR 0\n#endif\n\n#ifndef EV_USE_CLOCK_SYSCALL\n# if __linux && __GLIBC__ == 2 && __GLIBC_MINOR__ < 17\n#  define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS\n# else\n#  define EV_USE_CLOCK_SYSCALL 0\n# endif\n#endif\n\n#if !(_POSIX_TIMERS > 0)\n# ifndef EV_USE_MONOTONIC\n#  define EV_USE_MONOTONIC 0\n# endif\n# ifndef EV_USE_REALTIME\n#  define EV_USE_REALTIME 0\n# endif\n#endif\n\n#ifndef EV_USE_MONOTONIC\n# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0\n#  define EV_USE_MONOTONIC EV_FEATURE_OS\n# else\n#  define EV_USE_MONOTONIC 0\n# endif\n#endif\n\n#ifndef EV_USE_REALTIME\n# define EV_USE_REALTIME !EV_USE_CLOCK_SYSCALL\n#endif\n\n#ifndef EV_USE_NANOSLEEP\n# if _POSIX_C_SOURCE >= 199309L\n#  define EV_USE_NANOSLEEP EV_FEATURE_OS\n# else\n#  define EV_USE_NANOSLEEP 0\n# endif\n#endif\n\n#ifndef EV_USE_SELECT\n# define EV_USE_SELECT EV_FEATURE_BACKENDS\n#endif\n\n#ifndef EV_USE_POLL\n# ifdef _WIN32\n#  define EV_USE_POLL 0\n# else\n#  define EV_USE_POLL EV_FEATURE_BACKENDS\n# endif\n#endif\n\n#ifndef EV_USE_EPOLL\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))\n#  define EV_USE_EPOLL EV_FEATURE_BACKENDS\n# else\n#  define EV_USE_EPOLL 0\n# endif\n#endif\n\n#ifndef EV_USE_KQUEUE\n# define EV_USE_KQUEUE 0\n#endif\n\n#ifndef EV_USE_PORT\n# define EV_USE_PORT 0\n#endif\n\n#ifndef EV_USE_INOTIFY\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))\n#  define EV_USE_INOTIFY EV_FEATURE_OS\n# else\n#  define EV_USE_INOTIFY 0\n# endif\n#endif\n\n#ifndef EV_PID_HASHSIZE\n# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1\n#endif\n\n#ifndef EV_INOTIFY_HASHSIZE\n# define EV_INOTIFY_HASHSIZE EV_FEATURE_DATA ? 16 : 1\n#endif\n\n#ifndef EV_USE_EVENTFD\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))\n#  define EV_USE_EVENTFD EV_FEATURE_OS\n# else\n#  define EV_USE_EVENTFD 0\n# endif\n#endif\n\n#ifndef EV_USE_SIGNALFD\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))\n#  define EV_USE_SIGNALFD EV_FEATURE_OS\n# else\n#  define EV_USE_SIGNALFD 0\n# endif\n#endif\n\n#if 0 /* debugging */\n# define EV_VERIFY 3\n# define EV_USE_4HEAP 1\n# define EV_HEAP_CACHE_AT 1\n#endif\n\n#ifndef EV_VERIFY\n# define EV_VERIFY (EV_FEATURE_API ? 1 : 0)\n#endif\n\n#ifndef EV_USE_4HEAP\n# define EV_USE_4HEAP EV_FEATURE_DATA\n#endif\n\n#ifndef EV_HEAP_CACHE_AT\n# define EV_HEAP_CACHE_AT EV_FEATURE_DATA\n#endif\n\n#ifdef __ANDROID__\n/* supposedly, android doesn't typedef fd_mask */\n# undef EV_USE_SELECT\n# define EV_USE_SELECT 0\n/* supposedly, we need to include syscall.h, not sys/syscall.h, so just disable */\n# undef EV_USE_CLOCK_SYSCALL\n# define EV_USE_CLOCK_SYSCALL 0\n#endif\n\n/* aix's poll.h seems to cause lots of trouble */\n#ifdef _AIX\n/* AIX has a completely broken poll.h header */\n# undef EV_USE_POLL\n# define EV_USE_POLL 0\n#endif\n\n/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */\n/* which makes programs even slower. might work on other unices, too. */\n#if EV_USE_CLOCK_SYSCALL\n# include <sys/syscall.h>\n# ifdef SYS_clock_gettime\n#  define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))\n#  undef EV_USE_MONOTONIC\n#  define EV_USE_MONOTONIC 1\n# else\n#  undef EV_USE_CLOCK_SYSCALL\n#  define EV_USE_CLOCK_SYSCALL 0\n# endif\n#endif\n\n/* this block fixes any misconfiguration where we know we run into trouble otherwise */\n\n#ifndef CLOCK_MONOTONIC\n# undef EV_USE_MONOTONIC\n# define EV_USE_MONOTONIC 0\n#endif\n\n#ifndef CLOCK_REALTIME\n# undef EV_USE_REALTIME\n# define EV_USE_REALTIME 0\n#endif\n\n#if !EV_STAT_ENABLE\n# undef EV_USE_INOTIFY\n# define EV_USE_INOTIFY 0\n#endif\n\n#if !EV_USE_NANOSLEEP\n/* hp-ux has it in sys/time.h, which we unconditionally include above */\n# if !defined _WIN32 && !defined __hpux\n#  include <sys/select.h>\n# endif\n#endif\n\n#if EV_USE_INOTIFY\n# include <sys/statfs.h>\n# include <sys/inotify.h>\n/* some very old inotify.h headers don't have IN_DONT_FOLLOW */\n# ifndef IN_DONT_FOLLOW\n#  undef EV_USE_INOTIFY\n#  define EV_USE_INOTIFY 0\n# endif\n#endif\n\n#if EV_USE_EVENTFD\n/* our minimum requirement is glibc 2.7 which has the stub, but not the header */\n# include <stdint.h>\n# ifndef EFD_NONBLOCK\n#  define EFD_NONBLOCK O_NONBLOCK\n# endif\n# ifndef EFD_CLOEXEC\n#  ifdef O_CLOEXEC\n#   define EFD_CLOEXEC O_CLOEXEC\n#  else\n#   define EFD_CLOEXEC 02000000\n#  endif\n# endif\nEV_CPP(extern \"C\") int (eventfd) (unsigned int initval, int flags);\n#endif\n\n#if EV_USE_SIGNALFD\n/* our minimum requirement is glibc 2.7 which has the stub, but not the header */\n# include <stdint.h>\n# ifndef SFD_NONBLOCK\n#  define SFD_NONBLOCK O_NONBLOCK\n# endif\n# ifndef SFD_CLOEXEC\n#  ifdef O_CLOEXEC\n#   define SFD_CLOEXEC O_CLOEXEC\n#  else\n#   define SFD_CLOEXEC 02000000\n#  endif\n# endif\nEV_CPP (extern \"C\") int signalfd (int fd, const sigset_t *mask, int flags);\n\nstruct signalfd_siginfo\n{\n  uint32_t ssi_signo;\n  char pad[128 - sizeof (uint32_t)];\n};\n#endif\n\n/**/\n\n#if EV_VERIFY >= 3\n# define EV_FREQUENT_CHECK ev_verify (EV_A)\n#else\n# define EV_FREQUENT_CHECK do { } while (0)\n#endif\n\n/*\n * This is used to work around floating point rounding problems.\n * This value is good at least till the year 4000.\n */\n#define MIN_INTERVAL  0.0001220703125 /* 1/2**13, good till 4000 */\n/*#define MIN_INTERVAL  0.00000095367431640625 /* 1/2**20, good till 2200 */\n\n#define MIN_TIMEJUMP  1. /* minimum timejump that gets detected (if monotonic clock available) */\n#define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */\n\n#define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0)\n#define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)\n\n/* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */\n/* ECB.H BEGIN */\n/*\n * libecb - http://software.schmorp.de/pkg/libecb\n *\n * Copyright (©) 2009-2015 Marc Alexander Lehmann <libecb@schmorp.de>\n * Copyright (©) 2011 Emanuele Giaquinta\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef ECB_H\n#define ECB_H\n\n/* 16 bits major, 16 bits minor */\n#define ECB_VERSION 0x00010005\n\n#ifdef _WIN32\n  typedef   signed char   int8_t;\n  typedef unsigned char  uint8_t;\n  typedef   signed short  int16_t;\n  typedef unsigned short uint16_t;\n  typedef   signed int    int32_t;\n  typedef unsigned int   uint32_t;\n  #if __GNUC__\n    typedef   signed long long int64_t;\n    typedef unsigned long long uint64_t;\n  #else /* _MSC_VER || __BORLANDC__ */\n    typedef   signed __int64   int64_t;\n    typedef unsigned __int64   uint64_t;\n  #endif\n  #ifdef _WIN64\n    #define ECB_PTRSIZE 8\n    typedef uint64_t uintptr_t;\n    typedef  int64_t  intptr_t;\n  #else\n    #define ECB_PTRSIZE 4\n    typedef uint32_t uintptr_t;\n    typedef  int32_t  intptr_t;\n  #endif\n#else\n  #include <inttypes.h>\n  #if (defined INTPTR_MAX ? INTPTR_MAX : ULONG_MAX) > 0xffffffffU\n    #define ECB_PTRSIZE 8\n  #else\n    #define ECB_PTRSIZE 4\n  #endif\n#endif\n\n#define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__)\n#define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64)\n\n/* work around x32 idiocy by defining proper macros */\n#if ECB_GCC_AMD64 || ECB_MSVC_AMD64\n  #if _ILP32\n    #define ECB_AMD64_X32 1\n  #else\n    #define ECB_AMD64 1\n  #endif\n#endif\n\n/* many compilers define _GNUC_ to some versions but then only implement\n * what their idiot authors think are the \"more important\" extensions,\n * causing enormous grief in return for some better fake benchmark numbers.\n * or so.\n * we try to detect these and simply assume they are not gcc - if they have\n * an issue with that they should have done it right in the first place.\n */\n#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__\n  #define ECB_GCC_VERSION(major,minor) 0\n#else\n  #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))\n#endif\n\n#define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor)))\n\n#if __clang__ && defined __has_builtin\n  #define ECB_CLANG_BUILTIN(x) __has_builtin (x)\n#else\n  #define ECB_CLANG_BUILTIN(x) 0\n#endif\n\n#if __clang__ && defined __has_extension\n  #define ECB_CLANG_EXTENSION(x) __has_extension (x)\n#else\n  #define ECB_CLANG_EXTENSION(x) 0\n#endif\n\n#define ECB_CPP   (__cplusplus+0)\n#define ECB_CPP11 (__cplusplus >= 201103L)\n\n#if ECB_CPP\n  #define ECB_C            0\n  #define ECB_STDC_VERSION 0\n#else\n  #define ECB_C            1\n  #define ECB_STDC_VERSION __STDC_VERSION__\n#endif\n\n#define ECB_C99   (ECB_STDC_VERSION >= 199901L)\n#define ECB_C11   (ECB_STDC_VERSION >= 201112L)\n\n#if ECB_CPP\n  #define ECB_EXTERN_C extern \"C\"\n  #define ECB_EXTERN_C_BEG ECB_EXTERN_C {\n  #define ECB_EXTERN_C_END }\n#else\n  #define ECB_EXTERN_C extern\n  #define ECB_EXTERN_C_BEG\n  #define ECB_EXTERN_C_END\n#endif\n\n/*****************************************************************************/\n\n/* ECB_NO_THREADS - ecb is not used by multiple threads, ever */\n/* ECB_NO_SMP     - ecb might be used in multiple threads, but only on a single cpu */\n\n#if ECB_NO_THREADS\n  #define ECB_NO_SMP 1\n#endif\n\n#if ECB_NO_SMP\n  #define ECB_MEMORY_FENCE do { } while (0)\n#endif\n\n/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */\n#if __xlC__ && ECB_CPP\n  #include <builtins.h>\n#endif\n\n#if 1400 <= _MSC_VER\n  #include <intrin.h> /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n  #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110\n    #if __i386 || __i386__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"lock; orb $0, -1(%%esp)\" : : : \"memory\")\n      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (\"\"                        : : : \"memory\")\n      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ (\"\")\n    #elif ECB_GCC_AMD64\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"mfence\"   : : : \"memory\")\n      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (\"\"         : : : \"memory\")\n      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ (\"\")\n    #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"sync\"     : : : \"memory\")\n    #elif defined __ARM_ARCH_2__ \\\n      || defined __ARM_ARCH_3__  || defined __ARM_ARCH_3M__  \\\n      || defined __ARM_ARCH_4__  || defined __ARM_ARCH_4T__  \\\n      || defined __ARM_ARCH_5__  || defined __ARM_ARCH_5E__  \\\n      || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__ \\\n      || defined __ARM_ARCH_5TEJ__\n      /* should not need any, unless running old code on newer cpu - arm doesn't support that */\n    #elif defined __ARM_ARCH_6__  || defined __ARM_ARCH_6J__  \\\n       || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ \\\n       || defined __ARM_ARCH_6T2__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"mcr p15,0,%0,c7,c10,5\" : : \"r\" (0) : \"memory\")\n    #elif defined __ARM_ARCH_7__  || defined __ARM_ARCH_7A__  \\\n       || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"dmb\"      : : : \"memory\")\n    #elif __aarch64__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"dmb ish\"  : : : \"memory\")\n    #elif (__sparc || __sparc__) && !(__sparc_v8__ || defined __sparcv8)\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad\" : : : \"memory\")\n      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (\"membar #LoadStore | #LoadLoad\"                            : : : \"memory\")\n      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ (\"membar #LoadStore             | #StoreStore\")\n    #elif defined __s390__ || defined __s390x__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"bcr 15,0\" : : : \"memory\")\n    #elif defined __mips__\n      /* GNU/Linux emulates sync on mips1 architectures, so we force its use */\n      /* anybody else who still uses mips1 is supposed to send in their version, with detection code. */\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\".set mips2; sync; .set mips0\" : : : \"memory\")\n    #elif defined __alpha__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"mb\"       : : : \"memory\")\n    #elif defined __hppa__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"\"         : : : \"memory\")\n      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ (\"\")\n    #elif defined __ia64__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"mf\"       : : : \"memory\")\n    #elif defined __m68k__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"\"         : : : \"memory\")\n    #elif defined __m88k__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"tb1 0,%%r0,128\" : : : \"memory\")\n    #elif defined __sh__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"\"         : : : \"memory\")\n    #endif\n  #endif\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n  #if ECB_GCC_VERSION(4,7)\n    /* see comment below (stdatomic.h) about the C11 memory model. */\n    #define ECB_MEMORY_FENCE         __atomic_thread_fence (__ATOMIC_SEQ_CST)\n    #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)\n    #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)\n\n  #elif ECB_CLANG_EXTENSION(c_atomic)\n    /* see comment below (stdatomic.h) about the C11 memory model. */\n    #define ECB_MEMORY_FENCE         __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)\n    #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)\n    #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)\n\n  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__\n    #define ECB_MEMORY_FENCE         __sync_synchronize ()\n  #elif _MSC_VER >= 1500 /* VC++ 2008 */\n    /* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */\n    #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)\n    #define ECB_MEMORY_FENCE         _ReadWriteBarrier (); MemoryBarrier()\n    #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */\n    #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier()\n  #elif _MSC_VER >= 1400 /* VC++ 2005 */\n    #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)\n    #define ECB_MEMORY_FENCE         _ReadWriteBarrier ()\n    #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */\n    #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()\n  #elif defined _WIN32\n    #include <WinNT.h>\n    #define ECB_MEMORY_FENCE         MemoryBarrier () /* actually just xchg on x86... scary */\n  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110\n    #include <mbarrier.h>\n    #define ECB_MEMORY_FENCE         __machine_rw_barrier ()\n    #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier  ()\n    #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier  ()\n  #elif __xlC__\n    #define ECB_MEMORY_FENCE         __sync ()\n  #endif\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n  #if ECB_C11 && !defined __STDC_NO_ATOMICS__\n    /* we assume that these memory fences work on all variables/all memory accesses, */\n    /* not just C11 atomics and atomic accesses */\n    #include <stdatomic.h>\n    /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */\n    /* any fence other than seq_cst, which isn't very efficient for us. */\n    /* Why that is, we don't know - either the C11 memory model is quite useless */\n    /* for most usages, or gcc and clang have a bug */\n    /* I *currently* lean towards the latter, and inefficiently implement */\n    /* all three of ecb's fences as a seq_cst fence */\n    /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */\n    /* for all __atomic_thread_fence's except seq_cst */\n    #define ECB_MEMORY_FENCE         atomic_thread_fence (memory_order_seq_cst)\n  #endif\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n  #if !ECB_AVOID_PTHREADS\n    /*\n     * if you get undefined symbol references to pthread_mutex_lock,\n     * or failure to find pthread.h, then you should implement\n     * the ECB_MEMORY_FENCE operations for your cpu/compiler\n     * OR provide pthread.h and link against the posix thread library\n     * of your system.\n     */\n    #include <pthread.h>\n    #define ECB_NEEDS_PTHREADS 1\n    #define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1\n\n    static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER;\n    #define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0)\n  #endif\n#endif\n\n#if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE\n  #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE\n#endif\n\n#if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE\n  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE\n#endif\n\n/*****************************************************************************/\n\n#if ECB_CPP\n  #define ecb_inline static inline\n#elif ECB_GCC_VERSION(2,5)\n  #define ecb_inline static __inline__\n#elif ECB_C99\n  #define ecb_inline static inline\n#else\n  #define ecb_inline static\n#endif\n\n#if ECB_GCC_VERSION(3,3)\n  #define ecb_restrict __restrict__\n#elif ECB_C99\n  #define ecb_restrict restrict\n#else\n  #define ecb_restrict\n#endif\n\ntypedef int ecb_bool;\n\n#define ECB_CONCAT_(a, b) a ## b\n#define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)\n#define ECB_STRINGIFY_(a) # a\n#define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)\n#define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr))\n\n#define ecb_function_ ecb_inline\n\n#if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8)\n  #define ecb_attribute(attrlist)        __attribute__ (attrlist)\n#else\n  #define ecb_attribute(attrlist)\n#endif\n\n#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_constant_p)\n  #define ecb_is_constant(expr)          __builtin_constant_p (expr)\n#else\n  /* possible C11 impl for integral types\n  typedef struct ecb_is_constant_struct ecb_is_constant_struct;\n  #define ecb_is_constant(expr)          _Generic ((1 ? (struct ecb_is_constant_struct *)0 : (void *)((expr) - (expr)), ecb_is_constant_struct *: 0, default: 1)) */\n\n  #define ecb_is_constant(expr)          0\n#endif\n\n#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_expect)\n  #define ecb_expect(expr,value)         __builtin_expect ((expr),(value))\n#else\n  #define ecb_expect(expr,value)         (expr)\n#endif\n\n#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_prefetch)\n  #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)\n#else\n  #define ecb_prefetch(addr,rw,locality)\n#endif\n\n/* no emulation for ecb_decltype */\n#if ECB_CPP11\n  // older implementations might have problems with decltype(x)::type, work around it\n  template<class T> struct ecb_decltype_t { typedef T type; };\n  #define ecb_decltype(x) ecb_decltype_t<decltype (x)>::type\n#elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8)\n  #define ecb_decltype(x) __typeof__ (x)\n#endif\n\n#if _MSC_VER >= 1300\n  #define ecb_deprecated __declspec (deprecated)\n#else\n  #define ecb_deprecated ecb_attribute ((__deprecated__))\n#endif\n\n#if _MSC_VER >= 1500\n  #define ecb_deprecated_message(msg) __declspec (deprecated (msg))\n#elif ECB_GCC_VERSION(4,5)\n  #define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg))\n#else\n  #define ecb_deprecated_message(msg) ecb_deprecated\n#endif\n\n#if _MSC_VER >= 1400\n  #define ecb_noinline __declspec (noinline)\n#else\n  #define ecb_noinline ecb_attribute ((__noinline__))\n#endif\n\n#define ecb_unused     ecb_attribute ((__unused__))\n#define ecb_const      ecb_attribute ((__const__))\n#define ecb_pure       ecb_attribute ((__pure__))\n\n#if ECB_C11 || __IBMC_NORETURN\n  /* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */\n  #define ecb_noreturn   _Noreturn\n#elif ECB_CPP11\n  #define ecb_noreturn   [[noreturn]]\n#elif _MSC_VER >= 1200\n  /* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */\n  #define ecb_noreturn   __declspec (noreturn)\n#else\n  #define ecb_noreturn   ecb_attribute ((__noreturn__))\n#endif\n\n#if ECB_GCC_VERSION(4,3)\n  #define ecb_artificial ecb_attribute ((__artificial__))\n  #define ecb_hot        ecb_attribute ((__hot__))\n  #define ecb_cold       ecb_attribute ((__cold__))\n#else\n  #define ecb_artificial\n  #define ecb_hot\n  #define ecb_cold\n#endif\n\n/* put around conditional expressions if you are very sure that the  */\n/* expression is mostly true or mostly false. note that these return */\n/* booleans, not the expression.                                     */\n#define ecb_expect_false(expr) ecb_expect (!!(expr), 0)\n#define ecb_expect_true(expr)  ecb_expect (!!(expr), 1)\n/* for compatibility to the rest of the world */\n#define ecb_likely(expr)   ecb_expect_true  (expr)\n#define ecb_unlikely(expr) ecb_expect_false (expr)\n\n/* count trailing zero bits and count # of one bits */\n#if ECB_GCC_VERSION(3,4) \\\n    || (ECB_CLANG_BUILTIN(__builtin_clz) && ECB_CLANG_BUILTIN(__builtin_clzll) \\\n        && ECB_CLANG_BUILTIN(__builtin_ctz) && ECB_CLANG_BUILTIN(__builtin_ctzll) \\\n        && ECB_CLANG_BUILTIN(__builtin_popcount))\n  /* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */\n  #define ecb_ld32(x)      (__builtin_clz      (x) ^ 31)\n  #define ecb_ld64(x)      (__builtin_clzll    (x) ^ 63)\n  #define ecb_ctz32(x)      __builtin_ctz      (x)\n  #define ecb_ctz64(x)      __builtin_ctzll    (x)\n  #define ecb_popcount32(x) __builtin_popcount (x)\n  /* no popcountll */\n#else\n  ecb_function_ ecb_const int ecb_ctz32 (uint32_t x);\n  ecb_function_ ecb_const int\n  ecb_ctz32 (uint32_t x)\n  {\n#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)\n    unsigned long r;\n    _BitScanForward (&r, x);\n    return (int)r;\n#else\n    int r = 0;\n\n    x &= ~x + 1; /* this isolates the lowest bit */\n\n#if ECB_branchless_on_i386\n    r += !!(x & 0xaaaaaaaa) << 0;\n    r += !!(x & 0xcccccccc) << 1;\n    r += !!(x & 0xf0f0f0f0) << 2;\n    r += !!(x & 0xff00ff00) << 3;\n    r += !!(x & 0xffff0000) << 4;\n#else\n    if (x & 0xaaaaaaaa) r +=  1;\n    if (x & 0xcccccccc) r +=  2;\n    if (x & 0xf0f0f0f0) r +=  4;\n    if (x & 0xff00ff00) r +=  8;\n    if (x & 0xffff0000) r += 16;\n#endif\n\n    return r;\n#endif\n  }\n\n  ecb_function_ ecb_const int ecb_ctz64 (uint64_t x);\n  ecb_function_ ecb_const int\n  ecb_ctz64 (uint64_t x)\n  {\n#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)\n    unsigned long r;\n    _BitScanForward64 (&r, x);\n    return (int)r;\n#else\n    int shift = x & 0xffffffff ? 0 : 32;\n    return ecb_ctz32 (x >> shift) + shift;\n#endif\n  }\n\n  ecb_function_ ecb_const int ecb_popcount32 (uint32_t x);\n  ecb_function_ ecb_const int\n  ecb_popcount32 (uint32_t x)\n  {\n    x -=  (x >> 1) & 0x55555555;\n    x  = ((x >> 2) & 0x33333333) + (x & 0x33333333);\n    x  = ((x >> 4) + x) & 0x0f0f0f0f;\n    x *= 0x01010101;\n\n    return x >> 24;\n  }\n\n  ecb_function_ ecb_const int ecb_ld32 (uint32_t x);\n  ecb_function_ ecb_const int ecb_ld32 (uint32_t x)\n  {\n#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)\n    unsigned long r;\n    _BitScanReverse (&r, x);\n    return (int)r;\n#else\n    int r = 0;\n\n    if (x >> 16) { x >>= 16; r += 16; }\n    if (x >>  8) { x >>=  8; r +=  8; }\n    if (x >>  4) { x >>=  4; r +=  4; }\n    if (x >>  2) { x >>=  2; r +=  2; }\n    if (x >>  1) {           r +=  1; }\n\n    return r;\n#endif\n  }\n\n  ecb_function_ ecb_const int ecb_ld64 (uint64_t x);\n  ecb_function_ ecb_const int ecb_ld64 (uint64_t x)\n  {\n#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)\n    unsigned long r;\n    _BitScanReverse64 (&r, x);\n    return (int)r;\n#else\n    int r = 0;\n\n    if (x >> 32) { x >>= 32; r += 32; }\n\n    return r + ecb_ld32 (x);\n#endif\n  }\n#endif\n\necb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x);\necb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }\necb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x);\necb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }\n\necb_function_ ecb_const uint8_t  ecb_bitrev8  (uint8_t  x);\necb_function_ ecb_const uint8_t  ecb_bitrev8  (uint8_t  x)\n{\n  return (  (x * 0x0802U & 0x22110U)\n          | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;\n}\n\necb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x);\necb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x)\n{\n  x = ((x >>  1) &     0x5555) | ((x &     0x5555) <<  1);\n  x = ((x >>  2) &     0x3333) | ((x &     0x3333) <<  2);\n  x = ((x >>  4) &     0x0f0f) | ((x &     0x0f0f) <<  4);\n  x = ( x >>  8              ) | ( x               <<  8);\n\n  return x;\n}\n\necb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x);\necb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x)\n{\n  x = ((x >>  1) & 0x55555555) | ((x & 0x55555555) <<  1);\n  x = ((x >>  2) & 0x33333333) | ((x & 0x33333333) <<  2);\n  x = ((x >>  4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) <<  4);\n  x = ((x >>  8) & 0x00ff00ff) | ((x & 0x00ff00ff) <<  8);\n  x = ( x >> 16              ) | ( x               << 16);\n\n  return x;\n}\n\n/* popcount64 is only available on 64 bit cpus as gcc builtin */\n/* so for this version we are lazy */\necb_function_ ecb_const int ecb_popcount64 (uint64_t x);\necb_function_ ecb_const int\necb_popcount64 (uint64_t x)\n{\n  return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);\n}\n\necb_inline ecb_const uint8_t  ecb_rotl8  (uint8_t  x, unsigned int count);\necb_inline ecb_const uint8_t  ecb_rotr8  (uint8_t  x, unsigned int count);\necb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count);\necb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count);\necb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count);\necb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count);\necb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count);\necb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count);\n\necb_inline ecb_const uint8_t  ecb_rotl8  (uint8_t  x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }\necb_inline ecb_const uint8_t  ecb_rotr8  (uint8_t  x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }\necb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }\necb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }\necb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }\necb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }\necb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }\necb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }\n\n#if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64))\n  #if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16)\n  #define ecb_bswap16(x)  __builtin_bswap16 (x)\n  #else\n  #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)\n  #endif\n  #define ecb_bswap32(x)  __builtin_bswap32 (x)\n  #define ecb_bswap64(x)  __builtin_bswap64 (x)\n#elif _MSC_VER\n  #include <stdlib.h>\n  #define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x)))\n  #define ecb_bswap32(x) ((uint32_t)_byteswap_ulong  ((uint32_t)(x)))\n  #define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x)))\n#else\n  ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x);\n  ecb_function_ ecb_const uint16_t\n  ecb_bswap16 (uint16_t x)\n  {\n    return ecb_rotl16 (x, 8);\n  }\n\n  ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x);\n  ecb_function_ ecb_const uint32_t\n  ecb_bswap32 (uint32_t x)\n  {\n    return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);\n  }\n\n  ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x);\n  ecb_function_ ecb_const uint64_t\n  ecb_bswap64 (uint64_t x)\n  {\n    return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);\n  }\n#endif\n\n#if ECB_GCC_VERSION(4,5) || ECB_CLANG_BUILTIN(__builtin_unreachable)\n  #define ecb_unreachable() __builtin_unreachable ()\n#else\n  /* this seems to work fine, but gcc always emits a warning for it :/ */\n  ecb_inline ecb_noreturn void ecb_unreachable (void);\n  ecb_inline ecb_noreturn void ecb_unreachable (void) { }\n#endif\n\n/* try to tell the compiler that some condition is definitely true */\n#define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0\n\necb_inline ecb_const uint32_t ecb_byteorder_helper (void);\necb_inline ecb_const uint32_t\necb_byteorder_helper (void)\n{\n  /* the union code still generates code under pressure in gcc, */\n  /* but less than using pointers, and always seems to */\n  /* successfully return a constant. */\n  /* the reason why we have this horrible preprocessor mess */\n  /* is to avoid it in all cases, at least on common architectures */\n  /* or when using a recent enough gcc version (>= 4.6) */\n#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \\\n    || ((__i386 || __i386__ || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64) && !__VOS__)\n  #define ECB_LITTLE_ENDIAN 1\n  return 0x44332211;\n#elif (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \\\n      || ((__AARCH64EB__ || __MIPSEB__ || __ARMEB__) && !__VOS__)\n  #define ECB_BIG_ENDIAN 1\n  return 0x11223344;\n#else\n  union\n  {\n    uint8_t c[4];\n    uint32_t u;\n  } u = { 0x11, 0x22, 0x33, 0x44 };\n  return u.u;\n#endif\n}\n\necb_inline ecb_const ecb_bool ecb_big_endian    (void);\necb_inline ecb_const ecb_bool ecb_big_endian    (void) { return ecb_byteorder_helper () == 0x11223344; }\necb_inline ecb_const ecb_bool ecb_little_endian (void);\necb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44332211; }\n\n#if ECB_GCC_VERSION(3,0) || ECB_C99\n  #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))\n#else\n  #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))\n#endif\n\n#if ECB_CPP\n  template<typename T>\n  static inline T ecb_div_rd (T val, T div)\n  {\n    return val < 0 ? - ((-val + div - 1) / div) : (val          ) / div;\n  }\n  template<typename T>\n  static inline T ecb_div_ru (T val, T div)\n  {\n    return val < 0 ? - ((-val          ) / div) : (val + div - 1) / div;\n  }\n#else\n  #define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val)            ) / (div))\n  #define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val)            ) / (div)) : ((val) + (div) - 1) / (div))\n#endif\n\n#if ecb_cplusplus_does_not_suck\n  /* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */\n  template<typename T, int N>\n  static inline int ecb_array_length (const T (&arr)[N])\n  {\n    return N;\n  }\n#else\n  #define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))\n#endif\n\necb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x);\necb_function_ ecb_const uint32_t\necb_binary16_to_binary32 (uint32_t x)\n{\n  unsigned int s = (x & 0x8000) << (31 - 15);\n  int          e = (x >> 10) & 0x001f;\n  unsigned int m =  x        & 0x03ff;\n\n  if (ecb_expect_false (e == 31))\n    /* infinity or NaN */\n    e = 255 - (127 - 15);\n  else if (ecb_expect_false (!e))\n    {\n      if (ecb_expect_true (!m))\n        /* zero, handled by code below by forcing e to 0 */\n        e = 0 - (127 - 15);\n      else\n        {\n          /* subnormal, renormalise */\n          unsigned int s = 10 - ecb_ld32 (m);\n\n          m = (m << s) & 0x3ff; /* mask implicit bit */\n          e -= s - 1;\n        }\n    }\n\n  /* e and m now are normalised, or zero, (or inf or nan) */\n  e += 127 - 15;\n\n  return s | (e << 23) | (m << (23 - 10));\n}\n\necb_function_ ecb_const uint16_t ecb_binary32_to_binary16 (uint32_t x);\necb_function_ ecb_const uint16_t\necb_binary32_to_binary16 (uint32_t x)\n{\n  unsigned int s =  (x >> 16) & 0x00008000; /* sign bit, the easy part */\n  unsigned int e = ((x >> 23) & 0x000000ff) - (127 - 15); /* the desired exponent */\n  unsigned int m =   x        & 0x007fffff;\n\n  x &= 0x7fffffff;\n\n  /* if it's within range of binary16 normals, use fast path */\n  if (ecb_expect_true (0x38800000 <= x && x <= 0x477fefff))\n    {\n      /* mantissa round-to-even */\n      m += 0x00000fff + ((m >> (23 - 10)) & 1);\n\n      /* handle overflow */\n      if (ecb_expect_false (m >= 0x00800000))\n        {\n          m >>= 1;\n          e +=  1;\n        }\n\n      return s | (e << 10) | (m >> (23 - 10));\n    }\n\n  /* handle large numbers and infinity */\n  if (ecb_expect_true (0x477fefff < x && x <= 0x7f800000))\n    return s | 0x7c00;\n\n  /* handle zero, subnormals and small numbers */\n  if (ecb_expect_true (x < 0x38800000))\n    {\n      /* zero */\n      if (ecb_expect_true (!x))\n        return s;\n\n      /* handle subnormals */\n\n      /* too small, will be zero */\n      if (e < (14 - 24)) /* might not be sharp, but is good enough */\n        return s;\n\n      m |= 0x00800000; /* make implicit bit explicit */\n\n      /* very tricky - we need to round to the nearest e (+10) bit value */\n      {\n        unsigned int bits = 14 - e;\n        unsigned int half = (1 << (bits - 1)) - 1;\n        unsigned int even = (m >> bits) & 1;\n\n        /* if this overflows, we will end up with a normalised number */\n        m = (m + half + even) >> bits;\n      }\n\n      return s | m;\n    }\n\n  /* handle NaNs, preserve leftmost nan bits, but make sure we don't turn them into infinities */\n  m >>= 13;\n\n  return s | 0x7c00 | m | !m;\n}\n\n/*******************************************************************************/\n/* floating point stuff, can be disabled by defining ECB_NO_LIBM */\n\n/* basically, everything uses \"ieee pure-endian\" floating point numbers */\n/* the only noteworthy exception is ancient armle, which uses order 43218765 */\n#if 0 \\\n    || __i386 || __i386__ \\\n    || ECB_GCC_AMD64 \\\n    || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \\\n    || defined __s390__ || defined __s390x__ \\\n    || defined __mips__ \\\n    || defined __alpha__ \\\n    || defined __hppa__ \\\n    || defined __ia64__ \\\n    || defined __m68k__ \\\n    || defined __m88k__ \\\n    || defined __sh__ \\\n    || defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \\\n    || (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \\\n    || defined __aarch64__\n  #define ECB_STDFP 1\n  #include <string.h> /* for memcpy */\n#else\n  #define ECB_STDFP 0\n#endif\n\n#ifndef ECB_NO_LIBM\n\n  #include <math.h> /* for frexp*, ldexp*, INFINITY, NAN */\n\n  /* only the oldest of old doesn't have this one. solaris. */\n  #ifdef INFINITY\n    #define ECB_INFINITY INFINITY\n  #else\n    #define ECB_INFINITY HUGE_VAL\n  #endif\n\n  #ifdef NAN\n    #define ECB_NAN NAN\n  #else\n    #define ECB_NAN ECB_INFINITY\n  #endif\n\n  #if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L\n    #define ecb_ldexpf(x,e) ldexpf ((x), (e))\n    #define ecb_frexpf(x,e) frexpf ((x), (e))\n  #else\n    #define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e))\n    #define ecb_frexpf(x,e) (float) frexp ((double) (x), (e))\n  #endif\n\n  /* convert a float to ieee single/binary32 */\n  ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x);\n  ecb_function_ ecb_const uint32_t\n  ecb_float_to_binary32 (float x)\n  {\n    uint32_t r;\n\n    #if ECB_STDFP\n      memcpy (&r, &x, 4);\n    #else\n      /* slow emulation, works for anything but -0 */\n      uint32_t m;\n      int e;\n\n      if (x == 0e0f                    ) return 0x00000000U;\n      if (x > +3.40282346638528860e+38f) return 0x7f800000U;\n      if (x < -3.40282346638528860e+38f) return 0xff800000U;\n      if (x != x                       ) return 0x7fbfffffU;\n\n      m = ecb_frexpf (x, &e) * 0x1000000U;\n\n      r = m & 0x80000000U;\n\n      if (r)\n        m = -m;\n\n      if (e <= -126)\n        {\n          m &= 0xffffffU;\n          m >>= (-125 - e);\n          e = -126;\n        }\n\n      r |= (e + 126) << 23;\n      r |= m & 0x7fffffU;\n    #endif\n\n    return r;\n  }\n\n  /* converts an ieee single/binary32 to a float */\n  ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x);\n  ecb_function_ ecb_const float\n  ecb_binary32_to_float (uint32_t x)\n  {\n    float r;\n\n    #if ECB_STDFP\n      memcpy (&r, &x, 4);\n    #else\n      /* emulation, only works for normals and subnormals and +0 */\n      int neg = x >> 31;\n      int e = (x >> 23) & 0xffU;\n\n      x &= 0x7fffffU;\n\n      if (e)\n        x |= 0x800000U;\n      else\n        e = 1;\n\n      /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */\n      r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126);\n\n      r = neg ? -r : r;\n    #endif\n\n    return r;\n  }\n\n  /* convert a double to ieee double/binary64 */\n  ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x);\n  ecb_function_ ecb_const uint64_t\n  ecb_double_to_binary64 (double x)\n  {\n    uint64_t r;\n\n    #if ECB_STDFP\n      memcpy (&r, &x, 8);\n    #else\n      /* slow emulation, works for anything but -0 */\n      uint64_t m;\n      int e;\n\n      if (x == 0e0                     ) return 0x0000000000000000U;\n      if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;\n      if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;\n      if (x != x                       ) return 0X7ff7ffffffffffffU;\n\n      m = frexp (x, &e) * 0x20000000000000U;\n\n      r = m & 0x8000000000000000;;\n\n      if (r)\n        m = -m;\n\n      if (e <= -1022)\n        {\n          m &= 0x1fffffffffffffU;\n          m >>= (-1021 - e);\n          e = -1022;\n        }\n\n      r |= ((uint64_t)(e + 1022)) << 52;\n      r |= m & 0xfffffffffffffU;\n    #endif\n\n    return r;\n  }\n\n  /* converts an ieee double/binary64 to a double */\n  ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x);\n  ecb_function_ ecb_const double\n  ecb_binary64_to_double (uint64_t x)\n  {\n    double r;\n\n    #if ECB_STDFP\n      memcpy (&r, &x, 8);\n    #else\n      /* emulation, only works for normals and subnormals and +0 */\n      int neg = x >> 63;\n      int e = (x >> 52) & 0x7ffU;\n\n      x &= 0xfffffffffffffU;\n\n      if (e)\n        x |= 0x10000000000000U;\n      else\n        e = 1;\n\n      /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */\n      r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);\n\n      r = neg ? -r : r;\n    #endif\n\n    return r;\n  }\n\n  /* convert a float to ieee half/binary16 */\n  ecb_function_ ecb_const uint16_t ecb_float_to_binary16 (float x);\n  ecb_function_ ecb_const uint16_t\n  ecb_float_to_binary16 (float x)\n  {\n    return ecb_binary32_to_binary16 (ecb_float_to_binary32 (x));\n  }\n\n  /* convert an ieee half/binary16 to float */\n  ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);\n  ecb_function_ ecb_const float\n  ecb_binary16_to_float (uint16_t x)\n  {\n    return ecb_binary32_to_float (ecb_binary16_to_binary32 (x));\n  }\n\n#endif\n\n#endif\n\n/* ECB.H END */\n\n#if ECB_MEMORY_FENCE_NEEDS_PTHREADS\n/* if your architecture doesn't need memory fences, e.g. because it is\n * single-cpu/core, or if you use libev in a project that doesn't use libev\n * from multiple threads, then you can define ECB_AVOID_PTHREADS when compiling\n * libev, in which cases the memory fences become nops.\n * alternatively, you can remove this #error and link against libpthread,\n * which will then provide the memory fences.\n */\n# error \"memory fences not defined for your architecture, please report\"\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n# define ECB_MEMORY_FENCE do { } while (0)\n# define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE\n# define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE\n#endif\n\n#define expect_false(cond) ecb_expect_false (cond)\n#define expect_true(cond)  ecb_expect_true  (cond)\n#define noinline           ecb_noinline\n\n#define inline_size        ecb_inline\n\n#if EV_FEATURE_CODE\n# define inline_speed      ecb_inline\n#else\n# define inline_speed      noinline static\n#endif\n\n#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)\n\n#if EV_MINPRI == EV_MAXPRI\n# define ABSPRI(w) (((W)w), 0)\n#else\n# define ABSPRI(w) (((W)w)->priority - EV_MINPRI)\n#endif\n\n#define EMPTY       /* required for microsofts broken pseudo-c compiler */\n#define EMPTY2(a,b) /* used to suppress some warnings */\n\ntypedef ev_watcher *W;\ntypedef ev_watcher_list *WL;\ntypedef ev_watcher_time *WT;\n\n#define ev_active(w) ((W)(w))->active\n#define ev_at(w) ((WT)(w))->at\n\n#if EV_USE_REALTIME\n/* sig_atomic_t is used to avoid per-thread variables or locking but still */\n/* giving it a reasonably high chance of working on typical architectures */\nstatic EV_ATOMIC_T have_realtime; /* did clock_gettime (CLOCK_REALTIME) work? */\n#endif\n\n#if EV_USE_MONOTONIC\nstatic EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */\n#endif\n\n#ifndef EV_FD_TO_WIN32_HANDLE\n# define EV_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)\n#endif\n#ifndef EV_WIN32_HANDLE_TO_FD\n# define EV_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)\n#endif\n#ifndef EV_WIN32_CLOSE_FD\n# define EV_WIN32_CLOSE_FD(fd) close (fd)\n#endif\n\n#ifdef _WIN32\n# include \"ev_win32.c\"\n#endif\n\n/*****************************************************************************/\n\n/* define a suitable floor function (only used by periodics atm) */\n\n#if EV_USE_FLOOR\n# include <math.h>\n# define ev_floor(v) floor (v)\n#else\n\n#include <float.h>\n\n/* a floor() replacement function, should be independent of ev_tstamp type */\nnoinline\nstatic ev_tstamp\nev_floor (ev_tstamp v)\n{\n  /* the choice of shift factor is not terribly important */\n#if FLT_RADIX != 2 /* assume FLT_RADIX == 10 */\n  const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 10000000000000000000. : 1000000000.;\n#else\n  const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.;\n#endif\n\n  /* argument too large for an unsigned long? */\n  if (expect_false (v >= shift))\n    {\n      ev_tstamp f;\n\n      if (v == v - 1.)\n        return v; /* very large number */\n\n      f = shift * ev_floor (v * (1. / shift));\n      return f + ev_floor (v - f);\n    }\n\n  /* special treatment for negative args? */\n  if (expect_false (v < 0.))\n    {\n      ev_tstamp f = -ev_floor (-v);\n\n      return f - (f == v ? 0 : 1);\n    }\n\n  /* fits into an unsigned long */\n  return (unsigned long)v;\n}\n\n#endif\n\n/*****************************************************************************/\n\n#ifdef __linux\n# include <sys/utsname.h>\n#endif\n\nnoinline ecb_cold\nstatic unsigned int\nev_linux_version (void)\n{\n#ifdef __linux\n  unsigned int v = 0;\n  struct utsname buf;\n  int i;\n  char *p = buf.release;\n\n  if (uname (&buf))\n    return 0;\n\n  for (i = 3+1; --i; )\n    {\n      unsigned int c = 0;\n\n      for (;;)\n        {\n          if (*p >= '0' && *p <= '9')\n            c = c * 10 + *p++ - '0';\n          else\n            {\n              p += *p == '.';\n              break;\n            }\n        }\n\n      v = (v << 8) | c;\n    }\n\n  return v;\n#else\n  return 0;\n#endif\n}\n\n/*****************************************************************************/\n\n#if EV_AVOID_STDIO\nnoinline ecb_cold\nstatic void\nev_printerr (const char *msg)\n{\n  write (STDERR_FILENO, msg, strlen (msg));\n}\n#endif\n\nstatic void (*syserr_cb)(const char *msg) EV_THROW;\n\necb_cold\nvoid\nev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW\n{\n  syserr_cb = cb;\n}\n\nnoinline ecb_cold\nstatic void\nev_syserr (const char *msg)\n{\n  if (!msg)\n    msg = \"(libev) system error\";\n\n  if (syserr_cb)\n    syserr_cb (msg);\n  else\n    {\n#if EV_AVOID_STDIO\n      ev_printerr (msg);\n      ev_printerr (\": \");\n      ev_printerr (strerror (errno));\n      ev_printerr (\"\\n\");\n#else\n      perror (msg);\n#endif\n      abort ();\n    }\n}\n\nstatic void *\nev_realloc_emul (void *ptr, long size) EV_THROW\n{\n  /* some systems, notably openbsd and darwin, fail to properly\n   * implement realloc (x, 0) (as required by both ansi c-89 and\n   * the single unix specification, so work around them here.\n   * recently, also (at least) fedora and debian started breaking it,\n   * despite documenting it otherwise.\n   */\n\n  if (size)\n    return realloc (ptr, size);\n\n  free (ptr);\n  return 0;\n}\n\nstatic void *(*alloc)(void *ptr, long size) EV_THROW = ev_realloc_emul;\n\necb_cold\nvoid\nev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW\n{\n  alloc = cb;\n}\n\ninline_speed void *\nev_realloc (void *ptr, long size)\n{\n  ptr = alloc (ptr, size);\n\n  if (!ptr && size)\n    {\n#if EV_AVOID_STDIO\n      ev_printerr (\"(libev) memory allocation failed, aborting.\\n\");\n#else\n      fprintf (stderr, \"(libev) cannot allocate %ld bytes, aborting.\", size);\n#endif\n      abort ();\n    }\n\n  return ptr;\n}\n\n#define ev_malloc(size) ev_realloc (0, (size))\n#define ev_free(ptr)    ev_realloc ((ptr), 0)\n\n/*****************************************************************************/\n\n/* set in reify when reification needed */\n#define EV_ANFD_REIFY 1\n\n/* file descriptor info structure */\ntypedef struct\n{\n  WL head;\n  unsigned char events; /* the events watched for */\n  unsigned char reify;  /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */\n  unsigned char emask;  /* the epoll backend stores the actual kernel mask in here */\n  unsigned char unused;\n#if EV_USE_EPOLL\n  unsigned int egen;    /* generation counter to counter epoll bugs */\n#endif\n#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP\n  SOCKET handle;\n#endif\n#if EV_USE_IOCP\n  OVERLAPPED or, ow;\n#endif\n} ANFD;\n\n/* stores the pending event set for a given watcher */\ntypedef struct\n{\n  W w;\n  int events; /* the pending event set for the given watcher */\n} ANPENDING;\n\n#if EV_USE_INOTIFY\n/* hash table entry per inotify-id */\ntypedef struct\n{\n  WL head;\n} ANFS;\n#endif\n\n/* Heap Entry */\n#if EV_HEAP_CACHE_AT\n  /* a heap element */\n  typedef struct {\n    ev_tstamp at;\n    WT w;\n  } ANHE;\n\n  #define ANHE_w(he)        (he).w     /* access watcher, read-write */\n  #define ANHE_at(he)       (he).at    /* access cached at, read-only */\n  #define ANHE_at_cache(he) (he).at = (he).w->at /* update at from watcher */\n#else\n  /* a heap element */\n  typedef WT ANHE;\n\n  #define ANHE_w(he)        (he)\n  #define ANHE_at(he)       (he)->at\n  #define ANHE_at_cache(he)\n#endif\n\n#if EV_MULTIPLICITY\n\n  struct ev_loop\n  {\n    ev_tstamp ev_rt_now;\n    #define ev_rt_now ((loop)->ev_rt_now)\n    #define VAR(name,decl) decl;\n      #include \"ev_vars.h\"\n    #undef VAR\n  };\n  #include \"ev_wrap.h\"\n\n  static struct ev_loop default_loop_struct;\n  EV_API_DECL struct ev_loop *ev_default_loop_ptr = 0; /* needs to be initialised to make it a definition despite extern */\n\n#else\n\n  EV_API_DECL ev_tstamp ev_rt_now = 0; /* needs to be initialised to make it a definition despite extern */\n  #define VAR(name,decl) static decl;\n    #include \"ev_vars.h\"\n  #undef VAR\n\n  static int ev_default_loop_ptr;\n\n#endif\n\n#if EV_FEATURE_API\n# define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A)\n# define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A)\n# define EV_INVOKE_PENDING invoke_cb (EV_A)\n#else\n# define EV_RELEASE_CB (void)0\n# define EV_ACQUIRE_CB (void)0\n# define EV_INVOKE_PENDING ev_invoke_pending (EV_A)\n#endif\n\n#define EVBREAK_RECURSE 0x80\n\n/*****************************************************************************/\n\n#ifndef EV_HAVE_EV_TIME\nev_tstamp\nev_time (void) EV_THROW\n{\n#if EV_USE_REALTIME\n  if (expect_true (have_realtime))\n    {\n      struct timespec ts;\n      clock_gettime (CLOCK_REALTIME, &ts);\n      return ts.tv_sec + ts.tv_nsec * 1e-9;\n    }\n#endif\n\n  struct timeval tv;\n  gettimeofday (&tv, 0);\n  return tv.tv_sec + tv.tv_usec * 1e-6;\n}\n#endif\n\ninline_size ev_tstamp\nget_clock (void)\n{\n#if EV_USE_MONOTONIC\n  if (expect_true (have_monotonic))\n    {\n      struct timespec ts;\n      clock_gettime (CLOCK_MONOTONIC, &ts);\n      return ts.tv_sec + ts.tv_nsec * 1e-9;\n    }\n#endif\n\n  return ev_time ();\n}\n\n#if EV_MULTIPLICITY\nev_tstamp\nev_now (EV_P) EV_THROW\n{\n  return ev_rt_now;\n}\n#endif\n\nvoid\nev_sleep (ev_tstamp delay) EV_THROW\n{\n  if (delay > 0.)\n    {\n#if EV_USE_NANOSLEEP\n      struct timespec ts;\n\n      EV_TS_SET (ts, delay);\n      nanosleep (&ts, 0);\n#elif defined _WIN32\n      Sleep ((unsigned long)(delay * 1e3));\n#else\n      struct timeval tv;\n\n      /* here we rely on sys/time.h + sys/types.h + unistd.h providing select */\n      /* something not guaranteed by newer posix versions, but guaranteed */\n      /* by older ones */\n      EV_TV_SET (tv, delay);\n      select (0, 0, 0, 0, &tv);\n#endif\n    }\n}\n\n/*****************************************************************************/\n\n#define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */\n\n/* find a suitable new size for the given array, */\n/* hopefully by rounding to a nice-to-malloc size */\ninline_size int\narray_nextsize (int elem, int cur, int cnt)\n{\n  int ncur = cur + 1;\n\n  do\n    ncur <<= 1;\n  while (cnt > ncur);\n\n  /* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */\n  if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)\n    {\n      ncur *= elem;\n      ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1);\n      ncur = ncur - sizeof (void *) * 4;\n      ncur /= elem;\n    }\n\n  return ncur;\n}\n\nnoinline ecb_cold\nstatic void *\narray_realloc (int elem, void *base, int *cur, int cnt)\n{\n  *cur = array_nextsize (elem, *cur, cnt);\n  return ev_realloc (base, elem * *cur);\n}\n\n#define array_init_zero(base,count)\t\\\n  memset ((void *)(base), 0, sizeof (*(base)) * (count))\n\n#define array_needsize(type,base,cur,cnt,init)\t\t\t\\\n  if (expect_false ((cnt) > (cur)))\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      ecb_unused int ocur_ = (cur);\t\t\t\t\\\n      (base) = (type *)array_realloc\t\t\t\t\\\n         (sizeof (type), (base), &(cur), (cnt));\t\t\\\n      init ((base) + (ocur_), (cur) - ocur_);\t\t\t\\\n    }\n\n#if 0\n#define array_slim(type,stem)\t\t\t\t\t\\\n  if (stem ## max < array_roundsize (stem ## cnt >> 2))\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      stem ## max = array_roundsize (stem ## cnt >> 1);\t\t\\\n      base = (type *)ev_realloc (base, sizeof (type) * (stem ## max));\\\n      fprintf (stderr, \"slimmed down \" # stem \" to %d\\n\", stem ## max);/*D*/\\\n    }\n#endif\n\n#define array_free(stem, idx) \\\n  ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; stem ## s idx = 0\n\n/*****************************************************************************/\n\n/* dummy callback for pending events */\nnoinline\nstatic void\npendingcb (EV_P_ ev_prepare *w, int revents)\n{\n}\n\nnoinline\nvoid\nev_feed_event (EV_P_ void *w, int revents) EV_THROW\n{\n  W w_ = (W)w;\n  int pri = ABSPRI (w_);\n\n  if (expect_false (w_->pending))\n    pendings [pri][w_->pending - 1].events |= revents;\n  else\n    {\n      w_->pending = ++pendingcnt [pri];\n      array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2);\n      pendings [pri][w_->pending - 1].w      = w_;\n      pendings [pri][w_->pending - 1].events = revents;\n    }\n\n  pendingpri = NUMPRI - 1;\n}\n\ninline_speed void\nfeed_reverse (EV_P_ W w)\n{\n  array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, EMPTY2);\n  rfeeds [rfeedcnt++] = w;\n}\n\ninline_size void\nfeed_reverse_done (EV_P_ int revents)\n{\n  do\n    ev_feed_event (EV_A_ rfeeds [--rfeedcnt], revents);\n  while (rfeedcnt);\n}\n\ninline_speed void\nqueue_events (EV_P_ W *events, int eventcnt, int type)\n{\n  int i;\n\n  for (i = 0; i < eventcnt; ++i)\n    ev_feed_event (EV_A_ events [i], type);\n}\n\n/*****************************************************************************/\n\ninline_speed void\nfd_event_nocheck (EV_P_ int fd, int revents)\n{\n  ANFD *anfd = anfds + fd;\n  ev_io *w;\n\n  for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)\n    {\n      int ev = w->events & revents;\n\n      if (ev)\n        ev_feed_event (EV_A_ (W)w, ev);\n    }\n}\n\n/* do not submit kernel events for fds that have reify set */\n/* because that means they changed while we were polling for new events */\ninline_speed void\nfd_event (EV_P_ int fd, int revents)\n{\n  ANFD *anfd = anfds + fd;\n\n  if (expect_true (!anfd->reify))\n    fd_event_nocheck (EV_A_ fd, revents);\n}\n\nvoid\nev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW\n{\n  if (fd >= 0 && fd < anfdmax)\n    fd_event_nocheck (EV_A_ fd, revents);\n}\n\n/* make sure the external fd watch events are in-sync */\n/* with the kernel/libev internal state */\ninline_size void\nfd_reify (EV_P)\n{\n  int i;\n\n#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP\n  for (i = 0; i < fdchangecnt; ++i)\n    {\n      int fd = fdchanges [i];\n      ANFD *anfd = anfds + fd;\n\n      if (anfd->reify & EV__IOFDSET && anfd->head)\n        {\n          SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd);\n\n          if (handle != anfd->handle)\n            {\n              unsigned long arg;\n\n              assert ((\"libev: only socket fds supported in this configuration\", ioctlsocket (handle, FIONREAD, &arg) == 0));\n\n              /* handle changed, but fd didn't - we need to do it in two steps */\n              backend_modify (EV_A_ fd, anfd->events, 0);\n              anfd->events = 0;\n              anfd->handle = handle;\n            }\n        }\n    }\n#endif\n\n  for (i = 0; i < fdchangecnt; ++i)\n    {\n      int fd = fdchanges [i];\n      ANFD *anfd = anfds + fd;\n      ev_io *w;\n\n      unsigned char o_events = anfd->events;\n      unsigned char o_reify  = anfd->reify;\n\n      anfd->reify  = 0;\n\n      /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */\n        {\n          anfd->events = 0;\n\n          for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)\n            anfd->events |= (unsigned char)w->events;\n\n          if (o_events != anfd->events)\n            o_reify = EV__IOFDSET; /* actually |= */\n        }\n\n      if (o_reify & EV__IOFDSET)\n        backend_modify (EV_A_ fd, o_events, anfd->events);\n    }\n\n  fdchangecnt = 0;\n}\n\n/* something about the given fd changed */\ninline_size\nvoid\nfd_change (EV_P_ int fd, int flags)\n{\n  unsigned char reify = anfds [fd].reify;\n  anfds [fd].reify |= flags;\n\n  if (expect_true (!reify))\n    {\n      ++fdchangecnt;\n      array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);\n      fdchanges [fdchangecnt - 1] = fd;\n    }\n}\n\n/* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */\ninline_speed ecb_cold void\nfd_kill (EV_P_ int fd)\n{\n  ev_io *w;\n\n  while ((w = (ev_io *)anfds [fd].head))\n    {\n      ev_io_stop (EV_A_ w);\n      ev_feed_event (EV_A_ (W)w, EV_ERROR | EV_READ | EV_WRITE);\n    }\n}\n\n/* check whether the given fd is actually valid, for error recovery */\ninline_size ecb_cold int\nfd_valid (int fd)\n{\n#ifdef _WIN32\n  return EV_FD_TO_WIN32_HANDLE (fd) != -1;\n#else\n  return fcntl (fd, F_GETFD) != -1;\n#endif\n}\n\n/* called on EBADF to verify fds */\nnoinline ecb_cold\nstatic void\nfd_ebadf (EV_P)\n{\n  int fd;\n\n  for (fd = 0; fd < anfdmax; ++fd)\n    if (anfds [fd].events)\n      if (!fd_valid (fd) && errno == EBADF)\n        fd_kill (EV_A_ fd);\n}\n\n/* called on ENOMEM in select/poll to kill some fds and retry */\nnoinline ecb_cold\nstatic void\nfd_enomem (EV_P)\n{\n  int fd;\n\n  for (fd = anfdmax; fd--; )\n    if (anfds [fd].events)\n      {\n        fd_kill (EV_A_ fd);\n        break;\n      }\n}\n\n/* usually called after fork if backend needs to re-arm all fds from scratch */\nnoinline\nstatic void\nfd_rearm_all (EV_P)\n{\n  int fd;\n\n  for (fd = 0; fd < anfdmax; ++fd)\n    if (anfds [fd].events)\n      {\n        anfds [fd].events = 0;\n        anfds [fd].emask  = 0;\n        fd_change (EV_A_ fd, EV__IOFDSET | EV_ANFD_REIFY);\n      }\n}\n\n/* used to prepare libev internal fd's */\n/* this is not fork-safe */\ninline_speed void\nfd_intern (int fd)\n{\n#ifdef _WIN32\n  unsigned long arg = 1;\n  ioctlsocket (EV_FD_TO_WIN32_HANDLE (fd), FIONBIO, &arg);\n#else\n  fcntl (fd, F_SETFD, FD_CLOEXEC);\n  fcntl (fd, F_SETFL, O_NONBLOCK);\n#endif\n}\n\n/*****************************************************************************/\n\n/*\n * the heap functions want a real array index. array index 0 is guaranteed to not\n * be in-use at any time. the first heap entry is at array [HEAP0]. DHEAP gives\n * the branching factor of the d-tree.\n */\n\n/*\n * at the moment we allow libev the luxury of two heaps,\n * a small-code-size 2-heap one and a ~1.5kb larger 4-heap\n * which is more cache-efficient.\n * the difference is about 5% with 50000+ watchers.\n */\n#if EV_USE_4HEAP\n\n#define DHEAP 4\n#define HEAP0 (DHEAP - 1) /* index of first element in heap */\n#define HPARENT(k) ((((k) - HEAP0 - 1) / DHEAP) + HEAP0)\n#define UPHEAP_DONE(p,k) ((p) == (k))\n\n/* away from the root */\ninline_speed void\ndownheap (ANHE *heap, int N, int k)\n{\n  ANHE he = heap [k];\n  ANHE *E = heap + N + HEAP0;\n\n  for (;;)\n    {\n      ev_tstamp minat;\n      ANHE *minpos;\n      ANHE *pos = heap + DHEAP * (k - HEAP0) + HEAP0 + 1;\n\n      /* find minimum child */\n      if (expect_true (pos + DHEAP - 1 < E))\n        {\n          /* fast path */                               (minpos = pos + 0), (minat = ANHE_at (*minpos));\n          if (               ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos));\n          if (               ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos));\n          if (               ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos));\n        }\n      else if (pos < E)\n        {\n          /* slow path */                               (minpos = pos + 0), (minat = ANHE_at (*minpos));\n          if (pos + 1 < E && ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos));\n          if (pos + 2 < E && ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos));\n          if (pos + 3 < E && ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos));\n        }\n      else\n        break;\n\n      if (ANHE_at (he) <= minat)\n        break;\n\n      heap [k] = *minpos;\n      ev_active (ANHE_w (*minpos)) = k;\n\n      k = minpos - heap;\n    }\n\n  heap [k] = he;\n  ev_active (ANHE_w (he)) = k;\n}\n\n#else /* 4HEAP */\n\n#define HEAP0 1\n#define HPARENT(k) ((k) >> 1)\n#define UPHEAP_DONE(p,k) (!(p))\n\n/* away from the root */\ninline_speed void\ndownheap (ANHE *heap, int N, int k)\n{\n  ANHE he = heap [k];\n\n  for (;;)\n    {\n      int c = k << 1;\n\n      if (c >= N + HEAP0)\n        break;\n\n      c += c + 1 < N + HEAP0 && ANHE_at (heap [c]) > ANHE_at (heap [c + 1])\n           ? 1 : 0;\n\n      if (ANHE_at (he) <= ANHE_at (heap [c]))\n        break;\n\n      heap [k] = heap [c];\n      ev_active (ANHE_w (heap [k])) = k;\n      \n      k = c;\n    }\n\n  heap [k] = he;\n  ev_active (ANHE_w (he)) = k;\n}\n#endif\n\n/* towards the root */\ninline_speed void\nupheap (ANHE *heap, int k)\n{\n  ANHE he = heap [k];\n\n  for (;;)\n    {\n      int p = HPARENT (k);\n\n      if (UPHEAP_DONE (p, k) || ANHE_at (heap [p]) <= ANHE_at (he))\n        break;\n\n      heap [k] = heap [p];\n      ev_active (ANHE_w (heap [k])) = k;\n      k = p;\n    }\n\n  heap [k] = he;\n  ev_active (ANHE_w (he)) = k;\n}\n\n/* move an element suitably so it is in a correct place */\ninline_size void\nadjustheap (ANHE *heap, int N, int k)\n{\n  if (k > HEAP0 && ANHE_at (heap [k]) <= ANHE_at (heap [HPARENT (k)]))\n    upheap (heap, k);\n  else\n    downheap (heap, N, k);\n}\n\n/* rebuild the heap: this function is used only once and executed rarely */\ninline_size void\nreheap (ANHE *heap, int N)\n{\n  int i;\n\n  /* we don't use floyds algorithm, upheap is simpler and is more cache-efficient */\n  /* also, this is easy to implement and correct for both 2-heaps and 4-heaps */\n  for (i = 0; i < N; ++i)\n    upheap (heap, i + HEAP0);\n}\n\n/*****************************************************************************/\n\n/* associate signal watchers to a signal signal */\ntypedef struct\n{\n  EV_ATOMIC_T pending;\n#if EV_MULTIPLICITY\n  EV_P;\n#endif\n  WL head;\n} ANSIG;\n\nstatic ANSIG signals [EV_NSIG - 1];\n\n/*****************************************************************************/\n\n#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE\n\nnoinline ecb_cold\nstatic void\nevpipe_init (EV_P)\n{\n  if (!ev_is_active (&pipe_w))\n    {\n      int fds [2];\n\n# if EV_USE_EVENTFD\n      fds [0] = -1;\n      fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);\n      if (fds [1] < 0 && errno == EINVAL)\n        fds [1] = eventfd (0, 0);\n\n      if (fds [1] < 0)\n# endif\n        {\n          while (pipe (fds))\n            ev_syserr (\"(libev) error creating signal/async pipe\");\n\n          fd_intern (fds [0]);\n        }\n\n      evpipe [0] = fds [0];\n\n      if (evpipe [1] < 0)\n        evpipe [1] = fds [1]; /* first call, set write fd */\n      else\n        {\n          /* on subsequent calls, do not change evpipe [1] */\n          /* so that evpipe_write can always rely on its value. */\n          /* this branch does not do anything sensible on windows, */\n          /* so must not be executed on windows */\n\n          dup2 (fds [1], evpipe [1]);\n          close (fds [1]);\n        }\n\n      fd_intern (evpipe [1]);\n\n      ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ);\n      ev_io_start (EV_A_ &pipe_w);\n      ev_unref (EV_A); /* watcher should not keep loop alive */\n    }\n}\n\ninline_speed void\nevpipe_write (EV_P_ EV_ATOMIC_T *flag)\n{\n  ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */\n\n  if (expect_true (*flag))\n    return;\n\n  *flag = 1;\n  ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */\n\n  pipe_write_skipped = 1;\n\n  ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */\n\n  if (pipe_write_wanted)\n    {\n      int old_errno;\n\n      pipe_write_skipped = 0;\n      ECB_MEMORY_FENCE_RELEASE;\n\n      old_errno = errno; /* save errno because write will clobber it */\n\n#if EV_USE_EVENTFD\n      if (evpipe [0] < 0)\n        {\n          uint64_t counter = 1;\n          write (evpipe [1], &counter, sizeof (uint64_t));\n        }\n      else\n#endif\n        {\n#ifdef _WIN32\n          WSABUF buf;\n          DWORD sent;\n//\t  buf.buf=&buf;\n          buf.buf = (char *)&buf;\n          buf.len = 1;\n          WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);\n#else\n          write (evpipe [1], &(evpipe [1]), 1);\n#endif\n        }\n\n      errno = old_errno;\n    }\n}\n\n/* called whenever the libev signal pipe */\n/* got some events (signal, async) */\nstatic void\npipecb (EV_P_ ev_io *iow, int revents)\n{\n  int i;\n\n  if (revents & EV_READ)\n    {\n#if EV_USE_EVENTFD\n      if (evpipe [0] < 0)\n        {\n          uint64_t counter;\n          read (evpipe [1], &counter, sizeof (uint64_t));\n        }\n      else\n#endif\n        {\n          char dummy[4];\n#ifdef _WIN32\n          WSABUF buf;\n          DWORD recvd;\n          DWORD flags = 0;\n          buf.buf = dummy;\n          buf.len = sizeof (dummy);\n          WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0);\n#else\n          read (evpipe [0], &dummy, sizeof (dummy));\n#endif\n        }\n    }\n\n  pipe_write_skipped = 0;\n\n  ECB_MEMORY_FENCE; /* push out skipped, acquire flags */\n\n#if EV_SIGNAL_ENABLE\n  if (sig_pending)\n    {\n      sig_pending = 0;\n\n      ECB_MEMORY_FENCE;\n\n      for (i = EV_NSIG - 1; i--; )\n        if (expect_false (signals [i].pending))\n          ev_feed_signal_event (EV_A_ i + 1);\n    }\n#endif\n\n#if EV_ASYNC_ENABLE\n  if (async_pending)\n    {\n      async_pending = 0;\n\n      ECB_MEMORY_FENCE;\n\n      for (i = asynccnt; i--; )\n        if (asyncs [i]->sent)\n          {\n            asyncs [i]->sent = 0;\n            ECB_MEMORY_FENCE_RELEASE;\n            ev_feed_event (EV_A_ asyncs [i], EV_ASYNC);\n          }\n    }\n#endif\n}\n\n/*****************************************************************************/\n\nvoid\nev_feed_signal (int signum) EV_THROW\n{\n#if EV_MULTIPLICITY\n  EV_P;\n  ECB_MEMORY_FENCE_ACQUIRE;\n  EV_A = signals [signum - 1].loop;\n\n  if (!EV_A)\n    return;\n#endif\n\n  signals [signum - 1].pending = 1;\n  evpipe_write (EV_A_ &sig_pending);\n}\n\nstatic void\nev_sighandler (int signum)\n{\n#ifdef _WIN32\n  signal (signum, ev_sighandler);\n#endif\n\n  ev_feed_signal (signum);\n}\n\nnoinline\nvoid\nev_feed_signal_event (EV_P_ int signum) EV_THROW\n{\n  WL w;\n\n  if (expect_false (signum <= 0 || signum >= EV_NSIG))\n    return;\n\n  --signum;\n\n#if EV_MULTIPLICITY\n  /* it is permissible to try to feed a signal to the wrong loop */\n  /* or, likely more useful, feeding a signal nobody is waiting for */\n\n  if (expect_false (signals [signum].loop != EV_A))\n    return;\n#endif\n\n  signals [signum].pending = 0;\n  ECB_MEMORY_FENCE_RELEASE;\n\n  for (w = signals [signum].head; w; w = w->next)\n    ev_feed_event (EV_A_ (W)w, EV_SIGNAL);\n}\n\n#if EV_USE_SIGNALFD\nstatic void\nsigfdcb (EV_P_ ev_io *iow, int revents)\n{\n  struct signalfd_siginfo si[2], *sip; /* these structs are big */\n\n  for (;;)\n    {\n      ssize_t res = read (sigfd, si, sizeof (si));\n\n      /* not ISO-C, as res might be -1, but works with SuS */\n      for (sip = si; (char *)sip < (char *)si + res; ++sip)\n        ev_feed_signal_event (EV_A_ sip->ssi_signo);\n\n      if (res < (ssize_t)sizeof (si))\n        break;\n    }\n}\n#endif\n\n#endif\n\n/*****************************************************************************/\n\n#if EV_CHILD_ENABLE\nstatic WL childs [EV_PID_HASHSIZE];\n\nstatic ev_signal childev;\n\n#ifndef WIFCONTINUED\n# define WIFCONTINUED(status) 0\n#endif\n\n/* handle a single child status event */\ninline_speed void\nchild_reap (EV_P_ int chain, int pid, int status)\n{\n  ev_child *w;\n  int traced = WIFSTOPPED (status) || WIFCONTINUED (status);\n\n  for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next)\n    {\n      if ((w->pid == pid || !w->pid)\n          && (!traced || (w->flags & 1)))\n        {\n          ev_set_priority (w, EV_MAXPRI); /* need to do it *now*, this *must* be the same prio as the signal watcher itself */\n          w->rpid    = pid;\n          w->rstatus = status;\n          ev_feed_event (EV_A_ (W)w, EV_CHILD);\n        }\n    }\n}\n\n#ifndef WCONTINUED\n# define WCONTINUED 0\n#endif\n\n/* called on sigchld etc., calls waitpid */\nstatic void\nchildcb (EV_P_ ev_signal *sw, int revents)\n{\n  int pid, status;\n\n  /* some systems define WCONTINUED but then fail to support it (linux 2.4) */\n  if (0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED)))\n    if (!WCONTINUED\n        || errno != EINVAL\n        || 0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED)))\n      return;\n\n  /* make sure we are called again until all children have been reaped */\n  /* we need to do it this way so that the callback gets called before we continue */\n  ev_feed_event (EV_A_ (W)sw, EV_SIGNAL);\n\n  child_reap (EV_A_ pid, pid, status);\n  if ((EV_PID_HASHSIZE) > 1)\n    child_reap (EV_A_ 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */\n}\n\n#endif\n\n/*****************************************************************************/\n\n#if EV_USE_IOCP\n# include \"ev_iocp.c\"\n#endif\n#if EV_USE_PORT\n# include \"ev_port.c\"\n#endif\n#if EV_USE_KQUEUE\n# include \"ev_kqueue.c\"\n#endif\n#if EV_USE_EPOLL\n# include \"ev_epoll.c\"\n#endif\n#if EV_USE_POLL\n# include \"ev_poll.c\"\n#endif\n#if EV_USE_SELECT\n# include \"ev_select.c\"\n#endif\n\necb_cold int\nev_version_major (void) EV_THROW\n{\n  return EV_VERSION_MAJOR;\n}\n\necb_cold int\nev_version_minor (void) EV_THROW\n{\n  return EV_VERSION_MINOR;\n}\n\n/* return true if we are running with elevated privileges and should ignore env variables */\ninline_size ecb_cold int\nenable_secure (void)\n{\n#ifdef _WIN32\n  return 0;\n#else\n  return getuid () != geteuid ()\n      || getgid () != getegid ();\n#endif\n}\n\necb_cold\nunsigned int\nev_supported_backends (void) EV_THROW\n{\n  unsigned int flags = 0;\n\n  if (EV_USE_PORT  ) flags |= EVBACKEND_PORT;\n  if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;\n  if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;\n  if (EV_USE_POLL  ) flags |= EVBACKEND_POLL;\n  if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;\n  \n  return flags;\n}\n\necb_cold\nunsigned int\nev_recommended_backends (void) EV_THROW\n{\n  unsigned int flags = ev_supported_backends ();\n\n#ifndef __NetBSD__\n  /* kqueue is borked on everything but netbsd apparently */\n  /* it usually doesn't work correctly on anything but sockets and pipes */\n  flags &= ~EVBACKEND_KQUEUE;\n#endif\n#ifdef __APPLE__\n  /* only select works correctly on that \"unix-certified\" platform */\n  flags &= ~EVBACKEND_KQUEUE; /* horribly broken, even for sockets */\n  flags &= ~EVBACKEND_POLL;   /* poll is based on kqueue from 10.5 onwards */\n#endif\n#ifdef __FreeBSD__\n  flags &= ~EVBACKEND_POLL;   /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */\n#endif\n\n  return flags;\n}\n\necb_cold\nunsigned int\nev_embeddable_backends (void) EV_THROW\n{\n  int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;\n\n  /* epoll embeddability broken on all linux versions up to at least 2.6.23 */\n  if (ev_linux_version () < 0x020620) /* disable it on linux < 2.6.32 */\n    flags &= ~EVBACKEND_EPOLL;\n\n  return flags;\n}\n\nunsigned int\nev_backend (EV_P) EV_THROW\n{\n  return backend;\n}\n\n#if EV_FEATURE_API\nunsigned int\nev_iteration (EV_P) EV_THROW\n{\n  return loop_count;\n}\n\nunsigned int\nev_depth (EV_P) EV_THROW\n{\n  return loop_depth;\n}\n\nvoid\nev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW\n{\n  io_blocktime = interval;\n}\n\nvoid\nev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW\n{\n  timeout_blocktime = interval;\n}\n\nvoid\nev_set_userdata (EV_P_ void *data) EV_THROW\n{\n  userdata = data;\n}\n\nvoid *\nev_userdata (EV_P) EV_THROW\n{\n  return userdata;\n}\n\nvoid\nev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW\n{\n  invoke_cb = invoke_pending_cb;\n}\n\nvoid\nev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW\n{\n  release_cb = release;\n  acquire_cb = acquire;\n}\n#endif\n\n/* initialise a loop structure, must be zero-initialised */\nnoinline ecb_cold\nstatic void\nloop_init (EV_P_ unsigned int flags) EV_THROW\n{\n  if (!backend)\n    {\n      origflags = flags;\n\n#if EV_USE_REALTIME\n      if (!have_realtime)\n        {\n          struct timespec ts;\n\n          if (!clock_gettime (CLOCK_REALTIME, &ts))\n            have_realtime = 1;\n        }\n#endif\n\n#if EV_USE_MONOTONIC\n      if (!have_monotonic)\n        {\n          struct timespec ts;\n\n          if (!clock_gettime (CLOCK_MONOTONIC, &ts))\n            have_monotonic = 1;\n        }\n#endif\n\n      /* pid check not overridable via env */\n#ifndef _WIN32\n      if (flags & EVFLAG_FORKCHECK)\n        curpid = getpid ();\n#endif\n\n      if (!(flags & EVFLAG_NOENV)\n          && !enable_secure ()\n          && getenv (\"LIBEV_FLAGS\"))\n        flags = atoi (getenv (\"LIBEV_FLAGS\"));\n\n      ev_rt_now          = ev_time ();\n      mn_now             = get_clock ();\n      now_floor          = mn_now;\n      rtmn_diff          = ev_rt_now - mn_now;\n#if EV_FEATURE_API\n      invoke_cb          = ev_invoke_pending;\n#endif\n\n      io_blocktime       = 0.;\n      timeout_blocktime  = 0.;\n      backend            = 0;\n      backend_fd         = -1;\n      sig_pending        = 0;\n#if EV_ASYNC_ENABLE\n      async_pending      = 0;\n#endif\n      pipe_write_skipped = 0;\n      pipe_write_wanted  = 0;\n      evpipe [0]         = -1;\n      evpipe [1]         = -1;\n#if EV_USE_INOTIFY\n      fs_fd              = flags & EVFLAG_NOINOTIFY ? -1 : -2;\n#endif\n#if EV_USE_SIGNALFD\n      sigfd              = flags & EVFLAG_SIGNALFD  ? -2 : -1;\n#endif\n\n      if (!(flags & EVBACKEND_MASK))\n        flags |= ev_recommended_backends ();\n\n#if EV_USE_IOCP\n      if (!backend && (flags & EVBACKEND_IOCP  )) backend = iocp_init   (EV_A_ flags);\n#endif\n#if EV_USE_PORT\n      if (!backend && (flags & EVBACKEND_PORT  )) backend = port_init   (EV_A_ flags);\n#endif\n#if EV_USE_KQUEUE\n      if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags);\n#endif\n#if EV_USE_EPOLL\n      if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init  (EV_A_ flags);\n#endif\n#if EV_USE_POLL\n      if (!backend && (flags & EVBACKEND_POLL  )) backend = poll_init   (EV_A_ flags);\n#endif\n#if EV_USE_SELECT\n      if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);\n#endif\n\n      ev_prepare_init (&pending_w, pendingcb);\n\n#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE\n      ev_init (&pipe_w, pipecb);\n      ev_set_priority (&pipe_w, EV_MAXPRI);\n#endif\n    }\n}\n\n/* free up a loop structure */\necb_cold\nvoid\nev_loop_destroy (EV_P)\n{\n  int i;\n\n#if EV_MULTIPLICITY\n  /* mimic free (0) */\n  if (!EV_A)\n    return;\n#endif\n\n#if EV_CLEANUP_ENABLE\n  /* queue cleanup watchers (and execute them) */\n  if (expect_false (cleanupcnt))\n    {\n      queue_events (EV_A_ (W *)cleanups, cleanupcnt, EV_CLEANUP);\n      EV_INVOKE_PENDING;\n    }\n#endif\n\n#if EV_CHILD_ENABLE\n  if (ev_is_default_loop (EV_A) && ev_is_active (&childev))\n    {\n      ev_ref (EV_A); /* child watcher */\n      ev_signal_stop (EV_A_ &childev);\n    }\n#endif\n\n  if (ev_is_active (&pipe_w))\n    {\n      /*ev_ref (EV_A);*/\n      /*ev_io_stop (EV_A_ &pipe_w);*/\n\n      if (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]);\n      if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]);\n    }\n\n#if EV_USE_SIGNALFD\n  if (ev_is_active (&sigfd_w))\n    close (sigfd);\n#endif\n\n#if EV_USE_INOTIFY\n  if (fs_fd >= 0)\n    close (fs_fd);\n#endif\n\n  if (backend_fd >= 0)\n    close (backend_fd);\n\n#if EV_USE_IOCP\n  if (backend == EVBACKEND_IOCP  ) iocp_destroy   (EV_A);\n#endif\n#if EV_USE_PORT\n  if (backend == EVBACKEND_PORT  ) port_destroy   (EV_A);\n#endif\n#if EV_USE_KQUEUE\n  if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A);\n#endif\n#if EV_USE_EPOLL\n  if (backend == EVBACKEND_EPOLL ) epoll_destroy  (EV_A);\n#endif\n#if EV_USE_POLL\n  if (backend == EVBACKEND_POLL  ) poll_destroy   (EV_A);\n#endif\n#if EV_USE_SELECT\n  if (backend == EVBACKEND_SELECT) select_destroy (EV_A);\n#endif\n\n  for (i = NUMPRI; i--; )\n    {\n      array_free (pending, [i]);\n#if EV_IDLE_ENABLE\n      array_free (idle, [i]);\n#endif\n    }\n\n  ev_free (anfds); anfds = 0; anfdmax = 0;\n\n  /* have to use the microsoft-never-gets-it-right macro */\n  array_free (rfeed, EMPTY);\n  array_free (fdchange, EMPTY);\n  array_free (timer, EMPTY);\n#if EV_PERIODIC_ENABLE\n  array_free (periodic, EMPTY);\n#endif\n#if EV_FORK_ENABLE\n  array_free (fork, EMPTY);\n#endif\n#if EV_CLEANUP_ENABLE\n  array_free (cleanup, EMPTY);\n#endif\n  array_free (prepare, EMPTY);\n  array_free (check, EMPTY);\n#if EV_ASYNC_ENABLE\n  array_free (async, EMPTY);\n#endif\n\n  backend = 0;\n\n#if EV_MULTIPLICITY\n  if (ev_is_default_loop (EV_A))\n#endif\n    ev_default_loop_ptr = 0;\n#if EV_MULTIPLICITY\n  else\n    ev_free (EV_A);\n#endif\n}\n\n#if EV_USE_INOTIFY\ninline_size void infy_fork (EV_P);\n#endif\n\ninline_size void\nloop_fork (EV_P)\n{\n#if EV_USE_PORT\n  if (backend == EVBACKEND_PORT  ) port_fork   (EV_A);\n#endif\n#if EV_USE_KQUEUE\n  if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A);\n#endif\n#if EV_USE_EPOLL\n  if (backend == EVBACKEND_EPOLL ) epoll_fork  (EV_A);\n#endif\n#if EV_USE_INOTIFY\n  infy_fork (EV_A);\n#endif\n\n#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE\n  if (ev_is_active (&pipe_w) && postfork != 2)\n    {\n      /* pipe_write_wanted must be false now, so modifying fd vars should be safe */\n\n      ev_ref (EV_A);\n      ev_io_stop (EV_A_ &pipe_w);\n\n      if (evpipe [0] >= 0)\n        EV_WIN32_CLOSE_FD (evpipe [0]);\n\n      evpipe_init (EV_A);\n      /* iterate over everything, in case we missed something before */\n      ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);\n    }\n#endif\n\n  postfork = 0;\n}\n\n#if EV_MULTIPLICITY\n\necb_cold\nstruct ev_loop *\nev_loop_new (unsigned int flags) EV_THROW\n{\n  EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));\n\n  memset (EV_A, 0, sizeof (struct ev_loop));\n  loop_init (EV_A_ flags);\n\n  if (ev_backend (EV_A))\n    return EV_A;\n\n  ev_free (EV_A);\n  return 0;\n}\n\n#endif /* multiplicity */\n\n#if EV_VERIFY\nnoinline ecb_cold\nstatic void\nverify_watcher (EV_P_ W w)\n{\n  assert ((\"libev: watcher has invalid priority\", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));\n\n  if (w->pending)\n    assert ((\"libev: pending watcher not on pending queue\", pendings [ABSPRI (w)][w->pending - 1].w == w));\n}\n\nnoinline ecb_cold\nstatic void\nverify_heap (EV_P_ ANHE *heap, int N)\n{\n  int i;\n\n  for (i = HEAP0; i < N + HEAP0; ++i)\n    {\n      assert ((\"libev: active index mismatch in heap\", ev_active (ANHE_w (heap [i])) == i));\n      assert ((\"libev: heap condition violated\", i == HEAP0 || ANHE_at (heap [HPARENT (i)]) <= ANHE_at (heap [i])));\n      assert ((\"libev: heap at cache mismatch\", ANHE_at (heap [i]) == ev_at (ANHE_w (heap [i]))));\n\n      verify_watcher (EV_A_ (W)ANHE_w (heap [i]));\n    }\n}\n\nnoinline ecb_cold\nstatic void\narray_verify (EV_P_ W *ws, int cnt)\n{\n  while (cnt--)\n    {\n      assert ((\"libev: active index mismatch\", ev_active (ws [cnt]) == cnt + 1));\n      verify_watcher (EV_A_ ws [cnt]);\n    }\n}\n#endif\n\n#if EV_FEATURE_API\nvoid ecb_cold\nev_verify (EV_P) EV_THROW\n{\n#if EV_VERIFY\n  int i;\n  WL w, w2;\n\n  assert (activecnt >= -1);\n\n  assert (fdchangemax >= fdchangecnt);\n  for (i = 0; i < fdchangecnt; ++i)\n    assert ((\"libev: negative fd in fdchanges\", fdchanges [i] >= 0));\n\n  assert (anfdmax >= 0);\n  for (i = 0; i < anfdmax; ++i)\n    {\n      int j = 0;\n\n      for (w = w2 = anfds [i].head; w; w = w->next)\n        {\n          verify_watcher (EV_A_ (W)w);\n\n          if (j++ & 1)\n            {\n              assert ((\"libev: io watcher list contains a loop\", w != w2));\n              w2 = w2->next;\n            }\n\n          assert ((\"libev: inactive fd watcher on anfd list\", ev_active (w) == 1));\n          assert ((\"libev: fd mismatch between watcher and anfd\", ((ev_io *)w)->fd == i));\n        }\n    }\n\n  assert (timermax >= timercnt);\n  verify_heap (EV_A_ timers, timercnt);\n\n#if EV_PERIODIC_ENABLE\n  assert (periodicmax >= periodiccnt);\n  verify_heap (EV_A_ periodics, periodiccnt);\n#endif\n\n  for (i = NUMPRI; i--; )\n    {\n      assert (pendingmax [i] >= pendingcnt [i]);\n#if EV_IDLE_ENABLE\n      assert (idleall >= 0);\n      assert (idlemax [i] >= idlecnt [i]);\n      array_verify (EV_A_ (W *)idles [i], idlecnt [i]);\n#endif\n    }\n\n#if EV_FORK_ENABLE\n  assert (forkmax >= forkcnt);\n  array_verify (EV_A_ (W *)forks, forkcnt);\n#endif\n\n#if EV_CLEANUP_ENABLE\n  assert (cleanupmax >= cleanupcnt);\n  array_verify (EV_A_ (W *)cleanups, cleanupcnt);\n#endif\n\n#if EV_ASYNC_ENABLE\n  assert (asyncmax >= asynccnt);\n  array_verify (EV_A_ (W *)asyncs, asynccnt);\n#endif\n\n#if EV_PREPARE_ENABLE\n  assert (preparemax >= preparecnt);\n  array_verify (EV_A_ (W *)prepares, preparecnt);\n#endif\n\n#if EV_CHECK_ENABLE\n  assert (checkmax >= checkcnt);\n  array_verify (EV_A_ (W *)checks, checkcnt);\n#endif\n\n# if 0\n#if EV_CHILD_ENABLE\n  for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next)\n  for (signum = EV_NSIG; signum--; ) if (signals [signum].pending)\n#endif\n# endif\n#endif\n}\n#endif\n\n#if EV_MULTIPLICITY\necb_cold\nstruct ev_loop *\n#else\nint\n#endif\nev_default_loop (unsigned int flags) EV_THROW\n{\n  if (!ev_default_loop_ptr)\n    {\n#if EV_MULTIPLICITY\n      EV_P = ev_default_loop_ptr = &default_loop_struct;\n#else\n      ev_default_loop_ptr = 1;\n#endif\n\n      loop_init (EV_A_ flags);\n\n      if (ev_backend (EV_A))\n        {\n#if EV_CHILD_ENABLE\n          ev_signal_init (&childev, childcb, SIGCHLD);\n          ev_set_priority (&childev, EV_MAXPRI);\n          ev_signal_start (EV_A_ &childev);\n          ev_unref (EV_A); /* child watcher should not keep loop alive */\n#endif\n        }\n      else\n        ev_default_loop_ptr = 0;\n    }\n\n  return ev_default_loop_ptr;\n}\n\nvoid\nev_loop_fork (EV_P) EV_THROW\n{\n  postfork = 1;\n}\n\n/*****************************************************************************/\n\nvoid\nev_invoke (EV_P_ void *w, int revents)\n{\n  EV_CB_INVOKE ((W)w, revents);\n}\n\nunsigned int\nev_pending_count (EV_P) EV_THROW\n{\n  int pri;\n  unsigned int count = 0;\n\n  for (pri = NUMPRI; pri--; )\n    count += pendingcnt [pri];\n\n  return count;\n}\n\nnoinline\nvoid\nev_invoke_pending (EV_P)\n{\n  pendingpri = NUMPRI;\n\n  while (pendingpri) /* pendingpri possibly gets modified in the inner loop */\n    {\n      --pendingpri;\n\n      while (pendingcnt [pendingpri])\n        {\n          ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri];\n\n          p->w->pending = 0;\n          EV_CB_INVOKE (p->w, p->events);\n          EV_FREQUENT_CHECK;\n        }\n    }\n}\n\n#if EV_IDLE_ENABLE\n/* make idle watchers pending. this handles the \"call-idle */\n/* only when higher priorities are idle\" logic */\ninline_size void\nidle_reify (EV_P)\n{\n  if (expect_false (idleall))\n    {\n      int pri;\n\n      for (pri = NUMPRI; pri--; )\n        {\n          if (pendingcnt [pri])\n            break;\n\n          if (idlecnt [pri])\n            {\n              queue_events (EV_A_ (W *)idles [pri], idlecnt [pri], EV_IDLE);\n              break;\n            }\n        }\n    }\n}\n#endif\n\n/* make timers pending */\ninline_size void\ntimers_reify (EV_P)\n{\n  EV_FREQUENT_CHECK;\n\n  if (timercnt && ANHE_at (timers [HEAP0]) < mn_now)\n    {\n      do\n        {\n          ev_timer *w = (ev_timer *)ANHE_w (timers [HEAP0]);\n\n          /*assert ((\"libev: inactive timer on timer heap detected\", ev_is_active (w)));*/\n\n          /* first reschedule or stop timer */\n          if (w->repeat)\n            {\n              ev_at (w) += w->repeat;\n              if (ev_at (w) < mn_now)\n                ev_at (w) = mn_now;\n\n              assert ((\"libev: negative ev_timer repeat value found while processing timers\", w->repeat > 0.));\n\n              ANHE_at_cache (timers [HEAP0]);\n              downheap (timers, timercnt, HEAP0);\n            }\n          else\n            ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */\n\n          EV_FREQUENT_CHECK;\n          feed_reverse (EV_A_ (W)w);\n        }\n      while (timercnt && ANHE_at (timers [HEAP0]) < mn_now);\n\n      feed_reverse_done (EV_A_ EV_TIMER);\n    }\n}\n\n#if EV_PERIODIC_ENABLE\n\nnoinline\nstatic void\nperiodic_recalc (EV_P_ ev_periodic *w)\n{\n  ev_tstamp interval = w->interval > MIN_INTERVAL ? w->interval : MIN_INTERVAL;\n  ev_tstamp at = w->offset + interval * ev_floor ((ev_rt_now - w->offset) / interval);\n\n  /* the above almost always errs on the low side */\n  while (at <= ev_rt_now)\n    {\n      ev_tstamp nat = at + w->interval;\n\n      /* when resolution fails us, we use ev_rt_now */\n      if (expect_false (nat == at))\n        {\n          at = ev_rt_now;\n          break;\n        }\n\n      at = nat;\n    }\n\n  ev_at (w) = at;\n}\n\n/* make periodics pending */\ninline_size void\nperiodics_reify (EV_P)\n{\n  EV_FREQUENT_CHECK;\n\n  while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now)\n    {\n      do\n        {\n          ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);\n\n          /*assert ((\"libev: inactive timer on periodic heap detected\", ev_is_active (w)));*/\n\n          /* first reschedule or stop timer */\n          if (w->reschedule_cb)\n            {\n              ev_at (w) = w->reschedule_cb (w, ev_rt_now);\n\n              assert ((\"libev: ev_periodic reschedule callback returned time in the past\", ev_at (w) >= ev_rt_now));\n\n              ANHE_at_cache (periodics [HEAP0]);\n              downheap (periodics, periodiccnt, HEAP0);\n            }\n          else if (w->interval)\n            {\n              periodic_recalc (EV_A_ w);\n              ANHE_at_cache (periodics [HEAP0]);\n              downheap (periodics, periodiccnt, HEAP0);\n            }\n          else\n            ev_periodic_stop (EV_A_ w); /* nonrepeating: stop timer */\n\n          EV_FREQUENT_CHECK;\n          feed_reverse (EV_A_ (W)w);\n        }\n      while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now);\n\n      feed_reverse_done (EV_A_ EV_PERIODIC);\n    }\n}\n\n/* simply recalculate all periodics */\n/* TODO: maybe ensure that at least one event happens when jumping forward? */\nnoinline ecb_cold\nstatic void\nperiodics_reschedule (EV_P)\n{\n  int i;\n\n  /* adjust periodics after time jump */\n  for (i = HEAP0; i < periodiccnt + HEAP0; ++i)\n    {\n      ev_periodic *w = (ev_periodic *)ANHE_w (periodics [i]);\n\n      if (w->reschedule_cb)\n        ev_at (w) = w->reschedule_cb (w, ev_rt_now);\n      else if (w->interval)\n        periodic_recalc (EV_A_ w);\n\n      ANHE_at_cache (periodics [i]);\n    }\n\n  reheap (periodics, periodiccnt);\n}\n#endif\n\n/* adjust all timers by a given offset */\nnoinline ecb_cold\nstatic void\ntimers_reschedule (EV_P_ ev_tstamp adjust)\n{\n  int i;\n\n  for (i = 0; i < timercnt; ++i)\n    {\n      ANHE *he = timers + i + HEAP0;\n      ANHE_w (*he)->at += adjust;\n      ANHE_at_cache (*he);\n    }\n}\n\n/* fetch new monotonic and realtime times from the kernel */\n/* also detect if there was a timejump, and act accordingly */\ninline_speed void\ntime_update (EV_P_ ev_tstamp max_block)\n{\n#if EV_USE_MONOTONIC\n  if (expect_true (have_monotonic))\n    {\n      int i;\n      ev_tstamp odiff = rtmn_diff;\n\n      mn_now = get_clock ();\n\n      /* only fetch the realtime clock every 0.5*MIN_TIMEJUMP seconds */\n      /* interpolate in the meantime */\n      if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5))\n        {\n          ev_rt_now = rtmn_diff + mn_now;\n          return;\n        }\n\n      now_floor = mn_now;\n      ev_rt_now = ev_time ();\n\n      /* loop a few times, before making important decisions.\n       * on the choice of \"4\": one iteration isn't enough,\n       * in case we get preempted during the calls to\n       * ev_time and get_clock. a second call is almost guaranteed\n       * to succeed in that case, though. and looping a few more times\n       * doesn't hurt either as we only do this on time-jumps or\n       * in the unlikely event of having been preempted here.\n       */\n      for (i = 4; --i; )\n        {\n          ev_tstamp diff;\n          rtmn_diff = ev_rt_now - mn_now;\n\n          diff = odiff - rtmn_diff;\n\n          if (expect_true ((diff < 0. ? -diff : diff) < MIN_TIMEJUMP))\n            return; /* all is well */\n\n          ev_rt_now = ev_time ();\n          mn_now    = get_clock ();\n          now_floor = mn_now;\n        }\n\n      /* no timer adjustment, as the monotonic clock doesn't jump */\n      /* timers_reschedule (EV_A_ rtmn_diff - odiff) */\n# if EV_PERIODIC_ENABLE\n      periodics_reschedule (EV_A);\n# endif\n    }\n  else\n#endif\n    {\n      ev_rt_now = ev_time ();\n\n      if (expect_false (mn_now > ev_rt_now || ev_rt_now > mn_now + max_block + MIN_TIMEJUMP))\n        {\n          /* adjust timers. this is easy, as the offset is the same for all of them */\n          timers_reschedule (EV_A_ ev_rt_now - mn_now);\n#if EV_PERIODIC_ENABLE\n          periodics_reschedule (EV_A);\n#endif\n        }\n\n      mn_now = ev_rt_now;\n    }\n}\n\nint\nev_run (EV_P_ int flags)\n{\n#if EV_FEATURE_API\n  ++loop_depth;\n#endif\n\n  assert ((\"libev: ev_loop recursion during release detected\", loop_done != EVBREAK_RECURSE));\n\n  loop_done = EVBREAK_CANCEL;\n\n  EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */\n\n  do\n    {\n#if EV_VERIFY >= 2\n      ev_verify (EV_A);\n#endif\n\n#ifndef _WIN32\n      if (expect_false (curpid)) /* penalise the forking check even more */\n        if (expect_false (getpid () != curpid))\n          {\n            curpid = getpid ();\n            postfork = 1;\n          }\n#endif\n\n#if EV_FORK_ENABLE\n      /* we might have forked, so queue fork handlers */\n      if (expect_false (postfork))\n        if (forkcnt)\n          {\n            queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);\n            EV_INVOKE_PENDING;\n          }\n#endif\n\n#if EV_PREPARE_ENABLE\n      /* queue prepare watchers (and execute them) */\n      if (expect_false (preparecnt))\n        {\n          queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);\n          EV_INVOKE_PENDING;\n        }\n#endif\n\n      if (expect_false (loop_done))\n        break;\n\n      /* we might have forked, so reify kernel state if necessary */\n      if (expect_false (postfork))\n        loop_fork (EV_A);\n\n      /* update fd-related kernel structures */\n      fd_reify (EV_A);\n\n      /* calculate blocking time */\n      {\n        ev_tstamp waittime  = 0.;\n        ev_tstamp sleeptime = 0.;\n\n        /* remember old timestamp for io_blocktime calculation */\n        ev_tstamp prev_mn_now = mn_now;\n\n        /* update time to cancel out callback processing overhead */\n        time_update (EV_A_ 1e100);\n\n        /* from now on, we want a pipe-wake-up */\n        pipe_write_wanted = 1;\n\n        ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */\n\n        if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))\n          {\n            waittime = MAX_BLOCKTIME;\n\n            if (timercnt)\n              {\n                ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;\n                if (waittime > to) waittime = to;\n              }\n\n#if EV_PERIODIC_ENABLE\n            if (periodiccnt)\n              {\n                ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now;\n                if (waittime > to) waittime = to;\n              }\n#endif\n\n            /* don't let timeouts decrease the waittime below timeout_blocktime */\n            if (expect_false (waittime < timeout_blocktime))\n              waittime = timeout_blocktime;\n\n            /* at this point, we NEED to wait, so we have to ensure */\n            /* to pass a minimum nonzero value to the backend */\n            if (expect_false (waittime < backend_mintime))\n              waittime = backend_mintime;\n\n            /* extra check because io_blocktime is commonly 0 */\n            if (expect_false (io_blocktime))\n              {\n                sleeptime = io_blocktime - (mn_now - prev_mn_now);\n\n                if (sleeptime > waittime - backend_mintime)\n                  sleeptime = waittime - backend_mintime;\n\n                if (expect_true (sleeptime > 0.))\n                  {\n                    ev_sleep (sleeptime);\n                    waittime -= sleeptime;\n                  }\n              }\n          }\n\n#if EV_FEATURE_API\n        ++loop_count;\n#endif\n        assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */\n        backend_poll (EV_A_ waittime);\n        assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */\n\n        pipe_write_wanted = 0; /* just an optimisation, no fence needed */\n\n        ECB_MEMORY_FENCE_ACQUIRE;\n        if (pipe_write_skipped)\n          {\n            assert ((\"libev: pipe_w not active, but pipe not written\", ev_is_active (&pipe_w)));\n            ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);\n          }\n\n\n        /* update ev_rt_now, do magic */\n        time_update (EV_A_ waittime + sleeptime);\n      }\n\n      /* queue pending timers and reschedule them */\n      timers_reify (EV_A); /* relative timers called last */\n#if EV_PERIODIC_ENABLE\n      periodics_reify (EV_A); /* absolute timers called first */\n#endif\n\n#if EV_IDLE_ENABLE\n      /* queue idle watchers unless other events are pending */\n      idle_reify (EV_A);\n#endif\n\n#if EV_CHECK_ENABLE\n      /* queue check watchers, to be executed first */\n      if (expect_false (checkcnt))\n        queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);\n#endif\n\n      EV_INVOKE_PENDING;\n    }\n  while (expect_true (\n    activecnt\n    && !loop_done\n    && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))\n  ));\n\n  if (loop_done == EVBREAK_ONE)\n    loop_done = EVBREAK_CANCEL;\n\n#if EV_FEATURE_API\n  --loop_depth;\n#endif\n\n  return activecnt;\n}\n\nvoid\nev_break (EV_P_ int how) EV_THROW\n{\n  loop_done = how;\n}\n\nvoid\nev_ref (EV_P) EV_THROW\n{\n  ++activecnt;\n}\n\nvoid\nev_unref (EV_P) EV_THROW\n{\n  --activecnt;\n}\n\nvoid\nev_now_update (EV_P) EV_THROW\n{\n  time_update (EV_A_ 1e100);\n}\n\nvoid\nev_suspend (EV_P) EV_THROW\n{\n  ev_now_update (EV_A);\n}\n\nvoid\nev_resume (EV_P) EV_THROW\n{\n  ev_tstamp mn_prev = mn_now;\n\n  ev_now_update (EV_A);\n  timers_reschedule (EV_A_ mn_now - mn_prev);\n#if EV_PERIODIC_ENABLE\n  /* TODO: really do this? */\n  periodics_reschedule (EV_A);\n#endif\n}\n\n/*****************************************************************************/\n/* singly-linked list management, used when the expected list length is short */\n\ninline_size void\nwlist_add (WL *head, WL elem)\n{\n  elem->next = *head;\n  *head = elem;\n}\n\ninline_size void\nwlist_del (WL *head, WL elem)\n{\n  while (*head)\n    {\n      if (expect_true (*head == elem))\n        {\n          *head = elem->next;\n          break;\n        }\n\n      head = &(*head)->next;\n    }\n}\n\n/* internal, faster, version of ev_clear_pending */\ninline_speed void\nclear_pending (EV_P_ W w)\n{\n  if (w->pending)\n    {\n      pendings [ABSPRI (w)][w->pending - 1].w = (W)&pending_w;\n      w->pending = 0;\n    }\n}\n\nint\nev_clear_pending (EV_P_ void *w) EV_THROW\n{\n  W w_ = (W)w;\n  int pending = w_->pending;\n\n  if (expect_true (pending))\n    {\n      ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1;\n      p->w = (W)&pending_w;\n      w_->pending = 0;\n      return p->events;\n    }\n  else\n    return 0;\n}\n\ninline_size void\npri_adjust (EV_P_ W w)\n{\n  int pri = ev_priority (w);\n  pri = pri < EV_MINPRI ? EV_MINPRI : pri;\n  pri = pri > EV_MAXPRI ? EV_MAXPRI : pri;\n  ev_set_priority (w, pri);\n}\n\ninline_speed void\nev_start (EV_P_ W w, int active)\n{\n  pri_adjust (EV_A_ w);\n  w->active = active;\n  ev_ref (EV_A);\n}\n\ninline_size void\nev_stop (EV_P_ W w)\n{\n  ev_unref (EV_A);\n  w->active = 0;\n}\n\n/*****************************************************************************/\n\nnoinline\nvoid\nev_io_start (EV_P_ ev_io *w) EV_THROW\n{\n  int fd = w->fd;\n\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  assert ((\"libev: ev_io_start called with negative fd\", fd >= 0));\n  assert ((\"libev: ev_io_start called with illegal event mask\", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE))));\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, 1);\n  array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);\n  wlist_add (&anfds[fd].head, (WL)w);\n\n  /* common bug, apparently */\n  assert ((\"libev: ev_io_start called with corrupted watcher\", ((WL)w)->next != (WL)w));\n\n  fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY);\n  w->events &= ~EV__IOFDSET;\n\n  EV_FREQUENT_CHECK;\n}\n\nnoinline\nvoid\nev_io_stop (EV_P_ ev_io *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  assert ((\"libev: ev_io_stop called with illegal fd (must stay constant after start!)\", w->fd >= 0 && w->fd < anfdmax));\n\n  EV_FREQUENT_CHECK;\n\n  wlist_del (&anfds[w->fd].head, (WL)w);\n  ev_stop (EV_A_ (W)w);\n\n  fd_change (EV_A_ w->fd, EV_ANFD_REIFY);\n\n  EV_FREQUENT_CHECK;\n}\n\nnoinline\nvoid\nev_timer_start (EV_P_ ev_timer *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  ev_at (w) += mn_now;\n\n  assert ((\"libev: ev_timer_start called with negative timer repeat value\", w->repeat >= 0.));\n\n  EV_FREQUENT_CHECK;\n\n  ++timercnt;\n  ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);\n  array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);\n  ANHE_w (timers [ev_active (w)]) = (WT)w;\n  ANHE_at_cache (timers [ev_active (w)]);\n  upheap (timers, ev_active (w));\n\n  EV_FREQUENT_CHECK;\n\n  /*assert ((\"libev: internal timer heap corruption\", timers [ev_active (w)] == (WT)w));*/\n}\n\nnoinline\nvoid\nev_timer_stop (EV_P_ ev_timer *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    assert ((\"libev: internal timer heap corruption\", ANHE_w (timers [active]) == (WT)w));\n\n    --timercnt;\n\n    if (expect_true (active < timercnt + HEAP0))\n      {\n        timers [active] = timers [timercnt + HEAP0];\n        adjustheap (timers, timercnt, active);\n      }\n  }\n\n  ev_at (w) -= mn_now;\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n\nnoinline\nvoid\nev_timer_again (EV_P_ ev_timer *w) EV_THROW\n{\n  EV_FREQUENT_CHECK;\n\n  clear_pending (EV_A_ (W)w);\n\n  if (ev_is_active (w))\n    {\n      if (w->repeat)\n        {\n          ev_at (w) = mn_now + w->repeat;\n          ANHE_at_cache (timers [ev_active (w)]);\n          adjustheap (timers, timercnt, ev_active (w));\n        }\n      else\n        ev_timer_stop (EV_A_ w);\n    }\n  else if (w->repeat)\n    {\n      ev_at (w) = w->repeat;\n      ev_timer_start (EV_A_ w);\n    }\n\n  EV_FREQUENT_CHECK;\n}\n\nev_tstamp\nev_timer_remaining (EV_P_ ev_timer *w) EV_THROW\n{\n  return ev_at (w) - (ev_is_active (w) ? mn_now : 0.);\n}\n\n#if EV_PERIODIC_ENABLE\nnoinline\nvoid\nev_periodic_start (EV_P_ ev_periodic *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  if (w->reschedule_cb)\n    ev_at (w) = w->reschedule_cb (w, ev_rt_now);\n  else if (w->interval)\n    {\n      assert ((\"libev: ev_periodic_start called with negative interval value\", w->interval >= 0.));\n      periodic_recalc (EV_A_ w);\n    }\n  else\n    ev_at (w) = w->offset;\n\n  EV_FREQUENT_CHECK;\n\n  ++periodiccnt;\n  ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1);\n  array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, EMPTY2);\n  ANHE_w (periodics [ev_active (w)]) = (WT)w;\n  ANHE_at_cache (periodics [ev_active (w)]);\n  upheap (periodics, ev_active (w));\n\n  EV_FREQUENT_CHECK;\n\n  /*assert ((\"libev: internal periodic heap corruption\", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/\n}\n\nnoinline\nvoid\nev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    assert ((\"libev: internal periodic heap corruption\", ANHE_w (periodics [active]) == (WT)w));\n\n    --periodiccnt;\n\n    if (expect_true (active < periodiccnt + HEAP0))\n      {\n        periodics [active] = periodics [periodiccnt + HEAP0];\n        adjustheap (periodics, periodiccnt, active);\n      }\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n\nnoinline\nvoid\nev_periodic_again (EV_P_ ev_periodic *w) EV_THROW\n{\n  /* TODO: use adjustheap and recalculation */\n  ev_periodic_stop (EV_A_ w);\n  ev_periodic_start (EV_A_ w);\n}\n#endif\n\n#ifndef SA_RESTART\n# define SA_RESTART 0\n#endif\n\n#if EV_SIGNAL_ENABLE\n\nnoinline\nvoid\nev_signal_start (EV_P_ ev_signal *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  assert ((\"libev: ev_signal_start called with illegal signal number\", w->signum > 0 && w->signum < EV_NSIG));\n\n#if EV_MULTIPLICITY\n  assert ((\"libev: a signal must not be attached to two different loops\",\n           !signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop));\n\n  signals [w->signum - 1].loop = EV_A;\n  ECB_MEMORY_FENCE_RELEASE;\n#endif\n\n  EV_FREQUENT_CHECK;\n\n#if EV_USE_SIGNALFD\n  if (sigfd == -2)\n    {\n      sigfd = signalfd (-1, &sigfd_set, SFD_NONBLOCK | SFD_CLOEXEC);\n      if (sigfd < 0 && errno == EINVAL)\n        sigfd = signalfd (-1, &sigfd_set, 0); /* retry without flags */\n\n      if (sigfd >= 0)\n        {\n          fd_intern (sigfd); /* doing it twice will not hurt */\n\n          sigemptyset (&sigfd_set);\n\n          ev_io_init (&sigfd_w, sigfdcb, sigfd, EV_READ);\n          ev_set_priority (&sigfd_w, EV_MAXPRI);\n          ev_io_start (EV_A_ &sigfd_w);\n          ev_unref (EV_A); /* signalfd watcher should not keep loop alive */\n        }\n    }\n\n  if (sigfd >= 0)\n    {\n      /* TODO: check .head */\n      sigaddset (&sigfd_set, w->signum);\n      sigprocmask (SIG_BLOCK, &sigfd_set, 0);\n\n      signalfd (sigfd, &sigfd_set, 0);\n    }\n#endif\n\n  ev_start (EV_A_ (W)w, 1);\n  wlist_add (&signals [w->signum - 1].head, (WL)w);\n\n  if (!((WL)w)->next)\n# if EV_USE_SIGNALFD\n    if (sigfd < 0) /*TODO*/\n# endif\n      {\n# ifdef _WIN32\n        evpipe_init (EV_A);\n\n        signal (w->signum, ev_sighandler);\n# else\n        struct sigaction sa;\n\n        evpipe_init (EV_A);\n\n        sa.sa_handler = ev_sighandler;\n        sigfillset (&sa.sa_mask);\n        sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */\n        sigaction (w->signum, &sa, 0);\n\n        if (origflags & EVFLAG_NOSIGMASK)\n          {\n            sigemptyset (&sa.sa_mask);\n            sigaddset (&sa.sa_mask, w->signum);\n            sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0);\n          }\n#endif\n      }\n\n  EV_FREQUENT_CHECK;\n}\n\nnoinline\nvoid\nev_signal_stop (EV_P_ ev_signal *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  wlist_del (&signals [w->signum - 1].head, (WL)w);\n  ev_stop (EV_A_ (W)w);\n\n  if (!signals [w->signum - 1].head)\n    {\n#if EV_MULTIPLICITY\n      signals [w->signum - 1].loop = 0; /* unattach from signal */\n#endif\n#if EV_USE_SIGNALFD\n      if (sigfd >= 0)\n        {\n          sigset_t ss;\n\n          sigemptyset (&ss);\n          sigaddset (&ss, w->signum);\n          sigdelset (&sigfd_set, w->signum);\n\n          signalfd (sigfd, &sigfd_set, 0);\n          sigprocmask (SIG_UNBLOCK, &ss, 0);\n        }\n      else\n#endif\n        signal (w->signum, SIG_DFL);\n    }\n\n  EV_FREQUENT_CHECK;\n}\n\n#endif\n\n#if EV_CHILD_ENABLE\n\nvoid\nev_child_start (EV_P_ ev_child *w) EV_THROW\n{\n#if EV_MULTIPLICITY\n  assert ((\"libev: child watchers are only supported in the default loop\", loop == ev_default_loop_ptr));\n#endif\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, 1);\n  wlist_add (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w);\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_child_stop (EV_P_ ev_child *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  wlist_del (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w);\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n\n#endif\n\n#if EV_STAT_ENABLE\n\n# ifdef _WIN32\n#  undef lstat\n#  define lstat(a,b) _stati64 (a,b)\n# endif\n\n#define DEF_STAT_INTERVAL  5.0074891\n#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */\n#define MIN_STAT_INTERVAL  0.1074891\n\nnoinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);\n\n#if EV_USE_INOTIFY\n\n/* the * 2 is to allow for alignment padding, which for some reason is >> 8 */\n# define EV_INOTIFY_BUFSIZE (sizeof (struct inotify_event) * 2 + NAME_MAX)\n\nnoinline\nstatic void\ninfy_add (EV_P_ ev_stat *w)\n{\n  w->wd = inotify_add_watch (fs_fd, w->path,\n                             IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY\n                             | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO\n                             | IN_DONT_FOLLOW | IN_MASK_ADD);\n\n  if (w->wd >= 0)\n    {\n      struct statfs sfs;\n\n      /* now local changes will be tracked by inotify, but remote changes won't */\n      /* unless the filesystem is known to be local, we therefore still poll */\n      /* also do poll on <2.6.25, but with normal frequency */\n\n      if (!fs_2625)\n        w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;\n      else if (!statfs (w->path, &sfs)\n               && (sfs.f_type == 0x1373 /* devfs */\n                   || sfs.f_type == 0x4006 /* fat */\n                   || sfs.f_type == 0x4d44 /* msdos */\n                   || sfs.f_type == 0xEF53 /* ext2/3 */\n                   || sfs.f_type == 0x72b6 /* jffs2 */\n                   || sfs.f_type == 0x858458f6 /* ramfs */\n                   || sfs.f_type == 0x5346544e /* ntfs */\n                   || sfs.f_type == 0x3153464a /* jfs */\n                   || sfs.f_type == 0x9123683e /* btrfs */\n                   || sfs.f_type == 0x52654973 /* reiser3 */\n                   || sfs.f_type == 0x01021994 /* tmpfs */\n                   || sfs.f_type == 0x58465342 /* xfs */))\n        w->timer.repeat = 0.; /* filesystem is local, kernel new enough */\n      else\n        w->timer.repeat = w->interval ? w->interval : NFS_STAT_INTERVAL; /* remote, use reduced frequency */\n    }\n  else\n    {\n      /* can't use inotify, continue to stat */\n      w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;\n\n      /* if path is not there, monitor some parent directory for speedup hints */\n      /* note that exceeding the hardcoded path limit is not a correctness issue, */\n      /* but an efficiency issue only */\n      if ((errno == ENOENT || errno == EACCES) && strlen (w->path) < 4096)\n        {\n          char path [4096];\n          strcpy (path, w->path);\n\n          do\n            {\n              int mask = IN_MASK_ADD | IN_DELETE_SELF | IN_MOVE_SELF\n                       | (errno == EACCES ? IN_ATTRIB : IN_CREATE | IN_MOVED_TO);\n\n              char *pend = strrchr (path, '/');\n\n              if (!pend || pend == path)\n                break;\n\n              *pend = 0;\n              w->wd = inotify_add_watch (fs_fd, path, mask);\n            }\n          while (w->wd < 0 && (errno == ENOENT || errno == EACCES));\n        }\n    }\n\n  if (w->wd >= 0)\n    wlist_add (&fs_hash [w->wd & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w);\n\n  /* now re-arm timer, if required */\n  if (ev_is_active (&w->timer)) ev_ref (EV_A);\n  ev_timer_again (EV_A_ &w->timer);\n  if (ev_is_active (&w->timer)) ev_unref (EV_A);\n}\n\nnoinline\nstatic void\ninfy_del (EV_P_ ev_stat *w)\n{\n  int slot;\n  int wd = w->wd;\n\n  if (wd < 0)\n    return;\n\n  w->wd = -2;\n  slot = wd & ((EV_INOTIFY_HASHSIZE) - 1);\n  wlist_del (&fs_hash [slot].head, (WL)w);\n\n  /* remove this watcher, if others are watching it, they will rearm */\n  inotify_rm_watch (fs_fd, wd);\n}\n\nnoinline\nstatic void\ninfy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)\n{\n  if (slot < 0)\n    /* overflow, need to check for all hash slots */\n    for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot)\n      infy_wd (EV_A_ slot, wd, ev);\n  else\n    {\n      WL w_;\n\n      for (w_ = fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head; w_; )\n        {\n          ev_stat *w = (ev_stat *)w_;\n          w_ = w_->next; /* lets us remove this watcher and all before it */\n\n          if (w->wd == wd || wd == -1)\n            {\n              if (ev->mask & (IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF))\n                {\n                  wlist_del (&fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w);\n                  w->wd = -1;\n                  infy_add (EV_A_ w); /* re-add, no matter what */\n                }\n\n              stat_timer_cb (EV_A_ &w->timer, 0);\n            }\n        }\n    }\n}\n\nstatic void\ninfy_cb (EV_P_ ev_io *w, int revents)\n{\n  char buf [EV_INOTIFY_BUFSIZE];\n  int ofs;\n  int len = read (fs_fd, buf, sizeof (buf));\n\n  for (ofs = 0; ofs < len; )\n    {\n      struct inotify_event *ev = (struct inotify_event *)(buf + ofs);\n      infy_wd (EV_A_ ev->wd, ev->wd, ev);\n      ofs += sizeof (struct inotify_event) + ev->len;\n    }\n}\n\ninline_size ecb_cold\nvoid\nev_check_2625 (EV_P)\n{\n  /* kernels < 2.6.25 are borked\n   * http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html\n   */\n  if (ev_linux_version () < 0x020619)\n    return;\n\n  fs_2625 = 1;\n}\n\ninline_size int\ninfy_newfd (void)\n{\n#if defined IN_CLOEXEC && defined IN_NONBLOCK\n  int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK);\n  if (fd >= 0)\n    return fd;\n#endif\n  return inotify_init ();\n}\n\ninline_size void\ninfy_init (EV_P)\n{\n  if (fs_fd != -2)\n    return;\n\n  fs_fd = -1;\n\n  ev_check_2625 (EV_A);\n\n  fs_fd = infy_newfd ();\n\n  if (fs_fd >= 0)\n    {\n      fd_intern (fs_fd);\n      ev_io_init (&fs_w, infy_cb, fs_fd, EV_READ);\n      ev_set_priority (&fs_w, EV_MAXPRI);\n      ev_io_start (EV_A_ &fs_w);\n      ev_unref (EV_A);\n    }\n}\n\ninline_size void\ninfy_fork (EV_P)\n{\n  int slot;\n\n  if (fs_fd < 0)\n    return;\n\n  ev_ref (EV_A);\n  ev_io_stop (EV_A_ &fs_w);\n  close (fs_fd);\n  fs_fd = infy_newfd ();\n\n  if (fs_fd >= 0)\n    {\n      fd_intern (fs_fd);\n      ev_io_set (&fs_w, fs_fd, EV_READ);\n      ev_io_start (EV_A_ &fs_w);\n      ev_unref (EV_A);\n    }\n\n  for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot)\n    {\n      WL w_ = fs_hash [slot].head;\n      fs_hash [slot].head = 0;\n\n      while (w_)\n        {\n          ev_stat *w = (ev_stat *)w_;\n          w_ = w_->next; /* lets us add this watcher */\n\n          w->wd = -1;\n\n          if (fs_fd >= 0)\n            infy_add (EV_A_ w); /* re-add, no matter what */\n          else\n            {\n              w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;\n              if (ev_is_active (&w->timer)) ev_ref (EV_A);\n              ev_timer_again (EV_A_ &w->timer);\n              if (ev_is_active (&w->timer)) ev_unref (EV_A);\n            }\n        }\n    }\n}\n\n#endif\n\n#ifdef _WIN32\n# define EV_LSTAT(p,b) _stati64 (p, b)\n#else\n# define EV_LSTAT(p,b) lstat (p, b)\n#endif\n\nvoid\nev_stat_stat (EV_P_ ev_stat *w) EV_THROW\n{\n  if (lstat (w->path, &w->attr) < 0)\n    w->attr.st_nlink = 0;\n  else if (!w->attr.st_nlink)\n    w->attr.st_nlink = 1;\n}\n\nnoinline\nstatic void\nstat_timer_cb (EV_P_ ev_timer *w_, int revents)\n{\n  ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));\n\n  ev_statdata prev = w->attr;\n  ev_stat_stat (EV_A_ w);\n\n  /* memcmp doesn't work on netbsd, they.... do stuff to their struct stat */\n  if (\n    prev.st_dev      != w->attr.st_dev\n    || prev.st_ino   != w->attr.st_ino\n    || prev.st_mode  != w->attr.st_mode\n    || prev.st_nlink != w->attr.st_nlink\n    || prev.st_uid   != w->attr.st_uid\n    || prev.st_gid   != w->attr.st_gid\n    || prev.st_rdev  != w->attr.st_rdev\n    || prev.st_size  != w->attr.st_size\n    || prev.st_atime != w->attr.st_atime\n    || prev.st_mtime != w->attr.st_mtime\n    || prev.st_ctime != w->attr.st_ctime\n  ) {\n      /* we only update w->prev on actual differences */\n      /* in case we test more often than invoke the callback, */\n      /* to ensure that prev is always different to attr */\n      w->prev = prev;\n\n      #if EV_USE_INOTIFY\n        if (fs_fd >= 0)\n          {\n            infy_del (EV_A_ w);\n            infy_add (EV_A_ w);\n            ev_stat_stat (EV_A_ w); /* avoid race... */\n          }\n      #endif\n\n      ev_feed_event (EV_A_ w, EV_STAT);\n    }\n}\n\nvoid\nev_stat_start (EV_P_ ev_stat *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  ev_stat_stat (EV_A_ w);\n\n  if (w->interval < MIN_STAT_INTERVAL && w->interval)\n    w->interval = MIN_STAT_INTERVAL;\n\n  ev_timer_init (&w->timer, stat_timer_cb, 0., w->interval ? w->interval : DEF_STAT_INTERVAL);\n  ev_set_priority (&w->timer, ev_priority (w));\n\n#if EV_USE_INOTIFY\n  infy_init (EV_A);\n\n  if (fs_fd >= 0)\n    infy_add (EV_A_ w);\n  else\n#endif\n    {\n      ev_timer_again (EV_A_ &w->timer);\n      ev_unref (EV_A);\n    }\n\n  ev_start (EV_A_ (W)w, 1);\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_stat_stop (EV_P_ ev_stat *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n#if EV_USE_INOTIFY\n  infy_del (EV_A_ w);\n#endif\n\n  if (ev_is_active (&w->timer))\n    {\n      ev_ref (EV_A);\n      ev_timer_stop (EV_A_ &w->timer);\n    }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_IDLE_ENABLE\nvoid\nev_idle_start (EV_P_ ev_idle *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  pri_adjust (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ++idlecnt [ABSPRI (w)];\n\n    ++idleall;\n    ev_start (EV_A_ (W)w, active);\n\n    array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2);\n    idles [ABSPRI (w)][active - 1] = w;\n  }\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_idle_stop (EV_P_ ev_idle *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    idles [ABSPRI (w)][active - 1] = idles [ABSPRI (w)][--idlecnt [ABSPRI (w)]];\n    ev_active (idles [ABSPRI (w)][active - 1]) = active;\n\n    ev_stop (EV_A_ (W)w);\n    --idleall;\n  }\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_PREPARE_ENABLE\nvoid\nev_prepare_start (EV_P_ ev_prepare *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++preparecnt);\n  array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);\n  prepares [preparecnt - 1] = w;\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    prepares [active - 1] = prepares [--preparecnt];\n    ev_active (prepares [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_CHECK_ENABLE\nvoid\nev_check_start (EV_P_ ev_check *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++checkcnt);\n  array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);\n  checks [checkcnt - 1] = w;\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_check_stop (EV_P_ ev_check *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    checks [active - 1] = checks [--checkcnt];\n    ev_active (checks [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_EMBED_ENABLE\nnoinline\nvoid\nev_embed_sweep (EV_P_ ev_embed *w) EV_THROW\n{\n  ev_run (w->other, EVRUN_NOWAIT);\n}\n\nstatic void\nembed_io_cb (EV_P_ ev_io *io, int revents)\n{\n  ev_embed *w = (ev_embed *)(((char *)io) - offsetof (ev_embed, io));\n\n  if (ev_cb (w))\n    ev_feed_event (EV_A_ (W)w, EV_EMBED);\n  else\n    ev_run (w->other, EVRUN_NOWAIT);\n}\n\nstatic void\nembed_prepare_cb (EV_P_ ev_prepare *prepare, int revents)\n{\n  ev_embed *w = (ev_embed *)(((char *)prepare) - offsetof (ev_embed, prepare));\n\n  {\n    EV_P = w->other;\n\n    while (fdchangecnt)\n      {\n        fd_reify (EV_A);\n        ev_run (EV_A_ EVRUN_NOWAIT);\n      }\n  }\n}\n\nstatic void\nembed_fork_cb (EV_P_ ev_fork *fork_w, int revents)\n{\n  ev_embed *w = (ev_embed *)(((char *)fork_w) - offsetof (ev_embed, fork));\n\n  ev_embed_stop (EV_A_ w);\n\n  {\n    EV_P = w->other;\n\n    ev_loop_fork (EV_A);\n    ev_run (EV_A_ EVRUN_NOWAIT);\n  }\n\n  ev_embed_start (EV_A_ w);\n}\n\n#if 0\nstatic void\nembed_idle_cb (EV_P_ ev_idle *idle, int revents)\n{\n  ev_idle_stop (EV_A_ idle);\n}\n#endif\n\nvoid\nev_embed_start (EV_P_ ev_embed *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  {\n    EV_P = w->other;\n    assert ((\"libev: loop to be embedded is not embeddable\", backend & ev_embeddable_backends ()));\n    ev_io_init (&w->io, embed_io_cb, backend_fd, EV_READ);\n  }\n\n  EV_FREQUENT_CHECK;\n\n  ev_set_priority (&w->io, ev_priority (w));\n  ev_io_start (EV_A_ &w->io);\n\n  ev_prepare_init (&w->prepare, embed_prepare_cb);\n  ev_set_priority (&w->prepare, EV_MINPRI);\n  ev_prepare_start (EV_A_ &w->prepare);\n\n  ev_fork_init (&w->fork, embed_fork_cb);\n  ev_fork_start (EV_A_ &w->fork);\n\n  /*ev_idle_init (&w->idle, e,bed_idle_cb);*/\n\n  ev_start (EV_A_ (W)w, 1);\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_embed_stop (EV_P_ ev_embed *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_io_stop      (EV_A_ &w->io);\n  ev_prepare_stop (EV_A_ &w->prepare);\n  ev_fork_stop    (EV_A_ &w->fork);\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_FORK_ENABLE\nvoid\nev_fork_start (EV_P_ ev_fork *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++forkcnt);\n  array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);\n  forks [forkcnt - 1] = w;\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_fork_stop (EV_P_ ev_fork *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    forks [active - 1] = forks [--forkcnt];\n    ev_active (forks [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_CLEANUP_ENABLE\nvoid\nev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++cleanupcnt);\n  array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, EMPTY2);\n  cleanups [cleanupcnt - 1] = w;\n\n  /* cleanup watchers should never keep a refcount on the loop */\n  ev_unref (EV_A);\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n  ev_ref (EV_A);\n\n  {\n    int active = ev_active (w);\n\n    cleanups [active - 1] = cleanups [--cleanupcnt];\n    ev_active (cleanups [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_ASYNC_ENABLE\nvoid\nev_async_start (EV_P_ ev_async *w) EV_THROW\n{\n  if (expect_false (ev_is_active (w)))\n    return;\n\n  w->sent = 0;\n\n  evpipe_init (EV_A);\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++asynccnt);\n  array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2);\n  asyncs [asynccnt - 1] = w;\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_async_stop (EV_P_ ev_async *w) EV_THROW\n{\n  clear_pending (EV_A_ (W)w);\n  if (expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    asyncs [active - 1] = asyncs [--asynccnt];\n    ev_active (asyncs [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_async_send (EV_P_ ev_async *w) EV_THROW\n{\n  w->sent = 1;\n  evpipe_write (EV_A_ &async_pending);\n}\n#endif\n\n/*****************************************************************************/\n\nstruct ev_once\n{\n  ev_io io;\n  ev_timer to;\n  void (*cb)(int revents, void *arg);\n  void *arg;\n};\n\nstatic void\nonce_cb (EV_P_ struct ev_once *once, int revents)\n{\n  void (*cb)(int revents, void *arg) = once->cb;\n  void *arg = once->arg;\n\n  ev_io_stop    (EV_A_ &once->io);\n  ev_timer_stop (EV_A_ &once->to);\n  ev_free (once);\n\n  cb (revents, arg);\n}\n\nstatic void\nonce_cb_io (EV_P_ ev_io *w, int revents)\n{\n  struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, io));\n\n  once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->to));\n}\n\nstatic void\nonce_cb_to (EV_P_ ev_timer *w, int revents)\n{\n  struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, to));\n\n  once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->io));\n}\n\nvoid\nev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW\n{\n  struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));\n\n  if (expect_false (!once))\n    {\n      cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg);\n      return;\n    }\n\n  once->cb  = cb;\n  once->arg = arg;\n\n  ev_init (&once->io, once_cb_io);\n  if (fd >= 0)\n    {\n      ev_io_set (&once->io, fd, events);\n      ev_io_start (EV_A_ &once->io);\n    }\n\n  ev_init (&once->to, once_cb_to);\n  if (timeout >= 0.)\n    {\n      ev_timer_set (&once->to, timeout, 0.);\n      ev_timer_start (EV_A_ &once->to);\n    }\n}\n\n/*****************************************************************************/\n\n#if EV_WALK_ENABLE\necb_cold\nvoid\nev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW\n{\n  int i, j;\n  ev_watcher_list *wl, *wn;\n\n  if (types & (EV_IO | EV_EMBED))\n    for (i = 0; i < anfdmax; ++i)\n      for (wl = anfds [i].head; wl; )\n        {\n          wn = wl->next;\n\n#if EV_EMBED_ENABLE\n          if (ev_cb ((ev_io *)wl) == embed_io_cb)\n            {\n              if (types & EV_EMBED)\n                cb (EV_A_ EV_EMBED, ((char *)wl) - offsetof (struct ev_embed, io));\n            }\n          else\n#endif\n#if EV_USE_INOTIFY\n          if (ev_cb ((ev_io *)wl) == infy_cb)\n            ;\n          else\n#endif\n          if ((ev_io *)wl != &pipe_w)\n            if (types & EV_IO)\n              cb (EV_A_ EV_IO, wl);\n\n          wl = wn;\n        }\n\n  if (types & (EV_TIMER | EV_STAT))\n    for (i = timercnt + HEAP0; i-- > HEAP0; )\n#if EV_STAT_ENABLE\n      /*TODO: timer is not always active*/\n      if (ev_cb ((ev_timer *)ANHE_w (timers [i])) == stat_timer_cb)\n        {\n          if (types & EV_STAT)\n            cb (EV_A_ EV_STAT, ((char *)ANHE_w (timers [i])) - offsetof (struct ev_stat, timer));\n        }\n      else\n#endif\n      if (types & EV_TIMER)\n        cb (EV_A_ EV_TIMER, ANHE_w (timers [i]));\n\n#if EV_PERIODIC_ENABLE\n  if (types & EV_PERIODIC)\n    for (i = periodiccnt + HEAP0; i-- > HEAP0; )\n      cb (EV_A_ EV_PERIODIC, ANHE_w (periodics [i]));\n#endif\n\n#if EV_IDLE_ENABLE\n  if (types & EV_IDLE)\n    for (j = NUMPRI; j--; )\n      for (i = idlecnt [j]; i--; )\n        cb (EV_A_ EV_IDLE, idles [j][i]);\n#endif\n\n#if EV_FORK_ENABLE\n  if (types & EV_FORK)\n    for (i = forkcnt; i--; )\n      if (ev_cb (forks [i]) != embed_fork_cb)\n        cb (EV_A_ EV_FORK, forks [i]);\n#endif\n\n#if EV_ASYNC_ENABLE\n  if (types & EV_ASYNC)\n    for (i = asynccnt; i--; )\n      cb (EV_A_ EV_ASYNC, asyncs [i]);\n#endif\n\n#if EV_PREPARE_ENABLE\n  if (types & EV_PREPARE)\n    for (i = preparecnt; i--; )\n# if EV_EMBED_ENABLE\n      if (ev_cb (prepares [i]) != embed_prepare_cb)\n# endif\n        cb (EV_A_ EV_PREPARE, prepares [i]);\n#endif\n\n#if EV_CHECK_ENABLE\n  if (types & EV_CHECK)\n    for (i = checkcnt; i--; )\n      cb (EV_A_ EV_CHECK, checks [i]);\n#endif\n\n#if EV_SIGNAL_ENABLE\n  if (types & EV_SIGNAL)\n    for (i = 0; i < EV_NSIG - 1; ++i)\n      for (wl = signals [i].head; wl; )\n        {\n          wn = wl->next;\n          cb (EV_A_ EV_SIGNAL, wl);\n          wl = wn;\n        }\n#endif\n\n#if EV_CHILD_ENABLE\n  if (types & EV_CHILD)\n    for (i = (EV_PID_HASHSIZE); i--; )\n      for (wl = childs [i]; wl; )\n        {\n          wn = wl->next;\n          cb (EV_A_ EV_CHILD, wl);\n          wl = wn;\n        }\n#endif\n/* EV_STAT     0x00001000 /* stat data changed */\n/* EV_EMBED    0x00010000 /* embedded event loop needs sweep */\n}\n#endif\n\n#if EV_MULTIPLICITY\n  #include \"ev_wrap.h\"\n#endif\n\n"
  },
  {
    "path": "libev/ev.h",
    "content": "/*\n * libev native API header\n *\n * Copyright (c) 2007,2008,2009,2010,2011,2012,2015 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef EV_H_\n#define EV_H_\n\n#ifdef __cplusplus\n# define EV_CPP(x) x\n# if __cplusplus >= 201103L\n#  define EV_THROW noexcept\n# else\n#  define EV_THROW throw ()\n# endif\n#else\n# define EV_CPP(x)\n# define EV_THROW\n#endif\n\nEV_CPP(extern \"C\" {)\n\n/*****************************************************************************/\n\n/* pre-4.0 compatibility */\n#ifndef EV_COMPAT3\n# define EV_COMPAT3 1\n#endif\n\n#ifndef EV_FEATURES\n# if defined __OPTIMIZE_SIZE__\n#  define EV_FEATURES 0x7c\n# else\n#  define EV_FEATURES 0x7f\n# endif\n#endif\n\n#define EV_FEATURE_CODE     ((EV_FEATURES) &  1)\n#define EV_FEATURE_DATA     ((EV_FEATURES) &  2)\n#define EV_FEATURE_CONFIG   ((EV_FEATURES) &  4)\n#define EV_FEATURE_API      ((EV_FEATURES) &  8)\n#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 16)\n#define EV_FEATURE_BACKENDS ((EV_FEATURES) & 32)\n#define EV_FEATURE_OS       ((EV_FEATURES) & 64)\n\n/* these priorities are inclusive, higher priorities will be invoked earlier */\n#ifndef EV_MINPRI\n# define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0)\n#endif\n#ifndef EV_MAXPRI\n# define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0)\n#endif\n\n#ifndef EV_MULTIPLICITY\n# define EV_MULTIPLICITY EV_FEATURE_CONFIG\n#endif\n\n#ifndef EV_PERIODIC_ENABLE\n# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_STAT_ENABLE\n# define EV_STAT_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_PREPARE_ENABLE\n# define EV_PREPARE_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_CHECK_ENABLE\n# define EV_CHECK_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_IDLE_ENABLE\n# define EV_IDLE_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_FORK_ENABLE\n# define EV_FORK_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_CLEANUP_ENABLE\n# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_SIGNAL_ENABLE\n# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_CHILD_ENABLE\n# ifdef _WIN32\n#  define EV_CHILD_ENABLE 0\n# else\n#  define EV_CHILD_ENABLE EV_FEATURE_WATCHERS\n#endif\n#endif\n\n#ifndef EV_ASYNC_ENABLE\n# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_EMBED_ENABLE\n# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_WALK_ENABLE\n# define EV_WALK_ENABLE 0 /* not yet */\n#endif\n\n/*****************************************************************************/\n\n#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE\n# undef EV_SIGNAL_ENABLE\n# define EV_SIGNAL_ENABLE 1\n#endif\n\n/*****************************************************************************/\n\ntypedef double ev_tstamp;\n\n#include <string.h> /* for memmove */\n\n#ifndef EV_ATOMIC_T\n# include <signal.h>\n# define EV_ATOMIC_T sig_atomic_t volatile\n#endif\n\n#if EV_STAT_ENABLE\n# ifdef _WIN32\n#  include <time.h>\n#  include <sys/types.h>\n# endif\n# include <sys/stat.h>\n#endif\n\n/* support multiple event loops? */\n#if EV_MULTIPLICITY\nstruct ev_loop;\n# define EV_P  struct ev_loop *loop               /* a loop as sole parameter in a declaration */\n# define EV_P_ EV_P,                              /* a loop as first of multiple parameters */\n# define EV_A  loop                               /* a loop as sole argument to a function call */\n# define EV_A_ EV_A,                              /* a loop as first of multiple arguments */\n# define EV_DEFAULT_UC  ev_default_loop_uc_ ()    /* the default loop, if initialised, as sole arg */\n# define EV_DEFAULT_UC_ EV_DEFAULT_UC,            /* the default loop as first of multiple arguments */\n# define EV_DEFAULT  ev_default_loop (0)          /* the default loop as sole arg */\n# define EV_DEFAULT_ EV_DEFAULT,                  /* the default loop as first of multiple arguments */\n#else\n# define EV_P void\n# define EV_P_\n# define EV_A\n# define EV_A_\n# define EV_DEFAULT\n# define EV_DEFAULT_\n# define EV_DEFAULT_UC\n# define EV_DEFAULT_UC_\n# undef EV_EMBED_ENABLE\n#endif\n\n/* EV_INLINE is used for functions in header files */\n#if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3\n# define EV_INLINE static inline\n#else\n# define EV_INLINE static\n#endif\n\n#ifdef EV_API_STATIC\n# define EV_API_DECL static\n#else\n# define EV_API_DECL extern\n#endif\n\n/* EV_PROTOTYPES can be used to switch of prototype declarations */\n#ifndef EV_PROTOTYPES\n# define EV_PROTOTYPES 1\n#endif\n\n/*****************************************************************************/\n\n#define EV_VERSION_MAJOR 4\n#define EV_VERSION_MINOR 24\n\n/* eventmask, revents, events... */\nenum {\n  EV_UNDEF    = (int)0xFFFFFFFF, /* guaranteed to be invalid */\n  EV_NONE     =            0x00, /* no events */\n  EV_READ     =            0x01, /* ev_io detected read will not block */\n  EV_WRITE    =            0x02, /* ev_io detected write will not block */\n  EV__IOFDSET =            0x80, /* internal use only */\n  EV_IO       =         EV_READ, /* alias for type-detection */\n  EV_TIMER    =      0x00000100, /* timer timed out */\n#if EV_COMPAT3\n  EV_TIMEOUT  =        EV_TIMER, /* pre 4.0 API compatibility */\n#endif\n  EV_PERIODIC =      0x00000200, /* periodic timer timed out */\n  EV_SIGNAL   =      0x00000400, /* signal was received */\n  EV_CHILD    =      0x00000800, /* child/pid had status change */\n  EV_STAT     =      0x00001000, /* stat data changed */\n  EV_IDLE     =      0x00002000, /* event loop is idling */\n  EV_PREPARE  =      0x00004000, /* event loop about to poll */\n  EV_CHECK    =      0x00008000, /* event loop finished poll */\n  EV_EMBED    =      0x00010000, /* embedded event loop needs sweep */\n  EV_FORK     =      0x00020000, /* event loop resumed in child */\n  EV_CLEANUP  =      0x00040000, /* event loop resumed in child */\n  EV_ASYNC    =      0x00080000, /* async intra-loop signal */\n  EV_CUSTOM   =      0x01000000, /* for use by user code */\n  EV_ERROR    = (int)0x80000000  /* sent when an error occurs */\n};\n\n/* can be used to add custom fields to all watchers, while losing binary compatibility */\n#ifndef EV_COMMON\n# define EV_COMMON void *data;\n#endif\n\n#ifndef EV_CB_DECLARE\n# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents);\n#endif\n#ifndef EV_CB_INVOKE\n# define EV_CB_INVOKE(watcher,revents) (watcher)->cb (EV_A_ (watcher), (revents))\n#endif\n\n/* not official, do not use */\n#define EV_CB(type,name) void name (EV_P_ struct ev_ ## type *w, int revents)\n\n/*\n * struct member types:\n * private: you may look at them, but not change them,\n *          and they might not mean anything to you.\n * ro: can be read anytime, but only changed when the watcher isn't active.\n * rw: can be read and modified anytime, even when the watcher is active.\n *\n * some internal details that might be helpful for debugging:\n *\n * active is either 0, which means the watcher is not active,\n *           or the array index of the watcher (periodics, timers)\n *           or the array index + 1 (most other watchers)\n *           or simply 1 for watchers that aren't in some array.\n * pending is either 0, in which case the watcher isn't,\n *           or the array index + 1 in the pendings array.\n */\n\n#if EV_MINPRI == EV_MAXPRI\n# define EV_DECL_PRIORITY\n#elif !defined (EV_DECL_PRIORITY)\n# define EV_DECL_PRIORITY int priority;\n#endif\n\n/* shared by all watchers */\n#define EV_WATCHER(type)\t\t\t\\\n  int active; /* private */\t\t\t\\\n  int pending; /* private */\t\t\t\\\n  EV_DECL_PRIORITY /* private */\t\t\\\n  EV_COMMON /* rw */\t\t\t\t\\\n  EV_CB_DECLARE (type) /* private */\n\n#define EV_WATCHER_LIST(type)\t\t\t\\\n  EV_WATCHER (type)\t\t\t\t\\\n  struct ev_watcher_list *next; /* private */\n\n#define EV_WATCHER_TIME(type)\t\t\t\\\n  EV_WATCHER (type)\t\t\t\t\\\n  ev_tstamp at;     /* private */\n\n/* base class, nothing to see here unless you subclass */\ntypedef struct ev_watcher\n{\n  EV_WATCHER (ev_watcher)\n} ev_watcher;\n\n/* base class, nothing to see here unless you subclass */\ntypedef struct ev_watcher_list\n{\n  EV_WATCHER_LIST (ev_watcher_list)\n} ev_watcher_list;\n\n/* base class, nothing to see here unless you subclass */\ntypedef struct ev_watcher_time\n{\n  EV_WATCHER_TIME (ev_watcher_time)\n} ev_watcher_time;\n\n/* invoked when fd is either EV_READable or EV_WRITEable */\n/* revent EV_READ, EV_WRITE */\ntypedef struct ev_io\n{\n  EV_WATCHER_LIST (ev_io)\n\n  int fd;     /* ro */\n  int events; /* ro */\n} ev_io;\n\n/* invoked after a specific time, repeatable (based on monotonic clock) */\n/* revent EV_TIMEOUT */\ntypedef struct ev_timer\n{\n  EV_WATCHER_TIME (ev_timer)\n\n  ev_tstamp repeat; /* rw */\n} ev_timer;\n\n/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */\n/* revent EV_PERIODIC */\ntypedef struct ev_periodic\n{\n  EV_WATCHER_TIME (ev_periodic)\n\n  ev_tstamp offset; /* rw */\n  ev_tstamp interval; /* rw */\n  ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now) EV_THROW; /* rw */\n} ev_periodic;\n\n/* invoked when the given signal has been received */\n/* revent EV_SIGNAL */\ntypedef struct ev_signal\n{\n  EV_WATCHER_LIST (ev_signal)\n\n  int signum; /* ro */\n} ev_signal;\n\n/* invoked when sigchld is received and waitpid indicates the given pid */\n/* revent EV_CHILD */\n/* does not support priorities */\ntypedef struct ev_child\n{\n  EV_WATCHER_LIST (ev_child)\n\n  int flags;   /* private */\n  int pid;     /* ro */\n  int rpid;    /* rw, holds the received pid */\n  int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */\n} ev_child;\n\n#if EV_STAT_ENABLE\n/* st_nlink = 0 means missing file or other error */\n# ifdef _WIN32\ntypedef struct _stati64 ev_statdata;\n# else\ntypedef struct stat ev_statdata;\n# endif\n\n/* invoked each time the stat data changes for a given path */\n/* revent EV_STAT */\ntypedef struct ev_stat\n{\n  EV_WATCHER_LIST (ev_stat)\n\n  ev_timer timer;     /* private */\n  ev_tstamp interval; /* ro */\n  const char *path;   /* ro */\n  ev_statdata prev;   /* ro */\n  ev_statdata attr;   /* ro */\n\n  int wd; /* wd for inotify, fd for kqueue */\n} ev_stat;\n#endif\n\n#if EV_IDLE_ENABLE\n/* invoked when the nothing else needs to be done, keeps the process from blocking */\n/* revent EV_IDLE */\ntypedef struct ev_idle\n{\n  EV_WATCHER (ev_idle)\n} ev_idle;\n#endif\n\n/* invoked for each run of the mainloop, just before the blocking call */\n/* you can still change events in any way you like */\n/* revent EV_PREPARE */\ntypedef struct ev_prepare\n{\n  EV_WATCHER (ev_prepare)\n} ev_prepare;\n\n/* invoked for each run of the mainloop, just after the blocking call */\n/* revent EV_CHECK */\ntypedef struct ev_check\n{\n  EV_WATCHER (ev_check)\n} ev_check;\n\n#if EV_FORK_ENABLE\n/* the callback gets invoked before check in the child process when a fork was detected */\n/* revent EV_FORK */\ntypedef struct ev_fork\n{\n  EV_WATCHER (ev_fork)\n} ev_fork;\n#endif\n\n#if EV_CLEANUP_ENABLE\n/* is invoked just before the loop gets destroyed */\n/* revent EV_CLEANUP */\ntypedef struct ev_cleanup\n{\n  EV_WATCHER (ev_cleanup)\n} ev_cleanup;\n#endif\n\n#if EV_EMBED_ENABLE\n/* used to embed an event loop inside another */\n/* the callback gets invoked when the event loop has handled events, and can be 0 */\ntypedef struct ev_embed\n{\n  EV_WATCHER (ev_embed)\n\n  struct ev_loop *other; /* ro */\n  ev_io io;              /* private */\n  ev_prepare prepare;    /* private */\n  ev_check check;        /* unused */\n  ev_timer timer;        /* unused */\n  ev_periodic periodic;  /* unused */\n  ev_idle idle;          /* unused */\n  ev_fork fork;          /* private */\n#if EV_CLEANUP_ENABLE\n  ev_cleanup cleanup;    /* unused */\n#endif\n} ev_embed;\n#endif\n\n#if EV_ASYNC_ENABLE\n/* invoked when somebody calls ev_async_send on the watcher */\n/* revent EV_ASYNC */\ntypedef struct ev_async\n{\n  EV_WATCHER (ev_async)\n\n  EV_ATOMIC_T sent; /* private */\n} ev_async;\n\n# define ev_async_pending(w) (+(w)->sent)\n#endif\n\n/* the presence of this union forces similar struct layout */\nunion ev_any_watcher\n{\n  struct ev_watcher w;\n  struct ev_watcher_list wl;\n\n  struct ev_io io;\n  struct ev_timer timer;\n  struct ev_periodic periodic;\n  struct ev_signal signal;\n  struct ev_child child;\n#if EV_STAT_ENABLE\n  struct ev_stat stat;\n#endif\n#if EV_IDLE_ENABLE\n  struct ev_idle idle;\n#endif\n  struct ev_prepare prepare;\n  struct ev_check check;\n#if EV_FORK_ENABLE\n  struct ev_fork fork;\n#endif\n#if EV_CLEANUP_ENABLE\n  struct ev_cleanup cleanup;\n#endif\n#if EV_EMBED_ENABLE\n  struct ev_embed embed;\n#endif\n#if EV_ASYNC_ENABLE\n  struct ev_async async;\n#endif\n};\n\n/* flag bits for ev_default_loop and ev_loop_new */\nenum {\n  /* the default */\n  EVFLAG_AUTO      = 0x00000000U, /* not quite a mask */\n  /* flag bits */\n  EVFLAG_NOENV     = 0x01000000U, /* do NOT consult environment */\n  EVFLAG_FORKCHECK = 0x02000000U, /* check for a fork in each iteration */\n  /* debugging/feature disable */\n  EVFLAG_NOINOTIFY = 0x00100000U, /* do not attempt to use inotify */\n#if EV_COMPAT3\n  EVFLAG_NOSIGFD   = 0, /* compatibility to pre-3.9 */\n#endif\n  EVFLAG_SIGNALFD  = 0x00200000U, /* attempt to use signalfd */\n  EVFLAG_NOSIGMASK = 0x00400000U  /* avoid modifying the signal mask */\n};\n\n/* method bits to be ored together */\nenum {\n  EVBACKEND_SELECT  = 0x00000001U, /* available just about anywhere */\n  EVBACKEND_POLL    = 0x00000002U, /* !win, !aix, broken on osx */\n  EVBACKEND_EPOLL   = 0x00000004U, /* linux */\n  EVBACKEND_KQUEUE  = 0x00000008U, /* bsd, broken on osx */\n  EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */\n  EVBACKEND_PORT    = 0x00000020U, /* solaris 10 */\n  EVBACKEND_ALL     = 0x0000003FU, /* all known backends */\n  EVBACKEND_MASK    = 0x0000FFFFU  /* all future backends */\n};\n\n#if EV_PROTOTYPES\nEV_API_DECL int ev_version_major (void) EV_THROW;\nEV_API_DECL int ev_version_minor (void) EV_THROW;\n\nEV_API_DECL unsigned int ev_supported_backends (void) EV_THROW;\nEV_API_DECL unsigned int ev_recommended_backends (void) EV_THROW;\nEV_API_DECL unsigned int ev_embeddable_backends (void) EV_THROW;\n\nEV_API_DECL ev_tstamp ev_time (void) EV_THROW;\nEV_API_DECL void ev_sleep (ev_tstamp delay) EV_THROW; /* sleep for a while */\n\n/* Sets the allocation function to use, works like realloc.\n * It is used to allocate and free memory.\n * If it returns zero when memory needs to be allocated, the library might abort\n * or take some potentially destructive action.\n * The default is your system realloc function.\n */\nEV_API_DECL void ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW;\n\n/* set the callback function to call on a\n * retryable syscall error\n * (such as failed select, poll, epoll_wait)\n */\nEV_API_DECL void ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW;\n\n#if EV_MULTIPLICITY\n\n/* the default loop is the only one that handles signals and child watchers */\n/* you can call this as often as you like */\nEV_API_DECL struct ev_loop *ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_THROW;\n\n#ifdef EV_API_STATIC\nEV_API_DECL struct ev_loop *ev_default_loop_ptr;\n#endif\n\nEV_INLINE struct ev_loop *\nev_default_loop_uc_ (void) EV_THROW\n{\n  extern struct ev_loop *ev_default_loop_ptr;\n\n  return ev_default_loop_ptr;\n}\n\nEV_INLINE int\nev_is_default_loop (EV_P) EV_THROW\n{\n  return EV_A == EV_DEFAULT_UC;\n}\n\n/* create and destroy alternative loops that don't handle signals */\nEV_API_DECL struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0)) EV_THROW;\n\nEV_API_DECL ev_tstamp ev_now (EV_P) EV_THROW; /* time w.r.t. timers and the eventloop, updated after each poll */\n\n#else\n\nEV_API_DECL int ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_THROW; /* returns true when successful */\n\nEV_API_DECL ev_tstamp ev_rt_now;\n\nEV_INLINE ev_tstamp\nev_now (void) EV_THROW\n{\n  return ev_rt_now;\n}\n\n/* looks weird, but ev_is_default_loop (EV_A) still works if this exists */\nEV_INLINE int\nev_is_default_loop (void) EV_THROW\n{\n  return 1;\n}\n\n#endif /* multiplicity */\n\n/* destroy event loops, also works for the default loop */\nEV_API_DECL void ev_loop_destroy (EV_P);\n\n/* this needs to be called after fork, to duplicate the loop */\n/* when you want to re-use it in the child */\n/* you can call it in either the parent or the child */\n/* you can actually call it at any time, anywhere :) */\nEV_API_DECL void ev_loop_fork (EV_P) EV_THROW;\n\nEV_API_DECL unsigned int ev_backend (EV_P) EV_THROW; /* backend in use by loop */\n\nEV_API_DECL void ev_now_update (EV_P) EV_THROW; /* update event loop time */\n\n#if EV_WALK_ENABLE\n/* walk (almost) all watchers in the loop of a given type, invoking the */\n/* callback on every such watcher. The callback might stop the watcher, */\n/* but do nothing else with the loop */\nEV_API_DECL void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW;\n#endif\n\n#endif /* prototypes */\n\n/* ev_run flags values */\nenum {\n  EVRUN_NOWAIT = 1, /* do not block/wait */\n  EVRUN_ONCE   = 2  /* block *once* only */\n};\n\n/* ev_break how values */\nenum {\n  EVBREAK_CANCEL = 0, /* undo unloop */\n  EVBREAK_ONE    = 1, /* unloop once */\n  EVBREAK_ALL    = 2  /* unloop all loops */\n};\n\n#if EV_PROTOTYPES\nEV_API_DECL int  ev_run (EV_P_ int flags EV_CPP (= 0));\nEV_API_DECL void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)) EV_THROW; /* break out of the loop */\n\n/*\n * ref/unref can be used to add or remove a refcount on the mainloop. every watcher\n * keeps one reference. if you have a long-running watcher you never unregister that\n * should not keep ev_loop from running, unref() after starting, and ref() before stopping.\n */\nEV_API_DECL void ev_ref   (EV_P) EV_THROW;\nEV_API_DECL void ev_unref (EV_P) EV_THROW;\n\n/*\n * convenience function, wait for a single event, without registering an event watcher\n * if timeout is < 0, do wait indefinitely\n */\nEV_API_DECL void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW;\n\n# if EV_FEATURE_API\nEV_API_DECL unsigned int ev_iteration (EV_P) EV_THROW; /* number of loop iterations */\nEV_API_DECL unsigned int ev_depth     (EV_P) EV_THROW; /* #ev_loop enters - #ev_loop leaves */\nEV_API_DECL void         ev_verify    (EV_P) EV_THROW; /* abort if loop data corrupted */\n\nEV_API_DECL void ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW; /* sleep at least this time, default 0 */\nEV_API_DECL void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW; /* sleep at least this time, default 0 */\n\n/* advanced stuff for threading etc. support, see docs */\nEV_API_DECL void ev_set_userdata (EV_P_ void *data) EV_THROW;\nEV_API_DECL void *ev_userdata (EV_P) EV_THROW;\ntypedef void (*ev_loop_callback)(EV_P);\nEV_API_DECL void ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW;\n/* C++ doesn't allow the use of the ev_loop_callback typedef here, so we need to spell it out */\nEV_API_DECL void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW;\n\nEV_API_DECL unsigned int ev_pending_count (EV_P) EV_THROW; /* number of pending events, if any */\nEV_API_DECL void ev_invoke_pending (EV_P); /* invoke all pending watchers */\n\n/*\n * stop/start the timer handling.\n */\nEV_API_DECL void ev_suspend (EV_P) EV_THROW;\nEV_API_DECL void ev_resume  (EV_P) EV_THROW;\n#endif\n\n#endif\n\n/* these may evaluate ev multiple times, and the other arguments at most once */\n/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */\n#define ev_init(ev,cb_) do {\t\t\t\\\n  ((ev_watcher *)(void *)(ev))->active  =\t\\\n  ((ev_watcher *)(void *)(ev))->pending = 0;\t\\\n  ev_set_priority ((ev), 0);\t\t\t\\\n  ev_set_cb ((ev), cb_);\t\t\t\\\n} while (0)\n\n#define ev_io_set(ev,fd_,events_)            do { (ev)->fd = (fd_); (ev)->events = (events_) | EV__IOFDSET; } while (0)\n#define ev_timer_set(ev,after_,repeat_)      do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0)\n#define ev_periodic_set(ev,ofs_,ival_,rcb_)  do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0)\n#define ev_signal_set(ev,signum_)            do { (ev)->signum = (signum_); } while (0)\n#define ev_child_set(ev,pid_,trace_)         do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0)\n#define ev_stat_set(ev,path_,interval_)      do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0)\n#define ev_idle_set(ev)                      /* nop, yes, this is a serious in-joke */\n#define ev_prepare_set(ev)                   /* nop, yes, this is a serious in-joke */\n#define ev_check_set(ev)                     /* nop, yes, this is a serious in-joke */\n#define ev_embed_set(ev,other_)              do { (ev)->other = (other_); } while (0)\n#define ev_fork_set(ev)                      /* nop, yes, this is a serious in-joke */\n#define ev_cleanup_set(ev)                   /* nop, yes, this is a serious in-joke */\n#define ev_async_set(ev)                     /* nop, yes, this is a serious in-joke */\n\n#define ev_io_init(ev,cb,fd,events)          do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)\n#define ev_timer_init(ev,cb,after,repeat)    do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)\n#define ev_periodic_init(ev,cb,ofs,ival,rcb) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(ofs),(ival),(rcb)); } while (0)\n#define ev_signal_init(ev,cb,signum)         do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0)\n#define ev_child_init(ev,cb,pid,trace)       do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0)\n#define ev_stat_init(ev,cb,path,interval)    do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0)\n#define ev_idle_init(ev,cb)                  do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0)\n#define ev_prepare_init(ev,cb)               do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)\n#define ev_check_init(ev,cb)                 do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)\n#define ev_embed_init(ev,cb,other)           do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)\n#define ev_fork_init(ev,cb)                  do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)\n#define ev_cleanup_init(ev,cb)               do { ev_init ((ev), (cb)); ev_cleanup_set ((ev)); } while (0)\n#define ev_async_init(ev,cb)                 do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)\n\n#define ev_is_pending(ev)                    (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */\n#define ev_is_active(ev)                     (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */\n\n#define ev_cb_(ev)                           (ev)->cb /* rw */\n#define ev_cb(ev)                            (memmove (&ev_cb_ (ev), &((ev_watcher *)(ev))->cb, sizeof (ev_cb_ (ev))), (ev)->cb)\n\n#if EV_MINPRI == EV_MAXPRI\n# define ev_priority(ev)                     ((ev), EV_MINPRI)\n# define ev_set_priority(ev,pri)             ((ev), (pri))\n#else\n# define ev_priority(ev)                     (+(((ev_watcher *)(void *)(ev))->priority))\n# define ev_set_priority(ev,pri)             (   (ev_watcher *)(void *)(ev))->priority = (pri)\n#endif\n\n#define ev_periodic_at(ev)                   (+((ev_watcher_time *)(ev))->at)\n\n#ifndef ev_set_cb\n# define ev_set_cb(ev,cb_)                   (ev_cb_ (ev) = (cb_), memmove (&((ev_watcher *)(ev))->cb, &ev_cb_ (ev), sizeof (ev_cb_ (ev))))\n#endif\n\n/* stopping (enabling, adding) a watcher does nothing if it is already running */\n/* stopping (disabling, deleting) a watcher does nothing unless it's already running */\n#if EV_PROTOTYPES\n\n/* feeds an event into a watcher as if the event actually occurred */\n/* accepts any ev_watcher type */\nEV_API_DECL void ev_feed_event     (EV_P_ void *w, int revents) EV_THROW;\nEV_API_DECL void ev_feed_fd_event  (EV_P_ int fd, int revents) EV_THROW;\n#if EV_SIGNAL_ENABLE\nEV_API_DECL void ev_feed_signal    (int signum) EV_THROW;\nEV_API_DECL void ev_feed_signal_event (EV_P_ int signum) EV_THROW;\n#endif\nEV_API_DECL void ev_invoke         (EV_P_ void *w, int revents);\nEV_API_DECL int  ev_clear_pending  (EV_P_ void *w) EV_THROW;\n\nEV_API_DECL void ev_io_start       (EV_P_ ev_io *w) EV_THROW;\nEV_API_DECL void ev_io_stop        (EV_P_ ev_io *w) EV_THROW;\n\nEV_API_DECL void ev_timer_start    (EV_P_ ev_timer *w) EV_THROW;\nEV_API_DECL void ev_timer_stop     (EV_P_ ev_timer *w) EV_THROW;\n/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */\nEV_API_DECL void ev_timer_again    (EV_P_ ev_timer *w) EV_THROW;\n/* return remaining time */\nEV_API_DECL ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW;\n\n#if EV_PERIODIC_ENABLE\nEV_API_DECL void ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW;\nEV_API_DECL void ev_periodic_stop  (EV_P_ ev_periodic *w) EV_THROW;\nEV_API_DECL void ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW;\n#endif\n\n/* only supported in the default loop */\n#if EV_SIGNAL_ENABLE\nEV_API_DECL void ev_signal_start   (EV_P_ ev_signal *w) EV_THROW;\nEV_API_DECL void ev_signal_stop    (EV_P_ ev_signal *w) EV_THROW;\n#endif\n\n/* only supported in the default loop */\n# if EV_CHILD_ENABLE\nEV_API_DECL void ev_child_start    (EV_P_ ev_child *w) EV_THROW;\nEV_API_DECL void ev_child_stop     (EV_P_ ev_child *w) EV_THROW;\n# endif\n\n# if EV_STAT_ENABLE\nEV_API_DECL void ev_stat_start     (EV_P_ ev_stat *w) EV_THROW;\nEV_API_DECL void ev_stat_stop      (EV_P_ ev_stat *w) EV_THROW;\nEV_API_DECL void ev_stat_stat      (EV_P_ ev_stat *w) EV_THROW;\n# endif\n\n# if EV_IDLE_ENABLE\nEV_API_DECL void ev_idle_start     (EV_P_ ev_idle *w) EV_THROW;\nEV_API_DECL void ev_idle_stop      (EV_P_ ev_idle *w) EV_THROW;\n# endif\n\n#if EV_PREPARE_ENABLE\nEV_API_DECL void ev_prepare_start  (EV_P_ ev_prepare *w) EV_THROW;\nEV_API_DECL void ev_prepare_stop   (EV_P_ ev_prepare *w) EV_THROW;\n#endif\n\n#if EV_CHECK_ENABLE\nEV_API_DECL void ev_check_start    (EV_P_ ev_check *w) EV_THROW;\nEV_API_DECL void ev_check_stop     (EV_P_ ev_check *w) EV_THROW;\n#endif\n\n# if EV_FORK_ENABLE\nEV_API_DECL void ev_fork_start     (EV_P_ ev_fork *w) EV_THROW;\nEV_API_DECL void ev_fork_stop      (EV_P_ ev_fork *w) EV_THROW;\n# endif\n\n# if EV_CLEANUP_ENABLE\nEV_API_DECL void ev_cleanup_start  (EV_P_ ev_cleanup *w) EV_THROW;\nEV_API_DECL void ev_cleanup_stop   (EV_P_ ev_cleanup *w) EV_THROW;\n# endif\n\n# if EV_EMBED_ENABLE\n/* only supported when loop to be embedded is in fact embeddable */\nEV_API_DECL void ev_embed_start    (EV_P_ ev_embed *w) EV_THROW;\nEV_API_DECL void ev_embed_stop     (EV_P_ ev_embed *w) EV_THROW;\nEV_API_DECL void ev_embed_sweep    (EV_P_ ev_embed *w) EV_THROW;\n# endif\n\n# if EV_ASYNC_ENABLE\nEV_API_DECL void ev_async_start    (EV_P_ ev_async *w) EV_THROW;\nEV_API_DECL void ev_async_stop     (EV_P_ ev_async *w) EV_THROW;\nEV_API_DECL void ev_async_send     (EV_P_ ev_async *w) EV_THROW;\n# endif\n\n#if EV_COMPAT3\n  #define EVLOOP_NONBLOCK EVRUN_NOWAIT\n  #define EVLOOP_ONESHOT  EVRUN_ONCE\n  #define EVUNLOOP_CANCEL EVBREAK_CANCEL\n  #define EVUNLOOP_ONE    EVBREAK_ONE\n  #define EVUNLOOP_ALL    EVBREAK_ALL\n  #if EV_PROTOTYPES\n    EV_INLINE void ev_loop   (EV_P_ int flags) { ev_run   (EV_A_ flags); }\n    EV_INLINE void ev_unloop (EV_P_ int how  ) { ev_break (EV_A_ how  ); }\n    EV_INLINE void ev_default_destroy (void) { ev_loop_destroy (EV_DEFAULT); }\n    EV_INLINE void ev_default_fork    (void) { ev_loop_fork    (EV_DEFAULT); }\n    #if EV_FEATURE_API\n      EV_INLINE unsigned int ev_loop_count  (EV_P) { return ev_iteration  (EV_A); }\n      EV_INLINE unsigned int ev_loop_depth  (EV_P) { return ev_depth      (EV_A); }\n      EV_INLINE void         ev_loop_verify (EV_P) {        ev_verify     (EV_A); }\n    #endif\n  #endif\n#else\n  typedef struct ev_loop ev_loop;\n#endif\n\n#endif\n\nEV_CPP(})\n\n#endif\n\n"
  },
  {
    "path": "libev/ev.pod",
    "content": "=encoding utf-8\n\n=head1 NAME\n\nlibev - a high performance full-featured event loop written in C\n\n=head1 SYNOPSIS\n\n   #include <ev.h>\n\n=head2 EXAMPLE PROGRAM\n\n   // a single header file is required\n   #include <ev.h>\n\n   #include <stdio.h> // for puts\n\n   // every watcher type has its own typedef'd struct\n   // with the name ev_TYPE\n   ev_io stdin_watcher;\n   ev_timer timeout_watcher;\n\n   // all watcher callbacks have a similar signature\n   // this callback is called when data is readable on stdin\n   static void\n   stdin_cb (EV_P_ ev_io *w, int revents)\n   {\n     puts (\"stdin ready\");\n     // for one-shot events, one must manually stop the watcher\n     // with its corresponding stop function.\n     ev_io_stop (EV_A_ w);\n\n     // this causes all nested ev_run's to stop iterating\n     ev_break (EV_A_ EVBREAK_ALL);\n   }\n\n   // another callback, this time for a time-out\n   static void\n   timeout_cb (EV_P_ ev_timer *w, int revents)\n   {\n     puts (\"timeout\");\n     // this causes the innermost ev_run to stop iterating\n     ev_break (EV_A_ EVBREAK_ONE);\n   }\n\n   int\n   main (void)\n   {\n     // use the default event loop unless you have special needs\n     struct ev_loop *loop = EV_DEFAULT;\n\n     // initialise an io watcher, then start it\n     // this one will watch for stdin to become readable\n     ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);\n     ev_io_start (loop, &stdin_watcher);\n\n     // initialise a timer watcher, then start it\n     // simple non-repeating 5.5 second timeout\n     ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);\n     ev_timer_start (loop, &timeout_watcher);\n\n     // now wait for events to arrive\n     ev_run (loop, 0);\n\n     // break was called, so exit\n     return 0;\n   }\n\n=head1 ABOUT THIS DOCUMENT\n\nThis document documents the libev software package.\n\nThe newest version of this document is also available as an html-formatted\nweb page you might find easier to navigate when reading it for the first\ntime: L<http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod>.\n\nWhile this document tries to be as complete as possible in documenting\nlibev, its usage and the rationale behind its design, it is not a tutorial\non event-based programming, nor will it introduce event-based programming\nwith libev.\n\nFamiliarity with event based programming techniques in general is assumed\nthroughout this document.\n\n=head1 WHAT TO READ WHEN IN A HURRY\n\nThis manual tries to be very detailed, but unfortunately, this also makes\nit very long. If you just want to know the basics of libev, I suggest\nreading L</ANATOMY OF A WATCHER>, then the L</EXAMPLE PROGRAM> above and\nlook up the missing functions in L</GLOBAL FUNCTIONS> and the C<ev_io> and\nC<ev_timer> sections in L</WATCHER TYPES>.\n\n=head1 ABOUT LIBEV\n\nLibev is an event loop: you register interest in certain events (such as a\nfile descriptor being readable or a timeout occurring), and it will manage\nthese event sources and provide your program with events.\n\nTo do this, it must take more or less complete control over your process\n(or thread) by executing the I<event loop> handler, and will then\ncommunicate events via a callback mechanism.\n\nYou register interest in certain events by registering so-called I<event\nwatchers>, which are relatively small C structures you initialise with the\ndetails of the event, and then hand it over to libev by I<starting> the\nwatcher.\n\n=head2 FEATURES\n\nLibev supports C<select>, C<poll>, the Linux-specific C<epoll>, the\nBSD-specific C<kqueue> and the Solaris-specific event port mechanisms\nfor file descriptor events (C<ev_io>), the Linux C<inotify> interface\n(for C<ev_stat>), Linux eventfd/signalfd (for faster and cleaner\ninter-thread wakeup (C<ev_async>)/signal handling (C<ev_signal>)) relative\ntimers (C<ev_timer>), absolute timers with customised rescheduling\n(C<ev_periodic>), synchronous signals (C<ev_signal>), process status\nchange events (C<ev_child>), and event watchers dealing with the event\nloop mechanism itself (C<ev_idle>, C<ev_embed>, C<ev_prepare> and\nC<ev_check> watchers) as well as file watchers (C<ev_stat>) and even\nlimited support for fork events (C<ev_fork>).\n\nIt also is quite fast (see this\nL<benchmark|http://libev.schmorp.de/bench.html> comparing it to libevent\nfor example).\n\n=head2 CONVENTIONS\n\nLibev is very configurable. In this manual the default (and most common)\nconfiguration will be described, which supports multiple event loops. For\nmore info about various configuration options please have a look at\nB<EMBED> section in this manual. If libev was configured without support\nfor multiple event loops, then all functions taking an initial argument of\nname C<loop> (which is always of type C<struct ev_loop *>) will not have\nthis argument.\n\n=head2 TIME REPRESENTATION\n\nLibev represents time as a single floating point number, representing\nthe (fractional) number of seconds since the (POSIX) epoch (in practice\nsomewhere near the beginning of 1970, details are complicated, don't\nask). This type is called C<ev_tstamp>, which is what you should use\ntoo. It usually aliases to the C<double> type in C. When you need to do\nany calculations on it, you should treat it as some floating point value.\n\nUnlike the name component C<stamp> might indicate, it is also used for\ntime differences (e.g. delays) throughout libev.\n\n=head1 ERROR HANDLING\n\nLibev knows three classes of errors: operating system errors, usage errors\nand internal errors (bugs).\n\nWhen libev catches an operating system error it cannot handle (for example\na system call indicating a condition libev cannot fix), it calls the callback\nset via C<ev_set_syserr_cb>, which is supposed to fix the problem or\nabort. The default is to print a diagnostic message and to call C<abort\n()>.\n\nWhen libev detects a usage error such as a negative timer interval, then\nit will print a diagnostic message and abort (via the C<assert> mechanism,\nso C<NDEBUG> will disable this checking): these are programming errors in\nthe libev caller and need to be fixed there.\n\nLibev also has a few internal error-checking C<assert>ions, and also has\nextensive consistency checking code. These do not trigger under normal\ncircumstances, as they indicate either a bug in libev or worse.\n\n\n=head1 GLOBAL FUNCTIONS\n\nThese functions can be called anytime, even before initialising the\nlibrary in any way.\n\n=over 4\n\n=item ev_tstamp ev_time ()\n\nReturns the current time as libev would use it. Please note that the\nC<ev_now> function is usually faster and also often returns the timestamp\nyou actually want to know. Also interesting is the combination of\nC<ev_now_update> and C<ev_now>.\n\n=item ev_sleep (ev_tstamp interval)\n\nSleep for the given interval: The current thread will be blocked\nuntil either it is interrupted or the given time interval has\npassed (approximately - it might return a bit earlier even if not\ninterrupted). Returns immediately if C<< interval <= 0 >>.\n\nBasically this is a sub-second-resolution C<sleep ()>.\n\nThe range of the C<interval> is limited - libev only guarantees to work\nwith sleep times of up to one day (C<< interval <= 86400 >>).\n\n=item int ev_version_major ()\n\n=item int ev_version_minor ()\n\nYou can find out the major and minor ABI version numbers of the library\nyou linked against by calling the functions C<ev_version_major> and\nC<ev_version_minor>. If you want, you can compare against the global\nsymbols C<EV_VERSION_MAJOR> and C<EV_VERSION_MINOR>, which specify the\nversion of the library your program was compiled against.\n\nThese version numbers refer to the ABI version of the library, not the\nrelease version.\n\nUsually, it's a good idea to terminate if the major versions mismatch,\nas this indicates an incompatible change. Minor versions are usually\ncompatible to older versions, so a larger minor version alone is usually\nnot a problem.\n\nExample: Make sure we haven't accidentally been linked against the wrong\nversion (note, however, that this will not detect other ABI mismatches,\nsuch as LFS or reentrancy).\n\n   assert ((\"libev version mismatch\",\n            ev_version_major () == EV_VERSION_MAJOR\n            && ev_version_minor () >= EV_VERSION_MINOR));\n\n=item unsigned int ev_supported_backends ()\n\nReturn the set of all backends (i.e. their corresponding C<EV_BACKEND_*>\nvalue) compiled into this binary of libev (independent of their\navailability on the system you are running on). See C<ev_default_loop> for\na description of the set values.\n\nExample: make sure we have the epoll method, because yeah this is cool and\na must have and can we have a torrent of it please!!!11\n\n   assert ((\"sorry, no epoll, no sex\",\n            ev_supported_backends () & EVBACKEND_EPOLL));\n\n=item unsigned int ev_recommended_backends ()\n\nReturn the set of all backends compiled into this binary of libev and\nalso recommended for this platform, meaning it will work for most file\ndescriptor types. This set is often smaller than the one returned by\nC<ev_supported_backends>, as for example kqueue is broken on most BSDs\nand will not be auto-detected unless you explicitly request it (assuming\nyou know what you are doing). This is the set of backends that libev will\nprobe for if you specify no backends explicitly.\n\n=item unsigned int ev_embeddable_backends ()\n\nReturns the set of backends that are embeddable in other event loops. This\nvalue is platform-specific but can include backends not available on the\ncurrent system. To find which embeddable backends might be supported on\nthe current system, you would need to look at C<ev_embeddable_backends ()\n& ev_supported_backends ()>, likewise for recommended ones.\n\nSee the description of C<ev_embed> watchers for more info.\n\n=item ev_set_allocator (void *(*cb)(void *ptr, long size) throw ())\n\nSets the allocation function to use (the prototype is similar - the\nsemantics are identical to the C<realloc> C89/SuS/POSIX function). It is\nused to allocate and free memory (no surprises here). If it returns zero\nwhen memory needs to be allocated (C<size != 0>), the library might abort\nor take some potentially destructive action.\n\nSince some systems (at least OpenBSD and Darwin) fail to implement\ncorrect C<realloc> semantics, libev will use a wrapper around the system\nC<realloc> and C<free> functions by default.\n\nYou could override this function in high-availability programs to, say,\nfree some memory if it cannot allocate memory, to use a special allocator,\nor even to sleep a while and retry until some memory is available.\n\nExample: Replace the libev allocator with one that waits a bit and then\nretries (example requires a standards-compliant C<realloc>).\n\n   static void *\n   persistent_realloc (void *ptr, size_t size)\n   {\n     for (;;)\n       {\n         void *newptr = realloc (ptr, size);\n\n         if (newptr)\n           return newptr;\n\n         sleep (60);\n       }\n   }\n\n   ...\n   ev_set_allocator (persistent_realloc);\n\n=item ev_set_syserr_cb (void (*cb)(const char *msg) throw ())\n\nSet the callback function to call on a retryable system call error (such\nas failed select, poll, epoll_wait). The message is a printable string\nindicating the system call or subsystem causing the problem. If this\ncallback is set, then libev will expect it to remedy the situation, no\nmatter what, when it returns. That is, libev will generally retry the\nrequested operation, or, if the condition doesn't go away, do bad stuff\n(such as abort).\n\nExample: This is basically the same thing that libev does internally, too.\n\n   static void\n   fatal_error (const char *msg)\n   {\n     perror (msg);\n     abort ();\n   }\n\n   ...\n   ev_set_syserr_cb (fatal_error);\n\n=item ev_feed_signal (int signum)\n\nThis function can be used to \"simulate\" a signal receive. It is completely\nsafe to call this function at any time, from any context, including signal\nhandlers or random threads.\n\nIts main use is to customise signal handling in your process, especially\nin the presence of threads. For example, you could block signals\nby default in all threads (and specifying C<EVFLAG_NOSIGMASK> when\ncreating any loops), and in one thread, use C<sigwait> or any other\nmechanism to wait for signals, then \"deliver\" them to libev by calling\nC<ev_feed_signal>.\n\n=back\n\n=head1 FUNCTIONS CONTROLLING EVENT LOOPS\n\nAn event loop is described by a C<struct ev_loop *> (the C<struct> is\nI<not> optional in this case unless libev 3 compatibility is disabled, as\nlibev 3 had an C<ev_loop> function colliding with the struct name).\n\nThe library knows two types of such loops, the I<default> loop, which\nsupports child process events, and dynamically created event loops which\ndo not.\n\n=over 4\n\n=item struct ev_loop *ev_default_loop (unsigned int flags)\n\nThis returns the \"default\" event loop object, which is what you should\nnormally use when you just need \"the event loop\". Event loop objects and\nthe C<flags> parameter are described in more detail in the entry for\nC<ev_loop_new>.\n\nIf the default loop is already initialised then this function simply\nreturns it (and ignores the flags. If that is troubling you, check\nC<ev_backend ()> afterwards). Otherwise it will create it with the given\nflags, which should almost always be C<0>, unless the caller is also the\none calling C<ev_run> or otherwise qualifies as \"the main program\".\n\nIf you don't know what event loop to use, use the one returned from this\nfunction (or via the C<EV_DEFAULT> macro).\n\nNote that this function is I<not> thread-safe, so if you want to use it\nfrom multiple threads, you have to employ some kind of mutex (note also\nthat this case is unlikely, as loops cannot be shared easily between\nthreads anyway).\n\nThe default loop is the only loop that can handle C<ev_child> watchers,\nand to do this, it always registers a handler for C<SIGCHLD>. If this is\na problem for your application you can either create a dynamic loop with\nC<ev_loop_new> which doesn't do that, or you can simply overwrite the\nC<SIGCHLD> signal handler I<after> calling C<ev_default_init>.\n\nExample: This is the most typical usage.\n\n   if (!ev_default_loop (0))\n     fatal (\"could not initialise libev, bad $LIBEV_FLAGS in environment?\");\n\nExample: Restrict libev to the select and poll backends, and do not allow\nenvironment settings to be taken into account:\n\n   ev_default_loop (EVBACKEND_POLL | EVBACKEND_SELECT | EVFLAG_NOENV);\n\n=item struct ev_loop *ev_loop_new (unsigned int flags)\n\nThis will create and initialise a new event loop object. If the loop\ncould not be initialised, returns false.\n\nThis function is thread-safe, and one common way to use libev with\nthreads is indeed to create one loop per thread, and using the default\nloop in the \"main\" or \"initial\" thread.\n\nThe flags argument can be used to specify special behaviour or specific\nbackends to use, and is usually specified as C<0> (or C<EVFLAG_AUTO>).\n\nThe following flags are supported:\n\n=over 4\n\n=item C<EVFLAG_AUTO>\n\nThe default flags value. Use this if you have no clue (it's the right\nthing, believe me).\n\n=item C<EVFLAG_NOENV>\n\nIf this flag bit is or'ed into the flag value (or the program runs setuid\nor setgid) then libev will I<not> look at the environment variable\nC<LIBEV_FLAGS>. Otherwise (the default), this environment variable will\noverride the flags completely if it is found in the environment. This is\nuseful to try out specific backends to test their performance, to work\naround bugs, or to make libev threadsafe (accessing environment variables\ncannot be done in a threadsafe way, but usually it works if no other\nthread modifies them).\n\n=item C<EVFLAG_FORKCHECK>\n\nInstead of calling C<ev_loop_fork> manually after a fork, you can also\nmake libev check for a fork in each iteration by enabling this flag.\n\nThis works by calling C<getpid ()> on every iteration of the loop,\nand thus this might slow down your event loop if you do a lot of loop\niterations and little real work, but is usually not noticeable (on my\nGNU/Linux system for example, C<getpid> is actually a simple 5-insn\nsequence without a system call and thus I<very> fast, but my GNU/Linux\nsystem also has C<pthread_atfork> which is even faster). (Update: glibc\nversions 2.25 apparently removed the C<getpid> optimisation again).\n\nThe big advantage of this flag is that you can forget about fork (and\nforget about forgetting to tell libev about forking, although you still\nhave to ignore C<SIGPIPE>) when you use this flag.\n\nThis flag setting cannot be overridden or specified in the C<LIBEV_FLAGS>\nenvironment variable.\n\n=item C<EVFLAG_NOINOTIFY>\n\nWhen this flag is specified, then libev will not attempt to use the\nI<inotify> API for its C<ev_stat> watchers. Apart from debugging and\ntesting, this flag can be useful to conserve inotify file descriptors, as\notherwise each loop using C<ev_stat> watchers consumes one inotify handle.\n\n=item C<EVFLAG_SIGNALFD>\n\nWhen this flag is specified, then libev will attempt to use the\nI<signalfd> API for its C<ev_signal> (and C<ev_child>) watchers. This API\ndelivers signals synchronously, which makes it both faster and might make\nit possible to get the queued signal data. It can also simplify signal\nhandling with threads, as long as you properly block signals in your\nthreads that are not interested in handling them.\n\nSignalfd will not be used by default as this changes your signal mask, and\nthere are a lot of shoddy libraries and programs (glib's threadpool for\nexample) that can't properly initialise their signal masks.\n\n=item C<EVFLAG_NOSIGMASK>\n\nWhen this flag is specified, then libev will avoid to modify the signal\nmask. Specifically, this means you have to make sure signals are unblocked\nwhen you want to receive them.\n\nThis behaviour is useful when you want to do your own signal handling, or\nwant to handle signals only in specific threads and want to avoid libev\nunblocking the signals.\n\nIt's also required by POSIX in a threaded program, as libev calls\nC<sigprocmask>, whose behaviour is officially unspecified.\n\nThis flag's behaviour will become the default in future versions of libev.\n\n=item C<EVBACKEND_SELECT>  (value 1, portable select backend)\n\nThis is your standard select(2) backend. Not I<completely> standard, as\nlibev tries to roll its own fd_set with no limits on the number of fds,\nbut if that fails, expect a fairly low limit on the number of fds when\nusing this backend. It doesn't scale too well (O(highest_fd)), but its\nusually the fastest backend for a low number of (low-numbered :) fds.\n\nTo get good performance out of this backend you need a high amount of\nparallelism (most of the file descriptors should be busy). If you are\nwriting a server, you should C<accept ()> in a loop to accept as many\nconnections as possible during one iteration. You might also want to have\na look at C<ev_set_io_collect_interval ()> to increase the amount of\nreadiness notifications you get per iteration.\n\nThis backend maps C<EV_READ> to the C<readfds> set and C<EV_WRITE> to the\nC<writefds> set (and to work around Microsoft Windows bugs, also onto the\nC<exceptfds> set on that platform).\n\n=item C<EVBACKEND_POLL>    (value 2, poll backend, available everywhere except on windows)\n\nAnd this is your standard poll(2) backend. It's more complicated\nthan select, but handles sparse fds better and has no artificial\nlimit on the number of fds you can use (except it will slow down\nconsiderably with a lot of inactive fds). It scales similarly to select,\ni.e. O(total_fds). See the entry for C<EVBACKEND_SELECT>, above, for\nperformance tips.\n\nThis backend maps C<EV_READ> to C<POLLIN | POLLERR | POLLHUP>, and\nC<EV_WRITE> to C<POLLOUT | POLLERR | POLLHUP>.\n\n=item C<EVBACKEND_EPOLL>   (value 4, Linux)\n\nUse the linux-specific epoll(7) interface (for both pre- and post-2.6.9\nkernels).\n\nFor few fds, this backend is a bit little slower than poll and select, but\nit scales phenomenally better. While poll and select usually scale like\nO(total_fds) where total_fds is the total number of fds (or the highest\nfd), epoll scales either O(1) or O(active_fds).\n\nThe epoll mechanism deserves honorable mention as the most misdesigned\nof the more advanced event mechanisms: mere annoyances include silently\ndropping file descriptors, requiring a system call per change per file\ndescriptor (and unnecessary guessing of parameters), problems with dup,\nreturning before the timeout value, resulting in additional iterations\n(and only giving 5ms accuracy while select on the same platform gives\n0.1ms) and so on. The biggest issue is fork races, however - if a program\nforks then I<both> parent and child process have to recreate the epoll\nset, which can take considerable time (one syscall per file descriptor)\nand is of course hard to detect.\n\nEpoll is also notoriously buggy - embedding epoll fds I<should> work,\nbut of course I<doesn't>, and epoll just loves to report events for\ntotally I<different> file descriptors (even already closed ones, so\none cannot even remove them from the set) than registered in the set\n(especially on SMP systems). Libev tries to counter these spurious\nnotifications by employing an additional generation counter and comparing\nthat against the events to filter out spurious ones, recreating the set\nwhen required. Epoll also erroneously rounds down timeouts, but gives you\nno way to know when and by how much, so sometimes you have to busy-wait\nbecause epoll returns immediately despite a nonzero timeout. And last\nnot least, it also refuses to work with some file descriptors which work\nperfectly fine with C<select> (files, many character devices...).\n\nEpoll is truly the train wreck among event poll mechanisms, a frankenpoll,\ncobbled together in a hurry, no thought to design or interaction with\nothers. Oh, the pain, will it ever stop...\n\nWhile stopping, setting and starting an I/O watcher in the same iteration\nwill result in some caching, there is still a system call per such\nincident (because the same I<file descriptor> could point to a different\nI<file description> now), so its best to avoid that. Also, C<dup ()>'ed\nfile descriptors might not work very well if you register events for both\nfile descriptors.\n\nBest performance from this backend is achieved by not unregistering all\nwatchers for a file descriptor until it has been closed, if possible,\ni.e. keep at least one watcher active per fd at all times. Stopping and\nstarting a watcher (without re-setting it) also usually doesn't cause\nextra overhead. A fork can both result in spurious notifications as well\nas in libev having to destroy and recreate the epoll object, which can\ntake considerable time and thus should be avoided.\n\nAll this means that, in practice, C<EVBACKEND_SELECT> can be as fast or\nfaster than epoll for maybe up to a hundred file descriptors, depending on\nthe usage. So sad.\n\nWhile nominally embeddable in other event loops, this feature is broken in\nall kernel versions tested so far.\n\nThis backend maps C<EV_READ> and C<EV_WRITE> in the same way as\nC<EVBACKEND_POLL>.\n\n=item C<EVBACKEND_KQUEUE>  (value 8, most BSD clones)\n\nKqueue deserves special mention, as at the time of this writing, it\nwas broken on all BSDs except NetBSD (usually it doesn't work reliably\nwith anything but sockets and pipes, except on Darwin, where of course\nit's completely useless). Unlike epoll, however, whose brokenness\nis by design, these kqueue bugs can (and eventually will) be fixed\nwithout API changes to existing programs. For this reason it's not being\n\"auto-detected\" unless you explicitly specify it in the flags (i.e. using\nC<EVBACKEND_KQUEUE>) or libev was compiled on a known-to-be-good (-enough)\nsystem like NetBSD.\n\nYou still can embed kqueue into a normal poll or select backend and use it\nonly for sockets (after having made sure that sockets work with kqueue on\nthe target platform). See C<ev_embed> watchers for more info.\n\nIt scales in the same way as the epoll backend, but the interface to the\nkernel is more efficient (which says nothing about its actual speed, of\ncourse). While stopping, setting and starting an I/O watcher does never\ncause an extra system call as with C<EVBACKEND_EPOLL>, it still adds up to\ntwo event changes per incident. Support for C<fork ()> is very bad (you\nmight have to leak fd's on fork, but it's more sane than epoll) and it\ndrops fds silently in similarly hard-to-detect cases.\n\nThis backend usually performs well under most conditions.\n\nWhile nominally embeddable in other event loops, this doesn't work\neverywhere, so you might need to test for this. And since it is broken\nalmost everywhere, you should only use it when you have a lot of sockets\n(for which it usually works), by embedding it into another event loop\n(e.g. C<EVBACKEND_SELECT> or C<EVBACKEND_POLL> (but C<poll> is of course\nalso broken on OS X)) and, did I mention it, using it only for sockets.\n\nThis backend maps C<EV_READ> into an C<EVFILT_READ> kevent with\nC<NOTE_EOF>, and C<EV_WRITE> into an C<EVFILT_WRITE> kevent with\nC<NOTE_EOF>.\n\n=item C<EVBACKEND_DEVPOLL> (value 16, Solaris 8)\n\nThis is not implemented yet (and might never be, unless you send me an\nimplementation). According to reports, C</dev/poll> only supports sockets\nand is not embeddable, which would limit the usefulness of this backend\nimmensely.\n\n=item C<EVBACKEND_PORT>    (value 32, Solaris 10)\n\nThis uses the Solaris 10 event port mechanism. As with everything on Solaris,\nit's really slow, but it still scales very well (O(active_fds)).\n\nWhile this backend scales well, it requires one system call per active\nfile descriptor per loop iteration. For small and medium numbers of file\ndescriptors a \"slow\" C<EVBACKEND_SELECT> or C<EVBACKEND_POLL> backend\nmight perform better.\n\nOn the positive side, this backend actually performed fully to\nspecification in all tests and is fully embeddable, which is a rare feat\namong the OS-specific backends (I vastly prefer correctness over speed\nhacks).\n\nOn the negative side, the interface is I<bizarre> - so bizarre that\neven sun itself gets it wrong in their code examples: The event polling\nfunction sometimes returns events to the caller even though an error\noccurred, but with no indication whether it has done so or not (yes, it's\neven documented that way) - deadly for edge-triggered interfaces where you\nabsolutely have to know whether an event occurred or not because you have\nto re-arm the watcher.\n\nFortunately libev seems to be able to work around these idiocies.\n\nThis backend maps C<EV_READ> and C<EV_WRITE> in the same way as\nC<EVBACKEND_POLL>.\n\n=item C<EVBACKEND_ALL>\n\nTry all backends (even potentially broken ones that wouldn't be tried\nwith C<EVFLAG_AUTO>). Since this is a mask, you can do stuff such as\nC<EVBACKEND_ALL & ~EVBACKEND_KQUEUE>.\n\nIt is definitely not recommended to use this flag, use whatever\nC<ev_recommended_backends ()> returns, or simply do not specify a backend\nat all.\n\n=item C<EVBACKEND_MASK>\n\nNot a backend at all, but a mask to select all backend bits from a\nC<flags> value, in case you want to mask out any backends from a flags\nvalue (e.g. when modifying the C<LIBEV_FLAGS> environment variable).\n\n=back\n\nIf one or more of the backend flags are or'ed into the flags value,\nthen only these backends will be tried (in the reverse order as listed\nhere). If none are specified, all backends in C<ev_recommended_backends\n()> will be tried.\n\nExample: Try to create a event loop that uses epoll and nothing else.\n\n   struct ev_loop *epoller = ev_loop_new (EVBACKEND_EPOLL | EVFLAG_NOENV);\n   if (!epoller)\n     fatal (\"no epoll found here, maybe it hides under your chair\");\n\nExample: Use whatever libev has to offer, but make sure that kqueue is\nused if available.\n\n   struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_KQUEUE);\n\n=item ev_loop_destroy (loop)\n\nDestroys an event loop object (frees all memory and kernel state\netc.). None of the active event watchers will be stopped in the normal\nsense, so e.g. C<ev_is_active> might still return true. It is your\nresponsibility to either stop all watchers cleanly yourself I<before>\ncalling this function, or cope with the fact afterwards (which is usually\nthe easiest thing, you can just ignore the watchers and/or C<free ()> them\nfor example).\n\nNote that certain global state, such as signal state (and installed signal\nhandlers), will not be freed by this function, and related watchers (such\nas signal and child watchers) would need to be stopped manually.\n\nThis function is normally used on loop objects allocated by\nC<ev_loop_new>, but it can also be used on the default loop returned by\nC<ev_default_loop>, in which case it is not thread-safe.\n\nNote that it is not advisable to call this function on the default loop\nexcept in the rare occasion where you really need to free its resources.\nIf you need dynamically allocated loops it is better to use C<ev_loop_new>\nand C<ev_loop_destroy>.\n\n=item ev_loop_fork (loop)\n\nThis function sets a flag that causes subsequent C<ev_run> iterations\nto reinitialise the kernel state for backends that have one. Despite\nthe name, you can call it anytime you are allowed to start or stop\nwatchers (except inside an C<ev_prepare> callback), but it makes most\nsense after forking, in the child process. You I<must> call it (or use\nC<EVFLAG_FORKCHECK>) in the child before resuming or calling C<ev_run>.\n\nIn addition, if you want to reuse a loop (via this function or\nC<EVFLAG_FORKCHECK>), you I<also> have to ignore C<SIGPIPE>.\n\nAgain, you I<have> to call it on I<any> loop that you want to re-use after\na fork, I<even if you do not plan to use the loop in the parent>. This is\nbecause some kernel interfaces *cough* I<kqueue> *cough* do funny things\nduring fork.\n\nOn the other hand, you only need to call this function in the child\nprocess if and only if you want to use the event loop in the child. If\nyou just fork+exec or create a new loop in the child, you don't have to\ncall it at all (in fact, C<epoll> is so badly broken that it makes a\ndifference, but libev will usually detect this case on its own and do a\ncostly reset of the backend).\n\nThe function itself is quite fast and it's usually not a problem to call\nit just in case after a fork.\n\nExample: Automate calling C<ev_loop_fork> on the default loop when\nusing pthreads.\n\n   static void\n   post_fork_child (void)\n   {\n     ev_loop_fork (EV_DEFAULT);\n   }\n\n   ...\n   pthread_atfork (0, 0, post_fork_child);\n\n=item int ev_is_default_loop (loop)\n\nReturns true when the given loop is, in fact, the default loop, and false\notherwise.\n\n=item unsigned int ev_iteration (loop)\n\nReturns the current iteration count for the event loop, which is identical\nto the number of times libev did poll for new events. It starts at C<0>\nand happily wraps around with enough iterations.\n\nThis value can sometimes be useful as a generation counter of sorts (it\n\"ticks\" the number of loop iterations), as it roughly corresponds with\nC<ev_prepare> and C<ev_check> calls - and is incremented between the\nprepare and check phases.\n\n=item unsigned int ev_depth (loop)\n\nReturns the number of times C<ev_run> was entered minus the number of\ntimes C<ev_run> was exited normally, in other words, the recursion depth.\n\nOutside C<ev_run>, this number is zero. In a callback, this number is\nC<1>, unless C<ev_run> was invoked recursively (or from another thread),\nin which case it is higher.\n\nLeaving C<ev_run> abnormally (setjmp/longjmp, cancelling the thread,\nthrowing an exception etc.), doesn't count as \"exit\" - consider this\nas a hint to avoid such ungentleman-like behaviour unless it's really\nconvenient, in which case it is fully supported.\n\n=item unsigned int ev_backend (loop)\n\nReturns one of the C<EVBACKEND_*> flags indicating the event backend in\nuse.\n\n=item ev_tstamp ev_now (loop)\n\nReturns the current \"event loop time\", which is the time the event loop\nreceived events and started processing them. This timestamp does not\nchange as long as callbacks are being processed, and this is also the base\ntime used for relative timers. You can treat it as the timestamp of the\nevent occurring (or more correctly, libev finding out about it).\n\n=item ev_now_update (loop)\n\nEstablishes the current time by querying the kernel, updating the time\nreturned by C<ev_now ()> in the progress. This is a costly operation and\nis usually done automatically within C<ev_run ()>.\n\nThis function is rarely useful, but when some event callback runs for a\nvery long time without entering the event loop, updating libev's idea of\nthe current time is a good idea.\n\nSee also L</The special problem of time updates> in the C<ev_timer> section.\n\n=item ev_suspend (loop)\n\n=item ev_resume (loop)\n\nThese two functions suspend and resume an event loop, for use when the\nloop is not used for a while and timeouts should not be processed.\n\nA typical use case would be an interactive program such as a game:  When\nthe user presses C<^Z> to suspend the game and resumes it an hour later it\nwould be best to handle timeouts as if no time had actually passed while\nthe program was suspended. This can be achieved by calling C<ev_suspend>\nin your C<SIGTSTP> handler, sending yourself a C<SIGSTOP> and calling\nC<ev_resume> directly afterwards to resume timer processing.\n\nEffectively, all C<ev_timer> watchers will be delayed by the time spend\nbetween C<ev_suspend> and C<ev_resume>, and all C<ev_periodic> watchers\nwill be rescheduled (that is, they will lose any events that would have\noccurred while suspended).\n\nAfter calling C<ev_suspend> you B<must not> call I<any> function on the\ngiven loop other than C<ev_resume>, and you B<must not> call C<ev_resume>\nwithout a previous call to C<ev_suspend>.\n\nCalling C<ev_suspend>/C<ev_resume> has the side effect of updating the\nevent loop time (see C<ev_now_update>).\n\n=item bool ev_run (loop, int flags)\n\nFinally, this is it, the event handler. This function usually is called\nafter you have initialised all your watchers and you want to start\nhandling events. It will ask the operating system for any new events, call\nthe watcher callbacks, and then repeat the whole process indefinitely: This\nis why event loops are called I<loops>.\n\nIf the flags argument is specified as C<0>, it will keep handling events\nuntil either no event watchers are active anymore or C<ev_break> was\ncalled.\n\nThe return value is false if there are no more active watchers (which\nusually means \"all jobs done\" or \"deadlock\"), and true in all other cases\n(which usually means \" you should call C<ev_run> again\").\n\nPlease note that an explicit C<ev_break> is usually better than\nrelying on all watchers to be stopped when deciding when a program has\nfinished (especially in interactive programs), but having a program\nthat automatically loops as long as it has to and no longer by virtue\nof relying on its watchers stopping correctly, that is truly a thing of\nbeauty.\n\nThis function is I<mostly> exception-safe - you can break out of a\nC<ev_run> call by calling C<longjmp> in a callback, throwing a C++\nexception and so on. This does not decrement the C<ev_depth> value, nor\nwill it clear any outstanding C<EVBREAK_ONE> breaks.\n\nA flags value of C<EVRUN_NOWAIT> will look for new events, will handle\nthose events and any already outstanding ones, but will not wait and\nblock your process in case there are no events and will return after one\niteration of the loop. This is sometimes useful to poll and handle new\nevents while doing lengthy calculations, to keep the program responsive.\n\nA flags value of C<EVRUN_ONCE> will look for new events (waiting if\nnecessary) and will handle those and any already outstanding ones. It\nwill block your process until at least one new event arrives (which could\nbe an event internal to libev itself, so there is no guarantee that a\nuser-registered callback will be called), and will return after one\niteration of the loop.\n\nThis is useful if you are waiting for some external event in conjunction\nwith something not expressible using other libev watchers (i.e. \"roll your\nown C<ev_run>\"). However, a pair of C<ev_prepare>/C<ev_check> watchers is\nusually a better approach for this kind of thing.\n\nHere are the gory details of what C<ev_run> does (this is for your\nunderstanding, not a guarantee that things will work exactly like this in\nfuture versions):\n\n   - Increment loop depth.\n   - Reset the ev_break status.\n   - Before the first iteration, call any pending watchers.\n   LOOP:\n   - If EVFLAG_FORKCHECK was used, check for a fork.\n   - If a fork was detected (by any means), queue and call all fork watchers.\n   - Queue and call all prepare watchers.\n   - If ev_break was called, goto FINISH.\n   - If we have been forked, detach and recreate the kernel state\n     as to not disturb the other process.\n   - Update the kernel state with all outstanding changes.\n   - Update the \"event loop time\" (ev_now ()).\n   - Calculate for how long to sleep or block, if at all\n     (active idle watchers, EVRUN_NOWAIT or not having\n     any active watchers at all will result in not sleeping).\n   - Sleep if the I/O and timer collect interval say so.\n   - Increment loop iteration counter.\n   - Block the process, waiting for any events.\n   - Queue all outstanding I/O (fd) events.\n   - Update the \"event loop time\" (ev_now ()), and do time jump adjustments.\n   - Queue all expired timers.\n   - Queue all expired periodics.\n   - Queue all idle watchers with priority higher than that of pending events.\n   - Queue all check watchers.\n   - Call all queued watchers in reverse order (i.e. check watchers first).\n     Signals and child watchers are implemented as I/O watchers, and will\n     be handled here by queueing them when their watcher gets executed.\n   - If ev_break has been called, or EVRUN_ONCE or EVRUN_NOWAIT\n     were used, or there are no active watchers, goto FINISH, otherwise\n     continue with step LOOP.\n   FINISH:\n   - Reset the ev_break status iff it was EVBREAK_ONE.\n   - Decrement the loop depth.\n   - Return.\n\nExample: Queue some jobs and then loop until no events are outstanding\nanymore.\n\n   ... queue jobs here, make sure they register event watchers as long\n   ... as they still have work to do (even an idle watcher will do..)\n   ev_run (my_loop, 0);\n   ... jobs done or somebody called break. yeah!\n\n=item ev_break (loop, how)\n\nCan be used to make a call to C<ev_run> return early (but only after it\nhas processed all outstanding events). The C<how> argument must be either\nC<EVBREAK_ONE>, which will make the innermost C<ev_run> call return, or\nC<EVBREAK_ALL>, which will make all nested C<ev_run> calls return.\n\nThis \"break state\" will be cleared on the next call to C<ev_run>.\n\nIt is safe to call C<ev_break> from outside any C<ev_run> calls, too, in\nwhich case it will have no effect.\n\n=item ev_ref (loop)\n\n=item ev_unref (loop)\n\nRef/unref can be used to add or remove a reference count on the event\nloop: Every watcher keeps one reference, and as long as the reference\ncount is nonzero, C<ev_run> will not return on its own.\n\nThis is useful when you have a watcher that you never intend to\nunregister, but that nevertheless should not keep C<ev_run> from\nreturning. In such a case, call C<ev_unref> after starting, and C<ev_ref>\nbefore stopping it.\n\nAs an example, libev itself uses this for its internal signal pipe: It\nis not visible to the libev user and should not keep C<ev_run> from\nexiting if no event watchers registered by it are active. It is also an\nexcellent way to do this for generic recurring timers or from within\nthird-party libraries. Just remember to I<unref after start> and I<ref\nbefore stop> (but only if the watcher wasn't active before, or was active\nbefore, respectively. Note also that libev might stop watchers itself\n(e.g. non-repeating timers) in which case you have to C<ev_ref>\nin the callback).\n\nExample: Create a signal watcher, but keep it from keeping C<ev_run>\nrunning when nothing else is active.\n\n   ev_signal exitsig;\n   ev_signal_init (&exitsig, sig_cb, SIGINT);\n   ev_signal_start (loop, &exitsig);\n   ev_unref (loop);\n\nExample: For some weird reason, unregister the above signal handler again.\n\n   ev_ref (loop);\n   ev_signal_stop (loop, &exitsig);\n\n=item ev_set_io_collect_interval (loop, ev_tstamp interval)\n\n=item ev_set_timeout_collect_interval (loop, ev_tstamp interval)\n\nThese advanced functions influence the time that libev will spend waiting\nfor events. Both time intervals are by default C<0>, meaning that libev\nwill try to invoke timer/periodic callbacks and I/O callbacks with minimum\nlatency.\n\nSetting these to a higher value (the C<interval> I<must> be >= C<0>)\nallows libev to delay invocation of I/O and timer/periodic callbacks\nto increase efficiency of loop iterations (or to increase power-saving\nopportunities).\n\nThe idea is that sometimes your program runs just fast enough to handle\none (or very few) event(s) per loop iteration. While this makes the\nprogram responsive, it also wastes a lot of CPU time to poll for new\nevents, especially with backends like C<select ()> which have a high\noverhead for the actual polling but can deliver many events at once.\n\nBy setting a higher I<io collect interval> you allow libev to spend more\ntime collecting I/O events, so you can handle more events per iteration,\nat the cost of increasing latency. Timeouts (both C<ev_periodic> and\nC<ev_timer>) will not be affected. Setting this to a non-null value will\nintroduce an additional C<ev_sleep ()> call into most loop iterations. The\nsleep time ensures that libev will not poll for I/O events more often then\nonce per this interval, on average (as long as the host time resolution is\ngood enough).\n\nLikewise, by setting a higher I<timeout collect interval> you allow libev\nto spend more time collecting timeouts, at the expense of increased\nlatency/jitter/inexactness (the watcher callback will be called\nlater). C<ev_io> watchers will not be affected. Setting this to a non-null\nvalue will not introduce any overhead in libev.\n\nMany (busy) programs can usually benefit by setting the I/O collect\ninterval to a value near C<0.1> or so, which is often enough for\ninteractive servers (of course not for games), likewise for timeouts. It\nusually doesn't make much sense to set it to a lower value than C<0.01>,\nas this approaches the timing granularity of most systems. Note that if\nyou do transactions with the outside world and you can't increase the\nparallelity, then this setting will limit your transaction rate (if you\nneed to poll once per transaction and the I/O collect interval is 0.01,\nthen you can't do more than 100 transactions per second).\n\nSetting the I<timeout collect interval> can improve the opportunity for\nsaving power, as the program will \"bundle\" timer callback invocations that\nare \"near\" in time together, by delaying some, thus reducing the number of\ntimes the process sleeps and wakes up again. Another useful technique to\nreduce iterations/wake-ups is to use C<ev_periodic> watchers and make sure\nthey fire on, say, one-second boundaries only.\n\nExample: we only need 0.1s timeout granularity, and we wish not to poll\nmore often than 100 times per second:\n\n   ev_set_timeout_collect_interval (EV_DEFAULT_UC_ 0.1);\n   ev_set_io_collect_interval (EV_DEFAULT_UC_ 0.01);\n\n=item ev_invoke_pending (loop)\n\nThis call will simply invoke all pending watchers while resetting their\npending state. Normally, C<ev_run> does this automatically when required,\nbut when overriding the invoke callback this call comes handy. This\nfunction can be invoked from a watcher - this can be useful for example\nwhen you want to do some lengthy calculation and want to pass further\nevent handling to another thread (you still have to make sure only one\nthread executes within C<ev_invoke_pending> or C<ev_run> of course).\n\n=item int ev_pending_count (loop)\n\nReturns the number of pending watchers - zero indicates that no watchers\nare pending.\n\n=item ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(EV_P))\n\nThis overrides the invoke pending functionality of the loop: Instead of\ninvoking all pending watchers when there are any, C<ev_run> will call\nthis callback instead. This is useful, for example, when you want to\ninvoke the actual watchers inside another context (another thread etc.).\n\nIf you want to reset the callback, use C<ev_invoke_pending> as new\ncallback.\n\n=item ev_set_loop_release_cb (loop, void (*release)(EV_P) throw (), void (*acquire)(EV_P) throw ())\n\nSometimes you want to share the same loop between multiple threads. This\ncan be done relatively simply by putting mutex_lock/unlock calls around\neach call to a libev function.\n\nHowever, C<ev_run> can run an indefinite time, so it is not feasible\nto wait for it to return. One way around this is to wake up the event\nloop via C<ev_break> and C<ev_async_send>, another way is to set these\nI<release> and I<acquire> callbacks on the loop.\n\nWhen set, then C<release> will be called just before the thread is\nsuspended waiting for new events, and C<acquire> is called just\nafterwards.\n\nIdeally, C<release> will just call your mutex_unlock function, and\nC<acquire> will just call the mutex_lock function again.\n\nWhile event loop modifications are allowed between invocations of\nC<release> and C<acquire> (that's their only purpose after all), no\nmodifications done will affect the event loop, i.e. adding watchers will\nhave no effect on the set of file descriptors being watched, or the time\nwaited. Use an C<ev_async> watcher to wake up C<ev_run> when you want it\nto take note of any changes you made.\n\nIn theory, threads executing C<ev_run> will be async-cancel safe between\ninvocations of C<release> and C<acquire>.\n\nSee also the locking example in the C<THREADS> section later in this\ndocument.\n\n=item ev_set_userdata (loop, void *data)\n\n=item void *ev_userdata (loop)\n\nSet and retrieve a single C<void *> associated with a loop. When\nC<ev_set_userdata> has never been called, then C<ev_userdata> returns\nC<0>.\n\nThese two functions can be used to associate arbitrary data with a loop,\nand are intended solely for the C<invoke_pending_cb>, C<release> and\nC<acquire> callbacks described above, but of course can be (ab-)used for\nany other purpose as well.\n\n=item ev_verify (loop)\n\nThis function only does something when C<EV_VERIFY> support has been\ncompiled in, which is the default for non-minimal builds. It tries to go\nthrough all internal structures and checks them for validity. If anything\nis found to be inconsistent, it will print an error message to standard\nerror and call C<abort ()>.\n\nThis can be used to catch bugs inside libev itself: under normal\ncircumstances, this function will never abort as of course libev keeps its\ndata structures consistent.\n\n=back\n\n\n=head1 ANATOMY OF A WATCHER\n\nIn the following description, uppercase C<TYPE> in names stands for the\nwatcher type, e.g. C<ev_TYPE_start> can mean C<ev_timer_start> for timer\nwatchers and C<ev_io_start> for I/O watchers.\n\nA watcher is an opaque structure that you allocate and register to record\nyour interest in some event. To make a concrete example, imagine you want\nto wait for STDIN to become readable, you would create an C<ev_io> watcher\nfor that:\n\n   static void my_cb (struct ev_loop *loop, ev_io *w, int revents)\n   {\n     ev_io_stop (w);\n     ev_break (loop, EVBREAK_ALL);\n   }\n\n   struct ev_loop *loop = ev_default_loop (0);\n\n   ev_io stdin_watcher;\n\n   ev_init (&stdin_watcher, my_cb);\n   ev_io_set (&stdin_watcher, STDIN_FILENO, EV_READ);\n   ev_io_start (loop, &stdin_watcher);\n\n   ev_run (loop, 0);\n\nAs you can see, you are responsible for allocating the memory for your\nwatcher structures (and it is I<usually> a bad idea to do this on the\nstack).\n\nEach watcher has an associated watcher structure (called C<struct ev_TYPE>\nor simply C<ev_TYPE>, as typedefs are provided for all watcher structs).\n\nEach watcher structure must be initialised by a call to C<ev_init (watcher\n*, callback)>, which expects a callback to be provided. This callback is\ninvoked each time the event occurs (or, in the case of I/O watchers, each\ntime the event loop detects that the file descriptor given is readable\nand/or writable).\n\nEach watcher type further has its own C<< ev_TYPE_set (watcher *, ...) >>\nmacro to configure it, with arguments specific to the watcher type. There\nis also a macro to combine initialisation and setting in one call: C<<\nev_TYPE_init (watcher *, callback, ...) >>.\n\nTo make the watcher actually watch out for events, you have to start it\nwith a watcher-specific start function (C<< ev_TYPE_start (loop, watcher\n*) >>), and you can stop watching for events at any time by calling the\ncorresponding stop function (C<< ev_TYPE_stop (loop, watcher *) >>.\n\nAs long as your watcher is active (has been started but not stopped) you\nmust not touch the values stored in it. Most specifically you must never\nreinitialise it or call its C<ev_TYPE_set> macro.\n\nEach and every callback receives the event loop pointer as first, the\nregistered watcher structure as second, and a bitset of received events as\nthird argument.\n\nThe received events usually include a single bit per event type received\n(you can receive multiple events at the same time). The possible bit masks\nare:\n\n=over 4\n\n=item C<EV_READ>\n\n=item C<EV_WRITE>\n\nThe file descriptor in the C<ev_io> watcher has become readable and/or\nwritable.\n\n=item C<EV_TIMER>\n\nThe C<ev_timer> watcher has timed out.\n\n=item C<EV_PERIODIC>\n\nThe C<ev_periodic> watcher has timed out.\n\n=item C<EV_SIGNAL>\n\nThe signal specified in the C<ev_signal> watcher has been received by a thread.\n\n=item C<EV_CHILD>\n\nThe pid specified in the C<ev_child> watcher has received a status change.\n\n=item C<EV_STAT>\n\nThe path specified in the C<ev_stat> watcher changed its attributes somehow.\n\n=item C<EV_IDLE>\n\nThe C<ev_idle> watcher has determined that you have nothing better to do.\n\n=item C<EV_PREPARE>\n\n=item C<EV_CHECK>\n\nAll C<ev_prepare> watchers are invoked just I<before> C<ev_run> starts to\ngather new events, and all C<ev_check> watchers are queued (not invoked)\njust after C<ev_run> has gathered them, but before it queues any callbacks\nfor any received events. That means C<ev_prepare> watchers are the last\nwatchers invoked before the event loop sleeps or polls for new events, and\nC<ev_check> watchers will be invoked before any other watchers of the same\nor lower priority within an event loop iteration.\n\nCallbacks of both watcher types can start and stop as many watchers as\nthey want, and all of them will be taken into account (for example, a\nC<ev_prepare> watcher might start an idle watcher to keep C<ev_run> from\nblocking).\n\n=item C<EV_EMBED>\n\nThe embedded event loop specified in the C<ev_embed> watcher needs attention.\n\n=item C<EV_FORK>\n\nThe event loop has been resumed in the child process after fork (see\nC<ev_fork>).\n\n=item C<EV_CLEANUP>\n\nThe event loop is about to be destroyed (see C<ev_cleanup>).\n\n=item C<EV_ASYNC>\n\nThe given async watcher has been asynchronously notified (see C<ev_async>).\n\n=item C<EV_CUSTOM>\n\nNot ever sent (or otherwise used) by libev itself, but can be freely used\nby libev users to signal watchers (e.g. via C<ev_feed_event>).\n\n=item C<EV_ERROR>\n\nAn unspecified error has occurred, the watcher has been stopped. This might\nhappen because the watcher could not be properly started because libev\nran out of memory, a file descriptor was found to be closed or any other\nproblem. Libev considers these application bugs.\n\nYou best act on it by reporting the problem and somehow coping with the\nwatcher being stopped. Note that well-written programs should not receive\nan error ever, so when your watcher receives it, this usually indicates a\nbug in your program.\n\nLibev will usually signal a few \"dummy\" events together with an error, for\nexample it might indicate that a fd is readable or writable, and if your\ncallbacks is well-written it can just attempt the operation and cope with\nthe error from read() or write(). This will not work in multi-threaded\nprograms, though, as the fd could already be closed and reused for another\nthing, so beware.\n\n=back\n\n=head2 GENERIC WATCHER FUNCTIONS\n\n=over 4\n\n=item C<ev_init> (ev_TYPE *watcher, callback)\n\nThis macro initialises the generic portion of a watcher. The contents\nof the watcher object can be arbitrary (so C<malloc> will do). Only\nthe generic parts of the watcher are initialised, you I<need> to call\nthe type-specific C<ev_TYPE_set> macro afterwards to initialise the\ntype-specific parts. For each type there is also a C<ev_TYPE_init> macro\nwhich rolls both calls into one.\n\nYou can reinitialise a watcher at any time as long as it has been stopped\n(or never started) and there are no pending events outstanding.\n\nThe callback is always of type C<void (*)(struct ev_loop *loop, ev_TYPE *watcher,\nint revents)>.\n\nExample: Initialise an C<ev_io> watcher in two steps.\n\n   ev_io w;\n   ev_init (&w, my_cb);\n   ev_io_set (&w, STDIN_FILENO, EV_READ);\n\n=item C<ev_TYPE_set> (ev_TYPE *watcher, [args])\n\nThis macro initialises the type-specific parts of a watcher. You need to\ncall C<ev_init> at least once before you call this macro, but you can\ncall C<ev_TYPE_set> any number of times. You must not, however, call this\nmacro on a watcher that is active (it can be pending, however, which is a\ndifference to the C<ev_init> macro).\n\nAlthough some watcher types do not have type-specific arguments\n(e.g. C<ev_prepare>) you still need to call its C<set> macro.\n\nSee C<ev_init>, above, for an example.\n\n=item C<ev_TYPE_init> (ev_TYPE *watcher, callback, [args])\n\nThis convenience macro rolls both C<ev_init> and C<ev_TYPE_set> macro\ncalls into a single call. This is the most convenient method to initialise\na watcher. The same limitations apply, of course.\n\nExample: Initialise and set an C<ev_io> watcher in one step.\n\n   ev_io_init (&w, my_cb, STDIN_FILENO, EV_READ);\n\n=item C<ev_TYPE_start> (loop, ev_TYPE *watcher)\n\nStarts (activates) the given watcher. Only active watchers will receive\nevents. If the watcher is already active nothing will happen.\n\nExample: Start the C<ev_io> watcher that is being abused as example in this\nwhole section.\n\n   ev_io_start (EV_DEFAULT_UC, &w);\n\n=item C<ev_TYPE_stop> (loop, ev_TYPE *watcher)\n\nStops the given watcher if active, and clears the pending status (whether\nthe watcher was active or not).\n\nIt is possible that stopped watchers are pending - for example,\nnon-repeating timers are being stopped when they become pending - but\ncalling C<ev_TYPE_stop> ensures that the watcher is neither active nor\npending. If you want to free or reuse the memory used by the watcher it is\ntherefore a good idea to always call its C<ev_TYPE_stop> function.\n\n=item bool ev_is_active (ev_TYPE *watcher)\n\nReturns a true value iff the watcher is active (i.e. it has been started\nand not yet been stopped). As long as a watcher is active you must not modify\nit.\n\n=item bool ev_is_pending (ev_TYPE *watcher)\n\nReturns a true value iff the watcher is pending, (i.e. it has outstanding\nevents but its callback has not yet been invoked). As long as a watcher\nis pending (but not active) you must not call an init function on it (but\nC<ev_TYPE_set> is safe), you must not change its priority, and you must\nmake sure the watcher is available to libev (e.g. you cannot C<free ()>\nit).\n\n=item callback ev_cb (ev_TYPE *watcher)\n\nReturns the callback currently set on the watcher.\n\n=item ev_set_cb (ev_TYPE *watcher, callback)\n\nChange the callback. You can change the callback at virtually any time\n(modulo threads).\n\n=item ev_set_priority (ev_TYPE *watcher, int priority)\n\n=item int ev_priority (ev_TYPE *watcher)\n\nSet and query the priority of the watcher. The priority is a small\ninteger between C<EV_MAXPRI> (default: C<2>) and C<EV_MINPRI>\n(default: C<-2>). Pending watchers with higher priority will be invoked\nbefore watchers with lower priority, but priority will not keep watchers\nfrom being executed (except for C<ev_idle> watchers).\n\nIf you need to suppress invocation when higher priority events are pending\nyou need to look at C<ev_idle> watchers, which provide this functionality.\n\nYou I<must not> change the priority of a watcher as long as it is active or\npending.\n\nSetting a priority outside the range of C<EV_MINPRI> to C<EV_MAXPRI> is\nfine, as long as you do not mind that the priority value you query might\nor might not have been clamped to the valid range.\n\nThe default priority used by watchers when no priority has been set is\nalways C<0>, which is supposed to not be too high and not be too low :).\n\nSee L</WATCHER PRIORITY MODELS>, below, for a more thorough treatment of\npriorities.\n\n=item ev_invoke (loop, ev_TYPE *watcher, int revents)\n\nInvoke the C<watcher> with the given C<loop> and C<revents>. Neither\nC<loop> nor C<revents> need to be valid as long as the watcher callback\ncan deal with that fact, as both are simply passed through to the\ncallback.\n\n=item int ev_clear_pending (loop, ev_TYPE *watcher)\n\nIf the watcher is pending, this function clears its pending status and\nreturns its C<revents> bitset (as if its callback was invoked). If the\nwatcher isn't pending it does nothing and returns C<0>.\n\nSometimes it can be useful to \"poll\" a watcher instead of waiting for its\ncallback to be invoked, which can be accomplished with this function.\n\n=item ev_feed_event (loop, ev_TYPE *watcher, int revents)\n\nFeeds the given event set into the event loop, as if the specified event\nhad happened for the specified watcher (which must be a pointer to an\ninitialised but not necessarily started event watcher). Obviously you must\nnot free the watcher as long as it has pending events.\n\nStopping the watcher, letting libev invoke it, or calling\nC<ev_clear_pending> will clear the pending event, even if the watcher was\nnot started in the first place.\n\nSee also C<ev_feed_fd_event> and C<ev_feed_signal_event> for related\nfunctions that do not need a watcher.\n\n=back\n\nSee also the L</ASSOCIATING CUSTOM DATA WITH A WATCHER> and L</BUILDING YOUR\nOWN COMPOSITE WATCHERS> idioms.\n\n=head2 WATCHER STATES\n\nThere are various watcher states mentioned throughout this manual -\nactive, pending and so on. In this section these states and the rules to\ntransition between them will be described in more detail - and while these\nrules might look complicated, they usually do \"the right thing\".\n\n=over 4\n\n=item initialised\n\nBefore a watcher can be registered with the event loop it has to be\ninitialised. This can be done with a call to C<ev_TYPE_init>, or calls to\nC<ev_init> followed by the watcher-specific C<ev_TYPE_set> function.\n\nIn this state it is simply some block of memory that is suitable for\nuse in an event loop. It can be moved around, freed, reused etc. at\nwill - as long as you either keep the memory contents intact, or call\nC<ev_TYPE_init> again.\n\n=item started/running/active\n\nOnce a watcher has been started with a call to C<ev_TYPE_start> it becomes\nproperty of the event loop, and is actively waiting for events. While in\nthis state it cannot be accessed (except in a few documented ways), moved,\nfreed or anything else - the only legal thing is to keep a pointer to it,\nand call libev functions on it that are documented to work on active watchers.\n\n=item pending\n\nIf a watcher is active and libev determines that an event it is interested\nin has occurred (such as a timer expiring), it will become pending. It will\nstay in this pending state until either it is stopped or its callback is\nabout to be invoked, so it is not normally pending inside the watcher\ncallback.\n\nThe watcher might or might not be active while it is pending (for example,\nan expired non-repeating timer can be pending but no longer active). If it\nis stopped, it can be freely accessed (e.g. by calling C<ev_TYPE_set>),\nbut it is still property of the event loop at this time, so cannot be\nmoved, freed or reused. And if it is active the rules described in the\nprevious item still apply.\n\nIt is also possible to feed an event on a watcher that is not active (e.g.\nvia C<ev_feed_event>), in which case it becomes pending without being\nactive.\n\n=item stopped\n\nA watcher can be stopped implicitly by libev (in which case it might still\nbe pending), or explicitly by calling its C<ev_TYPE_stop> function. The\nlatter will clear any pending state the watcher might be in, regardless\nof whether it was active or not, so stopping a watcher explicitly before\nfreeing it is often a good idea.\n\nWhile stopped (and not pending) the watcher is essentially in the\ninitialised state, that is, it can be reused, moved, modified in any way\nyou wish (but when you trash the memory block, you need to C<ev_TYPE_init>\nit again).\n\n=back\n\n=head2 WATCHER PRIORITY MODELS\n\nMany event loops support I<watcher priorities>, which are usually small\nintegers that influence the ordering of event callback invocation\nbetween watchers in some way, all else being equal.\n\nIn libev, Watcher priorities can be set using C<ev_set_priority>. See its\ndescription for the more technical details such as the actual priority\nrange.\n\nThere are two common ways how these these priorities are being interpreted\nby event loops:\n\nIn the more common lock-out model, higher priorities \"lock out\" invocation\nof lower priority watchers, which means as long as higher priority\nwatchers receive events, lower priority watchers are not being invoked.\n\nThe less common only-for-ordering model uses priorities solely to order\ncallback invocation within a single event loop iteration: Higher priority\nwatchers are invoked before lower priority ones, but they all get invoked\nbefore polling for new events.\n\nLibev uses the second (only-for-ordering) model for all its watchers\nexcept for idle watchers (which use the lock-out model).\n\nThe rationale behind this is that implementing the lock-out model for\nwatchers is not well supported by most kernel interfaces, and most event\nlibraries will just poll for the same events again and again as long as\ntheir callbacks have not been executed, which is very inefficient in the\ncommon case of one high-priority watcher locking out a mass of lower\npriority ones.\n\nStatic (ordering) priorities are most useful when you have two or more\nwatchers handling the same resource: a typical usage example is having an\nC<ev_io> watcher to receive data, and an associated C<ev_timer> to handle\ntimeouts. Under load, data might be received while the program handles\nother jobs, but since timers normally get invoked first, the timeout\nhandler will be executed before checking for data. In that case, giving\nthe timer a lower priority than the I/O watcher ensures that I/O will be\nhandled first even under adverse conditions (which is usually, but not\nalways, what you want).\n\nSince idle watchers use the \"lock-out\" model, meaning that idle watchers\nwill only be executed when no same or higher priority watchers have\nreceived events, they can be used to implement the \"lock-out\" model when\nrequired.\n\nFor example, to emulate how many other event libraries handle priorities,\nyou can associate an C<ev_idle> watcher to each such watcher, and in\nthe normal watcher callback, you just start the idle watcher. The real\nprocessing is done in the idle watcher callback. This causes libev to\ncontinuously poll and process kernel event data for the watcher, but when\nthe lock-out case is known to be rare (which in turn is rare :), this is\nworkable.\n\nUsually, however, the lock-out model implemented that way will perform\nmiserably under the type of load it was designed to handle. In that case,\nit might be preferable to stop the real watcher before starting the\nidle watcher, so the kernel will not have to process the event in case\nthe actual processing will be delayed for considerable time.\n\nHere is an example of an I/O watcher that should run at a strictly lower\npriority than the default, and which should only process data when no\nother events are pending:\n\n   ev_idle idle; // actual processing watcher\n   ev_io io;     // actual event watcher\n\n   static void\n   io_cb (EV_P_ ev_io *w, int revents)\n   {\n     // stop the I/O watcher, we received the event, but\n     // are not yet ready to handle it.\n     ev_io_stop (EV_A_ w);\n\n     // start the idle watcher to handle the actual event.\n     // it will not be executed as long as other watchers\n     // with the default priority are receiving events.\n     ev_idle_start (EV_A_ &idle);\n   }\n\n   static void\n   idle_cb (EV_P_ ev_idle *w, int revents)\n   {\n     // actual processing\n     read (STDIN_FILENO, ...);\n\n     // have to start the I/O watcher again, as\n     // we have handled the event\n     ev_io_start (EV_P_ &io);\n   }\n\n   // initialisation\n   ev_idle_init (&idle, idle_cb);\n   ev_io_init (&io, io_cb, STDIN_FILENO, EV_READ);\n   ev_io_start (EV_DEFAULT_ &io);\n\nIn the \"real\" world, it might also be beneficial to start a timer, so that\nlow-priority connections can not be locked out forever under load. This\nenables your program to keep a lower latency for important connections\nduring short periods of high load, while not completely locking out less\nimportant ones.\n\n\n=head1 WATCHER TYPES\n\nThis section describes each watcher in detail, but will not repeat\ninformation given in the last section. Any initialisation/set macros,\nfunctions and members specific to the watcher type are explained.\n\nMembers are additionally marked with either I<[read-only]>, meaning that,\nwhile the watcher is active, you can look at the member and expect some\nsensible content, but you must not modify it (you can modify it while the\nwatcher is stopped to your hearts content), or I<[read-write]>, which\nmeans you can expect it to have some sensible content while the watcher\nis active, but you can also modify it. Modifying it may not do something\nsensible or take immediate effect (or do anything at all), but libev will\nnot crash or malfunction in any way.\n\n\n=head2 C<ev_io> - is this file descriptor readable or writable?\n\nI/O watchers check whether a file descriptor is readable or writable\nin each iteration of the event loop, or, more precisely, when reading\nwould not block the process and writing would at least be able to write\nsome data. This behaviour is called level-triggering because you keep\nreceiving events as long as the condition persists. Remember you can stop\nthe watcher if you don't want to act on the event and neither want to\nreceive future events.\n\nIn general you can register as many read and/or write event watchers per\nfd as you want (as long as you don't confuse yourself). Setting all file\ndescriptors to non-blocking mode is also usually a good idea (but not\nrequired if you know what you are doing).\n\nAnother thing you have to watch out for is that it is quite easy to\nreceive \"spurious\" readiness notifications, that is, your callback might\nbe called with C<EV_READ> but a subsequent C<read>(2) will actually block\nbecause there is no data. It is very easy to get into this situation even\nwith a relatively standard program structure. Thus it is best to always\nuse non-blocking I/O: An extra C<read>(2) returning C<EAGAIN> is far\npreferable to a program hanging until some data arrives.\n\nIf you cannot run the fd in non-blocking mode (for example you should\nnot play around with an Xlib connection), then you have to separately\nre-test whether a file descriptor is really ready with a known-to-be good\ninterface such as poll (fortunately in the case of Xlib, it already does\nthis on its own, so its quite safe to use). Some people additionally\nuse C<SIGALRM> and an interval timer, just to be sure you won't block\nindefinitely.\n\nBut really, best use non-blocking mode.\n\n=head3 The special problem of disappearing file descriptors\n\nSome backends (e.g. kqueue, epoll) need to be told about closing a file\ndescriptor (either due to calling C<close> explicitly or any other means,\nsuch as C<dup2>). The reason is that you register interest in some file\ndescriptor, but when it goes away, the operating system will silently drop\nthis interest. If another file descriptor with the same number then is\nregistered with libev, there is no efficient way to see that this is, in\nfact, a different file descriptor.\n\nTo avoid having to explicitly tell libev about such cases, libev follows\nthe following policy:  Each time C<ev_io_set> is being called, libev\nwill assume that this is potentially a new file descriptor, otherwise\nit is assumed that the file descriptor stays the same. That means that\nyou I<have> to call C<ev_io_set> (or C<ev_io_init>) when you change the\ndescriptor even if the file descriptor number itself did not change.\n\nThis is how one would do it normally anyway, the important point is that\nthe libev application should not optimise around libev but should leave\noptimisations to libev.\n\n=head3 The special problem of dup'ed file descriptors\n\nSome backends (e.g. epoll), cannot register events for file descriptors,\nbut only events for the underlying file descriptions. That means when you\nhave C<dup ()>'ed file descriptors or weirder constellations, and register\nevents for them, only one file descriptor might actually receive events.\n\nThere is no workaround possible except not registering events\nfor potentially C<dup ()>'ed file descriptors, or to resort to\nC<EVBACKEND_SELECT> or C<EVBACKEND_POLL>.\n\n=head3 The special problem of files\n\nMany people try to use C<select> (or libev) on file descriptors\nrepresenting files, and expect it to become ready when their program\ndoesn't block on disk accesses (which can take a long time on their own).\n\nHowever, this cannot ever work in the \"expected\" way - you get a readiness\nnotification as soon as the kernel knows whether and how much data is\nthere, and in the case of open files, that's always the case, so you\nalways get a readiness notification instantly, and your read (or possibly\nwrite) will still block on the disk I/O.\n\nAnother way to view it is that in the case of sockets, pipes, character\ndevices and so on, there is another party (the sender) that delivers data\non its own, but in the case of files, there is no such thing: the disk\nwill not send data on its own, simply because it doesn't know what you\nwish to read - you would first have to request some data.\n\nSince files are typically not-so-well supported by advanced notification\nmechanism, libev tries hard to emulate POSIX behaviour with respect\nto files, even though you should not use it. The reason for this is\nconvenience: sometimes you want to watch STDIN or STDOUT, which is\nusually a tty, often a pipe, but also sometimes files or special devices\n(for example, C<epoll> on Linux works with F</dev/random> but not with\nF</dev/urandom>), and even though the file might better be served with\nasynchronous I/O instead of with non-blocking I/O, it is still useful when\nit \"just works\" instead of freezing.\n\nSo avoid file descriptors pointing to files when you know it (e.g. use\nlibeio), but use them when it is convenient, e.g. for STDIN/STDOUT, or\nwhen you rarely read from a file instead of from a socket, and want to\nreuse the same code path.\n\n=head3 The special problem of fork\n\nSome backends (epoll, kqueue) do not support C<fork ()> at all or exhibit\nuseless behaviour. Libev fully supports fork, but needs to be told about\nit in the child if you want to continue to use it in the child.\n\nTo support fork in your child processes, you have to call C<ev_loop_fork\n()> after a fork in the child, enable C<EVFLAG_FORKCHECK>, or resort to\nC<EVBACKEND_SELECT> or C<EVBACKEND_POLL>.\n\n=head3 The special problem of SIGPIPE\n\nWhile not really specific to libev, it is easy to forget about C<SIGPIPE>:\nwhen writing to a pipe whose other end has been closed, your program gets\nsent a SIGPIPE, which, by default, aborts your program. For most programs\nthis is sensible behaviour, for daemons, this is usually undesirable.\n\nSo when you encounter spurious, unexplained daemon exits, make sure you\nignore SIGPIPE (and maybe make sure you log the exit status of your daemon\nsomewhere, as that would have given you a big clue).\n\n=head3 The special problem of accept()ing when you can't\n\nMany implementations of the POSIX C<accept> function (for example,\nfound in post-2004 Linux) have the peculiar behaviour of not removing a\nconnection from the pending queue in all error cases.\n\nFor example, larger servers often run out of file descriptors (because\nof resource limits), causing C<accept> to fail with C<ENFILE> but not\nrejecting the connection, leading to libev signalling readiness on\nthe next iteration again (the connection still exists after all), and\ntypically causing the program to loop at 100% CPU usage.\n\nUnfortunately, the set of errors that cause this issue differs between\noperating systems, there is usually little the app can do to remedy the\nsituation, and no known thread-safe method of removing the connection to\ncope with overload is known (to me).\n\nOne of the easiest ways to handle this situation is to just ignore it\n- when the program encounters an overload, it will just loop until the\nsituation is over. While this is a form of busy waiting, no OS offers an\nevent-based way to handle this situation, so it's the best one can do.\n\nA better way to handle the situation is to log any errors other than\nC<EAGAIN> and C<EWOULDBLOCK>, making sure not to flood the log with such\nmessages, and continue as usual, which at least gives the user an idea of\nwhat could be wrong (\"raise the ulimit!\"). For extra points one could stop\nthe C<ev_io> watcher on the listening fd \"for a while\", which reduces CPU\nusage.\n\nIf your program is single-threaded, then you could also keep a dummy file\ndescriptor for overload situations (e.g. by opening F</dev/null>), and\nwhen you run into C<ENFILE> or C<EMFILE>, close it, run C<accept>,\nclose that fd, and create a new dummy fd. This will gracefully refuse\nclients under typical overload conditions.\n\nThe last way to handle it is to simply log the error and C<exit>, as\nis often done with C<malloc> failures, but this results in an easy\nopportunity for a DoS attack.\n\n=head3 Watcher-Specific Functions\n\n=over 4\n\n=item ev_io_init (ev_io *, callback, int fd, int events)\n\n=item ev_io_set (ev_io *, int fd, int events)\n\nConfigures an C<ev_io> watcher. The C<fd> is the file descriptor to\nreceive events for and C<events> is either C<EV_READ>, C<EV_WRITE> or\nC<EV_READ | EV_WRITE>, to express the desire to receive the given events.\n\n=item int fd [read-only]\n\nThe file descriptor being watched.\n\n=item int events [read-only]\n\nThe events being watched.\n\n=back\n\n=head3 Examples\n\nExample: Call C<stdin_readable_cb> when STDIN_FILENO has become, well\nreadable, but only once. Since it is likely line-buffered, you could\nattempt to read a whole line in the callback.\n\n   static void\n   stdin_readable_cb (struct ev_loop *loop, ev_io *w, int revents)\n   {\n      ev_io_stop (loop, w);\n     .. read from stdin here (or from w->fd) and handle any I/O errors\n   }\n\n   ...\n   struct ev_loop *loop = ev_default_init (0);\n   ev_io stdin_readable;\n   ev_io_init (&stdin_readable, stdin_readable_cb, STDIN_FILENO, EV_READ);\n   ev_io_start (loop, &stdin_readable);\n   ev_run (loop, 0);\n\n\n=head2 C<ev_timer> - relative and optionally repeating timeouts\n\nTimer watchers are simple relative timers that generate an event after a\ngiven time, and optionally repeating in regular intervals after that.\n\nThe timers are based on real time, that is, if you register an event that\ntimes out after an hour and you reset your system clock to January last\nyear, it will still time out after (roughly) one hour. \"Roughly\" because\ndetecting time jumps is hard, and some inaccuracies are unavoidable (the\nmonotonic clock option helps a lot here).\n\nThe callback is guaranteed to be invoked only I<after> its timeout has\npassed (not I<at>, so on systems with very low-resolution clocks this\nmight introduce a small delay, see \"the special problem of being too\nearly\", below). If multiple timers become ready during the same loop\niteration then the ones with earlier time-out values are invoked before\nones of the same priority with later time-out values (but this is no\nlonger true when a callback calls C<ev_run> recursively).\n\n=head3 Be smart about timeouts\n\nMany real-world problems involve some kind of timeout, usually for error\nrecovery. A typical example is an HTTP request - if the other side hangs,\nyou want to raise some error after a while.\n\nWhat follows are some ways to handle this problem, from obvious and\ninefficient to smart and efficient.\n\nIn the following, a 60 second activity timeout is assumed - a timeout that\ngets reset to 60 seconds each time there is activity (e.g. each time some\ndata or other life sign was received).\n\n=over 4\n\n=item 1. Use a timer and stop, reinitialise and start it on activity.\n\nThis is the most obvious, but not the most simple way: In the beginning,\nstart the watcher:\n\n   ev_timer_init (timer, callback, 60., 0.);\n   ev_timer_start (loop, timer);\n\nThen, each time there is some activity, C<ev_timer_stop> it, initialise it\nand start it again:\n\n   ev_timer_stop (loop, timer);\n   ev_timer_set (timer, 60., 0.);\n   ev_timer_start (loop, timer);\n\nThis is relatively simple to implement, but means that each time there is\nsome activity, libev will first have to remove the timer from its internal\ndata structure and then add it again. Libev tries to be fast, but it's\nstill not a constant-time operation.\n\n=item 2. Use a timer and re-start it with C<ev_timer_again> inactivity.\n\nThis is the easiest way, and involves using C<ev_timer_again> instead of\nC<ev_timer_start>.\n\nTo implement this, configure an C<ev_timer> with a C<repeat> value\nof C<60> and then call C<ev_timer_again> at start and each time you\nsuccessfully read or write some data. If you go into an idle state where\nyou do not expect data to travel on the socket, you can C<ev_timer_stop>\nthe timer, and C<ev_timer_again> will automatically restart it if need be.\n\nThat means you can ignore both the C<ev_timer_start> function and the\nC<after> argument to C<ev_timer_set>, and only ever use the C<repeat>\nmember and C<ev_timer_again>.\n\nAt start:\n\n   ev_init (timer, callback);\n   timer->repeat = 60.;\n   ev_timer_again (loop, timer);\n\nEach time there is some activity:\n\n   ev_timer_again (loop, timer);\n\nIt is even possible to change the time-out on the fly, regardless of\nwhether the watcher is active or not:\n\n   timer->repeat = 30.;\n   ev_timer_again (loop, timer);\n\nThis is slightly more efficient then stopping/starting the timer each time\nyou want to modify its timeout value, as libev does not have to completely\nremove and re-insert the timer from/into its internal data structure.\n\nIt is, however, even simpler than the \"obvious\" way to do it.\n\n=item 3. Let the timer time out, but then re-arm it as required.\n\nThis method is more tricky, but usually most efficient: Most timeouts are\nrelatively long compared to the intervals between other activity - in\nour example, within 60 seconds, there are usually many I/O events with\nassociated activity resets.\n\nIn this case, it would be more efficient to leave the C<ev_timer> alone,\nbut remember the time of last activity, and check for a real timeout only\nwithin the callback:\n\n   ev_tstamp timeout = 60.;\n   ev_tstamp last_activity; // time of last activity\n   ev_timer timer;\n\n   static void\n   callback (EV_P_ ev_timer *w, int revents)\n   {\n     // calculate when the timeout would happen\n     ev_tstamp after = last_activity - ev_now (EV_A) + timeout;\n\n     // if negative, it means we the timeout already occurred\n     if (after < 0.)\n       {\n         // timeout occurred, take action\n       }\n     else\n       {\n         // callback was invoked, but there was some recent \n         // activity. simply restart the timer to time out\n         // after \"after\" seconds, which is the earliest time\n         // the timeout can occur.\n         ev_timer_set (w, after, 0.);\n         ev_timer_start (EV_A_ w);\n       }\n   }\n\nTo summarise the callback: first calculate in how many seconds the\ntimeout will occur (by calculating the absolute time when it would occur,\nC<last_activity + timeout>, and subtracting the current time, C<ev_now\n(EV_A)> from that).\n\nIf this value is negative, then we are already past the timeout, i.e. we\ntimed out, and need to do whatever is needed in this case.\n\nOtherwise, we now the earliest time at which the timeout would trigger,\nand simply start the timer with this timeout value.\n\nIn other words, each time the callback is invoked it will check whether\nthe timeout occurred. If not, it will simply reschedule itself to check\nagain at the earliest time it could time out. Rinse. Repeat.\n\nThis scheme causes more callback invocations (about one every 60 seconds\nminus half the average time between activity), but virtually no calls to\nlibev to change the timeout.\n\nTo start the machinery, simply initialise the watcher and set\nC<last_activity> to the current time (meaning there was some activity just\nnow), then call the callback, which will \"do the right thing\" and start\nthe timer:\n\n   last_activity = ev_now (EV_A);\n   ev_init (&timer, callback);\n   callback (EV_A_ &timer, 0);\n\nWhen there is some activity, simply store the current time in\nC<last_activity>, no libev calls at all:\n\n   if (activity detected)\n     last_activity = ev_now (EV_A);\n\nWhen your timeout value changes, then the timeout can be changed by simply\nproviding a new value, stopping the timer and calling the callback, which\nwill again do the right thing (for example, time out immediately :).\n\n   timeout = new_value;\n   ev_timer_stop (EV_A_ &timer);\n   callback (EV_A_ &timer, 0);\n\nThis technique is slightly more complex, but in most cases where the\ntime-out is unlikely to be triggered, much more efficient.\n\n=item 4. Wee, just use a double-linked list for your timeouts.\n\nIf there is not one request, but many thousands (millions...), all\nemploying some kind of timeout with the same timeout value, then one can\ndo even better:\n\nWhen starting the timeout, calculate the timeout value and put the timeout\nat the I<end> of the list.\n\nThen use an C<ev_timer> to fire when the timeout at the I<beginning> of\nthe list is expected to fire (for example, using the technique #3).\n\nWhen there is some activity, remove the timer from the list, recalculate\nthe timeout, append it to the end of the list again, and make sure to\nupdate the C<ev_timer> if it was taken from the beginning of the list.\n\nThis way, one can manage an unlimited number of timeouts in O(1) time for\nstarting, stopping and updating the timers, at the expense of a major\ncomplication, and having to use a constant timeout. The constant timeout\nensures that the list stays sorted.\n\n=back\n\nSo which method the best?\n\nMethod #2 is a simple no-brain-required solution that is adequate in most\nsituations. Method #3 requires a bit more thinking, but handles many cases\nbetter, and isn't very complicated either. In most case, choosing either\none is fine, with #3 being better in typical situations.\n\nMethod #1 is almost always a bad idea, and buys you nothing. Method #4 is\nrather complicated, but extremely efficient, something that really pays\noff after the first million or so of active timers, i.e. it's usually\noverkill :)\n\n=head3 The special problem of being too early\n\nIf you ask a timer to call your callback after three seconds, then\nyou expect it to be invoked after three seconds - but of course, this\ncannot be guaranteed to infinite precision. Less obviously, it cannot be\nguaranteed to any precision by libev - imagine somebody suspending the\nprocess with a STOP signal for a few hours for example.\n\nSo, libev tries to invoke your callback as soon as possible I<after> the\ndelay has occurred, but cannot guarantee this.\n\nA less obvious failure mode is calling your callback too early: many event\nloops compare timestamps with a \"elapsed delay >= requested delay\", but\nthis can cause your callback to be invoked much earlier than you would\nexpect.\n\nTo see why, imagine a system with a clock that only offers full second\nresolution (think windows if you can't come up with a broken enough OS\nyourself). If you schedule a one-second timer at the time 500.9, then the\nevent loop will schedule your timeout to elapse at a system time of 500\n(500.9 truncated to the resolution) + 1, or 501.\n\nIf an event library looks at the timeout 0.1s later, it will see \"501 >=\n501\" and invoke the callback 0.1s after it was started, even though a\none-second delay was requested - this is being \"too early\", despite best\nintentions.\n\nThis is the reason why libev will never invoke the callback if the elapsed\ndelay equals the requested delay, but only when the elapsed delay is\nlarger than the requested delay. In the example above, libev would only invoke\nthe callback at system time 502, or 1.1s after the timer was started.\n\nSo, while libev cannot guarantee that your callback will be invoked\nexactly when requested, it I<can> and I<does> guarantee that the requested\ndelay has actually elapsed, or in other words, it always errs on the \"too\nlate\" side of things.\n\n=head3 The special problem of time updates\n\nEstablishing the current time is a costly operation (it usually takes\nat least one system call): EV therefore updates its idea of the current\ntime only before and after C<ev_run> collects new events, which causes a\ngrowing difference between C<ev_now ()> and C<ev_time ()> when handling\nlots of events in one iteration.\n\nThe relative timeouts are calculated relative to the C<ev_now ()>\ntime. This is usually the right thing as this timestamp refers to the time\nof the event triggering whatever timeout you are modifying/starting. If\nyou suspect event processing to be delayed and you I<need> to base the\ntimeout on the current time, use something like the following to adjust\nfor it:\n\n   ev_timer_set (&timer, after + (ev_time () - ev_now ()), 0.);\n\nIf the event loop is suspended for a long time, you can also force an\nupdate of the time returned by C<ev_now ()> by calling C<ev_now_update\n()>, although that will push the event time of all outstanding events\nfurther into the future.\n\n=head3 The special problem of unsynchronised clocks\n\nModern systems have a variety of clocks - libev itself uses the normal\n\"wall clock\" clock and, if available, the monotonic clock (to avoid time\njumps).\n\nNeither of these clocks is synchronised with each other or any other clock\non the system, so C<ev_time ()> might return a considerably different time\nthan C<gettimeofday ()> or C<time ()>. On a GNU/Linux system, for example,\na call to C<gettimeofday> might return a second count that is one higher\nthan a directly following call to C<time>.\n\nThe moral of this is to only compare libev-related timestamps with\nC<ev_time ()> and C<ev_now ()>, at least if you want better precision than\na second or so.\n\nOne more problem arises due to this lack of synchronisation: if libev uses\nthe system monotonic clock and you compare timestamps from C<ev_time>\nor C<ev_now> from when you started your timer and when your callback is\ninvoked, you will find that sometimes the callback is a bit \"early\".\n\nThis is because C<ev_timer>s work in real time, not wall clock time, so\nlibev makes sure your callback is not invoked before the delay happened,\nI<measured according to the real time>, not the system clock.\n\nIf your timeouts are based on a physical timescale (e.g. \"time out this\nconnection after 100 seconds\") then this shouldn't bother you as it is\nexactly the right behaviour.\n\nIf you want to compare wall clock/system timestamps to your timers, then\nyou need to use C<ev_periodic>s, as these are based on the wall clock\ntime, where your comparisons will always generate correct results.\n\n=head3 The special problems of suspended animation\n\nWhen you leave the server world it is quite customary to hit machines that\ncan suspend/hibernate - what happens to the clocks during such a suspend?\n\nSome quick tests made with a Linux 2.6.28 indicate that a suspend freezes\nall processes, while the clocks (C<times>, C<CLOCK_MONOTONIC>) continue\nto run until the system is suspended, but they will not advance while the\nsystem is suspended. That means, on resume, it will be as if the program\nwas frozen for a few seconds, but the suspend time will not be counted\ntowards C<ev_timer> when a monotonic clock source is used. The real time\nclock advanced as expected, but if it is used as sole clocksource, then a\nlong suspend would be detected as a time jump by libev, and timers would\nbe adjusted accordingly.\n\nI would not be surprised to see different behaviour in different between\noperating systems, OS versions or even different hardware.\n\nThe other form of suspend (job control, or sending a SIGSTOP) will see a\ntime jump in the monotonic clocks and the realtime clock. If the program\nis suspended for a very long time, and monotonic clock sources are in use,\nthen you can expect C<ev_timer>s to expire as the full suspension time\nwill be counted towards the timers. When no monotonic clock source is in\nuse, then libev will again assume a timejump and adjust accordingly.\n\nIt might be beneficial for this latter case to call C<ev_suspend>\nand C<ev_resume> in code that handles C<SIGTSTP>, to at least get\ndeterministic behaviour in this case (you can do nothing against\nC<SIGSTOP>).\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_timer_init (ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)\n\n=item ev_timer_set (ev_timer *, ev_tstamp after, ev_tstamp repeat)\n\nConfigure the timer to trigger after C<after> seconds. If C<repeat>\nis C<0.>, then it will automatically be stopped once the timeout is\nreached. If it is positive, then the timer will automatically be\nconfigured to trigger again C<repeat> seconds later, again, and again,\nuntil stopped manually.\n\nThe timer itself will do a best-effort at avoiding drift, that is, if\nyou configure a timer to trigger every 10 seconds, then it will normally\ntrigger at exactly 10 second intervals. If, however, your program cannot\nkeep up with the timer (because it takes longer than those 10 seconds to\ndo stuff) the timer will not fire more than once per event loop iteration.\n\n=item ev_timer_again (loop, ev_timer *)\n\nThis will act as if the timer timed out, and restarts it again if it is\nrepeating. It basically works like calling C<ev_timer_stop>, updating the\ntimeout to the C<repeat> value and calling C<ev_timer_start>.\n\nThe exact semantics are as in the following rules, all of which will be\napplied to the watcher:\n\n=over 4\n\n=item If the timer is pending, the pending status is always cleared.\n\n=item If the timer is started but non-repeating, stop it (as if it timed\nout, without invoking it).\n\n=item If the timer is repeating, make the C<repeat> value the new timeout\nand start the timer, if necessary.\n\n=back\n\nThis sounds a bit complicated, see L</Be smart about timeouts>, above, for a\nusage example.\n\n=item ev_tstamp ev_timer_remaining (loop, ev_timer *)\n\nReturns the remaining time until a timer fires. If the timer is active,\nthen this time is relative to the current event loop time, otherwise it's\nthe timeout value currently configured.\n\nThat is, after an C<ev_timer_set (w, 5, 7)>, C<ev_timer_remaining> returns\nC<5>. When the timer is started and one second passes, C<ev_timer_remaining>\nwill return C<4>. When the timer expires and is restarted, it will return\nroughly C<7> (likely slightly less as callback invocation takes some time,\ntoo), and so on.\n\n=item ev_tstamp repeat [read-write]\n\nThe current C<repeat> value. Will be used each time the watcher times out\nor C<ev_timer_again> is called, and determines the next timeout (if any),\nwhich is also when any modifications are taken into account.\n\n=back\n\n=head3 Examples\n\nExample: Create a timer that fires after 60 seconds.\n\n   static void\n   one_minute_cb (struct ev_loop *loop, ev_timer *w, int revents)\n   {\n     .. one minute over, w is actually stopped right here\n   }\n\n   ev_timer mytimer;\n   ev_timer_init (&mytimer, one_minute_cb, 60., 0.);\n   ev_timer_start (loop, &mytimer);\n\nExample: Create a timeout timer that times out after 10 seconds of\ninactivity.\n\n   static void\n   timeout_cb (struct ev_loop *loop, ev_timer *w, int revents)\n   {\n     .. ten seconds without any activity\n   }\n\n   ev_timer mytimer;\n   ev_timer_init (&mytimer, timeout_cb, 0., 10.); /* note, only repeat used */\n   ev_timer_again (&mytimer); /* start timer */\n   ev_run (loop, 0);\n\n   // and in some piece of code that gets executed on any \"activity\":\n   // reset the timeout to start ticking again at 10 seconds\n   ev_timer_again (&mytimer);\n\n\n=head2 C<ev_periodic> - to cron or not to cron?\n\nPeriodic watchers are also timers of a kind, but they are very versatile\n(and unfortunately a bit complex).\n\nUnlike C<ev_timer>, periodic watchers are not based on real time (or\nrelative time, the physical time that passes) but on wall clock time\n(absolute time, the thing you can read on your calendar or clock). The\ndifference is that wall clock time can run faster or slower than real\ntime, and time jumps are not uncommon (e.g. when you adjust your\nwrist-watch).\n\nYou can tell a periodic watcher to trigger after some specific point\nin time: for example, if you tell a periodic watcher to trigger \"in 10\nseconds\" (by specifying e.g. C<ev_now () + 10.>, that is, an absolute time\nnot a delay) and then reset your system clock to January of the previous\nyear, then it will take a year or more to trigger the event (unlike an\nC<ev_timer>, which would still trigger roughly 10 seconds after starting\nit, as it uses a relative timeout).\n\nC<ev_periodic> watchers can also be used to implement vastly more complex\ntimers, such as triggering an event on each \"midnight, local time\", or\nother complicated rules. This cannot be done with C<ev_timer> watchers, as\nthose cannot react to time jumps.\n\nAs with timers, the callback is guaranteed to be invoked only when the\npoint in time where it is supposed to trigger has passed. If multiple\ntimers become ready during the same loop iteration then the ones with\nearlier time-out values are invoked before ones with later time-out values\n(but this is no longer true when a callback calls C<ev_run> recursively).\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_periodic_init (ev_periodic *, callback, ev_tstamp offset, ev_tstamp interval, reschedule_cb)\n\n=item ev_periodic_set (ev_periodic *, ev_tstamp offset, ev_tstamp interval, reschedule_cb)\n\nLots of arguments, let's sort it out... There are basically three modes of\noperation, and we will explain them from simplest to most complex:\n\n=over 4\n\n=item * absolute timer (offset = absolute time, interval = 0, reschedule_cb = 0)\n\nIn this configuration the watcher triggers an event after the wall clock\ntime C<offset> has passed. It will not repeat and will not adjust when a\ntime jump occurs, that is, if it is to be run at January 1st 2011 then it\nwill be stopped and invoked when the system clock reaches or surpasses\nthis point in time.\n\n=item * repeating interval timer (offset = offset within interval, interval > 0, reschedule_cb = 0)\n\nIn this mode the watcher will always be scheduled to time out at the next\nC<offset + N * interval> time (for some integer N, which can also be\nnegative) and then repeat, regardless of any time jumps. The C<offset>\nargument is merely an offset into the C<interval> periods.\n\nThis can be used to create timers that do not drift with respect to the\nsystem clock, for example, here is an C<ev_periodic> that triggers each\nhour, on the hour (with respect to UTC):\n\n   ev_periodic_set (&periodic, 0., 3600., 0);\n\nThis doesn't mean there will always be 3600 seconds in between triggers,\nbut only that the callback will be called when the system time shows a\nfull hour (UTC), or more correctly, when the system time is evenly divisible\nby 3600.\n\nAnother way to think about it (for the mathematically inclined) is that\nC<ev_periodic> will try to run the callback in this mode at the next possible\ntime where C<time = offset (mod interval)>, regardless of any time jumps.\n\nThe C<interval> I<MUST> be positive, and for numerical stability, the\ninterval value should be higher than C<1/8192> (which is around 100\nmicroseconds) and C<offset> should be higher than C<0> and should have\nat most a similar magnitude as the current time (say, within a factor of\nten). Typical values for offset are, in fact, C<0> or something between\nC<0> and C<interval>, which is also the recommended range.\n\nNote also that there is an upper limit to how often a timer can fire (CPU\nspeed for example), so if C<interval> is very small then timing stability\nwill of course deteriorate. Libev itself tries to be exact to be about one\nmillisecond (if the OS supports it and the machine is fast enough).\n\n=item * manual reschedule mode (offset ignored, interval ignored, reschedule_cb = callback)\n\nIn this mode the values for C<interval> and C<offset> are both being\nignored. Instead, each time the periodic watcher gets scheduled, the\nreschedule callback will be called with the watcher as first, and the\ncurrent time as second argument.\n\nNOTE: I<This callback MUST NOT stop or destroy any periodic watcher, ever,\nor make ANY other event loop modifications whatsoever, unless explicitly\nallowed by documentation here>.\n\nIf you need to stop it, return C<now + 1e30> (or so, fudge fudge) and stop\nit afterwards (e.g. by starting an C<ev_prepare> watcher, which is the\nonly event loop modification you are allowed to do).\n\nThe callback prototype is C<ev_tstamp (*reschedule_cb)(ev_periodic\n*w, ev_tstamp now)>, e.g.:\n\n   static ev_tstamp\n   my_rescheduler (ev_periodic *w, ev_tstamp now)\n   {\n     return now + 60.;\n   }\n\nIt must return the next time to trigger, based on the passed time value\n(that is, the lowest time value larger than to the second argument). It\nwill usually be called just before the callback will be triggered, but\nmight be called at other times, too.\n\nNOTE: I<< This callback must always return a time that is higher than or\nequal to the passed C<now> value >>.\n\nThis can be used to create very complex timers, such as a timer that\ntriggers on \"next midnight, local time\". To do this, you would calculate the\nnext midnight after C<now> and return the timestamp value for this. How\nyou do this is, again, up to you (but it is not trivial, which is the main\nreason I omitted it as an example).\n\n=back\n\n=item ev_periodic_again (loop, ev_periodic *)\n\nSimply stops and restarts the periodic watcher again. This is only useful\nwhen you changed some parameters or the reschedule callback would return\na different time than the last time it was called (e.g. in a crond like\nprogram when the crontabs have changed).\n\n=item ev_tstamp ev_periodic_at (ev_periodic *)\n\nWhen active, returns the absolute time that the watcher is supposed\nto trigger next. This is not the same as the C<offset> argument to\nC<ev_periodic_set>, but indeed works even in interval and manual\nrescheduling modes.\n\n=item ev_tstamp offset [read-write]\n\nWhen repeating, this contains the offset value, otherwise this is the\nabsolute point in time (the C<offset> value passed to C<ev_periodic_set>,\nalthough libev might modify this value for better numerical stability).\n\nCan be modified any time, but changes only take effect when the periodic\ntimer fires or C<ev_periodic_again> is being called.\n\n=item ev_tstamp interval [read-write]\n\nThe current interval value. Can be modified any time, but changes only\ntake effect when the periodic timer fires or C<ev_periodic_again> is being\ncalled.\n\n=item ev_tstamp (*reschedule_cb)(ev_periodic *w, ev_tstamp now) [read-write]\n\nThe current reschedule callback, or C<0>, if this functionality is\nswitched off. Can be changed any time, but changes only take effect when\nthe periodic timer fires or C<ev_periodic_again> is being called.\n\n=back\n\n=head3 Examples\n\nExample: Call a callback every hour, or, more precisely, whenever the\nsystem time is divisible by 3600. The callback invocation times have\npotentially a lot of jitter, but good long-term stability.\n\n   static void\n   clock_cb (struct ev_loop *loop, ev_periodic *w, int revents)\n   {\n     ... its now a full hour (UTC, or TAI or whatever your clock follows)\n   }\n\n   ev_periodic hourly_tick;\n   ev_periodic_init (&hourly_tick, clock_cb, 0., 3600., 0);\n   ev_periodic_start (loop, &hourly_tick);\n\nExample: The same as above, but use a reschedule callback to do it:\n\n   #include <math.h>\n\n   static ev_tstamp\n   my_scheduler_cb (ev_periodic *w, ev_tstamp now)\n   {\n     return now + (3600. - fmod (now, 3600.));\n   }\n\n   ev_periodic_init (&hourly_tick, clock_cb, 0., 0., my_scheduler_cb);\n\nExample: Call a callback every hour, starting now:\n\n   ev_periodic hourly_tick;\n   ev_periodic_init (&hourly_tick, clock_cb,\n                     fmod (ev_now (loop), 3600.), 3600., 0);\n   ev_periodic_start (loop, &hourly_tick);\n\n\n=head2 C<ev_signal> - signal me when a signal gets signalled!\n\nSignal watchers will trigger an event when the process receives a specific\nsignal one or more times. Even though signals are very asynchronous, libev\nwill try its best to deliver signals synchronously, i.e. as part of the\nnormal event processing, like any other event.\n\nIf you want signals to be delivered truly asynchronously, just use\nC<sigaction> as you would do without libev and forget about sharing\nthe signal. You can even use C<ev_async> from a signal handler to\nsynchronously wake up an event loop.\n\nYou can configure as many watchers as you like for the same signal, but\nonly within the same loop, i.e. you can watch for C<SIGINT> in your\ndefault loop and for C<SIGIO> in another loop, but you cannot watch for\nC<SIGINT> in both the default loop and another loop at the same time. At\nthe moment, C<SIGCHLD> is permanently tied to the default loop.\n\nOnly after the first watcher for a signal is started will libev actually\nregister something with the kernel. It thus coexists with your own signal\nhandlers as long as you don't register any with libev for the same signal.\n\nIf possible and supported, libev will install its handlers with\nC<SA_RESTART> (or equivalent) behaviour enabled, so system calls should\nnot be unduly interrupted. If you have a problem with system calls getting\ninterrupted by signals you can block all signals in an C<ev_check> watcher\nand unblock them in an C<ev_prepare> watcher.\n\n=head3 The special problem of inheritance over fork/execve/pthread_create\n\nBoth the signal mask (C<sigprocmask>) and the signal disposition\n(C<sigaction>) are unspecified after starting a signal watcher (and after\nstopping it again), that is, libev might or might not block the signal,\nand might or might not set or restore the installed signal handler (but\nsee C<EVFLAG_NOSIGMASK>).\n\nWhile this does not matter for the signal disposition (libev never\nsets signals to C<SIG_IGN>, so handlers will be reset to C<SIG_DFL> on\nC<execve>), this matters for the signal mask: many programs do not expect\ncertain signals to be blocked.\n\nThis means that before calling C<exec> (from the child) you should reset\nthe signal mask to whatever \"default\" you expect (all clear is a good\nchoice usually).\n\nThe simplest way to ensure that the signal mask is reset in the child is\nto install a fork handler with C<pthread_atfork> that resets it. That will\ncatch fork calls done by libraries (such as the libc) as well.\n\nIn current versions of libev, the signal will not be blocked indefinitely\nunless you use the C<signalfd> API (C<EV_SIGNALFD>). While this reduces\nthe window of opportunity for problems, it will not go away, as libev\nI<has> to modify the signal mask, at least temporarily.\n\nSo I can't stress this enough: I<If you do not reset your signal mask when\nyou expect it to be empty, you have a race condition in your code>. This\nis not a libev-specific thing, this is true for most event libraries.\n\n=head3 The special problem of threads signal handling\n\nPOSIX threads has problematic signal handling semantics, specifically,\na lot of functionality (sigfd, sigwait etc.) only really works if all\nthreads in a process block signals, which is hard to achieve.\n\nWhen you want to use sigwait (or mix libev signal handling with your own\nfor the same signals), you can tackle this problem by globally blocking\nall signals before creating any threads (or creating them with a fully set\nsigprocmask) and also specifying the C<EVFLAG_NOSIGMASK> when creating\nloops. Then designate one thread as \"signal receiver thread\" which handles\nthese signals. You can pass on any signals that libev might be interested\nin by calling C<ev_feed_signal>.\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_signal_init (ev_signal *, callback, int signum)\n\n=item ev_signal_set (ev_signal *, int signum)\n\nConfigures the watcher to trigger on the given signal number (usually one\nof the C<SIGxxx> constants).\n\n=item int signum [read-only]\n\nThe signal the watcher watches out for.\n\n=back\n\n=head3 Examples\n\nExample: Try to exit cleanly on SIGINT.\n\n   static void\n   sigint_cb (struct ev_loop *loop, ev_signal *w, int revents)\n   {\n     ev_break (loop, EVBREAK_ALL);\n   }\n\n   ev_signal signal_watcher;\n   ev_signal_init (&signal_watcher, sigint_cb, SIGINT);\n   ev_signal_start (loop, &signal_watcher);\n\n\n=head2 C<ev_child> - watch out for process status changes\n\nChild watchers trigger when your process receives a SIGCHLD in response to\nsome child status changes (most typically when a child of yours dies or\nexits). It is permissible to install a child watcher I<after> the child\nhas been forked (which implies it might have already exited), as long\nas the event loop isn't entered (or is continued from a watcher), i.e.,\nforking and then immediately registering a watcher for the child is fine,\nbut forking and registering a watcher a few event loop iterations later or\nin the next callback invocation is not.\n\nOnly the default event loop is capable of handling signals, and therefore\nyou can only register child watchers in the default event loop.\n\nDue to some design glitches inside libev, child watchers will always be\nhandled at maximum priority (their priority is set to C<EV_MAXPRI> by\nlibev)\n\n=head3 Process Interaction\n\nLibev grabs C<SIGCHLD> as soon as the default event loop is\ninitialised. This is necessary to guarantee proper behaviour even if the\nfirst child watcher is started after the child exits. The occurrence\nof C<SIGCHLD> is recorded asynchronously, but child reaping is done\nsynchronously as part of the event loop processing. Libev always reaps all\nchildren, even ones not watched.\n\n=head3 Overriding the Built-In Processing\n\nLibev offers no special support for overriding the built-in child\nprocessing, but if your application collides with libev's default child\nhandler, you can override it easily by installing your own handler for\nC<SIGCHLD> after initialising the default loop, and making sure the\ndefault loop never gets destroyed. You are encouraged, however, to use an\nevent-based approach to child reaping and thus use libev's support for\nthat, so other libev users can use C<ev_child> watchers freely.\n\n=head3 Stopping the Child Watcher\n\nCurrently, the child watcher never gets stopped, even when the\nchild terminates, so normally one needs to stop the watcher in the\ncallback. Future versions of libev might stop the watcher automatically\nwhen a child exit is detected (calling C<ev_child_stop> twice is not a\nproblem).\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_child_init (ev_child *, callback, int pid, int trace)\n\n=item ev_child_set (ev_child *, int pid, int trace)\n\nConfigures the watcher to wait for status changes of process C<pid> (or\nI<any> process if C<pid> is specified as C<0>). The callback can look\nat the C<rstatus> member of the C<ev_child> watcher structure to see\nthe status word (use the macros from C<sys/wait.h> and see your systems\nC<waitpid> documentation). The C<rpid> member contains the pid of the\nprocess causing the status change. C<trace> must be either C<0> (only\nactivate the watcher when the process terminates) or C<1> (additionally\nactivate the watcher when the process is stopped or continued).\n\n=item int pid [read-only]\n\nThe process id this watcher watches out for, or C<0>, meaning any process id.\n\n=item int rpid [read-write]\n\nThe process id that detected a status change.\n\n=item int rstatus [read-write]\n\nThe process exit/trace status caused by C<rpid> (see your systems\nC<waitpid> and C<sys/wait.h> documentation for details).\n\n=back\n\n=head3 Examples\n\nExample: C<fork()> a new process and install a child handler to wait for\nits completion.\n\n   ev_child cw;\n\n   static void\n   child_cb (EV_P_ ev_child *w, int revents)\n   {\n     ev_child_stop (EV_A_ w);\n     printf (\"process %d exited with status %x\\n\", w->rpid, w->rstatus);\n   }\n\n   pid_t pid = fork ();\n\n   if (pid < 0)\n     // error\n   else if (pid == 0)\n     {\n       // the forked child executes here\n       exit (1);\n     }\n   else\n     {\n       ev_child_init (&cw, child_cb, pid, 0);\n       ev_child_start (EV_DEFAULT_ &cw);\n     }\n\n\n=head2 C<ev_stat> - did the file attributes just change?\n\nThis watches a file system path for attribute changes. That is, it calls\nC<stat> on that path in regular intervals (or when the OS says it changed)\nand sees if it changed compared to the last time, invoking the callback\nif it did. Starting the watcher C<stat>'s the file, so only changes that\nhappen after the watcher has been started will be reported.\n\nThe path does not need to exist: changing from \"path exists\" to \"path does\nnot exist\" is a status change like any other. The condition \"path does not\nexist\" (or more correctly \"path cannot be stat'ed\") is signified by the\nC<st_nlink> field being zero (which is otherwise always forced to be at\nleast one) and all the other fields of the stat buffer having unspecified\ncontents.\n\nThe path I<must not> end in a slash or contain special components such as\nC<.> or C<..>. The path I<should> be absolute: If it is relative and\nyour working directory changes, then the behaviour is undefined.\n\nSince there is no portable change notification interface available, the\nportable implementation simply calls C<stat(2)> regularly on the path\nto see if it changed somehow. You can specify a recommended polling\ninterval for this case. If you specify a polling interval of C<0> (highly\nrecommended!) then a I<suitable, unspecified default> value will be used\n(which you can expect to be around five seconds, although this might\nchange dynamically). Libev will also impose a minimum interval which is\ncurrently around C<0.1>, but that's usually overkill.\n\nThis watcher type is not meant for massive numbers of stat watchers,\nas even with OS-supported change notifications, this can be\nresource-intensive.\n\nAt the time of this writing, the only OS-specific interface implemented\nis the Linux inotify interface (implementing kqueue support is left as an\nexercise for the reader. Note, however, that the author sees no way of\nimplementing C<ev_stat> semantics with kqueue, except as a hint).\n\n=head3 ABI Issues (Largefile Support)\n\nLibev by default (unless the user overrides this) uses the default\ncompilation environment, which means that on systems with large file\nsupport disabled by default, you get the 32 bit version of the stat\nstructure. When using the library from programs that change the ABI to\nuse 64 bit file offsets the programs will fail. In that case you have to\ncompile libev with the same flags to get binary compatibility. This is\nobviously the case with any flags that change the ABI, but the problem is\nmost noticeably displayed with ev_stat and large file support.\n\nThe solution for this is to lobby your distribution maker to make large\nfile interfaces available by default (as e.g. FreeBSD does) and not\noptional. Libev cannot simply switch on large file support because it has\nto exchange stat structures with application programs compiled using the\ndefault compilation environment.\n\n=head3 Inotify and Kqueue\n\nWhen C<inotify (7)> support has been compiled into libev and present at\nruntime, it will be used to speed up change detection where possible. The\ninotify descriptor will be created lazily when the first C<ev_stat>\nwatcher is being started.\n\nInotify presence does not change the semantics of C<ev_stat> watchers\nexcept that changes might be detected earlier, and in some cases, to avoid\nmaking regular C<stat> calls. Even in the presence of inotify support\nthere are many cases where libev has to resort to regular C<stat> polling,\nbut as long as kernel 2.6.25 or newer is used (2.6.24 and older have too\nmany bugs), the path exists (i.e. stat succeeds), and the path resides on\na local filesystem (libev currently assumes only ext2/3, jfs, reiserfs and\nxfs are fully working) libev usually gets away without polling.\n\nThere is no support for kqueue, as apparently it cannot be used to\nimplement this functionality, due to the requirement of having a file\ndescriptor open on the object at all times, and detecting renames, unlinks\netc. is difficult.\n\n=head3 C<stat ()> is a synchronous operation\n\nLibev doesn't normally do any kind of I/O itself, and so is not blocking\nthe process. The exception are C<ev_stat> watchers - those call C<stat\n()>, which is a synchronous operation.\n\nFor local paths, this usually doesn't matter: unless the system is very\nbusy or the intervals between stat's are large, a stat call will be fast,\nas the path data is usually in memory already (except when starting the\nwatcher).\n\nFor networked file systems, calling C<stat ()> can block an indefinite\ntime due to network issues, and even under good conditions, a stat call\noften takes multiple milliseconds.\n\nTherefore, it is best to avoid using C<ev_stat> watchers on networked\npaths, although this is fully supported by libev.\n\n=head3 The special problem of stat time resolution\n\nThe C<stat ()> system call only supports full-second resolution portably,\nand even on systems where the resolution is higher, most file systems\nstill only support whole seconds.\n\nThat means that, if the time is the only thing that changes, you can\neasily miss updates: on the first update, C<ev_stat> detects a change and\ncalls your callback, which does something. When there is another update\nwithin the same second, C<ev_stat> will be unable to detect unless the\nstat data does change in other ways (e.g. file size).\n\nThe solution to this is to delay acting on a change for slightly more\nthan a second (or till slightly after the next full second boundary), using\na roughly one-second-delay C<ev_timer> (e.g. C<ev_timer_set (w, 0., 1.02);\nev_timer_again (loop, w)>).\n\nThe C<.02> offset is added to work around small timing inconsistencies\nof some operating systems (where the second counter of the current time\nmight be be delayed. One such system is the Linux kernel, where a call to\nC<gettimeofday> might return a timestamp with a full second later than\na subsequent C<time> call - if the equivalent of C<time ()> is used to\nupdate file times then there will be a small window where the kernel uses\nthe previous second to update file times but libev might already execute\nthe timer callback).\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_stat_init (ev_stat *, callback, const char *path, ev_tstamp interval)\n\n=item ev_stat_set (ev_stat *, const char *path, ev_tstamp interval)\n\nConfigures the watcher to wait for status changes of the given\nC<path>. The C<interval> is a hint on how quickly a change is expected to\nbe detected and should normally be specified as C<0> to let libev choose\na suitable value. The memory pointed to by C<path> must point to the same\npath for as long as the watcher is active.\n\nThe callback will receive an C<EV_STAT> event when a change was detected,\nrelative to the attributes at the time the watcher was started (or the\nlast change was detected).\n\n=item ev_stat_stat (loop, ev_stat *)\n\nUpdates the stat buffer immediately with new values. If you change the\nwatched path in your callback, you could call this function to avoid\ndetecting this change (while introducing a race condition if you are not\nthe only one changing the path). Can also be useful simply to find out the\nnew values.\n\n=item ev_statdata attr [read-only]\n\nThe most-recently detected attributes of the file. Although the type is\nC<ev_statdata>, this is usually the (or one of the) C<struct stat> types\nsuitable for your system, but you can only rely on the POSIX-standardised\nmembers to be present. If the C<st_nlink> member is C<0>, then there was\nsome error while C<stat>ing the file.\n\n=item ev_statdata prev [read-only]\n\nThe previous attributes of the file. The callback gets invoked whenever\nC<prev> != C<attr>, or, more precisely, one or more of these members\ndiffer: C<st_dev>, C<st_ino>, C<st_mode>, C<st_nlink>, C<st_uid>,\nC<st_gid>, C<st_rdev>, C<st_size>, C<st_atime>, C<st_mtime>, C<st_ctime>.\n\n=item ev_tstamp interval [read-only]\n\nThe specified interval.\n\n=item const char *path [read-only]\n\nThe file system path that is being watched.\n\n=back\n\n=head3 Examples\n\nExample: Watch C</etc/passwd> for attribute changes.\n\n   static void\n   passwd_cb (struct ev_loop *loop, ev_stat *w, int revents)\n   {\n     /* /etc/passwd changed in some way */\n     if (w->attr.st_nlink)\n       {\n         printf (\"passwd current size  %ld\\n\", (long)w->attr.st_size);\n         printf (\"passwd current atime %ld\\n\", (long)w->attr.st_mtime);\n         printf (\"passwd current mtime %ld\\n\", (long)w->attr.st_mtime);\n       }\n     else\n       /* you shalt not abuse printf for puts */\n       puts (\"wow, /etc/passwd is not there, expect problems. \"\n             \"if this is windows, they already arrived\\n\");\n   }\n\n   ...\n   ev_stat passwd;\n\n   ev_stat_init (&passwd, passwd_cb, \"/etc/passwd\", 0.);\n   ev_stat_start (loop, &passwd);\n\nExample: Like above, but additionally use a one-second delay so we do not\nmiss updates (however, frequent updates will delay processing, too, so\none might do the work both on C<ev_stat> callback invocation I<and> on\nC<ev_timer> callback invocation).\n\n   static ev_stat passwd;\n   static ev_timer timer;\n\n   static void\n   timer_cb (EV_P_ ev_timer *w, int revents)\n   {\n     ev_timer_stop (EV_A_ w);\n\n     /* now it's one second after the most recent passwd change */\n   }\n\n   static void\n   stat_cb (EV_P_ ev_stat *w, int revents)\n   {\n     /* reset the one-second timer */\n     ev_timer_again (EV_A_ &timer);\n   }\n\n   ...\n   ev_stat_init (&passwd, stat_cb, \"/etc/passwd\", 0.);\n   ev_stat_start (loop, &passwd);\n   ev_timer_init (&timer, timer_cb, 0., 1.02);\n\n\n=head2 C<ev_idle> - when you've got nothing better to do...\n\nIdle watchers trigger events when no other events of the same or higher\npriority are pending (prepare, check and other idle watchers do not count\nas receiving \"events\").\n\nThat is, as long as your process is busy handling sockets or timeouts\n(or even signals, imagine) of the same or higher priority it will not be\ntriggered. But when your process is idle (or only lower-priority watchers\nare pending), the idle watchers are being called once per event loop\niteration - until stopped, that is, or your process receives more events\nand becomes busy again with higher priority stuff.\n\nThe most noteworthy effect is that as long as any idle watchers are\nactive, the process will not block when waiting for new events.\n\nApart from keeping your process non-blocking (which is a useful\neffect on its own sometimes), idle watchers are a good place to do\n\"pseudo-background processing\", or delay processing stuff to after the\nevent loop has handled all outstanding events.\n\n=head3 Abusing an C<ev_idle> watcher for its side-effect\n\nAs long as there is at least one active idle watcher, libev will never\nsleep unnecessarily. Or in other words, it will loop as fast as possible.\nFor this to work, the idle watcher doesn't need to be invoked at all - the\nlowest priority will do.\n\nThis mode of operation can be useful together with an C<ev_check> watcher,\nto do something on each event loop iteration - for example to balance load\nbetween different connections.\n\nSee L</Abusing an ev_check watcher for its side-effect> for a longer\nexample.\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_idle_init (ev_idle *, callback)\n\nInitialises and configures the idle watcher - it has no parameters of any\nkind. There is a C<ev_idle_set> macro, but using it is utterly pointless,\nbelieve me.\n\n=back\n\n=head3 Examples\n\nExample: Dynamically allocate an C<ev_idle> watcher, start it, and in the\ncallback, free it. Also, use no error checking, as usual.\n\n   static void\n   idle_cb (struct ev_loop *loop, ev_idle *w, int revents)\n   {\n     // stop the watcher\n     ev_idle_stop (loop, w);\n\n     // now we can free it\n     free (w);\n\n     // now do something you wanted to do when the program has\n     // no longer anything immediate to do.\n   }\n\n   ev_idle *idle_watcher = malloc (sizeof (ev_idle));\n   ev_idle_init (idle_watcher, idle_cb);\n   ev_idle_start (loop, idle_watcher);\n\n\n=head2 C<ev_prepare> and C<ev_check> - customise your event loop!\n\nPrepare and check watchers are often (but not always) used in pairs:\nprepare watchers get invoked before the process blocks and check watchers\nafterwards.\n\nYou I<must not> call C<ev_run> (or similar functions that enter the\ncurrent event loop) or C<ev_loop_fork> from either C<ev_prepare> or\nC<ev_check> watchers. Other loops than the current one are fine,\nhowever. The rationale behind this is that you do not need to check\nfor recursion in those watchers, i.e. the sequence will always be\nC<ev_prepare>, blocking, C<ev_check> so if you have one watcher of each\nkind they will always be called in pairs bracketing the blocking call.\n\nTheir main purpose is to integrate other event mechanisms into libev and\ntheir use is somewhat advanced. They could be used, for example, to track\nvariable changes, implement your own watchers, integrate net-snmp or a\ncoroutine library and lots more. They are also occasionally useful if\nyou cache some data and want to flush it before blocking (for example,\nin X programs you might want to do an C<XFlush ()> in an C<ev_prepare>\nwatcher).\n\nThis is done by examining in each prepare call which file descriptors\nneed to be watched by the other library, registering C<ev_io> watchers\nfor them and starting an C<ev_timer> watcher for any timeouts (many\nlibraries provide exactly this functionality). Then, in the check watcher,\nyou check for any events that occurred (by checking the pending status\nof all watchers and stopping them) and call back into the library. The\nI/O and timer callbacks will never actually be called (but must be valid\nnevertheless, because you never know, you know?).\n\nAs another example, the Perl Coro module uses these hooks to integrate\ncoroutines into libev programs, by yielding to other active coroutines\nduring each prepare and only letting the process block if no coroutines\nare ready to run (it's actually more complicated: it only runs coroutines\nwith priority higher than or equal to the event loop and one coroutine\nof lower priority, but only once, using idle watchers to keep the event\nloop from blocking if lower-priority coroutines are active, thus mapping\nlow-priority coroutines to idle/background tasks).\n\nWhen used for this purpose, it is recommended to give C<ev_check> watchers\nhighest (C<EV_MAXPRI>) priority, to ensure that they are being run before\nany other watchers after the poll (this doesn't matter for C<ev_prepare>\nwatchers).\n\nAlso, C<ev_check> watchers (and C<ev_prepare> watchers, too) should not\nactivate (\"feed\") events into libev. While libev fully supports this, they\nmight get executed before other C<ev_check> watchers did their job. As\nC<ev_check> watchers are often used to embed other (non-libev) event\nloops those other event loops might be in an unusable state until their\nC<ev_check> watcher ran (always remind yourself to coexist peacefully with\nothers).\n\n=head3 Abusing an C<ev_check> watcher for its side-effect\n\nC<ev_check> (and less often also C<ev_prepare>) watchers can also be\nuseful because they are called once per event loop iteration. For\nexample, if you want to handle a large number of connections fairly, you\nnormally only do a bit of work for each active connection, and if there\nis more work to do, you wait for the next event loop iteration, so other\nconnections have a chance of making progress.\n\nUsing an C<ev_check> watcher is almost enough: it will be called on the\nnext event loop iteration. However, that isn't as soon as possible -\nwithout external events, your C<ev_check> watcher will not be invoked.\n\nThis is where C<ev_idle> watchers come in handy - all you need is a\nsingle global idle watcher that is active as long as you have one active\nC<ev_check> watcher. The C<ev_idle> watcher makes sure the event loop\nwill not sleep, and the C<ev_check> watcher makes sure a callback gets\ninvoked. Neither watcher alone can do that.\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_prepare_init (ev_prepare *, callback)\n\n=item ev_check_init (ev_check *, callback)\n\nInitialises and configures the prepare or check watcher - they have no\nparameters of any kind. There are C<ev_prepare_set> and C<ev_check_set>\nmacros, but using them is utterly, utterly, utterly and completely\npointless.\n\n=back\n\n=head3 Examples\n\nThere are a number of principal ways to embed other event loops or modules\ninto libev. Here are some ideas on how to include libadns into libev\n(there is a Perl module named C<EV::ADNS> that does this, which you could\nuse as a working example. Another Perl module named C<EV::Glib> embeds a\nGlib main context into libev, and finally, C<Glib::EV> embeds EV into the\nGlib event loop).\n\nMethod 1: Add IO watchers and a timeout watcher in a prepare handler,\nand in a check watcher, destroy them and call into libadns. What follows\nis pseudo-code only of course. This requires you to either use a low\npriority for the check watcher or use C<ev_clear_pending> explicitly, as\nthe callbacks for the IO/timeout watchers might not have been called yet.\n\n   static ev_io iow [nfd];\n   static ev_timer tw;\n\n   static void\n   io_cb (struct ev_loop *loop, ev_io *w, int revents)\n   {\n   }\n\n   // create io watchers for each fd and a timer before blocking\n   static void\n   adns_prepare_cb (struct ev_loop *loop, ev_prepare *w, int revents)\n   {\n     int timeout = 3600000;\n     struct pollfd fds [nfd];\n     // actual code will need to loop here and realloc etc.\n     adns_beforepoll (ads, fds, &nfd, &timeout, timeval_from (ev_time ()));\n\n     /* the callback is illegal, but won't be called as we stop during check */\n     ev_timer_init (&tw, 0, timeout * 1e-3, 0.);\n     ev_timer_start (loop, &tw);\n\n     // create one ev_io per pollfd\n     for (int i = 0; i < nfd; ++i)\n       {\n         ev_io_init (iow + i, io_cb, fds [i].fd,\n           ((fds [i].events & POLLIN ? EV_READ : 0)\n            | (fds [i].events & POLLOUT ? EV_WRITE : 0)));\n\n         fds [i].revents = 0;\n         ev_io_start (loop, iow + i);\n       }\n   }\n\n   // stop all watchers after blocking\n   static void\n   adns_check_cb (struct ev_loop *loop, ev_check *w, int revents)\n   {\n     ev_timer_stop (loop, &tw);\n\n     for (int i = 0; i < nfd; ++i)\n       {\n         // set the relevant poll flags\n         // could also call adns_processreadable etc. here\n         struct pollfd *fd = fds + i;\n         int revents = ev_clear_pending (iow + i);\n         if (revents & EV_READ ) fd->revents |= fd->events & POLLIN;\n         if (revents & EV_WRITE) fd->revents |= fd->events & POLLOUT;\n\n         // now stop the watcher\n         ev_io_stop (loop, iow + i);\n       }\n\n     adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop));\n   }\n\nMethod 2: This would be just like method 1, but you run C<adns_afterpoll>\nin the prepare watcher and would dispose of the check watcher.\n\nMethod 3: If the module to be embedded supports explicit event\nnotification (libadns does), you can also make use of the actual watcher\ncallbacks, and only destroy/create the watchers in the prepare watcher.\n\n   static void\n   timer_cb (EV_P_ ev_timer *w, int revents)\n   {\n     adns_state ads = (adns_state)w->data;\n     update_now (EV_A);\n\n     adns_processtimeouts (ads, &tv_now);\n   }\n\n   static void\n   io_cb (EV_P_ ev_io *w, int revents)\n   {\n     adns_state ads = (adns_state)w->data;\n     update_now (EV_A);\n\n     if (revents & EV_READ ) adns_processreadable  (ads, w->fd, &tv_now);\n     if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);\n   }\n\n   // do not ever call adns_afterpoll\n\nMethod 4: Do not use a prepare or check watcher because the module you\nwant to embed is not flexible enough to support it. Instead, you can\noverride their poll function. The drawback with this solution is that the\nmain loop is now no longer controllable by EV. The C<Glib::EV> module uses\nthis approach, effectively embedding EV as a client into the horrible\nlibglib event loop.\n\n   static gint\n   event_poll_func (GPollFD *fds, guint nfds, gint timeout)\n   {\n     int got_events = 0;\n\n     for (n = 0; n < nfds; ++n)\n       // create/start io watcher that sets the relevant bits in fds[n] and increment got_events\n\n     if (timeout >= 0)\n       // create/start timer\n\n     // poll\n     ev_run (EV_A_ 0);\n\n     // stop timer again\n     if (timeout >= 0)\n       ev_timer_stop (EV_A_ &to);\n\n     // stop io watchers again - their callbacks should have set\n     for (n = 0; n < nfds; ++n)\n       ev_io_stop (EV_A_ iow [n]);\n\n     return got_events;\n   }\n\n\n=head2 C<ev_embed> - when one backend isn't enough...\n\nThis is a rather advanced watcher type that lets you embed one event loop\ninto another (currently only C<ev_io> events are supported in the embedded\nloop, other types of watchers might be handled in a delayed or incorrect\nfashion and must not be used).\n\nThere are primarily two reasons you would want that: work around bugs and\nprioritise I/O.\n\nAs an example for a bug workaround, the kqueue backend might only support\nsockets on some platform, so it is unusable as generic backend, but you\nstill want to make use of it because you have many sockets and it scales\nso nicely. In this case, you would create a kqueue-based loop and embed\nit into your default loop (which might use e.g. poll). Overall operation\nwill be a bit slower because first libev has to call C<poll> and then\nC<kevent>, but at least you can use both mechanisms for what they are\nbest: C<kqueue> for scalable sockets and C<poll> if you want it to work :)\n\nAs for prioritising I/O: under rare circumstances you have the case where\nsome fds have to be watched and handled very quickly (with low latency),\nand even priorities and idle watchers might have too much overhead. In\nthis case you would put all the high priority stuff in one loop and all\nthe rest in a second one, and embed the second one in the first.\n\nAs long as the watcher is active, the callback will be invoked every\ntime there might be events pending in the embedded loop. The callback\nmust then call C<ev_embed_sweep (mainloop, watcher)> to make a single\nsweep and invoke their callbacks (the callback doesn't need to invoke the\nC<ev_embed_sweep> function directly, it could also start an idle watcher\nto give the embedded loop strictly lower priority for example).\n\nYou can also set the callback to C<0>, in which case the embed watcher\nwill automatically execute the embedded loop sweep whenever necessary.\n\nFork detection will be handled transparently while the C<ev_embed> watcher\nis active, i.e., the embedded loop will automatically be forked when the\nembedding loop forks. In other cases, the user is responsible for calling\nC<ev_loop_fork> on the embedded loop.\n\nUnfortunately, not all backends are embeddable: only the ones returned by\nC<ev_embeddable_backends> are, which, unfortunately, does not include any\nportable one.\n\nSo when you want to use this feature you will always have to be prepared\nthat you cannot get an embeddable loop. The recommended way to get around\nthis is to have a separate variables for your embeddable loop, try to\ncreate it, and if that fails, use the normal loop for everything.\n\n=head3 C<ev_embed> and fork\n\nWhile the C<ev_embed> watcher is running, forks in the embedding loop will\nautomatically be applied to the embedded loop as well, so no special\nfork handling is required in that case. When the watcher is not running,\nhowever, it is still the task of the libev user to call C<ev_loop_fork ()>\nas applicable.\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_embed_init (ev_embed *, callback, struct ev_loop *embedded_loop)\n\n=item ev_embed_set (ev_embed *, struct ev_loop *embedded_loop)\n\nConfigures the watcher to embed the given loop, which must be\nembeddable. If the callback is C<0>, then C<ev_embed_sweep> will be\ninvoked automatically, otherwise it is the responsibility of the callback\nto invoke it (it will continue to be called until the sweep has been done,\nif you do not want that, you need to temporarily stop the embed watcher).\n\n=item ev_embed_sweep (loop, ev_embed *)\n\nMake a single, non-blocking sweep over the embedded loop. This works\nsimilarly to C<ev_run (embedded_loop, EVRUN_NOWAIT)>, but in the most\nappropriate way for embedded loops.\n\n=item struct ev_loop *other [read-only]\n\nThe embedded event loop.\n\n=back\n\n=head3 Examples\n\nExample: Try to get an embeddable event loop and embed it into the default\nevent loop. If that is not possible, use the default loop. The default\nloop is stored in C<loop_hi>, while the embeddable loop is stored in\nC<loop_lo> (which is C<loop_hi> in the case no embeddable loop can be\nused).\n\n   struct ev_loop *loop_hi = ev_default_init (0);\n   struct ev_loop *loop_lo = 0;\n   ev_embed embed;\n\n   // see if there is a chance of getting one that works\n   // (remember that a flags value of 0 means autodetection)\n   loop_lo = ev_embeddable_backends () & ev_recommended_backends ()\n     ? ev_loop_new (ev_embeddable_backends () & ev_recommended_backends ())\n     : 0;\n\n   // if we got one, then embed it, otherwise default to loop_hi\n   if (loop_lo)\n     {\n       ev_embed_init (&embed, 0, loop_lo);\n       ev_embed_start (loop_hi, &embed);\n     }\n   else\n     loop_lo = loop_hi;\n\nExample: Check if kqueue is available but not recommended and create\na kqueue backend for use with sockets (which usually work with any\nkqueue implementation). Store the kqueue/socket-only event loop in\nC<loop_socket>. (One might optionally use C<EVFLAG_NOENV>, too).\n\n   struct ev_loop *loop = ev_default_init (0);\n   struct ev_loop *loop_socket = 0;\n   ev_embed embed;\n\n   if (ev_supported_backends () & ~ev_recommended_backends () & EVBACKEND_KQUEUE)\n     if ((loop_socket = ev_loop_new (EVBACKEND_KQUEUE))\n       {\n         ev_embed_init (&embed, 0, loop_socket);\n         ev_embed_start (loop, &embed);\n       }\n\n   if (!loop_socket)\n     loop_socket = loop;\n\n   // now use loop_socket for all sockets, and loop for everything else\n\n\n=head2 C<ev_fork> - the audacity to resume the event loop after a fork\n\nFork watchers are called when a C<fork ()> was detected (usually because\nwhoever is a good citizen cared to tell libev about it by calling\nC<ev_loop_fork>). The invocation is done before the event loop blocks next\nand before C<ev_check> watchers are being called, and only in the child\nafter the fork. If whoever good citizen calling C<ev_default_fork> cheats\nand calls it in the wrong process, the fork handlers will be invoked, too,\nof course.\n\n=head3 The special problem of life after fork - how is it possible?\n\nMost uses of C<fork ()> consist of forking, then some simple calls to set\nup/change the process environment, followed by a call to C<exec()>. This\nsequence should be handled by libev without any problems.\n\nThis changes when the application actually wants to do event handling\nin the child, or both parent in child, in effect \"continuing\" after the\nfork.\n\nThe default mode of operation (for libev, with application help to detect\nforks) is to duplicate all the state in the child, as would be expected\nwhen I<either> the parent I<or> the child process continues.\n\nWhen both processes want to continue using libev, then this is usually the\nwrong result. In that case, usually one process (typically the parent) is\nsupposed to continue with all watchers in place as before, while the other\nprocess typically wants to start fresh, i.e. without any active watchers.\n\nThe cleanest and most efficient way to achieve that with libev is to\nsimply create a new event loop, which of course will be \"empty\", and\nuse that for new watchers. This has the advantage of not touching more\nmemory than necessary, and thus avoiding the copy-on-write, and the\ndisadvantage of having to use multiple event loops (which do not support\nsignal watchers).\n\nWhen this is not possible, or you want to use the default loop for\nother reasons, then in the process that wants to start \"fresh\", call\nC<ev_loop_destroy (EV_DEFAULT)> followed by C<ev_default_loop (...)>.\nDestroying the default loop will \"orphan\" (not stop) all registered\nwatchers, so you have to be careful not to execute code that modifies\nthose watchers. Note also that in that case, you have to re-register any\nsignal watchers.\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_fork_init (ev_fork *, callback)\n\nInitialises and configures the fork watcher - it has no parameters of any\nkind. There is a C<ev_fork_set> macro, but using it is utterly pointless,\nreally.\n\n=back\n\n\n=head2 C<ev_cleanup> - even the best things end\n\nCleanup watchers are called just before the event loop is being destroyed\nby a call to C<ev_loop_destroy>.\n\nWhile there is no guarantee that the event loop gets destroyed, cleanup\nwatchers provide a convenient method to install cleanup hooks for your\nprogram, worker threads and so on - you just to make sure to destroy the\nloop when you want them to be invoked.\n\nCleanup watchers are invoked in the same way as any other watcher. Unlike\nall other watchers, they do not keep a reference to the event loop (which\nmakes a lot of sense if you think about it). Like all other watchers, you\ncan call libev functions in the callback, except C<ev_cleanup_start>.\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_cleanup_init (ev_cleanup *, callback)\n\nInitialises and configures the cleanup watcher - it has no parameters of\nany kind. There is a C<ev_cleanup_set> macro, but using it is utterly\npointless, I assure you.\n\n=back\n\nExample: Register an atexit handler to destroy the default loop, so any\ncleanup functions are called.\n\n   static void\n   program_exits (void)\n   {\n     ev_loop_destroy (EV_DEFAULT_UC);\n   }\n\n   ...\n   atexit (program_exits);\n\n\n=head2 C<ev_async> - how to wake up an event loop\n\nIn general, you cannot use an C<ev_loop> from multiple threads or other\nasynchronous sources such as signal handlers (as opposed to multiple event\nloops - those are of course safe to use in different threads).\n\nSometimes, however, you need to wake up an event loop you do not control,\nfor example because it belongs to another thread. This is what C<ev_async>\nwatchers do: as long as the C<ev_async> watcher is active, you can signal\nit by calling C<ev_async_send>, which is thread- and signal safe.\n\nThis functionality is very similar to C<ev_signal> watchers, as signals,\ntoo, are asynchronous in nature, and signals, too, will be compressed\n(i.e. the number of callback invocations may be less than the number of\nC<ev_async_send> calls). In fact, you could use signal watchers as a kind\nof \"global async watchers\" by using a watcher on an otherwise unused\nsignal, and C<ev_feed_signal> to signal this watcher from another thread,\neven without knowing which loop owns the signal.\n\n=head3 Queueing\n\nC<ev_async> does not support queueing of data in any way. The reason\nis that the author does not know of a simple (or any) algorithm for a\nmultiple-writer-single-reader queue that works in all cases and doesn't\nneed elaborate support such as pthreads or unportable memory access\nsemantics.\n\nThat means that if you want to queue data, you have to provide your own\nqueue. But at least I can tell you how to implement locking around your\nqueue:\n\n=over 4\n\n=item queueing from a signal handler context\n\nTo implement race-free queueing, you simply add to the queue in the signal\nhandler but you block the signal handler in the watcher callback. Here is\nan example that does that for some fictitious SIGUSR1 handler:\n\n   static ev_async mysig;\n\n   static void\n   sigusr1_handler (void)\n   {\n     sometype data;\n\n     // no locking etc.\n     queue_put (data);\n     ev_async_send (EV_DEFAULT_ &mysig);\n   }\n\n   static void\n   mysig_cb (EV_P_ ev_async *w, int revents)\n   {\n     sometype data;\n     sigset_t block, prev;\n\n     sigemptyset (&block);\n     sigaddset (&block, SIGUSR1);\n     sigprocmask (SIG_BLOCK, &block, &prev);\n\n     while (queue_get (&data))\n       process (data);\n\n     if (sigismember (&prev, SIGUSR1)\n       sigprocmask (SIG_UNBLOCK, &block, 0);\n   }\n\n(Note: pthreads in theory requires you to use C<pthread_setmask>\ninstead of C<sigprocmask> when you use threads, but libev doesn't do it\neither...).\n\n=item queueing from a thread context\n\nThe strategy for threads is different, as you cannot (easily) block\nthreads but you can easily preempt them, so to queue safely you need to\nemploy a traditional mutex lock, such as in this pthread example:\n\n   static ev_async mysig;\n   static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;\n\n   static void\n   otherthread (void)\n   {\n     // only need to lock the actual queueing operation\n     pthread_mutex_lock (&mymutex);\n     queue_put (data);\n     pthread_mutex_unlock (&mymutex);\n\n     ev_async_send (EV_DEFAULT_ &mysig);\n   }\n\n   static void\n   mysig_cb (EV_P_ ev_async *w, int revents)\n   {\n     pthread_mutex_lock (&mymutex);\n\n     while (queue_get (&data))\n       process (data);\n\n     pthread_mutex_unlock (&mymutex);\n   }\n\n=back\n\n\n=head3 Watcher-Specific Functions and Data Members\n\n=over 4\n\n=item ev_async_init (ev_async *, callback)\n\nInitialises and configures the async watcher - it has no parameters of any\nkind. There is a C<ev_async_set> macro, but using it is utterly pointless,\ntrust me.\n\n=item ev_async_send (loop, ev_async *)\n\nSends/signals/activates the given C<ev_async> watcher, that is, feeds\nan C<EV_ASYNC> event on the watcher into the event loop, and instantly\nreturns.\n\nUnlike C<ev_feed_event>, this call is safe to do from other threads,\nsignal or similar contexts (see the discussion of C<EV_ATOMIC_T> in the\nembedding section below on what exactly this means).\n\nNote that, as with other watchers in libev, multiple events might get\ncompressed into a single callback invocation (another way to look at\nthis is that C<ev_async> watchers are level-triggered: they are set on\nC<ev_async_send>, reset when the event loop detects that).\n\nThis call incurs the overhead of at most one extra system call per event\nloop iteration, if the event loop is blocked, and no syscall at all if\nthe event loop (or your program) is processing events. That means that\nrepeated calls are basically free (there is no need to avoid calls for\nperformance reasons) and that the overhead becomes smaller (typically\nzero) under load.\n\n=item bool = ev_async_pending (ev_async *)\n\nReturns a non-zero value when C<ev_async_send> has been called on the\nwatcher but the event has not yet been processed (or even noted) by the\nevent loop.\n\nC<ev_async_send> sets a flag in the watcher and wakes up the loop. When\nthe loop iterates next and checks for the watcher to have become active,\nit will reset the flag again. C<ev_async_pending> can be used to very\nquickly check whether invoking the loop might be a good idea.\n\nNot that this does I<not> check whether the watcher itself is pending,\nonly whether it has been requested to make this watcher pending: there\nis a time window between the event loop checking and resetting the async\nnotification, and the callback being invoked.\n\n=back\n\n\n=head1 OTHER FUNCTIONS\n\nThere are some other functions of possible interest. Described. Here. Now.\n\n=over 4\n\n=item ev_once (loop, int fd, int events, ev_tstamp timeout, callback)\n\nThis function combines a simple timer and an I/O watcher, calls your\ncallback on whichever event happens first and automatically stops both\nwatchers. This is useful if you want to wait for a single event on an fd\nor timeout without having to allocate/configure/start/stop/free one or\nmore watchers yourself.\n\nIf C<fd> is less than 0, then no I/O watcher will be started and the\nC<events> argument is being ignored. Otherwise, an C<ev_io> watcher for\nthe given C<fd> and C<events> set will be created and started.\n\nIf C<timeout> is less than 0, then no timeout watcher will be\nstarted. Otherwise an C<ev_timer> watcher with after = C<timeout> (and\nrepeat = 0) will be started. C<0> is a valid timeout.\n\nThe callback has the type C<void (*cb)(int revents, void *arg)> and is\npassed an C<revents> set like normal event callbacks (a combination of\nC<EV_ERROR>, C<EV_READ>, C<EV_WRITE> or C<EV_TIMER>) and the C<arg>\nvalue passed to C<ev_once>. Note that it is possible to receive I<both>\na timeout and an io event at the same time - you probably should give io\nevents precedence.\n\nExample: wait up to ten seconds for data to appear on STDIN_FILENO.\n\n   static void stdin_ready (int revents, void *arg)\n   {\n     if (revents & EV_READ)\n       /* stdin might have data for us, joy! */;\n     else if (revents & EV_TIMER)\n       /* doh, nothing entered */;\n   }\n\n   ev_once (STDIN_FILENO, EV_READ, 10., stdin_ready, 0);\n\n=item ev_feed_fd_event (loop, int fd, int revents)\n\nFeed an event on the given fd, as if a file descriptor backend detected\nthe given events.\n\n=item ev_feed_signal_event (loop, int signum)\n\nFeed an event as if the given signal occurred. See also C<ev_feed_signal>,\nwhich is async-safe.\n\n=back\n\n\n=head1 COMMON OR USEFUL IDIOMS (OR BOTH)\n\nThis section explains some common idioms that are not immediately\nobvious. Note that examples are sprinkled over the whole manual, and this\nsection only contains stuff that wouldn't fit anywhere else.\n\n=head2 ASSOCIATING CUSTOM DATA WITH A WATCHER\n\nEach watcher has, by default, a C<void *data> member that you can read\nor modify at any time: libev will completely ignore it. This can be used\nto associate arbitrary data with your watcher. If you need more data and\ndon't want to allocate memory separately and store a pointer to it in that\ndata member, you can also \"subclass\" the watcher type and provide your own\ndata:\n\n   struct my_io\n   {\n     ev_io io;\n     int otherfd;\n     void *somedata;\n     struct whatever *mostinteresting;\n   };\n\n   ...\n   struct my_io w;\n   ev_io_init (&w.io, my_cb, fd, EV_READ);\n\nAnd since your callback will be called with a pointer to the watcher, you\ncan cast it back to your own type:\n\n   static void my_cb (struct ev_loop *loop, ev_io *w_, int revents)\n   {\n     struct my_io *w = (struct my_io *)w_;\n     ...\n   }\n\nMore interesting and less C-conformant ways of casting your callback\nfunction type instead have been omitted.\n\n=head2 BUILDING YOUR OWN COMPOSITE WATCHERS\n\nAnother common scenario is to use some data structure with multiple\nembedded watchers, in effect creating your own watcher that combines\nmultiple libev event sources into one \"super-watcher\":\n\n   struct my_biggy\n   {\n     int some_data;\n     ev_timer t1;\n     ev_timer t2;\n   }\n\nIn this case getting the pointer to C<my_biggy> is a bit more\ncomplicated: Either you store the address of your C<my_biggy> struct in\nthe C<data> member of the watcher (for woozies or C++ coders), or you need\nto use some pointer arithmetic using C<offsetof> inside your watchers (for\nreal programmers):\n\n   #include <stddef.h>\n\n   static void\n   t1_cb (EV_P_ ev_timer *w, int revents)\n   {\n     struct my_biggy big = (struct my_biggy *)\n       (((char *)w) - offsetof (struct my_biggy, t1));\n   }\n\n   static void\n   t2_cb (EV_P_ ev_timer *w, int revents)\n   {\n     struct my_biggy big = (struct my_biggy *)\n       (((char *)w) - offsetof (struct my_biggy, t2));\n   }\n\n=head2 AVOIDING FINISHING BEFORE RETURNING\n\nOften you have structures like this in event-based programs:\n\n  callback ()\n  {\n    free (request);\n  }\n\n  request = start_new_request (..., callback);\n\nThe intent is to start some \"lengthy\" operation. The C<request> could be\nused to cancel the operation, or do other things with it.\n\nIt's not uncommon to have code paths in C<start_new_request> that\nimmediately invoke the callback, for example, to report errors. Or you add\nsome caching layer that finds that it can skip the lengthy aspects of the\noperation and simply invoke the callback with the result.\n\nThe problem here is that this will happen I<before> C<start_new_request>\nhas returned, so C<request> is not set.\n\nEven if you pass the request by some safer means to the callback, you\nmight want to do something to the request after starting it, such as\ncanceling it, which probably isn't working so well when the callback has\nalready been invoked.\n\nA common way around all these issues is to make sure that\nC<start_new_request> I<always> returns before the callback is invoked. If\nC<start_new_request> immediately knows the result, it can artificially\ndelay invoking the callback by using a C<prepare> or C<idle> watcher for\nexample, or more sneakily, by reusing an existing (stopped) watcher and\npushing it into the pending queue:\n\n   ev_set_cb (watcher, callback);\n   ev_feed_event (EV_A_ watcher, 0);\n\nThis way, C<start_new_request> can safely return before the callback is\ninvoked, while not delaying callback invocation too much.\n\n=head2 MODEL/NESTED EVENT LOOP INVOCATIONS AND EXIT CONDITIONS\n\nOften (especially in GUI toolkits) there are places where you have\nI<modal> interaction, which is most easily implemented by recursively\ninvoking C<ev_run>.\n\nThis brings the problem of exiting - a callback might want to finish the\nmain C<ev_run> call, but not the nested one (e.g. user clicked \"Quit\", but\na modal \"Are you sure?\" dialog is still waiting), or just the nested one\nand not the main one (e.g. user clocked \"Ok\" in a modal dialog), or some\nother combination: In these cases, a simple C<ev_break> will not work.\n\nThe solution is to maintain \"break this loop\" variable for each C<ev_run>\ninvocation, and use a loop around C<ev_run> until the condition is\ntriggered, using C<EVRUN_ONCE>:\n\n   // main loop\n   int exit_main_loop = 0;\n\n   while (!exit_main_loop)\n     ev_run (EV_DEFAULT_ EVRUN_ONCE);\n\n   // in a modal watcher\n   int exit_nested_loop = 0;\n\n   while (!exit_nested_loop)\n     ev_run (EV_A_ EVRUN_ONCE);\n\nTo exit from any of these loops, just set the corresponding exit variable:\n\n   // exit modal loop\n   exit_nested_loop = 1;\n\n   // exit main program, after modal loop is finished\n   exit_main_loop = 1;\n\n   // exit both\n   exit_main_loop = exit_nested_loop = 1;\n\n=head2 THREAD LOCKING EXAMPLE\n\nHere is a fictitious example of how to run an event loop in a different\nthread from where callbacks are being invoked and watchers are\ncreated/added/removed.\n\nFor a real-world example, see the C<EV::Loop::Async> perl module,\nwhich uses exactly this technique (which is suited for many high-level\nlanguages).\n\nThe example uses a pthread mutex to protect the loop data, a condition\nvariable to wait for callback invocations, an async watcher to notify the\nevent loop thread and an unspecified mechanism to wake up the main thread.\n\nFirst, you need to associate some data with the event loop:\n\n   typedef struct {\n     mutex_t lock; /* global loop lock */\n     ev_async async_w;\n     thread_t tid;\n     cond_t invoke_cv;\n   } userdata;\n\n   void prepare_loop (EV_P)\n   {\n      // for simplicity, we use a static userdata struct.\n      static userdata u;\n\n      ev_async_init (&u->async_w, async_cb);\n      ev_async_start (EV_A_ &u->async_w);\n\n      pthread_mutex_init (&u->lock, 0);\n      pthread_cond_init (&u->invoke_cv, 0);\n\n      // now associate this with the loop\n      ev_set_userdata (EV_A_ u);\n      ev_set_invoke_pending_cb (EV_A_ l_invoke);\n      ev_set_loop_release_cb (EV_A_ l_release, l_acquire);\n\n      // then create the thread running ev_run\n      pthread_create (&u->tid, 0, l_run, EV_A);\n   }\n\nThe callback for the C<ev_async> watcher does nothing: the watcher is used\nsolely to wake up the event loop so it takes notice of any new watchers\nthat might have been added:\n\n   static void\n   async_cb (EV_P_ ev_async *w, int revents)\n   {\n      // just used for the side effects\n   }\n\nThe C<l_release> and C<l_acquire> callbacks simply unlock/lock the mutex\nprotecting the loop data, respectively.\n\n   static void\n   l_release (EV_P)\n   {\n     userdata *u = ev_userdata (EV_A);\n     pthread_mutex_unlock (&u->lock);\n   }\n\n   static void\n   l_acquire (EV_P)\n   {\n     userdata *u = ev_userdata (EV_A);\n     pthread_mutex_lock (&u->lock);\n   }\n\nThe event loop thread first acquires the mutex, and then jumps straight\ninto C<ev_run>:\n\n   void *\n   l_run (void *thr_arg)\n   {\n     struct ev_loop *loop = (struct ev_loop *)thr_arg;\n\n     l_acquire (EV_A);\n     pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);\n     ev_run (EV_A_ 0);\n     l_release (EV_A);\n\n     return 0;\n   }\n\nInstead of invoking all pending watchers, the C<l_invoke> callback will\nsignal the main thread via some unspecified mechanism (signals? pipe\nwrites? C<Async::Interrupt>?) and then waits until all pending watchers\nhave been called (in a while loop because a) spurious wakeups are possible\nand b) skipping inter-thread-communication when there are no pending\nwatchers is very beneficial):\n\n   static void\n   l_invoke (EV_P)\n   {\n     userdata *u = ev_userdata (EV_A);\n\n     while (ev_pending_count (EV_A))\n       {\n         wake_up_other_thread_in_some_magic_or_not_so_magic_way ();\n         pthread_cond_wait (&u->invoke_cv, &u->lock);\n       }\n   }\n\nNow, whenever the main thread gets told to invoke pending watchers, it\nwill grab the lock, call C<ev_invoke_pending> and then signal the loop\nthread to continue:\n\n   static void\n   real_invoke_pending (EV_P)\n   {\n     userdata *u = ev_userdata (EV_A);\n\n     pthread_mutex_lock (&u->lock);\n     ev_invoke_pending (EV_A);\n     pthread_cond_signal (&u->invoke_cv);\n     pthread_mutex_unlock (&u->lock);\n   }\n\nWhenever you want to start/stop a watcher or do other modifications to an\nevent loop, you will now have to lock:\n\n   ev_timer timeout_watcher;\n   userdata *u = ev_userdata (EV_A);\n\n   ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);\n\n   pthread_mutex_lock (&u->lock);\n   ev_timer_start (EV_A_ &timeout_watcher);\n   ev_async_send (EV_A_ &u->async_w);\n   pthread_mutex_unlock (&u->lock);\n\nNote that sending the C<ev_async> watcher is required because otherwise\nan event loop currently blocking in the kernel will have no knowledge\nabout the newly added timer. By waking up the loop it will pick up any new\nwatchers in the next event loop iteration.\n\n=head2 THREADS, COROUTINES, CONTINUATIONS, QUEUES... INSTEAD OF CALLBACKS\n\nWhile the overhead of a callback that e.g. schedules a thread is small, it\nis still an overhead. If you embed libev, and your main usage is with some\nkind of threads or coroutines, you might want to customise libev so that\ndoesn't need callbacks anymore.\n\nImagine you have coroutines that you can switch to using a function\nC<switch_to (coro)>, that libev runs in a coroutine called C<libev_coro>\nand that due to some magic, the currently active coroutine is stored in a\nglobal called C<current_coro>. Then you can build your own \"wait for libev\nevent\" primitive by changing C<EV_CB_DECLARE> and C<EV_CB_INVOKE> (note\nthe differing C<;> conventions):\n\n   #define EV_CB_DECLARE(type)   struct my_coro *cb;\n   #define EV_CB_INVOKE(watcher) switch_to ((watcher)->cb)\n\nThat means instead of having a C callback function, you store the\ncoroutine to switch to in each watcher, and instead of having libev call\nyour callback, you instead have it switch to that coroutine.\n\nA coroutine might now wait for an event with a function called\nC<wait_for_event>. (the watcher needs to be started, as always, but it doesn't\nmatter when, or whether the watcher is active or not when this function is\ncalled):\n\n   void\n   wait_for_event (ev_watcher *w)\n   {\n     ev_set_cb (w, current_coro);\n     switch_to (libev_coro);\n   }\n\nThat basically suspends the coroutine inside C<wait_for_event> and\ncontinues the libev coroutine, which, when appropriate, switches back to\nthis or any other coroutine.\n\nYou can do similar tricks if you have, say, threads with an event queue -\ninstead of storing a coroutine, you store the queue object and instead of\nswitching to a coroutine, you push the watcher onto the queue and notify\nany waiters.\n\nTo embed libev, see L</EMBEDDING>, but in short, it's easiest to create two\nfiles, F<my_ev.h> and F<my_ev.c> that include the respective libev files:\n\n   // my_ev.h\n   #define EV_CB_DECLARE(type)   struct my_coro *cb;\n   #define EV_CB_INVOKE(watcher) switch_to ((watcher)->cb)\n   #include \"../libev/ev.h\"\n\n   // my_ev.c\n   #define EV_H \"my_ev.h\"\n   #include \"../libev/ev.c\"\n\nAnd then use F<my_ev.h> when you would normally use F<ev.h>, and compile\nF<my_ev.c> into your project. When properly specifying include paths, you\ncan even use F<ev.h> as header file name directly.\n\n\n=head1 LIBEVENT EMULATION\n\nLibev offers a compatibility emulation layer for libevent. It cannot\nemulate the internals of libevent, so here are some usage hints:\n\n=over 4\n\n=item * Only the libevent-1.4.1-beta API is being emulated.\n\nThis was the newest libevent version available when libev was implemented,\nand is still mostly unchanged in 2010.\n\n=item * Use it by including <event.h>, as usual.\n\n=item * The following members are fully supported: ev_base, ev_callback,\nev_arg, ev_fd, ev_res, ev_events.\n\n=item * Avoid using ev_flags and the EVLIST_*-macros, while it is\nmaintained by libev, it does not work exactly the same way as in libevent (consider\nit a private API).\n\n=item * Priorities are not currently supported. Initialising priorities\nwill fail and all watchers will have the same priority, even though there\nis an ev_pri field.\n\n=item * In libevent, the last base created gets the signals, in libev, the\nbase that registered the signal gets the signals.\n\n=item * Other members are not supported.\n\n=item * The libev emulation is I<not> ABI compatible to libevent, you need\nto use the libev header file and library.\n\n=back\n\n=head1 C++ SUPPORT\n\n=head2 C API\n\nThe normal C API should work fine when used from C++: both ev.h and the\nlibev sources can be compiled as C++. Therefore, code that uses the C API\nwill work fine.\n\nProper exception specifications might have to be added to callbacks passed\nto libev: exceptions may be thrown only from watcher callbacks, all\nother callbacks (allocator, syserr, loop acquire/release and periodic\nreschedule callbacks) must not throw exceptions, and might need a C<throw\n()> specification. If you have code that needs to be compiled as both C\nand C++ you can use the C<EV_THROW> macro for this:\n\n   static void\n   fatal_error (const char *msg) EV_THROW\n   {\n     perror (msg);\n     abort ();\n   }\n\n   ...\n   ev_set_syserr_cb (fatal_error);\n\nThe only API functions that can currently throw exceptions are C<ev_run>,\nC<ev_invoke>, C<ev_invoke_pending> and C<ev_loop_destroy> (the latter\nbecause it runs cleanup watchers).\n\nThrowing exceptions in watcher callbacks is only supported if libev itself\nis compiled with a C++ compiler or your C and C++ environments allow\nthrowing exceptions through C libraries (most do).\n\n=head2 C++ API\n\nLibev comes with some simplistic wrapper classes for C++ that mainly allow\nyou to use some convenience methods to start/stop watchers and also change\nthe callback model to a model using method callbacks on objects.\n\nTo use it,\n\n   #include <ev++.h>\n\nThis automatically includes F<ev.h> and puts all of its definitions (many\nof them macros) into the global namespace. All C++ specific things are\nput into the C<ev> namespace. It should support all the same embedding\noptions as F<ev.h>, most notably C<EV_MULTIPLICITY>.\n\nCare has been taken to keep the overhead low. The only data member the C++\nclasses add (compared to plain C-style watchers) is the event loop pointer\nthat the watcher is associated with (or no additional members at all if\nyou disable C<EV_MULTIPLICITY> when embedding libev).\n\nCurrently, functions, static and non-static member functions and classes\nwith C<operator ()> can be used as callbacks. Other types should be easy\nto add as long as they only need one additional pointer for context. If\nyou need support for other types of functors please contact the author\n(preferably after implementing it).\n\nFor all this to work, your C++ compiler either has to use the same calling\nconventions as your C compiler (for static member functions), or you have\nto embed libev and compile libev itself as C++.\n\nHere is a list of things available in the C<ev> namespace:\n\n=over 4\n\n=item C<ev::READ>, C<ev::WRITE> etc.\n\nThese are just enum values with the same values as the C<EV_READ> etc.\nmacros from F<ev.h>.\n\n=item C<ev::tstamp>, C<ev::now>\n\nAliases to the same types/functions as with the C<ev_> prefix.\n\n=item C<ev::io>, C<ev::timer>, C<ev::periodic>, C<ev::idle>, C<ev::sig> etc.\n\nFor each C<ev_TYPE> watcher in F<ev.h> there is a corresponding class of\nthe same name in the C<ev> namespace, with the exception of C<ev_signal>\nwhich is called C<ev::sig> to avoid clashes with the C<signal> macro\ndefined by many implementations.\n\nAll of those classes have these methods:\n\n=over 4\n\n=item ev::TYPE::TYPE ()\n\n=item ev::TYPE::TYPE (loop)\n\n=item ev::TYPE::~TYPE\n\nThe constructor (optionally) takes an event loop to associate the watcher\nwith. If it is omitted, it will use C<EV_DEFAULT>.\n\nThe constructor calls C<ev_init> for you, which means you have to call the\nC<set> method before starting it.\n\nIt will not set a callback, however: You have to call the templated C<set>\nmethod to set a callback before you can start the watcher.\n\n(The reason why you have to use a method is a limitation in C++ which does\nnot allow explicit template arguments for constructors).\n\nThe destructor automatically stops the watcher if it is active.\n\n=item w->set<class, &class::method> (object *)\n\nThis method sets the callback method to call. The method has to have a\nsignature of C<void (*)(ev_TYPE &, int)>, it receives the watcher as\nfirst argument and the C<revents> as second. The object must be given as\nparameter and is stored in the C<data> member of the watcher.\n\nThis method synthesizes efficient thunking code to call your method from\nthe C callback that libev requires. If your compiler can inline your\ncallback (i.e. it is visible to it at the place of the C<set> call and\nyour compiler is good :), then the method will be fully inlined into the\nthunking function, making it as fast as a direct C callback.\n\nExample: simple class declaration and watcher initialisation\n\n   struct myclass\n   {\n     void io_cb (ev::io &w, int revents) { }\n   }\n\n   myclass obj;\n   ev::io iow;\n   iow.set <myclass, &myclass::io_cb> (&obj);\n\n=item w->set (object *)\n\nThis is a variation of a method callback - leaving out the method to call\nwill default the method to C<operator ()>, which makes it possible to use\nfunctor objects without having to manually specify the C<operator ()> all\nthe time. Incidentally, you can then also leave out the template argument\nlist.\n\nThe C<operator ()> method prototype must be C<void operator ()(watcher &w,\nint revents)>.\n\nSee the method-C<set> above for more details.\n\nExample: use a functor object as callback.\n\n   struct myfunctor\n   {\n     void operator() (ev::io &w, int revents)\n     {\n       ...\n     }\n   }\n\n   myfunctor f;\n\n   ev::io w;\n   w.set (&f);\n\n=item w->set<function> (void *data = 0)\n\nAlso sets a callback, but uses a static method or plain function as\ncallback. The optional C<data> argument will be stored in the watcher's\nC<data> member and is free for you to use.\n\nThe prototype of the C<function> must be C<void (*)(ev::TYPE &w, int)>.\n\nSee the method-C<set> above for more details.\n\nExample: Use a plain function as callback.\n\n   static void io_cb (ev::io &w, int revents) { }\n   iow.set <io_cb> ();\n\n=item w->set (loop)\n\nAssociates a different C<struct ev_loop> with this watcher. You can only\ndo this when the watcher is inactive (and not pending either).\n\n=item w->set ([arguments])\n\nBasically the same as C<ev_TYPE_set> (except for C<ev::embed> watchers>),\nwith the same arguments. Either this method or a suitable start method\nmust be called at least once. Unlike the C counterpart, an active watcher\ngets automatically stopped and restarted when reconfiguring it with this\nmethod.\n\nFor C<ev::embed> watchers this method is called C<set_embed>, to avoid\nclashing with the C<set (loop)> method.\n\n=item w->start ()\n\nStarts the watcher. Note that there is no C<loop> argument, as the\nconstructor already stores the event loop.\n\n=item w->start ([arguments])\n\nInstead of calling C<set> and C<start> methods separately, it is often\nconvenient to wrap them in one call. Uses the same type of arguments as\nthe configure C<set> method of the watcher.\n\n=item w->stop ()\n\nStops the watcher if it is active. Again, no C<loop> argument.\n\n=item w->again () (C<ev::timer>, C<ev::periodic> only)\n\nFor C<ev::timer> and C<ev::periodic>, this invokes the corresponding\nC<ev_TYPE_again> function.\n\n=item w->sweep () (C<ev::embed> only)\n\nInvokes C<ev_embed_sweep>.\n\n=item w->update () (C<ev::stat> only)\n\nInvokes C<ev_stat_stat>.\n\n=back\n\n=back\n\nExample: Define a class with two I/O and idle watchers, start the I/O\nwatchers in the constructor.\n\n   class myclass\n   {\n     ev::io   io  ; void io_cb   (ev::io   &w, int revents);\n     ev::io   io2 ; void io2_cb  (ev::io   &w, int revents);\n     ev::idle idle; void idle_cb (ev::idle &w, int revents);\n\n     myclass (int fd)\n     {\n       io  .set <myclass, &myclass::io_cb  > (this);\n       io2 .set <myclass, &myclass::io2_cb > (this);\n       idle.set <myclass, &myclass::idle_cb> (this);\n\n       io.set (fd, ev::WRITE); // configure the watcher\n       io.start ();            // start it whenever convenient\n\n       io2.start (fd, ev::READ); // set + start in one call\n     }\n   };\n\n\n=head1 OTHER LANGUAGE BINDINGS\n\nLibev does not offer other language bindings itself, but bindings for a\nnumber of languages exist in the form of third-party packages. If you know\nany interesting language binding in addition to the ones listed here, drop\nme a note.\n\n=over 4\n\n=item Perl\n\nThe EV module implements the full libev API and is actually used to test\nlibev. EV is developed together with libev. Apart from the EV core module,\nthere are additional modules that implement libev-compatible interfaces\nto C<libadns> (C<EV::ADNS>, but C<AnyEvent::DNS> is preferred nowadays),\nC<Net::SNMP> (C<Net::SNMP::EV>) and the C<libglib> event core (C<Glib::EV>\nand C<EV::Glib>).\n\nIt can be found and installed via CPAN, its homepage is at\nL<http://software.schmorp.de/pkg/EV>.\n\n=item Python\n\nPython bindings can be found at L<http://code.google.com/p/pyev/>. It\nseems to be quite complete and well-documented.\n\n=item Ruby\n\nTony Arcieri has written a ruby extension that offers access to a subset\nof the libev API and adds file handle abstractions, asynchronous DNS and\nmore on top of it. It can be found via gem servers. Its homepage is at\nL<http://rev.rubyforge.org/>.\n\nRoger Pack reports that using the link order C<-lws2_32 -lmsvcrt-ruby-190>\nmakes rev work even on mingw.\n\n=item Haskell\n\nA haskell binding to libev is available at\nL<http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hlibev>.\n\n=item D\n\nLeandro Lucarella has written a D language binding (F<ev.d>) for libev, to\nbe found at L<http://www.llucax.com.ar/proj/ev.d/index.html>.\n\n=item Ocaml\n\nErkki Seppala has written Ocaml bindings for libev, to be found at\nL<http://modeemi.cs.tut.fi/~flux/software/ocaml-ev/>.\n\n=item Lua\n\nBrian Maher has written a partial interface to libev for lua (at the\ntime of this writing, only C<ev_io> and C<ev_timer>), to be found at\nL<http://github.com/brimworks/lua-ev>.\n\n=item Javascript\n\nNode.js (L<http://nodejs.org>) uses libev as the underlying event library.\n\n=item Others\n\nThere are others, and I stopped counting.\n\n=back\n\n\n=head1 MACRO MAGIC\n\nLibev can be compiled with a variety of options, the most fundamental\nof which is C<EV_MULTIPLICITY>. This option determines whether (most)\nfunctions and callbacks have an initial C<struct ev_loop *> argument.\n\nTo make it easier to write programs that cope with either variant, the\nfollowing macros are defined:\n\n=over 4\n\n=item C<EV_A>, C<EV_A_>\n\nThis provides the loop I<argument> for functions, if one is required (\"ev\nloop argument\"). The C<EV_A> form is used when this is the sole argument,\nC<EV_A_> is used when other arguments are following. Example:\n\n   ev_unref (EV_A);\n   ev_timer_add (EV_A_ watcher);\n   ev_run (EV_A_ 0);\n\nIt assumes the variable C<loop> of type C<struct ev_loop *> is in scope,\nwhich is often provided by the following macro.\n\n=item C<EV_P>, C<EV_P_>\n\nThis provides the loop I<parameter> for functions, if one is required (\"ev\nloop parameter\"). The C<EV_P> form is used when this is the sole parameter,\nC<EV_P_> is used when other parameters are following. Example:\n\n   // this is how ev_unref is being declared\n   static void ev_unref (EV_P);\n\n   // this is how you can declare your typical callback\n   static void cb (EV_P_ ev_timer *w, int revents)\n\nIt declares a parameter C<loop> of type C<struct ev_loop *>, quite\nsuitable for use with C<EV_A>.\n\n=item C<EV_DEFAULT>, C<EV_DEFAULT_>\n\nSimilar to the other two macros, this gives you the value of the default\nloop, if multiple loops are supported (\"ev loop default\"). The default loop\nwill be initialised if it isn't already initialised.\n\nFor non-multiplicity builds, these macros do nothing, so you always have\nto initialise the loop somewhere.\n\n=item C<EV_DEFAULT_UC>, C<EV_DEFAULT_UC_>\n\nUsage identical to C<EV_DEFAULT> and C<EV_DEFAULT_>, but requires that the\ndefault loop has been initialised (C<UC> == unchecked). Their behaviour\nis undefined when the default loop has not been initialised by a previous\nexecution of C<EV_DEFAULT>, C<EV_DEFAULT_> or C<ev_default_init (...)>.\n\nIt is often prudent to use C<EV_DEFAULT> when initialising the first\nwatcher in a function but use C<EV_DEFAULT_UC> afterwards.\n\n=back\n\nExample: Declare and initialise a check watcher, utilising the above\nmacros so it will work regardless of whether multiple loops are supported\nor not.\n\n   static void\n   check_cb (EV_P_ ev_timer *w, int revents)\n   {\n     ev_check_stop (EV_A_ w);\n   }\n\n   ev_check check;\n   ev_check_init (&check, check_cb);\n   ev_check_start (EV_DEFAULT_ &check);\n   ev_run (EV_DEFAULT_ 0);\n\n=head1 EMBEDDING\n\nLibev can (and often is) directly embedded into host\napplications. Examples of applications that embed it include the Deliantra\nGame Server, the EV perl module, the GNU Virtual Private Ethernet (gvpe)\nand rxvt-unicode.\n\nThe goal is to enable you to just copy the necessary files into your\nsource directory without having to change even a single line in them, so\nyou can easily upgrade by simply copying (or having a checked-out copy of\nlibev somewhere in your source tree).\n\n=head2 FILESETS\n\nDepending on what features you need you need to include one or more sets of files\nin your application.\n\n=head3 CORE EVENT LOOP\n\nTo include only the libev core (all the C<ev_*> functions), with manual\nconfiguration (no autoconf):\n\n   #define EV_STANDALONE 1\n   #include \"ev.c\"\n\nThis will automatically include F<ev.h>, too, and should be done in a\nsingle C source file only to provide the function implementations. To use\nit, do the same for F<ev.h> in all files wishing to use this API (best\ndone by writing a wrapper around F<ev.h> that you can include instead and\nwhere you can put other configuration options):\n\n   #define EV_STANDALONE 1\n   #include \"ev.h\"\n\nBoth header files and implementation files can be compiled with a C++\ncompiler (at least, that's a stated goal, and breakage will be treated\nas a bug).\n\nYou need the following files in your source tree, or in a directory\nin your include path (e.g. in libev/ when using -Ilibev):\n\n   ev.h\n   ev.c\n   ev_vars.h\n   ev_wrap.h\n\n   ev_win32.c      required on win32 platforms only\n\n   ev_select.c     only when select backend is enabled\n   ev_poll.c       only when poll backend is enabled\n   ev_epoll.c      only when the epoll backend is enabled\n   ev_kqueue.c     only when the kqueue backend is enabled\n   ev_port.c       only when the solaris port backend is enabled\n\nF<ev.c> includes the backend files directly when enabled, so you only need\nto compile this single file.\n\n=head3 LIBEVENT COMPATIBILITY API\n\nTo include the libevent compatibility API, also include:\n\n   #include \"event.c\"\n\nin the file including F<ev.c>, and:\n\n   #include \"event.h\"\n\nin the files that want to use the libevent API. This also includes F<ev.h>.\n\nYou need the following additional files for this:\n\n   event.h\n   event.c\n\n=head3 AUTOCONF SUPPORT\n\nInstead of using C<EV_STANDALONE=1> and providing your configuration in\nwhatever way you want, you can also C<m4_include([libev.m4])> in your\nF<configure.ac> and leave C<EV_STANDALONE> undefined. F<ev.c> will then\ninclude F<config.h> and configure itself accordingly.\n\nFor this of course you need the m4 file:\n\n   libev.m4\n\n=head2 PREPROCESSOR SYMBOLS/MACROS\n\nLibev can be configured via a variety of preprocessor symbols you have to\ndefine before including (or compiling) any of its files. The default in\nthe absence of autoconf is documented for every option.\n\nSymbols marked with \"(h)\" do not change the ABI, and can have different\nvalues when compiling libev vs. including F<ev.h>, so it is permissible\nto redefine them before including F<ev.h> without breaking compatibility\nto a compiled library. All other symbols change the ABI, which means all\nusers of libev and the libev code itself must be compiled with compatible\nsettings.\n\n=over 4\n\n=item EV_COMPAT3 (h)\n\nBackwards compatibility is a major concern for libev. This is why this\nrelease of libev comes with wrappers for the functions and symbols that\nhave been renamed between libev version 3 and 4.\n\nYou can disable these wrappers (to test compatibility with future\nversions) by defining C<EV_COMPAT3> to C<0> when compiling your\nsources. This has the additional advantage that you can drop the C<struct>\nfrom C<struct ev_loop> declarations, as libev will provide an C<ev_loop>\ntypedef in that case.\n\nIn some future version, the default for C<EV_COMPAT3> will become C<0>,\nand in some even more future version the compatibility code will be\nremoved completely.\n\n=item EV_STANDALONE (h)\n\nMust always be C<1> if you do not use autoconf configuration, which\nkeeps libev from including F<config.h>, and it also defines dummy\nimplementations for some libevent functions (such as logging, which is not\nsupported). It will also not define any of the structs usually found in\nF<event.h> that are not directly supported by the libev core alone.\n\nIn standalone mode, libev will still try to automatically deduce the\nconfiguration, but has to be more conservative.\n\n=item EV_USE_FLOOR\n\nIf defined to be C<1>, libev will use the C<floor ()> function for its\nperiodic reschedule calculations, otherwise libev will fall back on a\nportable (slower) implementation. If you enable this, you usually have to\nlink against libm or something equivalent. Enabling this when the C<floor>\nfunction is not available will fail, so the safe default is to not enable\nthis.\n\n=item EV_USE_MONOTONIC\n\nIf defined to be C<1>, libev will try to detect the availability of the\nmonotonic clock option at both compile time and runtime. Otherwise no\nuse of the monotonic clock option will be attempted. If you enable this,\nyou usually have to link against librt or something similar. Enabling it\nwhen the functionality isn't available is safe, though, although you have\nto make sure you link against any libraries where the C<clock_gettime>\nfunction is hiding in (often F<-lrt>). See also C<EV_USE_CLOCK_SYSCALL>.\n\n=item EV_USE_REALTIME\n\nIf defined to be C<1>, libev will try to detect the availability of the\nreal-time clock option at compile time (and assume its availability\nat runtime if successful). Otherwise no use of the real-time clock\noption will be attempted. This effectively replaces C<gettimeofday>\nby C<clock_get (CLOCK_REALTIME, ...)> and will not normally affect\ncorrectness. See the note about libraries in the description of\nC<EV_USE_MONOTONIC>, though. Defaults to the opposite value of\nC<EV_USE_CLOCK_SYSCALL>.\n\n=item EV_USE_CLOCK_SYSCALL\n\nIf defined to be C<1>, libev will try to use a direct syscall instead\nof calling the system-provided C<clock_gettime> function. This option\nexists because on GNU/Linux, C<clock_gettime> is in C<librt>, but C<librt>\nunconditionally pulls in C<libpthread>, slowing down single-threaded\nprograms needlessly. Using a direct syscall is slightly slower (in\ntheory), because no optimised vdso implementation can be used, but avoids\nthe pthread dependency. Defaults to C<1> on GNU/Linux with glibc 2.x or\nhigher, as it simplifies linking (no need for C<-lrt>).\n\n=item EV_USE_NANOSLEEP\n\nIf defined to be C<1>, libev will assume that C<nanosleep ()> is available\nand will use it for delays. Otherwise it will use C<select ()>.\n\n=item EV_USE_EVENTFD\n\nIf defined to be C<1>, then libev will assume that C<eventfd ()> is\navailable and will probe for kernel support at runtime. This will improve\nC<ev_signal> and C<ev_async> performance and reduce resource consumption.\nIf undefined, it will be enabled if the headers indicate GNU/Linux + Glibc\n2.7 or newer, otherwise disabled.\n\n=item EV_USE_SELECT\n\nIf undefined or defined to be C<1>, libev will compile in support for the\nC<select>(2) backend. No attempt at auto-detection will be done: if no\nother method takes over, select will be it. Otherwise the select backend\nwill not be compiled in.\n\n=item EV_SELECT_USE_FD_SET\n\nIf defined to C<1>, then the select backend will use the system C<fd_set>\nstructure. This is useful if libev doesn't compile due to a missing\nC<NFDBITS> or C<fd_mask> definition or it mis-guesses the bitset layout\non exotic systems. This usually limits the range of file descriptors to\nsome low limit such as 1024 or might have other limitations (winsocket\nonly allows 64 sockets). The C<FD_SETSIZE> macro, set before compilation,\nconfigures the maximum size of the C<fd_set>.\n\n=item EV_SELECT_IS_WINSOCKET\n\nWhen defined to C<1>, the select backend will assume that\nselect/socket/connect etc. don't understand file descriptors but\nwants osf handles on win32 (this is the case when the select to\nbe used is the winsock select). This means that it will call\nC<_get_osfhandle> on the fd to convert it to an OS handle. Otherwise,\nit is assumed that all these functions actually work on fds, even\non win32. Should not be defined on non-win32 platforms.\n\n=item EV_FD_TO_WIN32_HANDLE(fd)\n\nIf C<EV_SELECT_IS_WINSOCKET> is enabled, then libev needs a way to map\nfile descriptors to socket handles. When not defining this symbol (the\ndefault), then libev will call C<_get_osfhandle>, which is usually\ncorrect. In some cases, programs use their own file descriptor management,\nin which case they can provide this function to map fds to socket handles.\n\n=item EV_WIN32_HANDLE_TO_FD(handle)\n\nIf C<EV_SELECT_IS_WINSOCKET> then libev maps handles to file descriptors\nusing the standard C<_open_osfhandle> function. For programs implementing\ntheir own fd to handle mapping, overwriting this function makes it easier\nto do so. This can be done by defining this macro to an appropriate value.\n\n=item EV_WIN32_CLOSE_FD(fd)\n\nIf programs implement their own fd to handle mapping on win32, then this\nmacro can be used to override the C<close> function, useful to unregister\nfile descriptors again. Note that the replacement function has to close\nthe underlying OS handle.\n\n=item EV_USE_WSASOCKET\n\nIf defined to be C<1>, libev will use C<WSASocket> to create its internal\ncommunication socket, which works better in some environments. Otherwise,\nthe normal C<socket> function will be used, which works better in other\nenvironments.\n\n=item EV_USE_POLL\n\nIf defined to be C<1>, libev will compile in support for the C<poll>(2)\nbackend. Otherwise it will be enabled on non-win32 platforms. It\ntakes precedence over select.\n\n=item EV_USE_EPOLL\n\nIf defined to be C<1>, libev will compile in support for the Linux\nC<epoll>(7) backend. Its availability will be detected at runtime,\notherwise another method will be used as fallback. This is the preferred\nbackend for GNU/Linux systems. If undefined, it will be enabled if the\nheaders indicate GNU/Linux + Glibc 2.4 or newer, otherwise disabled.\n\n=item EV_USE_KQUEUE\n\nIf defined to be C<1>, libev will compile in support for the BSD style\nC<kqueue>(2) backend. Its actual availability will be detected at runtime,\notherwise another method will be used as fallback. This is the preferred\nbackend for BSD and BSD-like systems, although on most BSDs kqueue only\nsupports some types of fds correctly (the only platform we found that\nsupports ptys for example was NetBSD), so kqueue might be compiled in, but\nnot be used unless explicitly requested. The best way to use it is to find\nout whether kqueue supports your type of fd properly and use an embedded\nkqueue loop.\n\n=item EV_USE_PORT\n\nIf defined to be C<1>, libev will compile in support for the Solaris\n10 port style backend. Its availability will be detected at runtime,\notherwise another method will be used as fallback. This is the preferred\nbackend for Solaris 10 systems.\n\n=item EV_USE_DEVPOLL\n\nReserved for future expansion, works like the USE symbols above.\n\n=item EV_USE_INOTIFY\n\nIf defined to be C<1>, libev will compile in support for the Linux inotify\ninterface to speed up C<ev_stat> watchers. Its actual availability will\nbe detected at runtime. If undefined, it will be enabled if the headers\nindicate GNU/Linux + Glibc 2.4 or newer, otherwise disabled.\n\n=item EV_NO_SMP\n\nIf defined to be C<1>, libev will assume that memory is always coherent\nbetween threads, that is, threads can be used, but threads never run on\ndifferent cpus (or different cpu cores). This reduces dependencies\nand makes libev faster.\n\n=item EV_NO_THREADS\n\nIf defined to be C<1>, libev will assume that it will never be called from\ndifferent threads (that includes signal handlers), which is a stronger\nassumption than C<EV_NO_SMP>, above. This reduces dependencies and makes\nlibev faster.\n\n=item EV_ATOMIC_T\n\nLibev requires an integer type (suitable for storing C<0> or C<1>) whose\naccess is atomic with respect to other threads or signal contexts. No\nsuch type is easily found in the C language, so you can provide your own\ntype that you know is safe for your purposes. It is used both for signal\nhandler \"locking\" as well as for signal and thread safety in C<ev_async>\nwatchers.\n\nIn the absence of this define, libev will use C<sig_atomic_t volatile>\n(from F<signal.h>), which is usually good enough on most platforms.\n\n=item EV_H (h)\n\nThe name of the F<ev.h> header file used to include it. The default if\nundefined is C<\"ev.h\"> in F<event.h>, F<ev.c> and F<ev++.h>. This can be\nused to virtually rename the F<ev.h> header file in case of conflicts.\n\n=item EV_CONFIG_H (h)\n\nIf C<EV_STANDALONE> isn't C<1>, this variable can be used to override\nF<ev.c>'s idea of where to find the F<config.h> file, similarly to\nC<EV_H>, above.\n\n=item EV_EVENT_H (h)\n\nSimilarly to C<EV_H>, this macro can be used to override F<event.c>'s idea\nof how the F<event.h> header can be found, the default is C<\"event.h\">.\n\n=item EV_PROTOTYPES (h)\n\nIf defined to be C<0>, then F<ev.h> will not define any function\nprototypes, but still define all the structs and other symbols. This is\noccasionally useful if you want to provide your own wrapper functions\naround libev functions.\n\n=item EV_MULTIPLICITY\n\nIf undefined or defined to C<1>, then all event-loop-specific functions\nwill have the C<struct ev_loop *> as first argument, and you can create\nadditional independent event loops. Otherwise there will be no support\nfor multiple event loops and there is no first event loop pointer\nargument. Instead, all functions act on the single default loop.\n\nNote that C<EV_DEFAULT> and C<EV_DEFAULT_> will no longer provide a\ndefault loop when multiplicity is switched off - you always have to\ninitialise the loop manually in this case.\n\n=item EV_MINPRI\n\n=item EV_MAXPRI\n\nThe range of allowed priorities. C<EV_MINPRI> must be smaller or equal to\nC<EV_MAXPRI>, but otherwise there are no non-obvious limitations. You can\nprovide for more priorities by overriding those symbols (usually defined\nto be C<-2> and C<2>, respectively).\n\nWhen doing priority-based operations, libev usually has to linearly search\nall the priorities, so having many of them (hundreds) uses a lot of space\nand time, so using the defaults of five priorities (-2 .. +2) is usually\nfine.\n\nIf your embedding application does not need any priorities, defining these\nboth to C<0> will save some memory and CPU.\n\n=item EV_PERIODIC_ENABLE, EV_IDLE_ENABLE, EV_EMBED_ENABLE, EV_STAT_ENABLE,\nEV_PREPARE_ENABLE, EV_CHECK_ENABLE, EV_FORK_ENABLE, EV_SIGNAL_ENABLE,\nEV_ASYNC_ENABLE, EV_CHILD_ENABLE.\n\nIf undefined or defined to be C<1> (and the platform supports it), then\nthe respective watcher type is supported. If defined to be C<0>, then it\nis not. Disabling watcher types mainly saves code size.\n\n=item EV_FEATURES\n\nIf you need to shave off some kilobytes of code at the expense of some\nspeed (but with the full API), you can define this symbol to request\ncertain subsets of functionality. The default is to enable all features\nthat can be enabled on the platform.\n\nA typical way to use this symbol is to define it to C<0> (or to a bitset\nwith some broad features you want) and then selectively re-enable\nadditional parts you want, for example if you want everything minimal,\nbut multiple event loop support, async and child watchers and the poll\nbackend, use this:\n\n   #define EV_FEATURES 0\n   #define EV_MULTIPLICITY 1\n   #define EV_USE_POLL 1\n   #define EV_CHILD_ENABLE 1\n   #define EV_ASYNC_ENABLE 1\n\nThe actual value is a bitset, it can be a combination of the following\nvalues (by default, all of these are enabled):\n\n=over 4\n\n=item C<1> - faster/larger code\n\nUse larger code to speed up some operations.\n\nCurrently this is used to override some inlining decisions (enlarging the\ncode size by roughly 30% on amd64).\n\nWhen optimising for size, use of compiler flags such as C<-Os> with\ngcc is recommended, as well as C<-DNDEBUG>, as libev contains a number of\nassertions.\n\nThe default is off when C<__OPTIMIZE_SIZE__> is defined by your compiler\n(e.g. gcc with C<-Os>).\n\n=item C<2> - faster/larger data structures\n\nReplaces the small 2-heap for timer management by a faster 4-heap, larger\nhash table sizes and so on. This will usually further increase code size\nand can additionally have an effect on the size of data structures at\nruntime.\n\nThe default is off when C<__OPTIMIZE_SIZE__> is defined by your compiler\n(e.g. gcc with C<-Os>).\n\n=item C<4> - full API configuration\n\nThis enables priorities (sets C<EV_MAXPRI>=2 and C<EV_MINPRI>=-2), and\nenables multiplicity (C<EV_MULTIPLICITY>=1).\n\n=item C<8> - full API\n\nThis enables a lot of the \"lesser used\" API functions. See C<ev.h> for\ndetails on which parts of the API are still available without this\nfeature, and do not complain if this subset changes over time.\n\n=item C<16> - enable all optional watcher types\n\nEnables all optional watcher types.  If you want to selectively enable\nonly some watcher types other than I/O and timers (e.g. prepare,\nembed, async, child...) you can enable them manually by defining\nC<EV_watchertype_ENABLE> to C<1> instead.\n\n=item C<32> - enable all backends\n\nThis enables all backends - without this feature, you need to enable at\nleast one backend manually (C<EV_USE_SELECT> is a good choice).\n\n=item C<64> - enable OS-specific \"helper\" APIs\n\nEnable inotify, eventfd, signalfd and similar OS-specific helper APIs by\ndefault.\n\n=back\n\nCompiling with C<gcc -Os -DEV_STANDALONE -DEV_USE_EPOLL=1 -DEV_FEATURES=0>\nreduces the compiled size of libev from 24.7Kb code/2.8Kb data to 6.5Kb\ncode/0.3Kb data on my GNU/Linux amd64 system, while still giving you I/O\nwatchers, timers and monotonic clock support.\n\nWith an intelligent-enough linker (gcc+binutils are intelligent enough\nwhen you use C<-Wl,--gc-sections -ffunction-sections>) functions unused by\nyour program might be left out as well - a binary starting a timer and an\nI/O watcher then might come out at only 5Kb.\n\n=item EV_API_STATIC\n\nIf this symbol is defined (by default it is not), then all identifiers\nwill have static linkage. This means that libev will not export any\nidentifiers, and you cannot link against libev anymore. This can be useful\nwhen you embed libev, only want to use libev functions in a single file,\nand do not want its identifiers to be visible.\n\nTo use this, define C<EV_API_STATIC> and include F<ev.c> in the file that\nwants to use libev.\n\nThis option only works when libev is compiled with a C compiler, as C++\ndoesn't support the required declaration syntax.\n\n=item EV_AVOID_STDIO\n\nIf this is set to C<1> at compiletime, then libev will avoid using stdio\nfunctions (printf, scanf, perror etc.). This will increase the code size\nsomewhat, but if your program doesn't otherwise depend on stdio and your\nlibc allows it, this avoids linking in the stdio library which is quite\nbig.\n\nNote that error messages might become less precise when this option is\nenabled.\n\n=item EV_NSIG\n\nThe highest supported signal number, +1 (or, the number of\nsignals): Normally, libev tries to deduce the maximum number of signals\nautomatically, but sometimes this fails, in which case it can be\nspecified. Also, using a lower number than detected (C<32> should be\ngood for about any system in existence) can save some memory, as libev\nstatically allocates some 12-24 bytes per signal number.\n\n=item EV_PID_HASHSIZE\n\nC<ev_child> watchers use a small hash table to distribute workload by\npid. The default size is C<16> (or C<1> with C<EV_FEATURES> disabled),\nusually more than enough. If you need to manage thousands of children you\nmight want to increase this value (I<must> be a power of two).\n\n=item EV_INOTIFY_HASHSIZE\n\nC<ev_stat> watchers use a small hash table to distribute workload by\ninotify watch id. The default size is C<16> (or C<1> with C<EV_FEATURES>\ndisabled), usually more than enough. If you need to manage thousands of\nC<ev_stat> watchers you might want to increase this value (I<must> be a\npower of two).\n\n=item EV_USE_4HEAP\n\nHeaps are not very cache-efficient. To improve the cache-efficiency of the\ntimer and periodics heaps, libev uses a 4-heap when this symbol is defined\nto C<1>. The 4-heap uses more complicated (longer) code but has noticeably\nfaster performance with many (thousands) of watchers.\n\nThe default is C<1>, unless C<EV_FEATURES> overrides it, in which case it\nwill be C<0>.\n\n=item EV_HEAP_CACHE_AT\n\nHeaps are not very cache-efficient. To improve the cache-efficiency of the\ntimer and periodics heaps, libev can cache the timestamp (I<at>) within\nthe heap structure (selected by defining C<EV_HEAP_CACHE_AT> to C<1>),\nwhich uses 8-12 bytes more per watcher and a few hundred bytes more code,\nbut avoids random read accesses on heap changes. This improves performance\nnoticeably with many (hundreds) of watchers.\n\nThe default is C<1>, unless C<EV_FEATURES> overrides it, in which case it\nwill be C<0>.\n\n=item EV_VERIFY\n\nControls how much internal verification (see C<ev_verify ()>) will\nbe done: If set to C<0>, no internal verification code will be compiled\nin. If set to C<1>, then verification code will be compiled in, but not\ncalled. If set to C<2>, then the internal verification code will be\ncalled once per loop, which can slow down libev. If set to C<3>, then the\nverification code will be called very frequently, which will slow down\nlibev considerably.\n\nThe default is C<1>, unless C<EV_FEATURES> overrides it, in which case it\nwill be C<0>.\n\n=item EV_COMMON\n\nBy default, all watchers have a C<void *data> member. By redefining\nthis macro to something else you can include more and other types of\nmembers. You have to define it each time you include one of the files,\nthough, and it must be identical each time.\n\nFor example, the perl EV module uses something like this:\n\n   #define EV_COMMON                       \\\n     SV *self; /* contains this struct */  \\\n     SV *cb_sv, *fh /* note no trailing \";\" */\n\n=item EV_CB_DECLARE (type)\n\n=item EV_CB_INVOKE (watcher, revents)\n\n=item ev_set_cb (ev, cb)\n\nCan be used to change the callback member declaration in each watcher,\nand the way callbacks are invoked and set. Must expand to a struct member\ndefinition and a statement, respectively. See the F<ev.h> header file for\ntheir default definitions. One possible use for overriding these is to\navoid the C<struct ev_loop *> as first argument in all cases, or to use\nmethod calls instead of plain function calls in C++.\n\n=back\n\n=head2 EXPORTED API SYMBOLS\n\nIf you need to re-export the API (e.g. via a DLL) and you need a list of\nexported symbols, you can use the provided F<Symbol.*> files which list\nall public symbols, one per line:\n\n   Symbols.ev      for libev proper\n   Symbols.event   for the libevent emulation\n\nThis can also be used to rename all public symbols to avoid clashes with\nmultiple versions of libev linked together (which is obviously bad in\nitself, but sometimes it is inconvenient to avoid this).\n\nA sed command like this will create wrapper C<#define>'s that you need to\ninclude before including F<ev.h>:\n\n   <Symbols.ev sed -e \"s/.*/#define & myprefix_&/\" >wrap.h\n\nThis would create a file F<wrap.h> which essentially looks like this:\n\n   #define ev_backend     myprefix_ev_backend\n   #define ev_check_start myprefix_ev_check_start\n   #define ev_check_stop  myprefix_ev_check_stop\n   ...\n\n=head2 EXAMPLES\n\nFor a real-world example of a program the includes libev\nverbatim, you can have a look at the EV perl module\n(L<http://software.schmorp.de/pkg/EV.html>). It has the libev files in\nthe F<libev/> subdirectory and includes them in the F<EV/EVAPI.h> (public\ninterface) and F<EV.xs> (implementation) files. Only the F<EV.xs> file\nwill be compiled. It is pretty complex because it provides its own header\nfile.\n\nThe usage in rxvt-unicode is simpler. It has a F<ev_cpp.h> header file\nthat everybody includes and which overrides some configure choices:\n\n   #define EV_FEATURES 8\n   #define EV_USE_SELECT 1\n   #define EV_PREPARE_ENABLE 1\n   #define EV_IDLE_ENABLE 1\n   #define EV_SIGNAL_ENABLE 1\n   #define EV_CHILD_ENABLE 1\n   #define EV_USE_STDEXCEPT 0\n   #define EV_CONFIG_H <config.h>\n\n   #include \"ev++.h\"\n\nAnd a F<ev_cpp.C> implementation file that contains libev proper and is compiled:\n\n   #include \"ev_cpp.h\"\n   #include \"ev.c\"\n\n=head1 INTERACTION WITH OTHER PROGRAMS, LIBRARIES OR THE ENVIRONMENT\n\n=head2 THREADS AND COROUTINES\n\n=head3 THREADS\n\nAll libev functions are reentrant and thread-safe unless explicitly\ndocumented otherwise, but libev implements no locking itself. This means\nthat you can use as many loops as you want in parallel, as long as there\nare no concurrent calls into any libev function with the same loop\nparameter (C<ev_default_*> calls have an implicit default loop parameter,\nof course): libev guarantees that different event loops share no data\nstructures that need any locking.\n\nOr to put it differently: calls with different loop parameters can be done\nconcurrently from multiple threads, calls with the same loop parameter\nmust be done serially (but can be done from different threads, as long as\nonly one thread ever is inside a call at any point in time, e.g. by using\na mutex per loop).\n\nSpecifically to support threads (and signal handlers), libev implements\nso-called C<ev_async> watchers, which allow some limited form of\nconcurrency on the same event loop, namely waking it up \"from the\noutside\".\n\nIf you want to know which design (one loop, locking, or multiple loops\nwithout or something else still) is best for your problem, then I cannot\nhelp you, but here is some generic advice:\n\n=over 4\n\n=item * most applications have a main thread: use the default libev loop\nin that thread, or create a separate thread running only the default loop.\n\nThis helps integrating other libraries or software modules that use libev\nthemselves and don't care/know about threading.\n\n=item * one loop per thread is usually a good model.\n\nDoing this is almost never wrong, sometimes a better-performance model\nexists, but it is always a good start.\n\n=item * other models exist, such as the leader/follower pattern, where one\nloop is handed through multiple threads in a kind of round-robin fashion.\n\nChoosing a model is hard - look around, learn, know that usually you can do\nbetter than you currently do :-)\n\n=item * often you need to talk to some other thread which blocks in the\nevent loop.\n\nC<ev_async> watchers can be used to wake them up from other threads safely\n(or from signal contexts...).\n\nAn example use would be to communicate signals or other events that only\nwork in the default loop by registering the signal watcher with the\ndefault loop and triggering an C<ev_async> watcher from the default loop\nwatcher callback into the event loop interested in the signal.\n\n=back\n\nSee also L</THREAD LOCKING EXAMPLE>.\n\n=head3 COROUTINES\n\nLibev is very accommodating to coroutines (\"cooperative threads\"):\nlibev fully supports nesting calls to its functions from different\ncoroutines (e.g. you can call C<ev_run> on the same loop from two\ndifferent coroutines, and switch freely between both coroutines running\nthe loop, as long as you don't confuse yourself). The only exception is\nthat you must not do this from C<ev_periodic> reschedule callbacks.\n\nCare has been taken to ensure that libev does not keep local state inside\nC<ev_run>, and other calls do not usually allow for coroutine switches as\nthey do not call any callbacks.\n\n=head2 COMPILER WARNINGS\n\nDepending on your compiler and compiler settings, you might get no or a\nlot of warnings when compiling libev code. Some people are apparently\nscared by this.\n\nHowever, these are unavoidable for many reasons. For one, each compiler\nhas different warnings, and each user has different tastes regarding\nwarning options. \"Warn-free\" code therefore cannot be a goal except when\ntargeting a specific compiler and compiler-version.\n\nAnother reason is that some compiler warnings require elaborate\nworkarounds, or other changes to the code that make it less clear and less\nmaintainable.\n\nAnd of course, some compiler warnings are just plain stupid, or simply\nwrong (because they don't actually warn about the condition their message\nseems to warn about). For example, certain older gcc versions had some\nwarnings that resulted in an extreme number of false positives. These have\nbeen fixed, but some people still insist on making code warn-free with\nsuch buggy versions.\n\nWhile libev is written to generate as few warnings as possible,\n\"warn-free\" code is not a goal, and it is recommended not to build libev\nwith any compiler warnings enabled unless you are prepared to cope with\nthem (e.g. by ignoring them). Remember that warnings are just that:\nwarnings, not errors, or proof of bugs.\n\n\n=head2 VALGRIND\n\nValgrind has a special section here because it is a popular tool that is\nhighly useful. Unfortunately, valgrind reports are very hard to interpret.\n\nIf you think you found a bug (memory leak, uninitialised data access etc.)\nin libev, then check twice: If valgrind reports something like:\n\n   ==2274==    definitely lost: 0 bytes in 0 blocks.\n   ==2274==      possibly lost: 0 bytes in 0 blocks.\n   ==2274==    still reachable: 256 bytes in 1 blocks.\n\nThen there is no memory leak, just as memory accounted to global variables\nis not a memleak - the memory is still being referenced, and didn't leak.\n\nSimilarly, under some circumstances, valgrind might report kernel bugs\nas if it were a bug in libev (e.g. in realloc or in the poll backend,\nalthough an acceptable workaround has been found here), or it might be\nconfused.\n\nKeep in mind that valgrind is a very good tool, but only a tool. Don't\nmake it into some kind of religion.\n\nIf you are unsure about something, feel free to contact the mailing list\nwith the full valgrind report and an explanation on why you think this\nis a bug in libev (best check the archives, too :). However, don't be\nannoyed when you get a brisk \"this is no bug\" answer and take the chance\nof learning how to interpret valgrind properly.\n\nIf you need, for some reason, empty reports from valgrind for your project\nI suggest using suppression lists.\n\n\n=head1 PORTABILITY NOTES\n\n=head2 GNU/LINUX 32 BIT LIMITATIONS\n\nGNU/Linux is the only common platform that supports 64 bit file/large file\ninterfaces but I<disables> them by default.\n\nThat means that libev compiled in the default environment doesn't support\nfiles larger than 2GiB or so, which mainly affects C<ev_stat> watchers.\n\nUnfortunately, many programs try to work around this GNU/Linux issue\nby enabling the large file API, which makes them incompatible with the\nstandard libev compiled for their system.\n\nLikewise, libev cannot enable the large file API itself as this would\nsuddenly make it incompatible to the default compile time environment,\ni.e. all programs not using special compile switches.\n\n=head2 OS/X AND DARWIN BUGS\n\nThe whole thing is a bug if you ask me - basically any system interface\nyou touch is broken, whether it is locales, poll, kqueue or even the\nOpenGL drivers.\n\n=head3 C<kqueue> is buggy\n\nThe kqueue syscall is broken in all known versions - most versions support\nonly sockets, many support pipes.\n\nLibev tries to work around this by not using C<kqueue> by default on this\nrotten platform, but of course you can still ask for it when creating a\nloop - embedding a socket-only kqueue loop into a select-based one is\nprobably going to work well.\n\n=head3 C<poll> is buggy\n\nInstead of fixing C<kqueue>, Apple replaced their (working) C<poll>\nimplementation by something calling C<kqueue> internally around the 10.5.6\nrelease, so now C<kqueue> I<and> C<poll> are broken.\n\nLibev tries to work around this by not using C<poll> by default on\nthis rotten platform, but of course you can still ask for it when creating\na loop.\n\n=head3 C<select> is buggy\n\nAll that's left is C<select>, and of course Apple found a way to fuck this\none up as well: On OS/X, C<select> actively limits the number of file\ndescriptors you can pass in to 1024 - your program suddenly crashes when\nyou use more.\n\nThere is an undocumented \"workaround\" for this - defining\nC<_DARWIN_UNLIMITED_SELECT>, which libev tries to use, so select I<should>\nwork on OS/X.\n\n=head2 SOLARIS PROBLEMS AND WORKAROUNDS\n\n=head3 C<errno> reentrancy\n\nThe default compile environment on Solaris is unfortunately so\nthread-unsafe that you can't even use components/libraries compiled\nwithout C<-D_REENTRANT> in a threaded program, which, of course, isn't\ndefined by default. A valid, if stupid, implementation choice.\n\nIf you want to use libev in threaded environments you have to make sure\nit's compiled with C<_REENTRANT> defined.\n\n=head3 Event port backend\n\nThe scalable event interface for Solaris is called \"event\nports\". Unfortunately, this mechanism is very buggy in all major\nreleases. If you run into high CPU usage, your program freezes or you get\na large number of spurious wakeups, make sure you have all the relevant\nand latest kernel patches applied. No, I don't know which ones, but there\nare multiple ones to apply, and afterwards, event ports actually work\ngreat.\n\nIf you can't get it to work, you can try running the program by setting\nthe environment variable C<LIBEV_FLAGS=3> to only allow C<poll> and\nC<select> backends.\n\n=head2 AIX POLL BUG\n\nAIX unfortunately has a broken C<poll.h> header. Libev works around\nthis by trying to avoid the poll backend altogether (i.e. it's not even\ncompiled in), which normally isn't a big problem as C<select> works fine\nwith large bitsets on AIX, and AIX is dead anyway.\n\n=head2 WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS\n\n=head3 General issues\n\nWin32 doesn't support any of the standards (e.g. POSIX) that libev\nrequires, and its I/O model is fundamentally incompatible with the POSIX\nmodel. Libev still offers limited functionality on this platform in\nthe form of the C<EVBACKEND_SELECT> backend, and only supports socket\ndescriptors. This only applies when using Win32 natively, not when using\ne.g. cygwin. Actually, it only applies to the microsofts own compilers,\nas every compiler comes with a slightly differently broken/incompatible\nenvironment.\n\nLifting these limitations would basically require the full\nre-implementation of the I/O system. If you are into this kind of thing,\nthen note that glib does exactly that for you in a very portable way (note\nalso that glib is the slowest event library known to man).\n\nThere is no supported compilation method available on windows except\nembedding it into other applications.\n\nSensible signal handling is officially unsupported by Microsoft - libev\ntries its best, but under most conditions, signals will simply not work.\n\nNot a libev limitation but worth mentioning: windows apparently doesn't\naccept large writes: instead of resulting in a partial write, windows will\neither accept everything or return C<ENOBUFS> if the buffer is too large,\nso make sure you only write small amounts into your sockets (less than a\nmegabyte seems safe, but this apparently depends on the amount of memory\navailable).\n\nDue to the many, low, and arbitrary limits on the win32 platform and\nthe abysmal performance of winsockets, using a large number of sockets\nis not recommended (and not reasonable). If your program needs to use\nmore than a hundred or so sockets, then likely it needs to use a totally\ndifferent implementation for windows, as libev offers the POSIX readiness\nnotification model, which cannot be implemented efficiently on windows\n(due to Microsoft monopoly games).\n\nA typical way to use libev under windows is to embed it (see the embedding\nsection for details) and use the following F<evwrap.h> header file instead\nof F<ev.h>:\n\n   #define EV_STANDALONE              /* keeps ev from requiring config.h */\n   #define EV_SELECT_IS_WINSOCKET 1   /* configure libev for windows select */\n\n   #include \"ev.h\"\n\nAnd compile the following F<evwrap.c> file into your project (make sure\nyou do I<not> compile the F<ev.c> or any other embedded source files!):\n\n   #include \"evwrap.h\"\n   #include \"ev.c\"\n\n=head3 The winsocket C<select> function\n\nThe winsocket C<select> function doesn't follow POSIX in that it\nrequires socket I<handles> and not socket I<file descriptors> (it is\nalso extremely buggy). This makes select very inefficient, and also\nrequires a mapping from file descriptors to socket handles (the Microsoft\nC runtime provides the function C<_open_osfhandle> for this). See the\ndiscussion of the C<EV_SELECT_USE_FD_SET>, C<EV_SELECT_IS_WINSOCKET> and\nC<EV_FD_TO_WIN32_HANDLE> preprocessor symbols for more info.\n\nThe configuration for a \"naked\" win32 using the Microsoft runtime\nlibraries and raw winsocket select is:\n\n   #define EV_USE_SELECT 1\n   #define EV_SELECT_IS_WINSOCKET 1   /* forces EV_SELECT_USE_FD_SET, too */\n\nNote that winsockets handling of fd sets is O(n), so you can easily get a\ncomplexity in the O(n²) range when using win32.\n\n=head3 Limited number of file descriptors\n\nWindows has numerous arbitrary (and low) limits on things.\n\nEarly versions of winsocket's select only supported waiting for a maximum\nof C<64> handles (probably owning to the fact that all windows kernels\ncan only wait for C<64> things at the same time internally; Microsoft\nrecommends spawning a chain of threads and wait for 63 handles and the\nprevious thread in each. Sounds great!).\n\nNewer versions support more handles, but you need to define C<FD_SETSIZE>\nto some high number (e.g. C<2048>) before compiling the winsocket select\ncall (which might be in libev or elsewhere, for example, perl and many\nother interpreters do their own select emulation on windows).\n\nAnother limit is the number of file descriptors in the Microsoft runtime\nlibraries, which by default is C<64> (there must be a hidden I<64>\nfetish or something like this inside Microsoft). You can increase this\nby calling C<_setmaxstdio>, which can increase this limit to C<2048>\n(another arbitrary limit), but is broken in many versions of the Microsoft\nruntime libraries. This might get you to about C<512> or C<2048> sockets\n(depending on windows version and/or the phase of the moon). To get more,\nyou need to wrap all I/O functions and provide your own fd management, but\nthe cost of calling select (O(n²)) will likely make this unworkable.\n\n=head2 PORTABILITY REQUIREMENTS\n\nIn addition to a working ISO-C implementation and of course the\nbackend-specific APIs, libev relies on a few additional extensions:\n\n=over 4\n\n=item C<void (*)(ev_watcher_type *, int revents)> must have compatible\ncalling conventions regardless of C<ev_watcher_type *>.\n\nLibev assumes not only that all watcher pointers have the same internal\nstructure (guaranteed by POSIX but not by ISO C for example), but it also\nassumes that the same (machine) code can be used to call any watcher\ncallback: The watcher callbacks have different type signatures, but libev\ncalls them using an C<ev_watcher *> internally.\n\n=item null pointers and integer zero are represented by 0 bytes\n\nLibev uses C<memset> to initialise structs and arrays to C<0> bytes, and\nrelies on this setting pointers and integers to null.\n\n=item pointer accesses must be thread-atomic\n\nAccessing a pointer value must be atomic, it must both be readable and\nwritable in one piece - this is the case on all current architectures.\n\n=item C<sig_atomic_t volatile> must be thread-atomic as well\n\nThe type C<sig_atomic_t volatile> (or whatever is defined as\nC<EV_ATOMIC_T>) must be atomic with respect to accesses from different\nthreads. This is not part of the specification for C<sig_atomic_t>, but is\nbelieved to be sufficiently portable.\n\n=item C<sigprocmask> must work in a threaded environment\n\nLibev uses C<sigprocmask> to temporarily block signals. This is not\nallowed in a threaded program (C<pthread_sigmask> has to be used). Typical\npthread implementations will either allow C<sigprocmask> in the \"main\nthread\" or will block signals process-wide, both behaviours would\nbe compatible with libev. Interaction between C<sigprocmask> and\nC<pthread_sigmask> could complicate things, however.\n\nThe most portable way to handle signals is to block signals in all threads\nexcept the initial one, and run the signal handling loop in the initial\nthread as well.\n\n=item C<long> must be large enough for common memory allocation sizes\n\nTo improve portability and simplify its API, libev uses C<long> internally\ninstead of C<size_t> when allocating its data structures. On non-POSIX\nsystems (Microsoft...) this might be unexpectedly low, but is still at\nleast 31 bits everywhere, which is enough for hundreds of millions of\nwatchers.\n\n=item C<double> must hold a time value in seconds with enough accuracy\n\nThe type C<double> is used to represent timestamps. It is required to\nhave at least 51 bits of mantissa (and 9 bits of exponent), which is\ngood enough for at least into the year 4000 with millisecond accuracy\n(the design goal for libev). This requirement is overfulfilled by\nimplementations using IEEE 754, which is basically all existing ones.\n\nWith IEEE 754 doubles, you get microsecond accuracy until at least the\nyear 2255 (and millisecond accuracy till the year 287396 - by then, libev\nis either obsolete or somebody patched it to use C<long double> or\nsomething like that, just kidding).\n\n=back\n\nIf you know of other additional requirements drop me a note.\n\n\n=head1 ALGORITHMIC COMPLEXITIES\n\nIn this section the complexities of (many of) the algorithms used inside\nlibev will be documented. For complexity discussions about backends see\nthe documentation for C<ev_default_init>.\n\nAll of the following are about amortised time: If an array needs to be\nextended, libev needs to realloc and move the whole array, but this\nhappens asymptotically rarer with higher number of elements, so O(1) might\nmean that libev does a lengthy realloc operation in rare cases, but on\naverage it is much faster and asymptotically approaches constant time.\n\n=over 4\n\n=item Starting and stopping timer/periodic watchers: O(log skipped_other_timers)\n\nThis means that, when you have a watcher that triggers in one hour and\nthere are 100 watchers that would trigger before that, then inserting will\nhave to skip roughly seven (C<ld 100>) of these watchers.\n\n=item Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers)\n\nThat means that changing a timer costs less than removing/adding them,\nas only the relative motion in the event queue has to be paid for.\n\n=item Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1)\n\nThese just add the watcher into an array or at the head of a list.\n\n=item Stopping check/prepare/idle/fork/async watchers: O(1)\n\n=item Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE))\n\nThese watchers are stored in lists, so they need to be walked to find the\ncorrect watcher to remove. The lists are usually short (you don't usually\nhave many watchers waiting for the same fd or signal: one is typical, two\nis rare).\n\n=item Finding the next timer in each loop iteration: O(1)\n\nBy virtue of using a binary or 4-heap, the next timer is always found at a\nfixed position in the storage array.\n\n=item Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd)\n\nA change means an I/O watcher gets started or stopped, which requires\nlibev to recalculate its status (and possibly tell the kernel, depending\non backend and whether C<ev_io_set> was used).\n\n=item Activating one watcher (putting it into the pending state): O(1)\n\n=item Priority handling: O(number_of_priorities)\n\nPriorities are implemented by allocating some space for each\npriority. When doing priority-based operations, libev usually has to\nlinearly search all the priorities, but starting/stopping and activating\nwatchers becomes O(1) with respect to priority handling.\n\n=item Sending an ev_async: O(1)\n\n=item Processing ev_async_send: O(number_of_async_watchers)\n\n=item Processing signals: O(max_signal_number)\n\nSending involves a system call I<iff> there were no other C<ev_async_send>\ncalls in the current loop iteration and the loop is currently\nblocked. Checking for async and signal events involves iterating over all\nrunning async watchers or all signal numbers.\n\n=back\n\n\n=head1 PORTING FROM LIBEV 3.X TO 4.X\n\nThe major version 4 introduced some incompatible changes to the API.\n\nAt the moment, the C<ev.h> header file provides compatibility definitions\nfor all changes, so most programs should still compile. The compatibility\nlayer might be removed in later versions of libev, so better update to the\nnew API early than late.\n\n=over 4\n\n=item C<EV_COMPAT3> backwards compatibility mechanism\n\nThe backward compatibility mechanism can be controlled by\nC<EV_COMPAT3>. See L</\"PREPROCESSOR SYMBOLS/MACROS\"> in the L</EMBEDDING>\nsection.\n\n=item C<ev_default_destroy> and C<ev_default_fork> have been removed\n\nThese calls can be replaced easily by their C<ev_loop_xxx> counterparts:\n\n   ev_loop_destroy (EV_DEFAULT_UC);\n   ev_loop_fork (EV_DEFAULT);\n\n=item function/symbol renames\n\nA number of functions and symbols have been renamed:\n\n  ev_loop         => ev_run\n  EVLOOP_NONBLOCK => EVRUN_NOWAIT\n  EVLOOP_ONESHOT  => EVRUN_ONCE\n\n  ev_unloop       => ev_break\n  EVUNLOOP_CANCEL => EVBREAK_CANCEL\n  EVUNLOOP_ONE    => EVBREAK_ONE\n  EVUNLOOP_ALL    => EVBREAK_ALL\n\n  EV_TIMEOUT      => EV_TIMER\n\n  ev_loop_count   => ev_iteration\n  ev_loop_depth   => ev_depth\n  ev_loop_verify  => ev_verify\n\nMost functions working on C<struct ev_loop> objects don't have an\nC<ev_loop_> prefix, so it was removed; C<ev_loop>, C<ev_unloop> and\nassociated constants have been renamed to not collide with the C<struct\nev_loop> anymore and C<EV_TIMER> now follows the same naming scheme\nas all other watcher types. Note that C<ev_loop_fork> is still called\nC<ev_loop_fork> because it would otherwise clash with the C<ev_fork>\ntypedef.\n\n=item C<EV_MINIMAL> mechanism replaced by C<EV_FEATURES>\n\nThe preprocessor symbol C<EV_MINIMAL> has been replaced by a different\nmechanism, C<EV_FEATURES>. Programs using C<EV_MINIMAL> usually compile\nand work, but the library code will of course be larger.\n\n=back\n\n\n=head1 GLOSSARY\n\n=over 4\n\n=item active\n\nA watcher is active as long as it has been started and not yet stopped.\nSee L</WATCHER STATES> for details.\n\n=item application\n\nIn this document, an application is whatever is using libev.\n\n=item backend\n\nThe part of the code dealing with the operating system interfaces.\n\n=item callback\n\nThe address of a function that is called when some event has been\ndetected. Callbacks are being passed the event loop, the watcher that\nreceived the event, and the actual event bitset.\n\n=item callback/watcher invocation\n\nThe act of calling the callback associated with a watcher.\n\n=item event\n\nA change of state of some external event, such as data now being available\nfor reading on a file descriptor, time having passed or simply not having\nany other events happening anymore.\n\nIn libev, events are represented as single bits (such as C<EV_READ> or\nC<EV_TIMER>).\n\n=item event library\n\nA software package implementing an event model and loop.\n\n=item event loop\n\nAn entity that handles and processes external events and converts them\ninto callback invocations.\n\n=item event model\n\nThe model used to describe how an event loop handles and processes\nwatchers and events.\n\n=item pending\n\nA watcher is pending as soon as the corresponding event has been\ndetected. See L</WATCHER STATES> for details.\n\n=item real time\n\nThe physical time that is observed. It is apparently strictly monotonic :)\n\n=item wall-clock time\n\nThe time and date as shown on clocks. Unlike real time, it can actually\nbe wrong and jump forwards and backwards, e.g. when you adjust your\nclock.\n\n=item watcher\n\nA data structure that describes interest in certain events. Watchers need\nto be started (attached to an event loop) before they can receive events.\n\n=back\n\n=head1 AUTHOR\n\nMarc Lehmann <libev@schmorp.de>, with repeated corrections by Mikael\nMagnusson and Emanuele Giaquinta, and minor corrections by many others.\n\n"
  },
  {
    "path": "libev/ev_epoll.c",
    "content": "/*\n * libev epoll fd activity backend\n *\n * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n/*\n * general notes about epoll:\n *\n * a) epoll silently removes fds from the fd set. as nothing tells us\n *    that an fd has been removed otherwise, we have to continually\n *    \"rearm\" fds that we suspect *might* have changed (same\n *    problem with kqueue, but much less costly there).\n * b) the fact that ADD != MOD creates a lot of extra syscalls due to a)\n *    and seems not to have any advantage.\n * c) the inability to handle fork or file descriptors (think dup)\n *    limits the applicability over poll, so this is not a generic\n *    poll replacement.\n * d) epoll doesn't work the same as select with many file descriptors\n *    (such as files). while not critical, no other advanced interface\n *    seems to share this (rather non-unixy) limitation.\n * e) epoll claims to be embeddable, but in practise you never get\n *    a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32).\n * f) epoll_ctl returning EPERM means the fd is always ready.\n *\n * lots of \"weird code\" and complication handling in this file is due\n * to these design problems with epoll, as we try very hard to avoid\n * epoll_ctl syscalls for common usage patterns and handle the breakage\n * ensuing from receiving events for closed and otherwise long gone\n * file descriptors.\n */\n\n#include <sys/epoll.h>\n\n#define EV_EMASK_EPERM 0x80\n\nstatic void\nepoll_modify (EV_P_ int fd, int oev, int nev)\n{\n  struct epoll_event ev;\n  unsigned char oldmask;\n\n  /*\n   * we handle EPOLL_CTL_DEL by ignoring it here\n   * on the assumption that the fd is gone anyways\n   * if that is wrong, we have to handle the spurious\n   * event in epoll_poll.\n   * if the fd is added again, we try to ADD it, and, if that\n   * fails, we assume it still has the same eventmask.\n   */\n  if (!nev)\n    return;\n\n  oldmask = anfds [fd].emask;\n  anfds [fd].emask = nev;\n\n  /* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */\n  ev.data.u64 = (uint64_t)(uint32_t)fd\n              | ((uint64_t)(uint32_t)++anfds [fd].egen << 32);\n  ev.events   = (nev & EV_READ  ? EPOLLIN  : 0)\n              | (nev & EV_WRITE ? EPOLLOUT : 0);\n\n  if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev)))\n    return;\n\n  if (expect_true (errno == ENOENT))\n    {\n      /* if ENOENT then the fd went away, so try to do the right thing */\n      if (!nev)\n        goto dec_egen;\n\n      if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev))\n        return;\n    }\n  else if (expect_true (errno == EEXIST))\n    {\n      /* EEXIST means we ignored a previous DEL, but the fd is still active */\n      /* if the kernel mask is the same as the new mask, we assume it hasn't changed */\n      if (oldmask == nev)\n        goto dec_egen;\n\n      if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))\n        return;\n    }\n  else if (expect_true (errno == EPERM))\n    {\n      /* EPERM means the fd is always ready, but epoll is too snobbish */\n      /* to handle it, unlike select or poll. */\n      anfds [fd].emask = EV_EMASK_EPERM;\n\n      /* add fd to epoll_eperms, if not already inside */\n      if (!(oldmask & EV_EMASK_EPERM))\n        {\n          array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2);\n          epoll_eperms [epoll_epermcnt++] = fd;\n        }\n\n      return;\n    }\n\n  fd_kill (EV_A_ fd);\n\ndec_egen:\n  /* we didn't successfully call epoll_ctl, so decrement the generation counter again */\n  --anfds [fd].egen;\n}\n\nstatic void\nepoll_poll (EV_P_ ev_tstamp timeout)\n{\n  int i;\n  int eventcnt;\n\n  if (expect_false (epoll_epermcnt))\n    timeout = 0.;\n\n  /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */\n  /* the default libev max wait time, however. */\n  EV_RELEASE_CB;\n  eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, timeout * 1e3);\n  EV_ACQUIRE_CB;\n\n  if (expect_false (eventcnt < 0))\n    {\n      if (errno != EINTR)\n        ev_syserr (\"(libev) epoll_wait\");\n\n      return;\n    }\n\n  for (i = 0; i < eventcnt; ++i)\n    {\n      struct epoll_event *ev = epoll_events + i;\n\n      int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */\n      int want = anfds [fd].events;\n      int got  = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)\n               | (ev->events & (EPOLLIN  | EPOLLERR | EPOLLHUP) ? EV_READ  : 0);\n\n      /*\n       * check for spurious notification.\n       * this only finds spurious notifications on egen updates\n       * other spurious notifications will be found by epoll_ctl, below\n       * we assume that fd is always in range, as we never shrink the anfds array\n       */\n      if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))\n        {\n          /* recreate kernel state */\n          postfork |= 2;\n          continue;\n        }\n\n      if (expect_false (got & ~want))\n        {\n          anfds [fd].emask = want;\n\n          /*\n           * we received an event but are not interested in it, try mod or del\n           * this often happens because we optimistically do not unregister fds\n           * when we are no longer interested in them, but also when we get spurious\n           * notifications for fds from another process. this is partially handled\n           * above with the gencounter check (== our fd is not the event fd), and\n           * partially here, when epoll_ctl returns an error (== a child has the fd\n           * but we closed it).\n           */\n          ev->events = (want & EV_READ  ? EPOLLIN  : 0)\n                     | (want & EV_WRITE ? EPOLLOUT : 0);\n\n          /* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, */\n          /* which is fortunately easy to do for us. */\n          if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev))\n            {\n              postfork |= 2; /* an error occurred, recreate kernel state */\n              continue;\n            }\n        }\n\n      fd_event (EV_A_ fd, got);\n    }\n\n  /* if the receive array was full, increase its size */\n  if (expect_false (eventcnt == epoll_eventmax))\n    {\n      ev_free (epoll_events);\n      epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1);\n      epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);\n    }\n\n  /* now synthesize events for all fds where epoll fails, while select works... */\n  for (i = epoll_epermcnt; i--; )\n    {\n      int fd = epoll_eperms [i];\n      unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE);\n\n      if (anfds [fd].emask & EV_EMASK_EPERM && events)\n        fd_event (EV_A_ fd, events);\n      else\n        {\n          epoll_eperms [i] = epoll_eperms [--epoll_epermcnt];\n          anfds [fd].emask = 0;\n        }\n    }\n}\n\ninline_size\nint\nepoll_init (EV_P_ int flags)\n{\n#if defined EPOLL_CLOEXEC && !defined __ANDROID__\n  backend_fd = epoll_create1 (EPOLL_CLOEXEC);\n\n  if (backend_fd < 0 && (errno == EINVAL || errno == ENOSYS))\n#endif\n    backend_fd = epoll_create (256);\n\n  if (backend_fd < 0)\n    return 0;\n\n  fcntl (backend_fd, F_SETFD, FD_CLOEXEC);\n\n  backend_mintime = 1e-3; /* epoll does sometimes return early, this is just to avoid the worst */\n  backend_modify  = epoll_modify;\n  backend_poll    = epoll_poll;\n\n  epoll_eventmax = 64; /* initial number of events receivable per poll */\n  epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);\n\n  return EVBACKEND_EPOLL;\n}\n\ninline_size\nvoid\nepoll_destroy (EV_P)\n{\n  ev_free (epoll_events);\n  array_free (epoll_eperm, EMPTY);\n}\n\ninline_size\nvoid\nepoll_fork (EV_P)\n{\n  close (backend_fd);\n\n  while ((backend_fd = epoll_create (256)) < 0)\n    ev_syserr (\"(libev) epoll_create\");\n\n  fcntl (backend_fd, F_SETFD, FD_CLOEXEC);\n\n  fd_rearm_all (EV_A);\n}\n\n"
  },
  {
    "path": "libev/ev_kqueue.c",
    "content": "/*\n * libev kqueue backend\n *\n * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/event.h>\n#include <string.h>\n#include <errno.h>\n\ninline_speed\nvoid\nkqueue_change (EV_P_ int fd, int filter, int flags, int fflags)\n{\n  ++kqueue_changecnt;\n  array_needsize (struct kevent, kqueue_changes, kqueue_changemax, kqueue_changecnt, EMPTY2);\n\n  EV_SET (&kqueue_changes [kqueue_changecnt - 1], fd, filter, flags, fflags, 0, 0);\n}\n\n/* OS X at least needs this */\n#ifndef EV_ENABLE\n# define EV_ENABLE 0\n#endif\n#ifndef NOTE_EOF\n# define NOTE_EOF 0\n#endif\n\nstatic void\nkqueue_modify (EV_P_ int fd, int oev, int nev)\n{\n  if (oev != nev)\n    {\n      if (oev & EV_READ)\n        kqueue_change (EV_A_ fd, EVFILT_READ , EV_DELETE, 0);\n\n      if (oev & EV_WRITE)\n        kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_DELETE, 0);\n    }\n\n  /* to detect close/reopen reliably, we have to re-add */\n  /* event requests even when oev == nev */\n\n  if (nev & EV_READ)\n    kqueue_change (EV_A_ fd, EVFILT_READ , EV_ADD | EV_ENABLE, NOTE_EOF);\n\n  if (nev & EV_WRITE)\n    kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, NOTE_EOF);\n}\n\nstatic void\nkqueue_poll (EV_P_ ev_tstamp timeout)\n{\n  int res, i;\n  struct timespec ts;\n\n  /* need to resize so there is enough space for errors */\n  if (kqueue_changecnt > kqueue_eventmax)\n    {\n      ev_free (kqueue_events);\n      kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_changecnt);\n      kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);\n    }\n\n  EV_RELEASE_CB;\n  EV_TS_SET (ts, timeout);\n  res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts);\n  EV_ACQUIRE_CB;\n  kqueue_changecnt = 0;\n\n  if (expect_false (res < 0))\n    {\n      if (errno != EINTR)\n        ev_syserr (\"(libev) kevent\");\n\n      return;\n    }\n\n  for (i = 0; i < res; ++i)\n    {\n      int fd = kqueue_events [i].ident;\n\n      if (expect_false (kqueue_events [i].flags & EV_ERROR))\n        {\n          int err = kqueue_events [i].data;\n\n          /* we are only interested in errors for fds that we are interested in :) */\n          if (anfds [fd].events)\n            {\n              if (err == ENOENT) /* resubmit changes on ENOENT */\n                kqueue_modify (EV_A_ fd, 0, anfds [fd].events);\n              else if (err == EBADF) /* on EBADF, we re-check the fd */\n                {\n                  if (fd_valid (fd))\n                    kqueue_modify (EV_A_ fd, 0, anfds [fd].events);\n                  else\n                    fd_kill (EV_A_ fd);\n                }\n              else /* on all other errors, we error out on the fd */\n                fd_kill (EV_A_ fd);\n            }\n        }\n      else\n        fd_event (\n          EV_A_\n          fd,\n          kqueue_events [i].filter == EVFILT_READ ? EV_READ\n          : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE\n          : 0\n        );\n    }\n\n  if (expect_false (res == kqueue_eventmax))\n    {\n      ev_free (kqueue_events);\n      kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_eventmax + 1);\n      kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);\n    }\n}\n\ninline_size\nint\nkqueue_init (EV_P_ int flags)\n{\n  /* initialize the kernel queue */\n  kqueue_fd_pid = getpid ();\n  if ((backend_fd = kqueue ()) < 0)\n    return 0;\n\n  fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */\n\n  backend_mintime = 1e-9; /* apparently, they did the right thing in freebsd */\n  backend_modify  = kqueue_modify;\n  backend_poll    = kqueue_poll;\n\n  kqueue_eventmax = 64; /* initial number of events receivable per poll */\n  kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);\n\n  kqueue_changes   = 0;\n  kqueue_changemax = 0;\n  kqueue_changecnt = 0;\n\n  return EVBACKEND_KQUEUE;\n}\n\ninline_size\nvoid\nkqueue_destroy (EV_P)\n{\n  ev_free (kqueue_events);\n  ev_free (kqueue_changes);\n}\n\ninline_size\nvoid\nkqueue_fork (EV_P)\n{\n  /* some BSD kernels don't just destroy the kqueue itself,\n   * but also close the fd, which isn't documented, and\n   * impossible to support properly.\n   * we remember the pid of the kqueue call and only close\n   * the fd if the pid is still the same.\n   * this leaks fds on sane kernels, but BSD interfaces are\n   * notoriously buggy and rarely get fixed.\n   */\n  pid_t newpid = getpid ();\n\n  if (newpid == kqueue_fd_pid)\n    close (backend_fd);\n\n  kqueue_fd_pid = newpid;\n  while ((backend_fd = kqueue ()) < 0)\n    ev_syserr (\"(libev) kqueue\");\n\n  fcntl (backend_fd, F_SETFD, FD_CLOEXEC);\n\n  /* re-register interest in fds */\n  fd_rearm_all (EV_A);\n}\n\n/* sys/event.h defines EV_ERROR */\n#undef EV_ERROR\n\n"
  },
  {
    "path": "libev/ev_poll.c",
    "content": "/*\n * libev poll fd activity backend\n *\n * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#include <poll.h>\n\ninline_size\nvoid\npollidx_init (int *base, int count)\n{\n  /* consider using memset (.., -1, ...), which is practically guaranteed\n   * to work on all systems implementing poll */\n  while (count--)\n    *base++ = -1;\n}\n\nstatic void\npoll_modify (EV_P_ int fd, int oev, int nev)\n{\n  int idx;\n\n  if (oev == nev)\n    return;\n\n  array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init);\n\n  idx = pollidxs [fd];\n\n  if (idx < 0) /* need to allocate a new pollfd */\n    {\n      pollidxs [fd] = idx = pollcnt++;\n      array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2);\n      polls [idx].fd = fd;\n    }\n\n  assert (polls [idx].fd == fd);\n\n  if (nev)\n    polls [idx].events =\n        (nev & EV_READ ? POLLIN : 0)\n        | (nev & EV_WRITE ? POLLOUT : 0);\n  else /* remove pollfd */\n    {\n      pollidxs [fd] = -1;\n\n      if (expect_true (idx < --pollcnt))\n        {\n          polls [idx] = polls [pollcnt];\n          pollidxs [polls [idx].fd] = idx;\n        }\n    }\n}\n\nstatic void\npoll_poll (EV_P_ ev_tstamp timeout)\n{\n  struct pollfd *p;\n  int res;\n  \n  EV_RELEASE_CB;\n  res = poll (polls, pollcnt, timeout * 1e3);\n  EV_ACQUIRE_CB;\n\n  if (expect_false (res < 0))\n    {\n      if (errno == EBADF)\n        fd_ebadf (EV_A);\n      else if (errno == ENOMEM && !syserr_cb)\n        fd_enomem (EV_A);\n      else if (errno != EINTR)\n        ev_syserr (\"(libev) poll\");\n    }\n  else\n    for (p = polls; res; ++p)\n      {\n        assert ((\"libev: poll() returned illegal result, broken BSD kernel?\", p < polls + pollcnt));\n\n        if (expect_false (p->revents)) /* this expect is debatable */\n          {\n            --res;\n\n            if (expect_false (p->revents & POLLNVAL))\n              fd_kill (EV_A_ p->fd);\n            else\n              fd_event (\n                EV_A_\n                p->fd,\n                (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)\n                | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)\n              );\n          }\n      }\n}\n\ninline_size\nint\npoll_init (EV_P_ int flags)\n{\n  backend_mintime = 1e-3;\n  backend_modify  = poll_modify;\n  backend_poll    = poll_poll;\n\n  pollidxs = 0; pollidxmax = 0;\n  polls    = 0; pollmax    = 0; pollcnt = 0;\n\n  return EVBACKEND_POLL;\n}\n\ninline_size\nvoid\npoll_destroy (EV_P)\n{\n  ev_free (pollidxs);\n  ev_free (polls);\n}\n\n"
  },
  {
    "path": "libev/ev_port.c",
    "content": "/*\n * libev solaris event port backend\n *\n * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n/* useful reading:\n *\n * http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results)\n * http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken)\n * http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME)\n * http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME)\n * http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget\n * http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc)\n * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel)\n */\n\n#include <sys/types.h>\n#include <sys/time.h>\n#include <poll.h>\n#include <port.h>\n#include <string.h>\n#include <errno.h>\n\ninline_speed\nvoid\nport_associate_and_check (EV_P_ int fd, int ev)\n{\n  if (0 >\n      port_associate (\n         backend_fd, PORT_SOURCE_FD, fd,\n         (ev & EV_READ ? POLLIN : 0)\n         | (ev & EV_WRITE ? POLLOUT : 0),\n         0\n      )\n  )\n    {\n      if (errno == EBADFD)\n        fd_kill (EV_A_ fd);\n      else\n        ev_syserr (\"(libev) port_associate\");\n    }\n}\n\nstatic void\nport_modify (EV_P_ int fd, int oev, int nev)\n{\n  /* we need to reassociate no matter what, as closes are\n   * once more silently being discarded.\n   */\n  if (!nev)\n    {\n      if (oev)\n        port_dissociate (backend_fd, PORT_SOURCE_FD, fd);\n    }\n  else\n    port_associate_and_check (EV_A_ fd, nev);\n}\n\nstatic void\nport_poll (EV_P_ ev_tstamp timeout)\n{\n  int res, i;\n  struct timespec ts;\n  uint_t nget = 1;\n\n  /* we initialise this to something we will skip in the loop, as */\n  /* port_getn can return with nget unchanged, but no indication */\n  /* whether it was the original value or has been updated :/ */\n  port_events [0].portev_source = 0;\n\n  EV_RELEASE_CB;\n  EV_TS_SET (ts, timeout);\n  res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);\n  EV_ACQUIRE_CB;\n\n  /* port_getn may or may not set nget on error */\n  /* so we rely on port_events [0].portev_source not being updated */\n  if (res == -1 && errno != ETIME && errno != EINTR)\n    ev_syserr (\"(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)\");\n\n  for (i = 0; i < nget; ++i)\n    {\n      if (port_events [i].portev_source == PORT_SOURCE_FD)\n        {\n          int fd = port_events [i].portev_object;\n\n          fd_event (\n            EV_A_\n            fd,\n            (port_events [i].portev_events & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)\n            | (port_events [i].portev_events & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)\n          );\n\n          fd_change (EV_A_ fd, EV__IOFDSET);\n        }\n    }\n\n  if (expect_false (nget == port_eventmax))\n    {\n      ev_free (port_events);\n      port_eventmax = array_nextsize (sizeof (port_event_t), port_eventmax, port_eventmax + 1);\n      port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);\n    }\n}\n\ninline_size\nint\nport_init (EV_P_ int flags)\n{\n  /* Initialize the kernel queue */\n  if ((backend_fd = port_create ()) < 0)\n    return 0;\n\n  assert ((\"libev: PORT_SOURCE_FD must not be zero\", PORT_SOURCE_FD));\n\n  fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */\n\n  /* if my reading of the opensolaris kernel sources are correct, then\n   * opensolaris does something very stupid: it checks if the time has already\n   * elapsed and doesn't round up if that is the case,m otherwise it DOES round\n   * up. Since we can't know what the case is, we need to guess by using a\n   * \"large enough\" timeout. Normally, 1e-9 would be correct.\n   */\n  backend_mintime = 1e-3; /* needed to compensate for port_getn returning early */\n  backend_modify  = port_modify;\n  backend_poll    = port_poll;\n\n  port_eventmax = 64; /* initial number of events receivable per poll */\n  port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);\n\n  return EVBACKEND_PORT;\n}\n\ninline_size\nvoid\nport_destroy (EV_P)\n{\n  ev_free (port_events);\n}\n\ninline_size\nvoid\nport_fork (EV_P)\n{\n  close (backend_fd);\n\n  while ((backend_fd = port_create ()) < 0)\n    ev_syserr (\"(libev) port\");\n\n  fcntl (backend_fd, F_SETFD, FD_CLOEXEC);\n\n  /* re-register interest in fds */\n  fd_rearm_all (EV_A);\n}\n\n"
  },
  {
    "path": "libev/ev_select.c",
    "content": "/*\n * libev select fd activity backend\n *\n * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef _WIN32\n/* for unix systems */\n# include <inttypes.h>\n# ifndef __hpux\n/* for REAL unix systems */\n#  include <sys/select.h>\n# endif\n#endif\n\n#ifndef EV_SELECT_USE_FD_SET\n# ifdef NFDBITS\n#  define EV_SELECT_USE_FD_SET 0\n# else\n#  define EV_SELECT_USE_FD_SET 1\n# endif\n#endif\n\n#if EV_SELECT_IS_WINSOCKET\n# undef EV_SELECT_USE_FD_SET\n# define EV_SELECT_USE_FD_SET 1\n# undef NFDBITS\n# define NFDBITS 0\n#endif\n\n#if !EV_SELECT_USE_FD_SET\n# define NFDBYTES (NFDBITS / 8)\n#endif\n\n#include <string.h>\n\nstatic void\nselect_modify (EV_P_ int fd, int oev, int nev)\n{\n  if (oev == nev)\n    return;\n\n  {\n#if EV_SELECT_USE_FD_SET\n\n    #if EV_SELECT_IS_WINSOCKET\n    SOCKET handle = anfds [fd].handle;\n    #else\n    int handle = fd;\n    #endif\n\n    assert ((\"libev: fd >= FD_SETSIZE passed to fd_set-based select backend\", fd < FD_SETSIZE));\n\n    /* FD_SET is broken on windows (it adds the fd to a set twice or more,\n     * which eventually leads to overflows). Need to call it only on changes.\n     */\n    #if EV_SELECT_IS_WINSOCKET\n    if ((oev ^ nev) & EV_READ)\n    #endif\n      if (nev & EV_READ)\n        FD_SET (handle, (fd_set *)vec_ri);\n      else\n        FD_CLR (handle, (fd_set *)vec_ri);\n\n    #if EV_SELECT_IS_WINSOCKET\n    if ((oev ^ nev) & EV_WRITE)\n    #endif\n      if (nev & EV_WRITE)\n        FD_SET (handle, (fd_set *)vec_wi);\n      else\n        FD_CLR (handle, (fd_set *)vec_wi);\n\n#else\n\n    int     word = fd / NFDBITS;\n    fd_mask mask = 1UL << (fd % NFDBITS);\n\n    if (expect_false (vec_max <= word))\n      {\n        int new_max = word + 1;\n\n        vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES);\n        vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */\n        vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES);\n        vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */\n        #ifdef _WIN32\n        vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */\n        #endif\n\n        for (; vec_max < new_max; ++vec_max)\n          ((fd_mask *)vec_ri) [vec_max] =\n          ((fd_mask *)vec_wi) [vec_max] = 0;\n      }\n\n    ((fd_mask *)vec_ri) [word] |= mask;\n    if (!(nev & EV_READ))\n      ((fd_mask *)vec_ri) [word] &= ~mask;\n\n    ((fd_mask *)vec_wi) [word] |= mask;\n    if (!(nev & EV_WRITE))\n      ((fd_mask *)vec_wi) [word] &= ~mask;\n#endif\n  }\n}\n\nstatic void\nselect_poll (EV_P_ ev_tstamp timeout)\n{\n  struct timeval tv;\n  int res;\n  int fd_setsize;\n\n  EV_RELEASE_CB;\n  EV_TV_SET (tv, timeout);\n\n#if EV_SELECT_USE_FD_SET\n  fd_setsize = sizeof (fd_set);\n#else\n  fd_setsize = vec_max * NFDBYTES;\n#endif\n\n  memcpy (vec_ro, vec_ri, fd_setsize);\n  memcpy (vec_wo, vec_wi, fd_setsize);\n\n#ifdef _WIN32\n  /* pass in the write set as except set.\n   * the idea behind this is to work around a windows bug that causes\n   * errors to be reported as an exception and not by setting\n   * the writable bit. this is so uncontrollably lame.\n   */\n  memcpy (vec_eo, vec_wi, fd_setsize);\n  res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv);\n#elif EV_SELECT_USE_FD_SET\n  fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE;\n  res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);\n#else\n  res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);\n#endif\n  EV_ACQUIRE_CB;\n\n  if (expect_false (res < 0))\n    {\n      #if EV_SELECT_IS_WINSOCKET\n      errno = WSAGetLastError ();\n      #endif\n      #ifdef WSABASEERR\n      /* on windows, select returns incompatible error codes, fix this */\n      if (errno >= WSABASEERR && errno < WSABASEERR + 1000)\n        if (errno == WSAENOTSOCK)\n          errno = EBADF;\n        else\n          errno -= WSABASEERR;\n      #endif\n\n      #ifdef _WIN32\n      /* select on windows erroneously returns EINVAL when no fd sets have been\n       * provided (this is documented). what microsoft doesn't tell you that this bug\n       * exists even when the fd sets _are_ provided, so we have to check for this bug\n       * here and emulate by sleeping manually.\n       * we also get EINVAL when the timeout is invalid, but we ignore this case here\n       * and assume that EINVAL always means: you have to wait manually.\n       */\n      if (errno == EINVAL)\n        {\n          if (timeout)\n            {\n              unsigned long ms = timeout * 1e3;\n              Sleep (ms ? ms : 1);\n            }\n\n          return;\n        }\n      #endif\n\n      if (errno == EBADF)\n        fd_ebadf (EV_A);\n      else if (errno == ENOMEM && !syserr_cb)\n        fd_enomem (EV_A);\n      else if (errno != EINTR)\n        ev_syserr (\"(libev) select\");\n\n      return;\n    }\n\n#if EV_SELECT_USE_FD_SET\n\n  {\n    int fd;\n\n    for (fd = 0; fd < anfdmax; ++fd)\n      if (anfds [fd].events)\n        {\n          int events = 0;\n          #if EV_SELECT_IS_WINSOCKET\n          SOCKET handle = anfds [fd].handle;\n          #else\n          int handle = fd;\n          #endif\n\n          if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;\n          if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;\n          #ifdef _WIN32\n          if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE;\n          #endif\n\n          if (expect_true (events))\n            fd_event (EV_A_ fd, events);\n        }\n  }\n\n#else\n\n  {\n    int word, bit;\n    for (word = vec_max; word--; )\n      {\n        fd_mask word_r = ((fd_mask *)vec_ro) [word];\n        fd_mask word_w = ((fd_mask *)vec_wo) [word];\n        #ifdef _WIN32\n        word_w |= ((fd_mask *)vec_eo) [word];\n        #endif\n\n        if (word_r || word_w)\n          for (bit = NFDBITS; bit--; )\n            {\n              fd_mask mask = 1UL << bit;\n              int events = 0;\n\n              events |= word_r & mask ? EV_READ  : 0;\n              events |= word_w & mask ? EV_WRITE : 0;\n\n              if (expect_true (events))\n                fd_event (EV_A_ word * NFDBITS + bit, events);\n            }\n      }\n  }\n\n#endif\n}\n\ninline_size\nint\nselect_init (EV_P_ int flags)\n{\n  backend_mintime = 1e-6;\n  backend_modify  = select_modify;\n  backend_poll    = select_poll;\n\n#if EV_SELECT_USE_FD_SET\n  vec_ri  = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri);\n  vec_ro  = ev_malloc (sizeof (fd_set));\n  vec_wi  = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi);\n  vec_wo  = ev_malloc (sizeof (fd_set));\n  #ifdef _WIN32\n  vec_eo  = ev_malloc (sizeof (fd_set));\n  #endif\n#else\n  vec_max = 0;\n  vec_ri  = 0;\n  vec_ro  = 0;\n  vec_wi  = 0;\n  vec_wo  = 0;\n  #ifdef _WIN32\n  vec_eo  = 0;\n  #endif\n#endif\n\n  return EVBACKEND_SELECT;\n}\n\ninline_size\nvoid\nselect_destroy (EV_P)\n{\n  ev_free (vec_ri);\n  ev_free (vec_ro);\n  ev_free (vec_wi);\n  ev_free (vec_wo);\n  #ifdef _WIN32\n  ev_free (vec_eo);\n  #endif\n}\n\n"
  },
  {
    "path": "libev/ev_vars.h",
    "content": "/*\n * loop member variable declarations\n *\n * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#define VARx(type,name) VAR(name, type name)\n\nVARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */\nVARx(ev_tstamp, mn_now)    /* monotonic clock \"now\" */\nVARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */\n\n/* for reverse feeding of events */\nVARx(W *, rfeeds)\nVARx(int, rfeedmax)\nVARx(int, rfeedcnt)\n\nVAR (pendings, ANPENDING *pendings [NUMPRI])\nVAR (pendingmax, int pendingmax [NUMPRI])\nVAR (pendingcnt, int pendingcnt [NUMPRI])\nVARx(int, pendingpri) /* highest priority currently pending */\nVARx(ev_prepare, pending_w) /* dummy pending watcher */\n\nVARx(ev_tstamp, io_blocktime)\nVARx(ev_tstamp, timeout_blocktime)\n\nVARx(int, backend)\nVARx(int, activecnt) /* total number of active events (\"refcount\") */\nVARx(EV_ATOMIC_T, loop_done)  /* signal by ev_break */\n\nVARx(int, backend_fd)\nVARx(ev_tstamp, backend_mintime) /* assumed typical timer resolution */\nVAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev))\nVAR (backend_poll  , void (*backend_poll)(EV_P_ ev_tstamp timeout))\n\nVARx(ANFD *, anfds)\nVARx(int, anfdmax)\n\nVAR (evpipe, int evpipe [2])\nVARx(ev_io, pipe_w)\nVARx(EV_ATOMIC_T, pipe_write_wanted)\nVARx(EV_ATOMIC_T, pipe_write_skipped)\n\n#if !defined(_WIN32) || EV_GENWRAP\nVARx(pid_t, curpid)\n#endif\n\nVARx(char, postfork)  /* true if we need to recreate kernel state after fork */\n\n#if EV_USE_SELECT || EV_GENWRAP\nVARx(void *, vec_ri)\nVARx(void *, vec_ro)\nVARx(void *, vec_wi)\nVARx(void *, vec_wo)\n#if defined(_WIN32) || EV_GENWRAP\nVARx(void *, vec_eo)\n#endif\nVARx(int, vec_max)\n#endif\n\n#if EV_USE_POLL || EV_GENWRAP\nVARx(struct pollfd *, polls)\nVARx(int, pollmax)\nVARx(int, pollcnt)\nVARx(int *, pollidxs) /* maps fds into structure indices */\nVARx(int, pollidxmax)\n#endif\n\n#if EV_USE_EPOLL || EV_GENWRAP\nVARx(struct epoll_event *, epoll_events)\nVARx(int, epoll_eventmax)\nVARx(int *, epoll_eperms)\nVARx(int, epoll_epermcnt)\nVARx(int, epoll_epermmax)\n#endif\n\n#if EV_USE_KQUEUE || EV_GENWRAP\nVARx(pid_t, kqueue_fd_pid)\nVARx(struct kevent *, kqueue_changes)\nVARx(int, kqueue_changemax)\nVARx(int, kqueue_changecnt)\nVARx(struct kevent *, kqueue_events)\nVARx(int, kqueue_eventmax)\n#endif\n\n#if EV_USE_PORT || EV_GENWRAP\nVARx(struct port_event *, port_events)\nVARx(int, port_eventmax)\n#endif\n\n#if EV_USE_IOCP || EV_GENWRAP\nVARx(HANDLE, iocp)\n#endif\n\nVARx(int *, fdchanges)\nVARx(int, fdchangemax)\nVARx(int, fdchangecnt)\n\nVARx(ANHE *, timers)\nVARx(int, timermax)\nVARx(int, timercnt)\n\n#if EV_PERIODIC_ENABLE || EV_GENWRAP\nVARx(ANHE *, periodics)\nVARx(int, periodicmax)\nVARx(int, periodiccnt)\n#endif\n\n#if EV_IDLE_ENABLE || EV_GENWRAP\nVAR (idles, ev_idle **idles [NUMPRI])\nVAR (idlemax, int idlemax [NUMPRI])\nVAR (idlecnt, int idlecnt [NUMPRI])\n#endif\nVARx(int, idleall) /* total number */\n\nVARx(struct ev_prepare **, prepares)\nVARx(int, preparemax)\nVARx(int, preparecnt)\n\nVARx(struct ev_check **, checks)\nVARx(int, checkmax)\nVARx(int, checkcnt)\n\n#if EV_FORK_ENABLE || EV_GENWRAP\nVARx(struct ev_fork **, forks)\nVARx(int, forkmax)\nVARx(int, forkcnt)\n#endif\n\n#if EV_CLEANUP_ENABLE || EV_GENWRAP\nVARx(struct ev_cleanup **, cleanups)\nVARx(int, cleanupmax)\nVARx(int, cleanupcnt)\n#endif\n\n#if EV_ASYNC_ENABLE || EV_GENWRAP\nVARx(EV_ATOMIC_T, async_pending)\nVARx(struct ev_async **, asyncs)\nVARx(int, asyncmax)\nVARx(int, asynccnt)\n#endif\n\n#if EV_USE_INOTIFY || EV_GENWRAP\nVARx(int, fs_fd)\nVARx(ev_io, fs_w)\nVARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */\nVAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])\n#endif\n\nVARx(EV_ATOMIC_T, sig_pending)\n#if EV_USE_SIGNALFD || EV_GENWRAP\nVARx(int, sigfd)\nVARx(ev_io, sigfd_w)\nVARx(sigset_t, sigfd_set)\n#endif\n\nVARx(unsigned int, origflags) /* original loop flags */\n\n#if EV_FEATURE_API || EV_GENWRAP\nVARx(unsigned int, loop_count) /* total number of loop iterations/blocks */\nVARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */\n\nVARx(void *, userdata)\n/* C++ doesn't support the ev_loop_callback typedef here. stinks. */\nVAR (release_cb, void (*release_cb)(EV_P) EV_THROW)\nVAR (acquire_cb, void (*acquire_cb)(EV_P) EV_THROW)\nVAR (invoke_cb , ev_loop_callback invoke_cb)\n#endif\n\n#undef VARx\n\n"
  },
  {
    "path": "libev/ev_win32.c",
    "content": "/*\n * libev win32 compatibility cruft (_not_ a backend)\n *\n * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifdef _WIN32\n\n/* note: the comment below could not be substantiated, but what would I care */\n/* MSDN says this is required to handle SIGFPE */\n/* my wild guess would be that using something floating-pointy is required */\n/* for the crt to do something about it */\nvolatile double SIGFPE_REQ = 0.0f;\n\nstatic SOCKET\nev_tcp_socket (void)\n{\n#if EV_USE_WSASOCKET\n  return WSASocket (AF_INET, SOCK_STREAM, 0, 0, 0, 0);\n#else\n  return socket (AF_INET, SOCK_STREAM, 0);\n#endif\n}\n\n/* oh, the humanity! */\nstatic int\nev_pipe (int filedes [2])\n{\n  struct sockaddr_in addr = { 0 };\n  int addr_size = sizeof (addr);\n  struct sockaddr_in adr2;\n  int adr2_size = sizeof (adr2);\n  SOCKET listener;\n  SOCKET sock [2] = { -1, -1 };\n\n  if ((listener = ev_tcp_socket ()) == INVALID_SOCKET)\n    return -1;\n\n  addr.sin_family = AF_INET;\n  addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);\n  addr.sin_port = 0;\n\n  if (bind (listener, (struct sockaddr *)&addr, addr_size))\n    goto fail;\n\n  if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))\n    goto fail;\n\n  if (listen (listener, 1))\n    goto fail;\n\n  if ((sock [0] = ev_tcp_socket ()) == INVALID_SOCKET)\n    goto fail;\n\n  if (connect (sock [0], (struct sockaddr *)&addr, addr_size))\n    goto fail;\n\n  /* TODO: returns INVALID_SOCKET on winsock accept, not < 0. fix it */\n  /* when convenient, probably by just removing error checking altogether? */\n  if ((sock [1] = accept (listener, 0, 0)) < 0)\n    goto fail;\n\n  /* windows vista returns fantasy port numbers for sockets:\n   * example for two interconnected tcp sockets:\n   *\n   * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364\n   * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363\n   * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363\n   * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365\n   *\n   * wow! tridirectional sockets!\n   *\n   * this way of checking ports seems to work:\n   */\n  if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))\n    goto fail;\n\n  if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))\n    goto fail;\n\n  errno = WSAEINVAL;\n  if (addr_size != adr2_size\n      || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */\n      || addr.sin_port        != adr2.sin_port)\n    goto fail;\n\n  closesocket (listener);\n\n#if EV_SELECT_IS_WINSOCKET\n  filedes [0] = EV_WIN32_HANDLE_TO_FD (sock [0]);\n  filedes [1] = EV_WIN32_HANDLE_TO_FD (sock [1]);\n#else\n  /* when select isn't winsocket, we also expect socket, connect, accept etc.\n   * to work on fds */\n  filedes [0] = sock [0];\n  filedes [1] = sock [1];\n#endif\n\n  return 0;\n\nfail:\n  closesocket (listener);\n\n  if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);\n  if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);\n\n  return -1;\n}\n\n#undef pipe\n#define pipe(filedes) ev_pipe (filedes)\n\n#define EV_HAVE_EV_TIME 1\nev_tstamp\nev_time (void)\n{\n  FILETIME ft;\n  ULARGE_INTEGER ui;\n\n  GetSystemTimeAsFileTime (&ft);\n  ui.u.LowPart  = ft.dwLowDateTime;\n  ui.u.HighPart = ft.dwHighDateTime;\n\n  /* msvc cannot convert ulonglong to double... yes, it is that sucky */\n  return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7;\n}\n\n#endif\n\n"
  },
  {
    "path": "libev/ev_wrap.h",
    "content": "/* DO NOT EDIT, automatically generated by update_ev_wrap */\n#ifndef EV_WRAP_H\n#define EV_WRAP_H\n#define acquire_cb ((loop)->acquire_cb)\n#define activecnt ((loop)->activecnt)\n#define anfdmax ((loop)->anfdmax)\n#define anfds ((loop)->anfds)\n#define async_pending ((loop)->async_pending)\n#define asynccnt ((loop)->asynccnt)\n#define asyncmax ((loop)->asyncmax)\n#define asyncs ((loop)->asyncs)\n#define backend ((loop)->backend)\n#define backend_fd ((loop)->backend_fd)\n#define backend_mintime ((loop)->backend_mintime)\n#define backend_modify ((loop)->backend_modify)\n#define backend_poll ((loop)->backend_poll)\n#define checkcnt ((loop)->checkcnt)\n#define checkmax ((loop)->checkmax)\n#define checks ((loop)->checks)\n#define cleanupcnt ((loop)->cleanupcnt)\n#define cleanupmax ((loop)->cleanupmax)\n#define cleanups ((loop)->cleanups)\n#define curpid ((loop)->curpid)\n#define epoll_epermcnt ((loop)->epoll_epermcnt)\n#define epoll_epermmax ((loop)->epoll_epermmax)\n#define epoll_eperms ((loop)->epoll_eperms)\n#define epoll_eventmax ((loop)->epoll_eventmax)\n#define epoll_events ((loop)->epoll_events)\n#define evpipe ((loop)->evpipe)\n#define fdchangecnt ((loop)->fdchangecnt)\n#define fdchangemax ((loop)->fdchangemax)\n#define fdchanges ((loop)->fdchanges)\n#define forkcnt ((loop)->forkcnt)\n#define forkmax ((loop)->forkmax)\n#define forks ((loop)->forks)\n#define fs_2625 ((loop)->fs_2625)\n#define fs_fd ((loop)->fs_fd)\n#define fs_hash ((loop)->fs_hash)\n#define fs_w ((loop)->fs_w)\n#define idleall ((loop)->idleall)\n#define idlecnt ((loop)->idlecnt)\n#define idlemax ((loop)->idlemax)\n#define idles ((loop)->idles)\n#define invoke_cb ((loop)->invoke_cb)\n#define io_blocktime ((loop)->io_blocktime)\n#define iocp ((loop)->iocp)\n#define kqueue_changecnt ((loop)->kqueue_changecnt)\n#define kqueue_changemax ((loop)->kqueue_changemax)\n#define kqueue_changes ((loop)->kqueue_changes)\n#define kqueue_eventmax ((loop)->kqueue_eventmax)\n#define kqueue_events ((loop)->kqueue_events)\n#define kqueue_fd_pid ((loop)->kqueue_fd_pid)\n#define loop_count ((loop)->loop_count)\n#define loop_depth ((loop)->loop_depth)\n#define loop_done ((loop)->loop_done)\n#define mn_now ((loop)->mn_now)\n#define now_floor ((loop)->now_floor)\n#define origflags ((loop)->origflags)\n#define pending_w ((loop)->pending_w)\n#define pendingcnt ((loop)->pendingcnt)\n#define pendingmax ((loop)->pendingmax)\n#define pendingpri ((loop)->pendingpri)\n#define pendings ((loop)->pendings)\n#define periodiccnt ((loop)->periodiccnt)\n#define periodicmax ((loop)->periodicmax)\n#define periodics ((loop)->periodics)\n#define pipe_w ((loop)->pipe_w)\n#define pipe_write_skipped ((loop)->pipe_write_skipped)\n#define pipe_write_wanted ((loop)->pipe_write_wanted)\n#define pollcnt ((loop)->pollcnt)\n#define pollidxmax ((loop)->pollidxmax)\n#define pollidxs ((loop)->pollidxs)\n#define pollmax ((loop)->pollmax)\n#define polls ((loop)->polls)\n#define port_eventmax ((loop)->port_eventmax)\n#define port_events ((loop)->port_events)\n#define postfork ((loop)->postfork)\n#define preparecnt ((loop)->preparecnt)\n#define preparemax ((loop)->preparemax)\n#define prepares ((loop)->prepares)\n#define release_cb ((loop)->release_cb)\n#define rfeedcnt ((loop)->rfeedcnt)\n#define rfeedmax ((loop)->rfeedmax)\n#define rfeeds ((loop)->rfeeds)\n#define rtmn_diff ((loop)->rtmn_diff)\n#define sig_pending ((loop)->sig_pending)\n#define sigfd ((loop)->sigfd)\n#define sigfd_set ((loop)->sigfd_set)\n#define sigfd_w ((loop)->sigfd_w)\n#define timeout_blocktime ((loop)->timeout_blocktime)\n#define timercnt ((loop)->timercnt)\n#define timermax ((loop)->timermax)\n#define timers ((loop)->timers)\n#define userdata ((loop)->userdata)\n#define vec_eo ((loop)->vec_eo)\n#define vec_max ((loop)->vec_max)\n#define vec_ri ((loop)->vec_ri)\n#define vec_ro ((loop)->vec_ro)\n#define vec_wi ((loop)->vec_wi)\n#define vec_wo ((loop)->vec_wo)\n#else\n#undef EV_WRAP_H\n#undef acquire_cb\n#undef activecnt\n#undef anfdmax\n#undef anfds\n#undef async_pending\n#undef asynccnt\n#undef asyncmax\n#undef asyncs\n#undef backend\n#undef backend_fd\n#undef backend_mintime\n#undef backend_modify\n#undef backend_poll\n#undef checkcnt\n#undef checkmax\n#undef checks\n#undef cleanupcnt\n#undef cleanupmax\n#undef cleanups\n#undef curpid\n#undef epoll_epermcnt\n#undef epoll_epermmax\n#undef epoll_eperms\n#undef epoll_eventmax\n#undef epoll_events\n#undef evpipe\n#undef fdchangecnt\n#undef fdchangemax\n#undef fdchanges\n#undef forkcnt\n#undef forkmax\n#undef forks\n#undef fs_2625\n#undef fs_fd\n#undef fs_hash\n#undef fs_w\n#undef idleall\n#undef idlecnt\n#undef idlemax\n#undef idles\n#undef invoke_cb\n#undef io_blocktime\n#undef iocp\n#undef kqueue_changecnt\n#undef kqueue_changemax\n#undef kqueue_changes\n#undef kqueue_eventmax\n#undef kqueue_events\n#undef kqueue_fd_pid\n#undef loop_count\n#undef loop_depth\n#undef loop_done\n#undef mn_now\n#undef now_floor\n#undef origflags\n#undef pending_w\n#undef pendingcnt\n#undef pendingmax\n#undef pendingpri\n#undef pendings\n#undef periodiccnt\n#undef periodicmax\n#undef periodics\n#undef pipe_w\n#undef pipe_write_skipped\n#undef pipe_write_wanted\n#undef pollcnt\n#undef pollidxmax\n#undef pollidxs\n#undef pollmax\n#undef polls\n#undef port_eventmax\n#undef port_events\n#undef postfork\n#undef preparecnt\n#undef preparemax\n#undef prepares\n#undef release_cb\n#undef rfeedcnt\n#undef rfeedmax\n#undef rfeeds\n#undef rtmn_diff\n#undef sig_pending\n#undef sigfd\n#undef sigfd_set\n#undef sigfd_w\n#undef timeout_blocktime\n#undef timercnt\n#undef timermax\n#undef timers\n#undef userdata\n#undef vec_eo\n#undef vec_max\n#undef vec_ri\n#undef vec_ro\n#undef vec_wi\n#undef vec_wo\n#endif\n"
  },
  {
    "path": "libev/event.c",
    "content": "/*\n * libevent compatibility layer\n *\n * Copyright (c) 2007,2008,2009,2010,2012 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <assert.h>\n\n#ifdef EV_EVENT_H\n# include EV_EVENT_H\n#else\n# include \"event.h\"\n#endif\n\n#if EV_MULTIPLICITY\n# define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base\n# define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base\n#else\n# define dLOOPev\n# define dLOOPbase\n#endif\n\n/* never accessed, will always be cast from/to ev_loop */\nstruct event_base\n{\n  int dummy;\n};\n\nstatic struct event_base *ev_x_cur;\n\nstatic ev_tstamp\nev_tv_get (struct timeval *tv)\n{\n  if (tv)\n    {\n      ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6;\n      return after ? after : 1e-6;\n    }\n  else\n    return -1.;\n}\n\n#define EVENT_STRINGIFY(s) # s\n#define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) \".\" EVENT_STRINGIFY (b)\n\nconst char *\nevent_get_version (void)\n{\n  /* returns ABI, not API or library, version */\n  return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);\n}\n\nconst char *\nevent_get_method (void)\n{\n  return \"libev\";\n}\n\nvoid *event_init (void)\n{\n#if EV_MULTIPLICITY\n  if (ev_x_cur)\n    ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);\n  else\n    ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);\n#else\n  assert ((\"libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY\", !ev_x_cur));\n\n  ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);\n#endif\n\n  return ev_x_cur;\n}\n\nconst char *\nevent_base_get_method (const struct event_base *base)\n{\n  return \"libev\";\n}\n\nstruct event_base *\nevent_base_new (void)\n{\n#if EV_MULTIPLICITY\n  return (struct event_base *)ev_loop_new (EVFLAG_AUTO);\n#else\n  assert ((\"libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY\"));\n  return NULL;\n#endif\n}\n\nvoid event_base_free (struct event_base *base)\n{\n  dLOOPbase;\n\n#if EV_MULTIPLICITY\n  if (!ev_is_default_loop (loop))\n    ev_loop_destroy (loop);\n#endif\n}\n\nint event_dispatch (void)\n{\n  return event_base_dispatch (ev_x_cur);\n}\n\n#ifdef EV_STANDALONE\nvoid event_set_log_callback (event_log_cb cb)\n{\n  /* nop */\n}\n#endif\n\nint event_loop (int flags)\n{\n  return event_base_loop (ev_x_cur, flags);\n}\n\nint event_loopexit (struct timeval *tv)\n{\n  return event_base_loopexit (ev_x_cur, tv);\n}\n\nevent_callback_fn event_get_callback\n(const struct event *ev)\n{\n  return ev->ev_callback;\n}\n\nstatic void\nev_x_cb (struct event *ev, int revents)\n{\n  revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL;\n\n  ev->ev_res = revents;\n  ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);\n}\n\nstatic void\nev_x_cb_sig (EV_P_ struct ev_signal *w, int revents)\n{\n  struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));\n\n  if (revents & EV_ERROR)\n    event_del (ev);\n\n  ev_x_cb (ev, revents);\n}\n\nstatic void\nev_x_cb_io (EV_P_ struct ev_io *w, int revents)\n{\n  struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));\n\n  if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))\n    event_del (ev);\n\n  ev_x_cb (ev, revents);\n}\n\nstatic void\nev_x_cb_to (EV_P_ struct ev_timer *w, int revents)\n{\n  struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));\n\n  event_del (ev);\n\n  ev_x_cb (ev, revents);\n}\n\nvoid event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)\n{\n  if (events & EV_SIGNAL)\n    ev_init (&ev->iosig.sig, ev_x_cb_sig);\n  else\n    ev_init (&ev->iosig.io, ev_x_cb_io);\n\n  ev_init (&ev->to, ev_x_cb_to);\n\n  ev->ev_base     = ev_x_cur; /* not threadsafe, but it's how libevent works */\n  ev->ev_fd       = fd;\n  ev->ev_events   = events;\n  ev->ev_pri      = 0;\n  ev->ev_callback = cb;\n  ev->ev_arg      = arg;\n  ev->ev_res      = 0;\n  ev->ev_flags    = EVLIST_INIT;\n}\n\nint event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)\n{\n  return event_base_once (ev_x_cur, fd, events, cb, arg, tv);\n}\n\nint event_add (struct event *ev, struct timeval *tv)\n{\n  dLOOPev;\n\n  if (ev->ev_events & EV_SIGNAL)\n    {\n      if (!ev_is_active (&ev->iosig.sig))\n        {\n          ev_signal_set (&ev->iosig.sig, ev->ev_fd);\n          ev_signal_start (EV_A_ &ev->iosig.sig);\n\n          ev->ev_flags |= EVLIST_SIGNAL;\n        }\n    }\n  else if (ev->ev_events & (EV_READ | EV_WRITE))\n    {\n      if (!ev_is_active (&ev->iosig.io))\n        {\n          ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));\n          ev_io_start (EV_A_ &ev->iosig.io);\n\n          ev->ev_flags |= EVLIST_INSERTED;\n        }\n    }\n\n  if (tv)\n    {\n      ev->to.repeat = ev_tv_get (tv);\n      ev_timer_again (EV_A_ &ev->to);\n      ev->ev_flags |= EVLIST_TIMEOUT;\n    }\n  else\n    {\n      ev_timer_stop (EV_A_ &ev->to);\n      ev->ev_flags &= ~EVLIST_TIMEOUT;\n    }\n\n  ev->ev_flags |= EVLIST_ACTIVE;\n\n  return 0;\n}\n\nint event_del (struct event *ev)\n{\n  dLOOPev;\n\n  if (ev->ev_events & EV_SIGNAL)\n    ev_signal_stop (EV_A_ &ev->iosig.sig);\n  else if (ev->ev_events & (EV_READ | EV_WRITE))\n    ev_io_stop (EV_A_ &ev->iosig.io);\n\n  if (ev_is_active (&ev->to))\n    ev_timer_stop (EV_A_ &ev->to);\n\n  ev->ev_flags = EVLIST_INIT;\n\n  return 0;\n}\n\nvoid event_active (struct event *ev, int res, short ncalls)\n{\n  dLOOPev;\n\n  if (res & EV_TIMEOUT)\n    ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);\n\n  if (res & EV_SIGNAL)\n    ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);\n\n  if (res & (EV_READ | EV_WRITE))\n    ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));\n}\n\nint event_pending (struct event *ev, short events, struct timeval *tv)\n{\n  short revents = 0;\n  dLOOPev;\n\n  if (ev->ev_events & EV_SIGNAL)\n    {\n      /* sig */\n      if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))\n        revents |= EV_SIGNAL;\n    }\n  else if (ev->ev_events & (EV_READ | EV_WRITE))\n    {\n      /* io */\n      if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))\n        revents |= ev->ev_events & (EV_READ | EV_WRITE);\n    }\n\n  if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))\n    {\n      revents |= EV_TIMEOUT;\n\n      if (tv)\n        {\n          ev_tstamp at = ev_now (EV_A);\n\n          tv->tv_sec  = (long)at;\n          tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);\n        }\n    }\n\n  return events & revents;\n}\n\nint event_priority_init (int npri)\n{\n  return event_base_priority_init (ev_x_cur, npri);\n}\n\nint event_priority_set (struct event *ev, int pri)\n{\n  ev->ev_pri = pri;\n\n  return 0;\n}\n\nint event_base_set (struct event_base *base, struct event *ev)\n{\n  ev->ev_base = base;\n\n  return 0;\n}\n\nint event_base_loop (struct event_base *base, int flags)\n{\n  dLOOPbase;\n\n  return !ev_run (EV_A_ flags);\n}\n\nint event_base_dispatch (struct event_base *base)\n{\n  return event_base_loop (base, 0);\n}\n\nstatic void\nev_x_loopexit_cb (int revents, void *base)\n{\n  dLOOPbase;\n\n  ev_break (EV_A_ EVBREAK_ONE);\n}\n\nint event_base_loopexit (struct event_base *base, struct timeval *tv)\n{\n  ev_tstamp after = ev_tv_get (tv);\n  dLOOPbase;\n\n  ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base);\n\n  return 0;\n}\n\nstruct ev_x_once\n{\n  int fd;\n  void (*cb)(int, short, void *);\n  void *arg;\n};\n\nstatic void\nev_x_once_cb (int revents, void *arg)\n{\n  struct ev_x_once *once = (struct ev_x_once *)arg;\n\n  once->cb (once->fd, (short)revents, once->arg);\n  free (once);\n}\n\nint event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)\n{\n  struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once));\n  dLOOPbase;\n\n  if (!once)\n    return -1;\n\n  once->fd  = fd;\n  once->cb  = cb;\n  once->arg = arg;\n\n  ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once);\n\n  return 0;\n}\n\nint event_base_priority_init (struct event_base *base, int npri)\n{\n  /*dLOOPbase;*/\n\n  return 0;\n}\n\n"
  },
  {
    "path": "libev/event.h",
    "content": "/*\n * libevent compatibility header, only core events supported\n *\n * Copyright (c) 2007,2008,2010,2012 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef EVENT_H_\n#define EVENT_H_\n\n#ifdef EV_H\n# include EV_H\n#else\n# include \"ev.h\"\n#endif\n\n#ifndef EVLOOP_NONBLOCK\n# define EVLOOP_NONBLOCK EVRUN_NOWAIT\n#endif\n#ifndef EVLOOP_ONESHOT\n# define EVLOOP_ONESHOT EVRUN_ONCE\n#endif\n#ifndef EV_TIMEOUT\n# define EV_TIMEOUT EV_TIMER\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* we need sys/time.h for struct timeval only */\n#if !defined (WIN32) || defined (__MINGW32__)\n# include <time.h> /* mingw seems to need this, for whatever reason */\n# include <sys/time.h>\n#endif\n\nstruct event_base;\n\n#define EVLIST_TIMEOUT  0x01\n#define EVLIST_INSERTED 0x02\n#define EVLIST_SIGNAL   0x04\n#define EVLIST_ACTIVE   0x08\n#define EVLIST_INTERNAL 0x10\n#define EVLIST_INIT     0x80\n\ntypedef void (*event_callback_fn)(int, short, void *);\n\nstruct event\n{\n  /* libev watchers we map onto */\n  union {\n    struct ev_io io;\n    struct ev_signal sig;\n  } iosig;\n  struct ev_timer to;\n\n  /* compatibility slots */\n  struct event_base *ev_base;\n  event_callback_fn ev_callback;\n  void *ev_arg;\n  int ev_fd;\n  int ev_pri;\n  int ev_res;\n  int ev_flags;\n  short ev_events;\n};\n\nevent_callback_fn event_get_callback (const struct event *ev);\n\n#define EV_READ                    EV_READ\n#define EV_WRITE                   EV_WRITE\n#define EV_PERSIST                 0x10\n#define EV_ET                      0x20 /* nop */\n\n#define EVENT_SIGNAL(ev)           ((int) (ev)->ev_fd)\n#define EVENT_FD(ev)               ((int) (ev)->ev_fd)\n\n#define event_initialized(ev)      ((ev)->ev_flags & EVLIST_INIT)\n\n#define evtimer_add(ev,tv)         event_add (ev, tv)\n#define evtimer_set(ev,cb,data)    event_set (ev, -1, 0, cb, data)\n#define evtimer_del(ev)            event_del (ev)\n#define evtimer_pending(ev,tv)     event_pending (ev, EV_TIMEOUT, tv)\n#define evtimer_initialized(ev)    event_initialized (ev)\n\n#define timeout_add(ev,tv)         evtimer_add (ev, tv)\n#define timeout_set(ev,cb,data)    evtimer_set (ev, cb, data)\n#define timeout_del(ev)            evtimer_del (ev)\n#define timeout_pending(ev,tv)     evtimer_pending (ev, tv)\n#define timeout_initialized(ev)    evtimer_initialized (ev)\n\n#define signal_add(ev,tv)          event_add (ev, tv)\n#define signal_set(ev,sig,cb,data) event_set (ev, sig, EV_SIGNAL | EV_PERSIST, cb, data)\n#define signal_del(ev)             event_del (ev)\n#define signal_pending(ev,tv)      event_pending (ev, EV_SIGNAL, tv)\n#define signal_initialized(ev)     event_initialized (ev)\n\nconst char *event_get_version (void);\nconst char *event_get_method (void);\n\nvoid *event_init (void);\nvoid event_base_free (struct event_base *base);\n\n#define EVLOOP_ONCE      EVLOOP_ONESHOT\nint event_loop (int);\nint event_loopexit (struct timeval *tv);\nint event_dispatch (void);\n\n#define _EVENT_LOG_DEBUG 0\n#define _EVENT_LOG_MSG   1\n#define _EVENT_LOG_WARN  2\n#define _EVENT_LOG_ERR   3\ntypedef void (*event_log_cb)(int severity, const char *msg);\nvoid event_set_log_callback(event_log_cb cb);\n\nvoid event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg);\nint event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv);\n\nint event_add (struct event *ev, struct timeval *tv);\nint event_del (struct event *ev);\nvoid event_active (struct event *ev, int res, short ncalls); /* ncalls is being ignored */\n\nint event_pending (struct event *ev, short, struct timeval *tv);\n\nint event_priority_init (int npri);\nint event_priority_set (struct event *ev, int pri);\n\nstruct event_base *event_base_new (void);\nconst char *event_base_get_method (const struct event_base *);\nint event_base_set (struct event_base *base, struct event *ev);\nint event_base_loop (struct event_base *base, int);\nint event_base_loopexit (struct event_base *base, struct timeval *tv);\nint event_base_dispatch (struct event_base *base);\nint event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv);\nint event_base_priority_init (struct event_base *base, int fd);\n\n/* next line is different in the libevent+libev version */\n/*libevent-include*/\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n"
  },
  {
    "path": "libev/event_compat.h",
    "content": "/*\n * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>\n * Copyright (c) 2008      Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef _WIN32\n# define WIN32_LEAN_AND_MEAN\n# include <windows.h>\n# undef WIN32_LEAN_AND_MEAN\ntypedef unsigned char u_char;\ntypedef unsigned short u_short;\n#else\n# include <sys/types.h>\n# include <sys/time.h>\n# include <inttypes.h>\n#endif\n\n#include <stdarg.h>\n\n/* Fix so that ppl dont have to run with <sys/queue.h> */\n#ifndef TAILQ_ENTRY\n#define _EVENT_DEFINED_TQENTRY\n#define TAILQ_ENTRY(type)\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *tqe_next;\t/* next element */\t\t\t\\\n\tstruct type **tqe_prev;\t/* address of previous next element */\t\\\n}\n#endif /* !TAILQ_ENTRY */\n#ifndef RB_ENTRY\n#define _EVENT_DEFINED_RBENTRY\n#define RB_ENTRY(type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *rbe_left;\t\t/* left element */\t\t\\\n\tstruct type *rbe_right;\t\t/* right element */\t\t\\\n\tstruct type *rbe_parent;\t/* parent element */\t\t\\\n\tint rbe_color;\t\t\t/* node color */\t\t\\\n}\n#endif /* !RB_ENTRY */\n\n/*\n * Key-Value pairs.  Can be used for HTTP headers but also for\n * query argument parsing.\n */\nstruct evkeyval {\n\tTAILQ_ENTRY(evkeyval) next;\n\n\tchar *key;\n\tchar *value;\n};\n\n#ifdef _EVENT_DEFINED_TQENTRY\n#undef TAILQ_ENTRY\nstruct event_list;\nstruct evkeyvalq;\n#undef _EVENT_DEFINED_TQENTRY\n#else\nTAILQ_HEAD (event_list, event);\nTAILQ_HEAD (evkeyvalq, evkeyval);\n#endif /* _EVENT_DEFINED_TQENTRY */\n#ifdef _EVENT_DEFINED_RBENTRY\n#undef RB_ENTRY\n#undef _EVENT_DEFINED_RBENTRY\n#endif /* _EVENT_DEFINED_RBENTRY */\n\nstruct eventop {\n\tchar *name;\n\tvoid *(*init)(struct event_base *);\n\tint (*add)(void *, struct event *);\n\tint (*del)(void *, struct event *);\n\tint (*recalc)(struct event_base *, void *, int);\n\tint (*dispatch)(struct event_base *, void *, struct timeval *);\n\tvoid (*dealloc)(struct event_base *, void *);\n};\n\n/* These functions deal with buffering input and output */\n\nstruct evbuffer {\n\tu_char *buffer;\n\tu_char *orig_buffer;\n\n\tsize_t misalign;\n\tsize_t totallen;\n\tsize_t off;\n\n\tvoid (*cb)(struct evbuffer *, size_t, size_t, void *);\n\tvoid *cbarg;\n};\n\n/* Just for error reporting - use other constants otherwise */\n#define EVBUFFER_READ\t\t0x01\n#define EVBUFFER_WRITE\t\t0x02\n#define EVBUFFER_EOF\t\t0x10\n#define EVBUFFER_ERROR\t\t0x20\n#define EVBUFFER_TIMEOUT\t0x40\n\nstruct bufferevent;\ntypedef void (*evbuffercb)(struct bufferevent *, void *);\ntypedef void (*everrorcb)(struct bufferevent *, short what, void *);\n\nstruct event_watermark {\n\tsize_t low;\n\tsize_t high;\n};\n\nstruct bufferevent {\n\tstruct event ev_read;\n\tstruct event ev_write;\n\n\tstruct evbuffer *input;\n\tstruct evbuffer *output;\n\n\tstruct event_watermark wm_read;\n\tstruct event_watermark wm_write;\n\n\tevbuffercb readcb;\n\tevbuffercb writecb;\n\teverrorcb errorcb;\n\tvoid *cbarg;\n\n\tint timeout_read;\t/* in seconds */\n\tint timeout_write;\t/* in seconds */\n\n\tshort enabled;\t/* events that are currently enabled */\n};\n\nstruct bufferevent *bufferevent_new(int fd,\n    evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);\nint bufferevent_base_set(struct event_base *base, struct bufferevent *bufev);\nint bufferevent_priority_set(struct bufferevent *bufev, int pri);\nvoid bufferevent_free(struct bufferevent *bufev);\nint bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);\nint bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);\nsize_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);\nint bufferevent_enable(struct bufferevent *bufev, short event);\nint bufferevent_disable(struct bufferevent *bufev, short event);\nvoid bufferevent_settimeout(struct bufferevent *bufev,\n    int timeout_read, int timeout_write);\n\n#define EVBUFFER_LENGTH(x)\t(x)->off\n#define EVBUFFER_DATA(x)\t(x)->buffer\n#define EVBUFFER_INPUT(x)\t(x)->input\n#define EVBUFFER_OUTPUT(x)\t(x)->output\n\nstruct evbuffer *evbuffer_new(void);\nvoid evbuffer_free(struct evbuffer *);\nint evbuffer_expand(struct evbuffer *, size_t);\nint evbuffer_add(struct evbuffer *, const void *, size_t);\nint evbuffer_remove(struct evbuffer *, void *, size_t);\nchar *evbuffer_readline(struct evbuffer *);\nint evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);\nint evbuffer_add_printf(struct evbuffer *, const char *fmt, ...);\nint evbuffer_add_vprintf(struct evbuffer *, const char *fmt, va_list ap);\nvoid evbuffer_drain(struct evbuffer *, size_t);\nint evbuffer_write(struct evbuffer *, int);\nint evbuffer_read(struct evbuffer *, int, int);\nu_char *evbuffer_find(struct evbuffer *, const u_char *, size_t);\nvoid evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *);\n\n/*\n * Marshaling tagged data - We assume that all tags are inserted in their\n * numeric order - so that unknown tags will always be higher than the\n * known ones - and we can just ignore the end of an event buffer.\n */\n\nvoid evtag_init(void);\n\nvoid evtag_marshal(struct evbuffer *evbuf, uint32_t tag, const void *data,\n    uint32_t len);\n\nvoid encode_int(struct evbuffer *evbuf, uint32_t number);\n\nvoid evtag_marshal_int(struct evbuffer *evbuf, uint32_t tag, uint32_t integer);\n\nvoid evtag_marshal_string(struct evbuffer *buf, uint32_t tag,\n    const char *string);\n\nvoid evtag_marshal_timeval(struct evbuffer *evbuf, uint32_t tag,\n    struct timeval *tv);\n\nint evtag_unmarshal(struct evbuffer *src, uint32_t *ptag, struct evbuffer *dst);\nint evtag_peek(struct evbuffer *evbuf, uint32_t *ptag);\nint evtag_peek_length(struct evbuffer *evbuf, uint32_t *plength);\nint evtag_payload_length(struct evbuffer *evbuf, uint32_t *plength);\nint evtag_consume(struct evbuffer *evbuf);\n\nint evtag_unmarshal_int(struct evbuffer *evbuf, uint32_t need_tag,\n    uint32_t *pinteger);\n\nint evtag_unmarshal_fixed(struct evbuffer *src, uint32_t need_tag, void *data,\n    size_t len);\n\nint evtag_unmarshal_string(struct evbuffer *evbuf, uint32_t need_tag,\n    char **pstring);\n\nint evtag_unmarshal_timeval(struct evbuffer *evbuf, uint32_t need_tag,\n    struct timeval *ptv);\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "libev/import_libevent",
    "content": "#!/bin/sh\n\nLE=../libevent-1.4.3-stable\n\nif ! [ -e evbuffer.c ]; then\n   echo do not run this programm unless you know what you are doing\n   exit 1\nfi\n\n# this program combines libev and libevent into a single package\n\ncvs update -AdP libev\nrsync -avP libev/. . --exclude CVS\n\nrm -f configure.ac\n\ncp $LE/evdns.h .\n\nperl -i -pe 's%^/.libevent-include./%#include \"event_compat.h\"%' event.h\n\nperl -ne '\n   s/\\s+char buf\\[64\\];/\\tchar buf[96];/;\n   if (/#include \"event.h\"/) {\n      print \"#ifndef EV_STANDALONE\\n$_#endif\\n\";\n      next;\n   }\n   if (/#include \"misc.h\"/) {\n      print \"#ifndef EV_STANDALONE\\n$_#endif\\n\";\n      next;\n   }\n   if (/#include \"(unistd.h|sys\\/time.h)\"/) {\n      print \"#ifndef WIN32\\n$_#endif\\n\";\n      next;\n   }\n   next if /#include \"log.h\"/;\n\n   print;\n' <$LE/evdns.c >evdns.c\n\ncp $LE/autogen.sh .\ncp $LE/epoll_sub.c .\ncp $LE/evbuffer.c .\ncp $LE/buffer.c .\ncp $LE/evhttp.h .\ncp $LE/evutil.h .\ncp $LE/evutil.c .\ncp $LE/event-config.h .\ncp $LE/event-internal.h .\ncp $LE/evrpc.h .\ncp $LE/evrpc.c .\ncp $LE/evrpc-internal.h .\ncp $LE/http.c .\ncp $LE/event_tagging.c .\ncp $LE/http-internal.h .\ncp $LE/strlcpy-internal.h .\ncp $LE/log.c .\ncp $LE/log.h .\ncp $LE/strlcpy.c .\nrsync -a $LE/WIN32* $LE/sample $LE/test $LE/compat . --del\n#rename 's/libevent/libev/' WIN32-Prj/lib*\ncp $LE/aclocal.m4 .\n#cp $LE/acconfig.h .\ncp $LE/config.h.in .\ncp $LE/event_rpcgen.py .\ncp $LE/*.3 .\n\n#perl -i -pe 's/libevent/libev/g' sample/Makefile.am\n#perl -i -pe 's/libevent/libev/g' test/Makefile.am\n\nperl -i -pe 's/#include <event.h>$/#include \"event.h\"/' test/*.c\n\nperl -i -ne '\n   next if /\"event-internal.h\"/;\n   s/base\\d?->sig.ev_signal_added/0/;\n   s/base\\d?->sig.ev_signal_pair\\[0\\]/-1/;\n   s/base->sig.evsignal_caught/0/;\n   next if /^\\ttest_signal_(dealloc|pipeloss|switchbase|assert|restore)\\(\\)/;\n   next if /^\\ttest_simplesignal\\(\\)/; # non-default-loop\n   next if /^\\ttest_immediatesignal\\(\\)/; # non-default-loop\n   next if /test_priorities\\(\\d\\)/;\n   print;\n' test/regress.c\n\nperl -ne '\n   s/\\bmin_heap.h\\b//g;\n   s/\\bsignal.c\\b//g;\n   s/\\bevport.c\\b//g;\n   s/\\bkqueue.c\\b//g;\n   s/\\bdevpoll.c\\b//g;\n   s/\\brtsig.c\\b//g;\n   s/\\bselect.c\\b//g;\n   s/\\bpoll.c\\b//g;\n   s/\\bepoll.c\\b//g;\n   s/\\bepoll_sub.c\\b//g;\n   s/\\bevent-internal.h\\b//g;\n   s/\\bevsignal.h\\b//g;\n   s/^(man_MANS\\s*=)/$1 ev.3 /;\n   s/^(EXTRA_DIST\\s*=)/$1 libev.m4 ev.h ev_vars.h ev_wrap.h event_compat.h ev++.h ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c ev.3 ev.pod /;\n   s/^(include_HEADERS\\s*=)/$1 ev.h event_compat.h ev++.h /;\n   s/^(CORE_SRC\\s*=)/$1 ev.c /;\n   s/^(SYS_LIBS\\s*=)/$1 -lm /;\n   #s/libevent/libev/g;\n   print;\n' <$LE/Makefile.am >Makefile.am\n\nperl -ne '\n   #s/-Wall/-Wall -Wno-comment -Wunused-function -Wno-unused-value/;\n   s/-Wall//g;\n   #s/libevent/libev/g;\n   #VERSION\n   s/AM_INIT_AUTOMAKE\\s*\\(.*,(.*)\\)/AM_INIT_AUTOMAKE(libevent-$1+libev,3.1)/;\n   s/AC_LIBOBJ\\(select\\)/: ;/g;\n   s/AC_LIBOBJ\\(poll\\)/: ;/g;\n   s/AC_LIBOBJ\\(kqueue\\)/: ;/g;\n   s/AC_LIBOBJ\\(epoll\\)/: ;/g;\n   s/AC_LIBOBJ\\(devpoll\\)/: ;/g;\n   s/AC_LIBOBJ\\(evport\\)/: ;/g;\n   s/AC_LIBOBJ\\(signal\\)/: ;/g;\n   s/AC_LIBOBJ\\(rtsig\\)/: ;/g;\n   print \"m4_include([libev.m4])\\n\" if /^AC_OUTPUT/;\n   print;\n' <$LE/configure.in >configure.in\n\naclocal-1.7\nautomake-1.7 --add-missing\nautoconf\nautoheader\nlibtoolize\nCC=\"ccache gcc\" ./configure --prefix=/opt/libev --disable-shared \"$@\"\n\n\n"
  },
  {
    "path": "libev/libev.m4",
    "content": "dnl this file is part of libev, do not make local modifications\ndnl http://software.schmorp.de/pkg/libev\n\ndnl libev support\nAC_CHECK_HEADERS(sys/inotify.h sys/epoll.h sys/event.h port.h poll.h sys/select.h sys/eventfd.h sys/signalfd.h)\n \nAC_CHECK_FUNCS(inotify_init epoll_ctl kqueue port_create poll select eventfd signalfd)\n \nAC_CHECK_FUNCS(clock_gettime, [], [\n   dnl on linux, try syscall wrapper first\n   if test $(uname) = Linux; then\n      AC_MSG_CHECKING(for clock_gettime syscall)\n      AC_LINK_IFELSE([AC_LANG_PROGRAM(\n                      [#include <unistd.h>\n                       #include <sys/syscall.h>\n                       #include <time.h>],\n                      [struct timespec ts; int status = syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts)])],\n                     [ac_have_clock_syscall=1\n                      AC_DEFINE(HAVE_CLOCK_SYSCALL, 1, Define to 1 to use the syscall interface for clock_gettime)\n                      AC_MSG_RESULT(yes)],\n                     [AC_MSG_RESULT(no)])\n   fi\n   if test -z \"$LIBEV_M4_AVOID_LIBRT\" && test -z \"$ac_have_clock_syscall\"; then\n      AC_CHECK_LIB(rt, clock_gettime)\n      unset ac_cv_func_clock_gettime\n      AC_CHECK_FUNCS(clock_gettime)\n   fi\n])\n\nAC_CHECK_FUNCS(nanosleep, [], [\n   if test -z \"$LIBEV_M4_AVOID_LIBRT\"; then\n      AC_CHECK_LIB(rt, nanosleep)\n      unset ac_cv_func_nanosleep\n      AC_CHECK_FUNCS(nanosleep)\n   fi\n])\n\nif test -z \"$LIBEV_M4_AVOID_LIBM\"; then\n   LIBM=m\nfi\nAC_SEARCH_LIBS(floor, $LIBM, [AC_DEFINE(HAVE_FLOOR, 1, Define to 1 if the floor function is available)])\n\n"
  },
  {
    "path": "libev/update_ev_c",
    "content": "#!/bin/sh -e\n\n(\n   sed -ne '1,\\%/\\* ECB.H BEGIN \\*/%p' ev.c\n   cat ~/src/libecb/ecb.h\n   sed -ne '\\%/\\* ECB.H END \\*/%,$p' ev.c\n) >ev.c~ && mv ev.c~ ev.c\n\n"
  },
  {
    "path": "libev/update_ev_wrap",
    "content": "#!/bin/sh\n\n(\n   echo '#define VAR(name,decl) name'\n   echo '#define EV_GENWRAP 1'\n   cat ev_vars.h\n) | cc -E -o - - | perl -ne '\n   while (<>) {\n      push @syms, $1 if /(^\\w+)/;\n   }\n   print \"/* DO NOT EDIT, automatically generated by update_ev_wrap */\\n\",\n         \"#ifndef EV_WRAP_H\\n\",\n         \"#define EV_WRAP_H\\n\",\n         (map \"#define $_ ((loop)->$_)\\n\", sort @syms),\n         \"#else\\n\",\n         \"#undef EV_WRAP_H\\n\",\n         (map \"#undef $_\\n\", sort @syms),\n         \"#endif\\n\";\n' >ev_wrap.h\n"
  },
  {
    "path": "libev/update_symbols",
    "content": "#!/bin/sh\n\nmake ev.o event.o || exit\n\nnm ev.o           | perl -ne 'print \"$1\\n\" if /\\S+ [A-Z] (\\S+)/' > Symbols.ev\nnm event.o        | perl -ne 'print \"$1\\n\" if /\\S+ [A-Z] (\\S+)/' > Symbols.event\n\n"
  },
  {
    "path": "log.cpp",
    "content": "#include \"log.h\"\n#include \"misc.h\"\n\nint log_level = log_info;\n\nint enable_log_position = 0;\nint enable_log_color = 1;\n\nvoid log0(const char* file, const char* function, int line, int level, const char* str, ...) {\n    if (level > log_level) return;\n    if (level > log_trace || level < 0) return;\n\n    time_t timer;\n    char buffer[100];\n    struct tm* tm_info;\n\n    time(&timer);\n    tm_info = localtime(&timer);\n\n    if (enable_log_color)\n        printf(\"%s\", log_color[level]);\n\n    strftime(buffer, 100, \"%Y-%m-%d %H:%M:%S\", tm_info);\n    printf(\"[%s][%s]\", buffer, log_text[level]);\n\n    if (enable_log_position) printf(\"[%s,func:%s,line:%d]\", file, function, line);\n\n    va_list vlist;\n    va_start(vlist, str);\n    vfprintf(stdout, str, vlist);\n    va_end(vlist);\n    if (enable_log_color)\n        printf(\"%s\", RESET);\n\n    // printf(\"\\n\");\n    // if(enable_log_color)\n    // printf(log_color[level]);\n    fflush(stdout);\n\n    if (log_level == log_fatal) {\n        about_to_exit = 1;\n    }\n}\n\nvoid log_bare(int level, const char* str, ...) {\n    if (level > log_level) return;\n    if (level > log_trace || level < 0) return;\n    if (enable_log_color)\n        printf(\"%s\", log_color[level]);\n    va_list vlist;\n    va_start(vlist, str);\n    vfprintf(stdout, str, vlist);\n    va_end(vlist);\n    if (enable_log_color)\n        printf(\"%s\", RESET);\n    fflush(stdout);\n}\n"
  },
  {
    "path": "log.h",
    "content": "\n#ifndef UDP2RAW_LOG_MYLOG_H_\n#define UDP2RAW_LOG_MYLOG_H_\n\n#include \"common.h\"\n\nusing namespace std;\n\n#define RED \"\\x1B[31m\"\n#define GRN \"\\x1B[32m\"\n#define YEL \"\\x1B[33m\"\n#define BLU \"\\x1B[34m\"\n#define MAG \"\\x1B[35m\"\n#define CYN \"\\x1B[36m\"\n#define WHT \"\\x1B[37m\"\n#define RESET \"\\x1B[0m\"\n\nconst int log_never = 0;\nconst int log_fatal = 1;\nconst int log_error = 2;\nconst int log_warn = 3;\nconst int log_info = 4;\nconst int log_debug = 5;\nconst int log_trace = 6;\nconst int log_end = 7;\n\nconst char log_text[][20] = {\"NEVER\", \"FATAL\", \"ERROR\", \"WARN\", \"INFO\", \"DEBUG\", \"TRACE\", \"\"};\nconst char log_color[][20] = {RED, RED, RED, YEL, GRN, MAG, \"\"};\n\nextern int log_level;\nextern int enable_log_position;\nextern int enable_log_color;\n\n#ifdef MY_DEBUG\n#define mylog(__first_argu__dummy_abcde__, ...) printf(__VA_ARGS__)\n\n#else\n#define mylog(...) log0(__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)\n#endif\n\n//#define mylog(__first_argu__dummy_abcde__,...) {;}\n\nvoid log0(const char* file, const char* function, int line, int level, const char* str, ...);\n\nvoid log_bare(int level, const char* str, ...);\n\n#endif\n"
  },
  {
    "path": "main.cpp",
    "content": "#include \"common.h\"\n#include \"network.h\"\n#include \"connection.h\"\n#include \"misc.h\"\n#include \"log.h\"\n#include \"lib/md5.h\"\n#include \"encrypt.h\"\n#include \"fd_manager.h\"\n\nvoid sigpipe_cb(struct ev_loop *l, ev_signal *w, int revents) {\n    mylog(log_info, \"got sigpipe, ignored\");\n}\n\nvoid sigterm_cb(struct ev_loop *l, ev_signal *w, int revents) {\n    mylog(log_info, \"got sigterm, exit\");\n    myexit(0);\n}\n\nvoid sigint_cb(struct ev_loop *l, ev_signal *w, int revents) {\n    mylog(log_info, \"got sigint, exit\");\n    myexit(0);\n}\n\nint client_event_loop();\nint server_event_loop();\n\nint main(int argc, char *argv[]) {\n    assert(sizeof(unsigned short) == 2);\n    assert(sizeof(unsigned int) == 4);\n    assert(sizeof(unsigned long long) == 8);\n\n#ifdef UDP2RAW_MP\n    init_ws();\n#endif\n\n    dup2(1, 2);  // redirect stderr to stdout\n#if defined(__MINGW32__)\n    enable_log_color = 0;\n#endif\n\n    pre_process_arg(argc, argv);\n\n    ev_signal signal_watcher_sigpipe;\n    ev_signal signal_watcher_sigterm;\n    ev_signal signal_watcher_sigint;\n\n    if (program_mode == client_mode) {\n        struct ev_loop *loop = ev_default_loop(0);\n#if !defined(__MINGW32__)\n        ev_signal_init(&signal_watcher_sigpipe, sigpipe_cb, SIGPIPE);\n        ev_signal_start(loop, &signal_watcher_sigpipe);\n#endif\n        ev_signal_init(&signal_watcher_sigterm, sigterm_cb, SIGTERM);\n        ev_signal_start(loop, &signal_watcher_sigterm);\n\n        ev_signal_init(&signal_watcher_sigint, sigint_cb, SIGINT);\n        ev_signal_start(loop, &signal_watcher_sigint);\n    } else {\n#ifdef UDP2RAW_LINUX\n        signal(SIGINT, signal_handler);\n        signal(SIGHUP, signal_handler);\n        signal(SIGKILL, signal_handler);\n        signal(SIGTERM, signal_handler);\n        signal(SIGQUIT, signal_handler);\n#else\n        mylog(log_fatal, \"server mode not supported in multi-platform version\\n\");\n        myexit(-1);\n#endif\n    }\n#if !defined(__MINGW32__)\n    if (geteuid() != 0) {\n        mylog(log_warn, \"root check failed, it seems like you are using a non-root account. we can try to continue, but it may fail. If you want to run udp2raw as non-root, you have to add iptables rule manually, and grant udp2raw CAP_NET_RAW capability, check README.md in repo for more info.\\n\");\n    } else {\n        mylog(log_warn, \"you can run udp2raw with non-root account for better security. check README.md in repo for more info.\\n\");\n    }\n#endif\n\n    mylog(log_info, \"remote_ip=[%s], make sure this is a vaild IP address\\n\", remote_addr.get_ip());\n\n    // init_random_number_fd();\n    srand(get_true_random_number_nz());\n    const_id = get_true_random_number_nz();\n\n    mylog(log_info, \"const_id:%x\\n\", const_id);\n\n    my_init_keys(key_string, program_mode == client_mode ? 1 : 0);\n\n    iptables_rule();\n\n#ifdef UDP2RAW_LINUX\n    init_raw_socket();\n#endif\n\n    if (program_mode == client_mode) {\n        client_event_loop();\n    } else {\n#ifdef UDP2RAW_LINUX\n        server_event_loop();\n#else\n        mylog(log_fatal, \"server mode not supported in multi-platform version\\n\");\n        myexit(-1);\n#endif\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "makefile",
    "content": "cc_cross=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-g++\ncc_local=g++\ncc_mips24kc_be=/toolchains/lede-sdk-17.01.2-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl-1.1.16/bin/mips-openwrt-linux-musl-g++\ncc_mips24kc_le=/toolchains/lede-sdk-17.01.2-ramips-mt7621_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.16/bin/mipsel-openwrt-linux-musl-g++\ncc_arm= /toolchains/lede-sdk-17.01.2-bcm53xx_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a9_gcc-5.4.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-c++\ncc_mingw_cross=i686-w64-mingw32-g++-posix\ncc_mac_cross=o64-clang++ -stdlib=libc++\ncc_x86=/toolchains/lede-sdk-17.01.2-x86-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-i386_pentium4_gcc-5.4.0_musl-1.1.16/bin/i486-openwrt-linux-c++\ncc_amd64=/toolchains/lede-sdk-17.01.2-x86-64_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-x86_64_gcc-5.4.0_musl-1.1.16/bin/x86_64-openwrt-linux-c++\n#cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ \n\n\nFLAGS= -std=c++11   -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT}\n\nCOMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp  connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread\n\nSOURCES0= $(COMMON) lib/aes_faster_c/aes.cpp lib/aes_faster_c/wrapper.cpp\nSOURCES= ${SOURCES0} my_ev.cpp -isystem libev\nSOURCES_AES_ACC= $(COMMON) $(wildcard lib/aes_acc/aes*.c) my_ev.cpp -isystem libev\nPCAP=\"-lpcap\"\nMP=\"-DUDP2RAW_MP\"\n\n\nNAME=udp2raw\n\nTARGETS=amd64 arm amd64_hw_aes arm_asm_aes mips24kc_be mips24kc_be_asm_aes x86 x86_asm_aes mips24kc_le mips24kc_le_asm_aes\n\nTAR=${NAME}_binaries.tar.gz `echo ${TARGETS}|sed -r 's/([^ ]+)/${NAME}_\\1/g'` version.txt\n\nTARGETS_MP= mingw_cross mingw_cross_wepoll mac_cross\n\nexport STAGING_DIR=/tmp/    #just for supress warning of staging_dir not define\n\n# targets for nativei (non-cross) compile \nall:git_version\n\trm -f ${NAME}\n\t${cc_local}   -o ${NAME}          -I. ${SOURCES} ${FLAGS} -lrt -ggdb -static -O2\n\n#dynamic link\ndynamic: git_version\n\t${cc_local}   -o ${NAME}_$@          -I. ${SOURCES} ${FLAGS} -lrt -O2\n\n#targes for general cross compile\n\ncross:git_version\n\t${cc_cross}   -o ${NAME}_cross    -I. ${SOURCES} ${FLAGS} -lrt -O2\n\ncross2:git_version\n\t${cc_cross}   -o ${NAME}_cross    -I. ${SOURCES} ${FLAGS} -lrt -static -lgcc_eh -O2\n\ncross3:git_version\n\t${cc_cross}   -o ${NAME}_cross    -I. ${SOURCES} ${FLAGS} -lrt -static -O2\n\n#targets only for debug purpose\nfast: git_version\n\trm -f ${NAME}\n\t${cc_local}   -o ${NAME}          -I. ${SOURCES} ${FLAGS} -lrt -ggdb\ndebug: git_version\n\trm -f ${NAME}\n\t${cc_local}   -o ${NAME}          -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG  -ggdb\ndebug2: git_version\n\trm -f ${NAME}\n\t${cc_local}   -o ${NAME}          -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -ggdb -fsanitize=address\n\n#targets only for 'make release'\n\nmips24kc_be: git_version\n\t${cc_mips24kc_be}  -o ${NAME}_$@   -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O2\nmips24kc_be_asm_aes: git_version\n\t${cc_mips24kc_be}  -o ${NAME}_$@   -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -lgcc_eh -static -O2 lib/aes_acc/asm/mips_be.S\nmips24kc_le: git_version\n\t${cc_mips24kc_le}  -o ${NAME}_$@   -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O2\nmips24kc_le_asm_aes: git_version\n\t${cc_mips24kc_le}  -o ${NAME}_$@   -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -lgcc_eh -static -O2 lib/aes_acc/asm/mips.S\namd64:git_version\n\t${cc_amd64}   -o ${NAME}_$@    -I. ${SOURCES} ${FLAGS} -lrt -static -O2 -lgcc_eh -ggdb\namd64_hw_aes:git_version\n\t${cc_amd64}   -o ${NAME}_$@   -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O2 lib/aes_acc/asm/x64.S -lgcc_eh -ggdb\nx86:git_version\n\t${cc_x86}   -o ${NAME}_$@      -I. ${SOURCES} ${FLAGS} -lrt -static -O2 -lgcc_eh -ggdb\nx86_asm_aes:git_version\n\t${cc_x86}   -o ${NAME}_$@    -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O2 lib/aes_acc/asm/x86.S -lgcc_eh -ggdb\narm:git_version\n\t${cc_arm}   -o ${NAME}_$@      -I. ${SOURCES} ${FLAGS} -lrt -static -O2 -lgcc_eh\narm_asm_aes:git_version\n\t${cc_arm}   -o ${NAME}_$@    -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O2 lib/aes_acc/asm/arm.S -lgcc_eh\n\nrelease: ${TARGETS}\n\tcp git_version.h version.txt\n\ttar -zcvf ${TAR}\n\n#targets for multi-platform version (native compile)\ncygwin:git_version\n\t${cc_local}   -o ${NAME}_$@          -I. ${SOURCES} pcap_wrapper.cpp ${FLAGS} -lrt -ggdb -static -O2 -D_GNU_SOURCE ${MP}\n\nmingw:git_version\n\t${cc_local}   -o ${NAME}_$@         -I. ${SOURCES} pcap_wrapper.cpp ${FLAGS} -ggdb -static -O2 -lws2_32 ${MP}\n\nmingw_wepoll:git_version\n\t${cc_local}   -o ${NAME}_$@        -I. ${SOURCES0} pcap_wrapper.cpp ${FLAGS} -ggdb -static -O2 -DNO_LIBEV_EMBED -D_WIN32 -lev -lws2_32 ${MP}\n\nlinux:git_version\n\t${cc_local}   -o ${NAME}_$@          -I. ${SOURCES} ${PCAP} ${FLAGS} -lrt -ggdb -static -O2 ${MP}\n\nfreebsd:git_version\n\t${cc_local}   -o ${NAME}_$@        -I. ${SOURCES} ${PCAP} ${FLAGS} -lrt -ggdb -static -libverbs -O2 ${MP}\n\nmac:git_version\n\t${cc_local}   -o ${NAME}_$@        -I. ${SOURCES} ${PCAP} ${FLAGS} -ggdb -O2 ${MP}\n\n#targets for multi-platform version (cross compile)\n\nmingw_cross:git_version\n\t${cc_mingw_cross}   -o ${NAME}_mp.exe          -I. ${SOURCES} pcap_wrapper.cpp ${FLAGS} -ggdb -static -O2 -lws2_32 ${MP}\n\nmingw_cross_wepoll:git_version\n\t${cc_mingw_cross}   -o ${NAME}_mp_wepoll.exe   -I. ${SOURCES0} pcap_wrapper.cpp ${FLAGS} -ggdb -static -O2 -DNO_LIBEV_EMBED -D_WIN32 -lev -lws2_32 ${MP}\n\nmac_cross:git_version\n\t${cc_mac_cross}   -o ${NAME}_mp_mac            -I. ${SOURCES} ${PCAP} ${FLAGS} -ggdb -O2 ${MP}\n\nrelease_mp:${TARGETS_MP}\n\tcp git_version.h version.txt\n\ttar -zcvf ${NAME}_mp_binaries.tar.gz ${NAME}_mp.exe ${NAME}_mp_wepoll.exe ${NAME}_mp_mac version.txt\n\n\nclean:\t\n\trm -f ${TAR}\n\trm -f ${NAME} ${NAME}_cross ${NAME}.exe ${NAME}_wepoll.exe ${NAME}_mac\n\trm -f ${NAME}_mp_binaries.tar.gz ${NAME}_mp.exe ${NAME}_mp_wepoll.exe ${NAME}_mp_mac\n\trm -f git_version.h\n\ngit_version:\n\t    echo \"const char *gitversion = \\\"$(shell git rev-parse HEAD)\\\";\" > git_version.h\n"
  },
  {
    "path": "misc.cpp",
    "content": "/*\n * misc.cpp\n *\n *  Created on: Sep 23, 2017\n *      Author: root\n */\n#include \"git_version.h\"\n#include \"common.h\"\n#include \"encrypt.h\"\n#include \"misc.h\"\n#include \"network.h\"\n#include \"connection.h\"\n#include \"fd_manager.h\"\n\nint hb_mode = 1;\nint hb_len = 1200;\nchar hb_buf[buf_len];\n\nint mtu_warn = 1375;  // if a packet larger than mtu warn is receviced,there will be a warning\n\nint max_rst_to_show = 15;\n\nint max_rst_allowed = -1;\n\nint enable_dns_resolve = 0;\n\nint ttl_value = 64;\n\nfd_manager_t fd_manager;\n\n// char remote_address[max_address_len]=\"\";\n// char local_ip[100]=\"0.0.0.0\", remote_ip[100]=\"255.255.255.255\",source_ip[100]=\"0.0.0.0\";//local_ip is for -l option,remote_ip for -r option,source for --source-ip\n// u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.\n// int local_port = -1, remote_port=-1,source_port=0;//similiar to local_ip  remote_ip,buf for port.source_port=0 indicates --source-port is not enabled\naddress_t local_addr, remote_addr, source_addr;\n\nmy_ip_t bind_addr;\n\nint source_port = -1;\n\nint bind_addr_used = 0;\nint force_source_ip = 0;  // if --source-ip is enabled\nint force_source_port = 0;\n\nmy_id_t const_id = 0;  // an id used for connection recovery,its generated randomly,it never change since its generated\n\nint udp_fd = -1;   // for client only. client use this fd to listen and handle udp connection\nint bind_fd = -1;  // bind only,never send or recv.  its just a dummy fd for bind,so that other program wont occupy the same port\n#ifdef UDP2RAW_LINUX\nint epollfd = -1;   // fd for epoll\nint timer_fd = -1;  // the general timer fd for client and server.for server this is not the only timer find,every connection has a timer fd.\n#endif\nint fail_time_counter = 0;      // determine if the max_fail_time is reached\nint epoll_trigger_counter = 0;  // for debug only\nint debug_flag = 0;             // for debug only\n\nint simple_rule = 0;                 // deprecated.\nint keep_rule = 0;                   // whether to monitor the iptables rule periodly,re-add if losted\nint auto_add_iptables_rule = 0;      // if -a is set\nint generate_iptables_rule = 0;      // if -g is set\nint generate_iptables_rule_add = 0;  // if --gen-add is set\n\nint retry_on_error = 0;\n\nint debug_resend = 0;  // debug only\n\nchar key_string[1000] = \"secret key\";  // -k option\n\nchar fifo_file[1000] = \"\";\n\nint clear_iptables = 0;\nint wait_xtables_lock = 0;\n#ifdef UDP2RAW_LINUX\nstring iptables_command0 = \"iptables/ip6tables \";\nstring iptables_command = \"\";\nstring iptables_pattern = \"\";\nint iptables_rule_added = 0;\nint iptables_rule_keeped = 0;\nint iptables_rule_keep_index = 0;\n#endif\n\nprogram_mode_t program_mode = unset_mode;  // 0 unset; 1client 2server\nraw_mode_t raw_mode = mode_faketcp;\nu32_t raw_ip_version = (u32_t)-1;\nunordered_map<int, const char *> raw_mode_tostring = {{mode_faketcp, \"faketcp\"}, {mode_udp, \"udp\"}, {mode_icmp, \"icmp\"}};\n\nint about_to_exit = 0;\n\nint socket_buf_size = 1024 * 1024;\n// int force_socket_buf=0;\n\n// char lower_level_arg[1000];\n#ifdef UDP2RAW_LINUX\nint process_lower_level_arg()  // handle --lower-level option\n{\n    lower_level = 1;\n    if (strcmp(optarg, \"auto\") == 0) {\n        return 0;\n    }\n\n    lower_level_manual = 1;\n    if (strchr(optarg, '#') == 0) {\n        mylog(log_fatal,\n              \"lower-level parameter invaild,check help page for format\\n\");\n        myexit(-1);\n    }\n    lower_level = 1;\n    u32_t hw[6];\n    memset(hw, 0, sizeof(hw));\n    sscanf(optarg, \"%[^#]#%x:%x:%x:%x:%x:%x\", if_name, &hw[0], &hw[1], &hw[2],\n           &hw[3], &hw[4], &hw[5]);\n\n    mylog(log_warn,\n          \"make sure this is correct:   if_name=<%s>  dest_mac_adress=<%02x:%02x:%02x:%02x:%02x:%02x>  \\n\",\n          if_name, hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);\n    for (int i = 0; i < 6; i++) {\n        dest_hw_addr[i] = uint8_t(hw[i]);\n    }\n    return 0;\n}\n#endif\nvoid print_help() {\n    char git_version_buf[100] = {0};\n    strncpy(git_version_buf, gitversion, 10);\n    printf(\"udp2raw-tunnel\\n\");\n    printf(\"git version:%s    \", git_version_buf);\n    printf(\"build date:%s %s\\n\", __DATE__, __TIME__);\n    printf(\"repository: https://github.com/wangyu-/udp2raw-tunnel\\n\");\n    printf(\"\\n\");\n#ifdef UDP2RAW_MP\n#ifdef NO_LIBNET\n    printf(\"libnet is disabled at compile time\\n\");\n    printf(\"\\n\");\n#endif\n#endif\n    printf(\"usage:\\n\");\n    printf(\"    run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port  [options]\\n\");\n    printf(\"    run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port  [options]\\n\");\n    printf(\"\\n\");\n    printf(\"common options,these options must be same on both side:\\n\");\n    printf(\"    --raw-mode            <string>        available values:faketcp(default),udp,icmp and easy-faketcp\\n\");\n    printf(\"    -k,--key              <string>        password to gen symetric key,default:\\\"secret key\\\"\\n\");\n    printf(\"    --cipher-mode         <string>        available values:aes128cfb,aes128cbc(default),xor,none\\n\");\n    printf(\"    --auth-mode           <string>        available values:hmac_sha1,md5(default),crc32,simple,none\\n\");\n    printf(\"    -a,--auto-rule                        auto add (and delete) iptables rule\\n\");\n    printf(\"    -g,--gen-rule                         generate iptables rule then exit,so that you can copy and\\n\");\n    printf(\"                                          add it manually.overrides -a\\n\");\n    printf(\"    --disable-anti-replay                 disable anti-replay,not suggested\\n\");\n    printf(\"    --fix-gro                             try to fix huge packet caused by GRO. this option is at an early stage.\\n\");\n    printf(\"                                          make sure client and server are at same version.\\n\");\n\n    // printf(\"\\n\");\n    printf(\"client options:\\n\");\n    printf(\"    --source-ip           <ip>            force source-ip for raw socket\\n\");\n    printf(\"    --source-port         <port>          force source-port for raw socket,tcp/udp only\\n\");\n    printf(\"                                          this option disables port changing while re-connecting\\n\");\n    //\tprintf(\"                                          \\n\");\n    printf(\"other options:\\n\");\n    printf(\"    --conf-file           <string>        read options from a configuration file instead of command line.\\n\");\n    printf(\"                                          check example.conf in repo for format\\n\");\n    printf(\"    --fifo                <string>        use a fifo(named pipe) for sending commands to the running program,\\n\");\n    printf(\"                                          check readme.md in repository for supported commands.\\n\");\n    printf(\"    --log-level           <number>        0:never    1:fatal   2:error   3:warn \\n\");\n    printf(\"                                          4:info (default)     5:debug   6:trace\\n\");\n    //\tprintf(\"\\n\");\n    printf(\"    --log-position                        enable file name,function name,line number in log\\n\");\n    printf(\"    --disable-color                       disable log color\\n\");\n    printf(\"    --disable-bpf                         disable the kernel space filter,most time its not necessary\\n\");\n    printf(\"                                          unless you suspect there is a bug\\n\");\n//\tprintf(\"\\n\");\n#ifdef UDP2RAW_LINUX\n    printf(\"    --dev                 <string>        bind raw socket to a device, not necessary but improves performance\\n\");\n#endif\n    printf(\"    --sock-buf            <number>        buf size for socket,>=10 and <=10240,unit:kbyte,default:1024\\n\");\n    printf(\"    --force-sock-buf                      bypass system limitation while setting sock-buf\\n\");\n    printf(\"    --seq-mode            <number>        seq increase mode for faketcp:\\n\");\n    printf(\"                                          0:static header,do not increase seq and ack_seq\\n\");\n    printf(\"                                          1:increase seq for every packet,simply ack last seq\\n\");\n    printf(\"                                          2:increase seq randomly, about every 3 packets,simply ack last seq\\n\");\n    printf(\"                                          3:simulate an almost real seq/ack procedure(default)\\n\");\n    printf(\"                                          4:similiar to 3,but do not consider TCP Option Window_Scale,\\n\");\n    printf(\"                                          maybe useful when firewall doesnt support TCP Option \\n\");\n    //\tprintf(\"\\n\");\n    printf(\"    --lower-level         <string>        send packets at OSI level 2, format:'if_name#dest_mac_adress'\\n\");\n    printf(\"                                          ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain\\n\");\n    printf(\"                                          the parameter automatically,specify it manually if 'auto' failed\\n\");\n    printf(\"    --wait-lock                           wait for xtables lock while invoking iptables, need iptables v1.4.20+\\n\");\n    printf(\"    --gen-add                             generate iptables rule and add it permanently,then exit.overrides -g\\n\");\n    printf(\"    --keep-rule                           monitor iptables and auto re-add if necessary.implys -a\\n\");\n    printf(\"    --hb-len              <number>        length of heart-beat packet, >=0 and <=1500\\n\");\n    printf(\"    --mtu-warn            <number>        mtu warning threshold, unit:byte, default:1375\\n\");\n    printf(\"    --clear                               clear any iptables rules added by this program.overrides everything\\n\");\n    printf(\"    --retry-on-error                      retry on error, allow to start udp2raw before network is initialized\\n\");\n    printf(\"    -h,--help                             print this help message\\n\");\n    // printf(\"common options,these options must be same on both side\\n\");\n}\n\nint load_config(char *file_name, int &argc, vector<string> &argv)  // load conf file and append to argv\n{\n    // Load configurations from config_file instead of the command line.\n    // See config.example for example configurations\n    std::ifstream conf_file(file_name);\n    std::string line;\n    if (conf_file.fail()) {\n        mylog(log_fatal, \"conf_file %s open failed,reason :%s\\n\", file_name, get_sock_error());\n        myexit(-1);\n    }\n    while (std::getline(conf_file, line)) {\n        auto res = parse_conf_line(line);\n\n        argc += res.size();\n        for (int i = 0; i < (int)res.size(); i++) {\n            argv.push_back(res[i]);\n        }\n    }\n    conf_file.close();\n\n    return 0;\n}\n\nint process_log_level(int argc, char *argv[])  // process  --log-level and --disable-cloer --log-postion options\n{\n    int i, j, k;\n    for (i = 0; i < argc; i++) {\n        if (strcmp(argv[i], \"--log-level\") == 0) {\n            if (i < argc - 1) {\n                sscanf(argv[i + 1], \"%d\", &log_level);\n                if (0 <= log_level && log_level < log_end) {\n                } else {\n                    log_bare(log_fatal, \"invalid log_level\\n\");\n                    myexit(-1);\n                }\n            }\n        }\n        if (strcmp(argv[i], \"--enable-color\") == 0) {\n            enable_log_color = 1;\n        }\n        if (strcmp(argv[i], \"--disable-color\") == 0) {\n            enable_log_color = 0;\n        }\n        if (strcmp(argv[i], \"--log-position\") == 0) {\n            enable_log_position = 1;\n        }\n    }\n    return 0;\n}\nvoid process_arg(int argc, char *argv[])  // process all options\n{\n    int i, j, k, opt;\n\n    int option_index = 0;\n\n    char options[] = \"l:r:schk:ag\";\n    static struct option long_options[] =\n        {\n            /* These options set a flag. */\n            {\"source-ip\", required_argument, 0, 1},\n            {\"source-port\", required_argument, 0, 1},\n            {\"log-level\", required_argument, 0, 1},\n            {\"key\", required_argument, 0, 'k'},\n            {\"auth-mode\", required_argument, 0, 1},\n            {\"cipher-mode\", required_argument, 0, 1},\n            {\"raw-mode\", required_argument, 0, 1},\n            {\"disable-color\", no_argument, 0, 1},\n            {\"enable-color\", no_argument, 0, 1},\n            {\"log-position\", no_argument, 0, 1},\n            {\"disable-bpf\", no_argument, 0, 1},\n            {\"disable-anti-replay\", no_argument, 0, 1},\n            {\"auto-rule\", no_argument, 0, 'a'},\n            {\"gen-rule\", no_argument, 0, 'g'},\n            {\"gen-add\", no_argument, 0, 1},\n            {\"debug\", no_argument, 0, 1},\n            {\"retry-on-error\", no_argument, 0, 1},\n            {\"clear\", no_argument, 0, 1},\n            {\"simple-rule\", no_argument, 0, 1},\n            {\"keep-rule\", no_argument, 0, 1},\n            {\"lower-level\", required_argument, 0, 1},\n            {\"sock-buf\", required_argument, 0, 1},\n            {\"seq-mode\", required_argument, 0, 1},\n            {\"conf-file\", required_argument, 0, 1},\n            {\"force-sock-buf\", no_argument, 0, 1},\n            {\"wait-lock\", no_argument, 0, 1},\n            {\"random-drop\", required_argument, 0, 1},\n            {\"fifo\", required_argument, 0, 1},\n            {\"hb-mode\", required_argument, 0, 1},\n            {\"hb-len\", required_argument, 0, 1},\n            {\"mtu-warn\", required_argument, 0, 1},\n            {\"max-rst-to-show\", required_argument, 0, 1},\n            {\"max-rst-allowed\", required_argument, 0, 1},\n            {\"set-ttl\", required_argument, 0, 1},\n            {\"dev\", required_argument, 0, 1},\n            {\"dns-resolve\", no_argument, 0, 1},\n            {\"easy-tcp\", no_argument, 0, 1},\n#ifdef UDP2RAW_MP\n            {\"pcap-send\", no_argument, 0, 1},\n            {\"no-pcap-mutex\", no_argument, 0, 1},\n#endif\n            {\"fix-gro\", no_argument, 0, 1},\n            {NULL, 0, 0, 0}};\n\n    process_log_level(argc, argv);\n\n    set<string> all_options;\n    map<string, string> shortcut_map;\n\n    all_options.insert(\"--help\");\n    all_options.insert(\"-h\");\n    string dummy = \"\";\n    for (i = 0; i < (int)strlen(options); i++) {\n        char val = options[i];\n        if ((val >= '0' && val <= '9') || (val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z')) {\n            all_options.insert(dummy + '-' + val);\n        }\n    }\n    for (i = 0; i < int(sizeof(long_options) / sizeof(long_options[0])); i++) {\n        if (long_options[i].name == NULL) break;\n        int val = long_options[i].val;\n        if ((val >= '0' && val <= '9') || (val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z')) {\n            shortcut_map[dummy + \"--\" + long_options[i].name] = dummy + \"-\" + char(val);\n        }\n        all_options.insert(dummy + \"--\" + long_options[i].name);\n    }\n\n    for (i = 0; i < argc; i++) {\n        int len = strlen(argv[i]);\n        if (len == 0) {\n            mylog(log_fatal, \"found an empty string in options\\n\");\n            myexit(-1);\n        }\n        if (len == 1 && argv[i][0] == '-') {\n            mylog(log_fatal, \"invaild option '-' in argv\\n\");\n            myexit(-1);\n        }\n        if (len == 2 && argv[i][0] == '-' && argv[i][1] == '-') {\n            mylog(log_fatal, \"invaild option '--' in argv\\n\");\n            myexit(-1);\n        }\n    }\n\n    mylog(log_info, \"argc=%d \", argc);\n\n    for (i = 0; i < argc; i++) {\n        log_bare(log_info, \"%s \", argv[i]);\n    }\n    log_bare(log_info, \"\\n\");\n\n    // string dummy=\"\";\n    for (i = +1; i < argc; i++) {\n        if (argv[i][0] != '-') continue;\n        string a = argv[i];\n        if (a[0] == '-' && a[1] != '-')\n            a = dummy + a[0] + a[1];\n\n        if (all_options.find(a.c_str()) == all_options.end()) {\n            mylog(log_fatal, \"invaild option %s\\n\", a.c_str());\n            myexit(-1);\n        }\n        for (j = i + 1; j < argc; j++) {\n            if (argv[j][0] != '-') continue;\n\n            string b = argv[j];\n\n            if (b[0] == '-' && b[1] != '-')\n                b = dummy + b[0] + b[1];\n\n            if (shortcut_map.find(a) != shortcut_map.end())\n                a = shortcut_map[a];\n            if (shortcut_map.find(b) != shortcut_map.end())\n                b = shortcut_map[b];\n            if (a == b) {\n                mylog(log_fatal, \"%s duplicates with %s\\n\", argv[i], argv[j]);\n                myexit(-1);\n            }\n        }\n    }\n\n    int no_l = 1, no_r = 1;\n    while ((opt = getopt_long(argc, argv, options, long_options, &option_index)) != -1) {\n        // string opt_key;\n        // opt_key+=opt;\n        switch (opt) {\n            case 'l':\n                no_l = 0;\n                local_addr.from_str(optarg);\n                if (local_addr.get_port() == 22) {\n                    mylog(log_fatal, \"port 22 not allowed\\n\");\n                    myexit(-1);\n                }\n                /*\n                if (strchr(optarg, ':') != 0) {\n                        sscanf(optarg, \"%[^:]:%d\", local_ip, &local_port);\n                        if(local_port==22)\n                        {\n                                mylog(log_fatal,\"port 22 not allowed\\n\");\n                                myexit(-1);\n                        }\n                } else {\n                        mylog(log_fatal,\"invalid parameter for -l ,%s,should be ip:port\\n\",optarg);\n                        myexit(-1);\n                }*/\n                break;\n            case 'r':\n                no_r = 0;\n                remote_addr.from_str(optarg);\n                if (remote_addr.get_port() == 22) {\n                    mylog(log_fatal, \"port 22 not allowed\\n\");\n                    myexit(-1);\n                }\n                /*\n                if (strchr(optarg, ':') != 0) {\n                        sscanf(optarg, \"%[^:]:%d\", remote_address, &remote_port);\n                        if(remote_port==22)\n                        {\n                                mylog(log_fatal,\"port 22 not allowed\\n\");\n                                myexit(-1);\n                        }\n                } else {\n                        mylog(log_fatal,\"invalid parameter for -r ,%s,should be ip:port\\n\",optarg);\n                        myexit(-1);\n                }*/\n                break;\n            case 's':\n                if (program_mode == 0) {\n                    program_mode = server_mode;\n                } else {\n                    mylog(log_fatal, \"-s /-c has already been set,conflict\\n\");\n                    myexit(-1);\n                }\n                break;\n            case 'c':\n                if (program_mode == 0) {\n                    program_mode = client_mode;\n                } else {\n                    mylog(log_fatal, \"-s /-c has already been set,conflict\\n\");\n                    myexit(-1);\n                }\n                break;\n            case 'h':\n                break;\n            case 'a':\n                if (is_udp2raw_mp) {\n                    mylog(log_fatal, \"-a not supported in this version, check -g or --raw-mode easyfaketcp\\n\");\n                    myexit(-1);\n                }\n                auto_add_iptables_rule = 1;\n                break;\n            case 'g':\n                generate_iptables_rule = 1;\n                break;\n            case 'k':\n                mylog(log_debug, \"parsing key option\\n\");\n                sscanf(optarg, \"%s\", key_string);\n                break;\n            case 1:\n                mylog(log_debug, \"option_index: %d\\n\", option_index);\n                if (strcmp(long_options[option_index].name, \"clear\") == 0) {\n                    if (is_udp2raw_mp) {\n                        mylog(log_fatal, \"--clear not supported in this version\\n\");\n                        myexit(-1);\n                    }\n\n                    clear_iptables = 1;\n                } else if (strcmp(long_options[option_index].name, \"source-ip\") == 0) {\n                    mylog(log_debug, \"parsing long option :source-ip\\n\");\n                    // sscanf(optarg, \"%s\", source_ip);\n                    source_addr.from_str_ip_only(optarg);\n                    mylog(log_debug, \"source: %s\\n\", source_addr.get_ip());\n                    force_source_ip = 1;\n                } else if (strcmp(long_options[option_index].name, \"source-port\") == 0) {\n                    mylog(log_debug, \"parsing long option :source-port\\n\");\n                    sscanf(optarg, \"%d\", &source_port);\n                    mylog(log_info, \"source: %d\\n\", source_port);\n                    force_source_port = 1;\n                } else if (strcmp(long_options[option_index].name, \"raw-mode\") == 0) {\n                    /*\n                    for(i=0;i<mode_end;i++)\n                    {\n                            if(strcmp(optarg,raw_mode_tostring[i])==0)\n                            {\n                                    //printf(\"%d i\\n\",i);\n                                    //printf(\"%s\",raw_mode_tostring[i]);\n                                    raw_mode=(raw_mode_t)i;\n                                    break;\n                            }\n                    }\n                    if(i==mode_end)\n                    {\n                            mylog(log_fatal,\"no such raw_mode %s\\n\",optarg);\n                            myexit(-1);\n                    }\n                     */\n                    if (strcmp(optarg, \"easyfaketcp\") == 0 || strcmp(optarg, \"easy_faketcp\") == 0 || strcmp(optarg, \"easy-faketcp\") == 0) {\n                        raw_mode = mode_faketcp;\n                        use_tcp_dummy_socket = 1;\n                    } else {\n                        for (i = 0; i < mode_end; i++) {\n                            if (strcmp(optarg, raw_mode_tostring[i]) == 0) {\n                                // printf(\"%d i\\n\",i);\n                                // printf(\"%s\",raw_mode_tostring[i]);\n                                raw_mode = (raw_mode_t)i;\n                                break;\n                            }\n                        }\n                        if (i == mode_end) {\n                            mylog(log_fatal, \"no such raw_mode %s\\n\", optarg);\n                            myexit(-1);\n                        }\n                    }\n                } else if (strcmp(long_options[option_index].name, \"auth-mode\") == 0) {\n                    for (i = 0; i < auth_end; i++) {\n                        if (strcmp(optarg, auth_mode_tostring[i]) == 0) {\n                            auth_mode = (auth_mode_t)i;\n                            if (auth_mode == auth_none) {\n                                disable_anti_replay = 1;\n                            }\n                            break;\n                        }\n                    }\n                    if (i == auth_end) {\n                        mylog(log_fatal, \"no such auth_mode %s\\n\", optarg);\n                        myexit(-1);\n                    }\n                } else if (strcmp(long_options[option_index].name, \"cipher-mode\") == 0) {\n                    string s = optarg;\n                    if (s == \"aes128cfb_0\") {\n                        s = \"aes128cfb\";\n                        aes128cfb_old = 1;\n                        mylog(log_warn, \"aes128cfb_0 is used\\n\");\n                    }\n                    for (i = 0; i < cipher_end; i++) {\n                        if (strcmp(s.c_str(), cipher_mode_tostring[i]) == 0) {\n                            cipher_mode = (cipher_mode_t)i;\n                            break;\n                        }\n                    }\n                    if (i == cipher_end) {\n                        mylog(log_fatal, \"no such cipher_mode %s\\n\", optarg);\n                        myexit(-1);\n                    }\n                } else if (strcmp(long_options[option_index].name, \"log-level\") == 0) {\n                } else if (strcmp(long_options[option_index].name, \"lower-level\") == 0) {\n                    if (is_udp2raw_mp) {\n                        mylog(log_fatal, \"--lower-level not supported in this version\\n\");\n                        myexit(-1);\n                    }\n\n#ifdef UDP2RAW_LINUX\n                    process_lower_level_arg();\n#endif\n                    // process_lower_level_arg();\n                    // lower_level=1;\n                    // strcpy(lower_level_arg,optarg);\n                } else if (strcmp(long_options[option_index].name, \"simple-rule\") == 0) {\n                    if (is_udp2raw_mp) {\n                        mylog(log_fatal, \"--simple-rule not supported in this version\\n\");\n                        myexit(-1);\n                    }\n                    simple_rule = 1;\n                } else if (strcmp(long_options[option_index].name, \"keep-rule\") == 0) {\n                    if (is_udp2raw_mp) {\n                        mylog(log_fatal, \"--keep-rule not supported in this version\\n\");\n                        myexit(-1);\n                    }\n                    keep_rule = 1;\n                } else if (strcmp(long_options[option_index].name, \"gen-add\") == 0) {\n                    if (is_udp2raw_mp) {\n                        mylog(log_fatal, \"--gen-add not supported in this version\\n\");\n                        myexit(-1);\n                    }\n                    generate_iptables_rule_add = 1;\n                } else if (strcmp(long_options[option_index].name, \"disable-color\") == 0) {\n                    // enable_log_color=0;\n                } else if (strcmp(long_options[option_index].name, \"enable-color\") == 0) {\n                    // enable_log_color=0;\n                } else if (strcmp(long_options[option_index].name, \"debug\") == 0) {\n                    debug_flag = 1;\n                    // enable_log_color=0;\n                } else if (strcmp(long_options[option_index].name, \"dev\") == 0) {\n                    sscanf(optarg, \"%s\", dev);\n                    // enable_log_color=0;\n                    mylog(log_info, \"dev=[%s]\\n\", dev);\n                } else if (strcmp(long_options[option_index].name, \"debug-resend\") == 0) {\n                    // debug_resend=1;\n                    // enable_log_color=0;\n                } else if (strcmp(long_options[option_index].name, \"log-position\") == 0) {\n                    // enable_log_position=1;\n                } else if (strcmp(long_options[option_index].name, \"force-sock-buf\") == 0) {\n                    if (is_udp2raw_mp) {\n                        mylog(log_fatal, \"--force-sock-buf not supported in this version\\n\");\n                        myexit(-1);\n                    }\n                    force_socket_buf = 1;\n                } else if (strcmp(long_options[option_index].name, \"retry-on-error\") == 0) {\n                    retry_on_error = 1;\n                } else if (strcmp(long_options[option_index].name, \"wait-lock\") == 0) {\n                    wait_xtables_lock = 1;\n                } else if (strcmp(long_options[option_index].name, \"disable-bpf\") == 0) {\n                    disable_bpf_filter = 1;\n                } else if (strcmp(long_options[option_index].name, \"disable-anti-replay\") == 0) {\n                    disable_anti_replay = 1;\n                } else if (strcmp(long_options[option_index].name, \"sock-buf\") == 0) {\n                    int tmp = -1;\n                    sscanf(optarg, \"%d\", &tmp);\n                    if (10 <= tmp && tmp <= 10 * 1024) {\n                        socket_buf_size = tmp * 1024;\n                    } else {\n                        mylog(log_fatal, \"sock-buf value must be between 1 and 10240 (kbyte) \\n\");\n                        myexit(-1);\n                    }\n                } else if (strcmp(long_options[option_index].name, \"seq-mode\") == 0) {\n                    sscanf(optarg, \"%d\", &seq_mode);\n                    if (0 <= seq_mode && seq_mode <= max_seq_mode) {\n                    } else {\n                        mylog(log_fatal, \"seq_mode value must be  0,1,or 2 \\n\");\n                        myexit(-1);\n                    }\n                } else if (strcmp(long_options[option_index].name, \"random-drop\") == 0) {\n                    sscanf(optarg, \"%d\", &random_drop);\n                    if (random_drop < 0 || random_drop > 10000) {\n                        mylog(log_fatal, \"random_drop must be between 0 10000 \\n\");\n                        myexit(-1);\n                    }\n                    mylog(log_info, \"random_drop =%d \\n\", random_drop);\n                } else if (strcmp(long_options[option_index].name, \"fifo\") == 0) {\n                    if (is_udp2raw_mp) {\n                        mylog(log_fatal, \"--fifo not supported in this version\\n\");\n                        myexit(-1);\n                    }\n                    sscanf(optarg, \"%s\", fifo_file);\n\n                    mylog(log_info, \"fifo_file =%s \\n\", fifo_file);\n                } else if (strcmp(long_options[option_index].name, \"conf-file\") == 0) {\n                    mylog(log_info, \"configuration loaded from %s\\n\", optarg);\n                } else if (strcmp(long_options[option_index].name, \"hb-mode\") == 0) {\n                    sscanf(optarg, \"%d\", &hb_mode);\n                    assert(hb_mode == 0 || hb_mode == 1);\n                    mylog(log_info, \"hb_mode =%d \\n\", hb_mode);\n                } else if (strcmp(long_options[option_index].name, \"hb-len\") == 0) {\n                    sscanf(optarg, \"%d\", &hb_len);\n                    assert(hb_len >= 0 && hb_len <= 1500);\n                    mylog(log_info, \"hb_len =%d \\n\", hb_len);\n                } else if (strcmp(long_options[option_index].name, \"mtu-warn\") == 0) {\n                    sscanf(optarg, \"%d\", &mtu_warn);\n                    assert(mtu_warn > 0);\n                    mylog(log_info, \"mtu_warn=%d \\n\", mtu_warn);\n                } else if (strcmp(long_options[option_index].name, \"max-rst-to-show\") == 0) {\n                    sscanf(optarg, \"%d\", &max_rst_to_show);\n                    assert(max_rst_to_show >= -1);\n                    mylog(log_info, \"max_rst_to_show=%d \\n\", max_rst_to_show);\n                } else if (strcmp(long_options[option_index].name, \"max-rst-allowed\") == 0) {\n                    sscanf(optarg, \"%d\", &max_rst_allowed);\n                    assert(max_rst_allowed >= -1);\n                    mylog(log_info, \"max_rst_allowed=%d \\n\", max_rst_allowed);\n                } else if (strcmp(long_options[option_index].name, \"set-ttl\") == 0) {\n                    sscanf(optarg, \"%d\", &ttl_value);\n                    assert(ttl_value >= 0 && ttl_value <= 255);\n                    mylog(log_info, \"ttl_value=%d\\n\", ttl_value);\n                }\n\n                else if (strcmp(long_options[option_index].name, \"dns-resolve\") == 0)  // currently not used\n                {\n                    enable_dns_resolve = 1;\n                    mylog(log_info, \"dns-resolve enabled\\n\");\n                }\n#ifdef UDP2RAW_MP\n                else if (strcmp(long_options[option_index].name, \"pcap-send\") == 0) {\n                    send_with_pcap = 1;\n                    mylog(log_info, \"--pcap-send enabled, now pcap will be used for sending packet instead of libnet\\n\");\n                } else if (strcmp(long_options[option_index].name, \"no-pcap-mutex\") == 0) {\n                    use_pcap_mutex = 0;\n                    mylog(log_warn, \"--no-pcap-mutex enabled, we will assume the underlying pcap calls are threadsafe\\n\");\n                }\n#endif\n                else if (strcmp(long_options[option_index].name, \"easy-tcp\") == 0) {\n                    use_tcp_dummy_socket = 1;\n                    mylog(log_info, \"--easy-tcp enabled, now a dummy tcp socket will be created for handshake and block rst\\n\");\n                } else if (strcmp(long_options[option_index].name, \"fix-gro\") == 0) {\n                    mylog(log_info, \"--fix-gro enabled\\n\");\n                    g_fix_gro = 1;\n                } else {\n                    mylog(log_warn, \"ignored unknown long option ,option_index:%d code:<%x>\\n\", option_index, optopt);\n                }\n                break;\n            default:\n                mylog(log_fatal, \"unknown option ,code:<%c>,<%x>\\n\", optopt, optopt);\n                myexit(-1);\n        }\n    }\n\n    if (no_l)\n        mylog(log_fatal, \"error: -l not found\\n\");\n    if (no_r)\n        mylog(log_fatal, \"error: -r not found\\n\");\n    if (program_mode == 0)\n        mylog(log_fatal, \"error: -c /-s  hasnt been set\\n\");\n    if (no_l || no_r || program_mode == 0) {\n        print_help();\n        myexit(-1);\n    }\n    if (program_mode == client_mode) {\n        raw_ip_version = remote_addr.get_type();\n    } else {\n        raw_ip_version = local_addr.get_type();\n    }\n\n    if (auto_add_iptables_rule && use_tcp_dummy_socket) {\n        mylog(log_error, \"-a,--auto-rule is not supposed to be used with easyfaketcp mode, you are likely making a mistake, but we can try to continue\\n\");\n    }\n\n    if (keep_rule && use_tcp_dummy_socket) {\n        mylog(log_error, \"--keep-rule is not supposed to be used with easyfaketcp mode, you are likely making a mistake, but we can try to continue\\n\");\n    }\n\n    mylog(log_info, \"important variables: \");\n\n    log_bare(log_info, \"log_level=%d:%s \", log_level, log_text[log_level]);\n    log_bare(log_info, \"raw_mode=%s \", raw_mode_tostring[raw_mode]);\n    log_bare(log_info, \"cipher_mode=%s \", cipher_mode_tostring[cipher_mode]);\n    log_bare(log_info, \"auth_mode=%s \", auth_mode_tostring[auth_mode]);\n\n    log_bare(log_info, \"key=%s \", key_string);\n\n    log_bare(log_info, \"local_addr=%s \", local_addr.get_str());\n    log_bare(log_info, \"remote_addr=%s \", remote_addr.get_str());\n\n    if (force_source_ip)\n        log_bare(log_info, \"source_addr=%s \", source_addr.get_ip());\n\n    if (force_source_port)\n        log_bare(log_info, \"source_port=%d \", source_port);\n\n    log_bare(log_info, \"socket_buf_size=%d \", socket_buf_size);\n\n    log_bare(log_info, \"\\n\");\n}\n\nvoid pre_process_arg(int argc, char *argv[])  // mainly for load conf file\n{\n    int i, j, k;\n    for (i = 0; i < argc; i++) {\n        if (strcmp(argv[i], \"--unit-test\") == 0) {\n            unit_test();\n            myexit(0);\n        }\n    }\n\n    for (i = 0; i < argc; i++) {\n        if (strcmp(argv[i], \"-h\") == 0 || strcmp(argv[i], \"--help\") == 0) {\n            print_help();\n            myexit(0);\n        }\n    }\n\n    if (argc == 1) {\n        print_help();\n        myexit(-1);\n    }\n\n    process_log_level(argc, argv);\n\n    int new_argc = 0;\n    vector<string> new_argv;\n\n    int count = 0;\n    int pos = -1;\n\n    for (i = 0; i < argc; i++) {\n        if (strcmp(argv[i], \"--conf-file\") == 0) {\n            count++;\n            pos = i;\n            if (i == argc) {\n                mylog(log_fatal, \"--conf-file need a parameter\\n\");\n                myexit(-1);\n            }\n            if (argv[i + 1][0] == '-') {\n                mylog(log_fatal, \"--conf-file need a parameter\\n\");\n                myexit(-1);\n            }\n            i++;\n        } else {\n            // printf(\"<%s>\",argv[i]);\n            new_argc++;\n            new_argv.push_back(argv[i]);\n        }\n    }\n    if (count > 1) {\n        mylog(log_fatal, \"duplicated --conf-file option\\n\");\n        myexit(-1);\n    }\n\n    if (count > 0) {\n        load_config(argv[pos + 1], new_argc, new_argv);\n    }\n    char *new_argv_char[new_argv.size()];\n\n    new_argc = 0;\n    for (i = 0; i < (int)new_argv.size(); i++) {\n        if (strcmp(new_argv[i].c_str(), \"--conf-file\") == 0) {\n            mylog(log_fatal, \"cant have --conf-file in a config file\\n\");\n            myexit(-1);\n        }\n        new_argv_char[new_argc++] = (char *)new_argv[i].c_str();\n    }\n    process_arg(new_argc, new_argv_char);\n}\n#ifdef UDP2RAW_LINUX\nvoid *run_keep(void *none)  // called in a new thread for --keep-rule option\n{\n    while (1) {\n        sleep(iptables_rule_keep_interval);\n        keep_iptables_rule();\n        if (about_to_exit)  // just incase it runs forever if there is some bug,not necessary\n        {\n            sleep(10);\n            keep_thread_running = 0;  // not thread safe ,but wont cause problem\n            break;\n        }\n    }\n    return NULL;\n}\nvoid iptables_rule()  // handles -a -g --gen-add  --keep-rule --clear --wait-lock\n{\n    assert(raw_ip_version == AF_INET || raw_ip_version == AF_INET6);\n\n    if (raw_ip_version == AF_INET) {\n        iptables_command0 = \"iptables \";\n    } else\n        iptables_command0 = \"ip6tables \";\n    if (!wait_xtables_lock) {\n        iptables_command = iptables_command0;\n    } else {\n        iptables_command = iptables_command0 + \"-w \";\n    }\n\n    if (clear_iptables) {\n        char *output;\n        // int ret =system(\"iptables-save |grep udp2raw_dWRwMnJhdw|sed -n 's/^-A/iptables -D/p'|sh\");\n        int ret = run_command(iptables_command + \"-S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-A/\" + iptables_command + \"-D/p'|sh\", output);\n\n        int ret2 = run_command(iptables_command + \"-S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-N/\" + iptables_command + \"-X/p'|sh\", output);\n        // system(\"iptables-save |grep udp2raw_dWRwMnJhdw|sed 's/^-A/iptables -D/'|sh\");\n        // system(\"iptables-save|grep -v udp2raw_dWRwMnJhdw|iptables-restore\");\n        mylog(log_info, \"tried to clear all iptables rule created previously,return value %d %d\\n\", ret, ret2);\n        myexit(-1);\n    }\n\n    if (auto_add_iptables_rule && generate_iptables_rule) {\n        mylog(log_warn, \" -g overrides -a\\n\");\n        auto_add_iptables_rule = 0;\n        // myexit(-1);\n    }\n    if (generate_iptables_rule_add && generate_iptables_rule) {\n        mylog(log_warn, \" --gen-add overrides -g\\n\");\n        generate_iptables_rule = 0;\n        // myexit(-1);\n    }\n\n    if (keep_rule && auto_add_iptables_rule == 0) {\n        auto_add_iptables_rule = 1;\n        mylog(log_warn, \" --keep_rule implys -a\\n\");\n        generate_iptables_rule = 0;\n        // myexit(-1);\n    }\n    char tmp_pattern[200];\n    string pattern = \"\";\n\n    if (program_mode == client_mode) {\n        tmp_pattern[0] = 0;\n        if (raw_mode == mode_faketcp) {\n            sprintf(tmp_pattern, \"-s %s -p tcp -m tcp --sport %d\", remote_addr.get_ip(), remote_addr.get_port());\n        }\n        if (raw_mode == mode_udp) {\n            sprintf(tmp_pattern, \"-s %s -p udp -m udp --sport %d\", remote_addr.get_ip(), remote_addr.get_port());\n        }\n        if (raw_mode == mode_icmp) {\n            if (raw_ip_version == AF_INET)\n                sprintf(tmp_pattern, \"-s %s -p icmp --icmp-type 0\", remote_addr.get_ip());\n            else\n                sprintf(tmp_pattern, \"-s %s -p icmpv6 --icmpv6-type 129\", remote_addr.get_ip());\n        }\n        pattern += tmp_pattern;\n    }\n    if (program_mode == server_mode) {\n        tmp_pattern[0] = 0;\n        if (raw_ip_version == AF_INET) {\n            if (local_addr.inner.ipv4.sin_addr.s_addr != 0) {\n                sprintf(tmp_pattern, \"-d %s \", local_addr.get_ip());\n            }\n        } else {\n            char zero_arr[16] = {0};\n            if (memcmp(&local_addr.inner.ipv6.sin6_addr, zero_arr, 16) != 0) {\n                sprintf(tmp_pattern, \"-d %s \", local_addr.get_ip());\n            }\n        }\n        pattern += tmp_pattern;\n\n        tmp_pattern[0] = 0;\n        if (raw_mode == mode_faketcp) {\n            sprintf(tmp_pattern, \"-p tcp -m tcp --dport %d\", local_addr.get_port());\n        }\n        if (raw_mode == mode_udp) {\n            sprintf(tmp_pattern, \"-p udp -m udp --dport %d\", local_addr.get_port());\n        }\n        if (raw_mode == mode_icmp) {\n            if (raw_ip_version == AF_INET)\n                sprintf(tmp_pattern, \"-p icmp --icmp-type 8\");\n            else\n                sprintf(tmp_pattern, \"-p icmpv6 --icmpv6-type 128\");\n        }\n        pattern += tmp_pattern;\n    }\n    /*\n            if(!simple_rule)\n            {\n                    pattern += \" -m comment --comment udp2rawDwrW_\";\n\n                    char const_id_str[100];\n                    sprintf(const_id_str, \"%x_\", const_id);\n\n                    pattern += const_id_str;\n\n                    time_t timer;\n                    char buffer[26];\n                    struct tm* tm_info;\n\n                    time(&timer);\n                    tm_info = localtime(&timer);\n\n                    strftime(buffer, 26, \"%Y-%m-%d-%H:%M:%S\", tm_info);\n\n                    pattern += buffer;\n\n\n            }*/\n\n    if (generate_iptables_rule) {\n        string rule = iptables_command + \"-I INPUT \";\n        rule += pattern;\n        rule += \" -j DROP\";\n\n        printf(\"generated iptables rule:\\n\");\n        printf(\"%s\\n\", rule.c_str());\n        myexit(0);\n    }\n    if (generate_iptables_rule_add) {\n        iptables_gen_add(pattern.c_str(), const_id);\n        myexit(0);\n    }\n\n    if (auto_add_iptables_rule) {\n        iptables_rule_init(pattern.c_str(), const_id, keep_rule);\n        if (keep_rule) {\n            if (pthread_create(&keep_thread, NULL, run_keep, 0)) {\n                mylog(log_fatal, \"Error creating thread\\n\");\n                myexit(-1);\n            }\n            keep_thread_running = 1;\n        }\n    } else {\n        mylog(log_warn, \" -a has not been set, make sure you have added the needed iptables rules manually\\n\");\n    }\n}\n#endif\n\nint unit_test() {\n    printf(\"running unit test\\n\");\n    vector<string> conf_lines = {\"---aaa\", \"--aaa bbb\", \"-a bbb\", \" \\t \\t \\t-a\\t \\t \\t bbbbb\\t \\t \\t \"};\n    for (int i = 0; i < int(conf_lines.size()); i++) {\n        printf(\"orign:%s\\n\", conf_lines[i].c_str());\n        auto res = parse_conf_line(conf_lines[i]);\n        printf(\"pasrse_result: size %d\", int(res.size()));\n        for (int j = 0; j < int(res.size()); j++) {\n            printf(\"<%s>\", res[j].c_str());\n        }\n        printf(\"\\n\");\n    }\n\n    char s1[] = {1, 2, 3, 4, 5};\n\n    char s2[] = {1};\n\n    short c1 = csum((unsigned short *)s1, 5);\n    short c2 = csum((unsigned short *)s2, 1);\n    // c2=0;\n\n    printf(\"%x %x\\n\", (int)c1, (int)c2);\n\n    const char buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 13, 14, 15, 16};\n    char key[100] = {0};\n    char buf2[100] = {0};\n    char buf3[100] = {0};\n    char buf4[100] = {0};\n    int len = 16;\n    for (int i = 0; i < len; i++) {\n        printf(\"<%d>\", buf[i]);\n    }\n    printf(\"\\n\");\n    cipher_encrypt(buf, buf2, len, key);\n    for (int i = 0; i < len; i++) {\n        printf(\"<%d>\", buf2[i]);\n    }\n    printf(\"\\n\");\n    int temp_len = len;\n    cipher_decrypt(buf2, buf3, len, key);\n    for (int i = 0; i < len; i++) {\n        printf(\"<%d>\", buf3[i]);\n    }\n    printf(\"\\n\");\n    cipher_encrypt(buf2, buf4, temp_len, key);\n    for (int i = 0; i < temp_len; i++) {\n        printf(\"<%d>\", buf4[i]);\n    }\n    return 0;\n}\n\n#ifdef UDP2RAW_LINUX\nint set_timer(int epollfd, int &timer_fd)  // put a timer_fd into epoll,general function,used both in client and server\n{\n    int ret;\n    epoll_event ev;\n\n    itimerspec its;\n    memset(&its, 0, sizeof(its));\n\n    if ((timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) < 0) {\n        mylog(log_fatal, \"timer_fd create error\\n\");\n        myexit(1);\n    }\n    its.it_interval.tv_sec = (timer_interval / 1000);\n    its.it_interval.tv_nsec = (timer_interval % 1000) * 1000ll * 1000ll;\n    its.it_value.tv_nsec = 1;  // imidiately\n    timerfd_settime(timer_fd, 0, &its, 0);\n\n    ev.events = EPOLLIN;\n    ev.data.u64 = timer_fd;\n\n    ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev);\n    if (ret < 0) {\n        mylog(log_fatal, \"epoll_ctl return %d\\n\", ret);\n        myexit(-1);\n    }\n    return 0;\n}\n\nint set_timer_server(int epollfd, int &timer_fd, fd64_t &fd64)  // only for server\n{\n    int ret;\n    epoll_event ev;\n\n    itimerspec its;\n    memset(&its, 0, sizeof(its));\n\n    if ((timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) < 0) {\n        mylog(log_fatal, \"timer_fd create error\\n\");\n        myexit(1);\n    }\n    its.it_interval.tv_sec = (timer_interval / 1000);\n    its.it_interval.tv_nsec = (timer_interval % 1000) * 1000ll * 1000ll;\n    its.it_value.tv_nsec = 1;  // imidiately\n    timerfd_settime(timer_fd, 0, &its, 0);\n\n    fd64 = fd_manager.create(timer_fd);\n\n    ev.events = EPOLLIN;\n    ev.data.u64 = fd64;  ////difference\n\n    ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev);\n    if (ret < 0) {\n        mylog(log_fatal, \"epoll_ctl return %d\\n\", ret);\n        myexit(-1);\n    }\n    return 0;\n}\n\nint handle_lower_level(raw_info_t &raw_info)  // fill lower_level info,when --lower-level is enabled,only for server\n{\n    packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    if (lower_level_manual) {\n        memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));\n        send_info.addr_ll.sll_family = AF_PACKET;\n        send_info.addr_ll.sll_ifindex = ifindex;\n        send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;\n        send_info.addr_ll.sll_protocol = htons(ETH_P_IP);\n        memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);\n        mylog(log_debug, \"[manual]lower level info %x %x\\n \", send_info.addr_ll.sll_halen, send_info.addr_ll.sll_protocol);\n    } else {\n        memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));\n        send_info.addr_ll.sll_family = recv_info.addr_ll.sll_family;\n        send_info.addr_ll.sll_ifindex = recv_info.addr_ll.sll_ifindex;\n        send_info.addr_ll.sll_protocol = recv_info.addr_ll.sll_protocol;\n        send_info.addr_ll.sll_halen = recv_info.addr_ll.sll_halen;\n        memcpy(send_info.addr_ll.sll_addr, recv_info.addr_ll.sll_addr, sizeof(send_info.addr_ll.sll_addr));\n        // other bytes should be kept zero.\n\n        mylog(log_debug, \"[auto]lower level info %x %x\\n \", send_info.addr_ll.sll_halen, send_info.addr_ll.sll_protocol);\n    }\n    return 0;\n}\n\nstring chain[2];\nstring rule_keep[2];\nstring rule_keep_add[2];\nstring rule_keep_del[2];\nu64_t keep_rule_last_time = 0;\n\npthread_t keep_thread;\nint keep_thread_running = 0;\nint iptables_gen_add(const char *s, u32_t const_id) {\n    string dummy = \"\";\n    iptables_pattern = s;\n    chain[0] = dummy + \"udp2rawDwrW_C\";\n    rule_keep[0] = dummy + iptables_pattern + \" -j \" + chain[0];\n    rule_keep_add[0] = iptables_command + \"-I INPUT \" + rule_keep[0];\n\n    char *output;\n    run_command(iptables_command + \"-N \" + chain[0], output, show_none);\n    run_command(iptables_command + \"-F \" + chain[0], output);\n    run_command(iptables_command + \"-I \" + chain[0] + \" -j DROP\", output);\n\n    rule_keep_del[0] = iptables_command + \"-D INPUT \" + rule_keep[0];\n\n    run_command(rule_keep_del[0], output, show_none);\n    run_command(rule_keep_del[0], output, show_none);\n\n    if (run_command(rule_keep_add[0], output) != 0) {\n        mylog(log_fatal, \"auto added iptables failed by: %s\\n\", rule_keep_add[0].c_str());\n        myexit(-1);\n    }\n    return 0;\n}\nint iptables_rule_init(const char *s, u32_t const_id, int keep) {\n    iptables_pattern = s;\n    iptables_rule_added = 1;\n    iptables_rule_keeped = keep;\n\n    string dummy = \"\";\n    char const_id_str[100];\n    sprintf(const_id_str, \"%x\", const_id);\n\n    chain[0] = dummy + \"udp2rawDwrW_\" + const_id_str + \"_C0\";\n    chain[1] = dummy + \"udp2rawDwrW_\" + const_id_str + \"_C1\";\n\n    rule_keep[0] = dummy + iptables_pattern + \" -j \" + chain[0];\n    rule_keep[1] = dummy + iptables_pattern + \" -j \" + chain[1];\n\n    rule_keep_add[0] = iptables_command + \"-I INPUT \" + rule_keep[0];\n    rule_keep_add[1] = iptables_command + \"-I INPUT \" + rule_keep[1];\n\n    rule_keep_del[0] = iptables_command + \"-D INPUT \" + rule_keep[0];\n    rule_keep_del[1] = iptables_command + \"-D INPUT \" + rule_keep[1];\n\n    keep_rule_last_time = get_current_time();\n\n    char *output;\n\n    for (int i = 0; i <= iptables_rule_keeped; i++) {\n        run_command(iptables_command + \"-N \" + chain[i], output);\n        run_command(iptables_command + \"-F \" + chain[i], output);\n        run_command(iptables_command + \"-I \" + chain[i] + \" -j DROP\", output);\n\n        if (run_command(rule_keep_add[i], output) != 0) {\n            mylog(log_fatal, \"auto added iptables failed by: %s\\n\", rule_keep_add[i].c_str());\n            myexit(-1);\n        }\n    }\n    mylog(log_warn, \"auto added iptables rules\\n\");\n    return 0;\n}\n\nint keep_iptables_rule()  // magic to work on a machine without grep/iptables --check/-m commment\n{\n    /*\n    if(iptables_rule_keeped==0) return  0;\n\n\n    uint64_t tmp_current_time=get_current_time();\n    if(tmp_current_time-keep_rule_last_time<=iptables_rule_keep_interval)\n    {\n            return 0;\n    }\n    else\n    {\n            keep_rule_last_time=tmp_current_time;\n    }*/\n\n    mylog(log_debug, \"keep_iptables_rule begin %llu\\n\", get_current_time());\n    iptables_rule_keep_index += 1;\n    iptables_rule_keep_index %= 2;\n\n    string dummy = \"\";\n    char *output;\n\n    int i = iptables_rule_keep_index;\n\n    run_command(iptables_command + \"-N \" + chain[i], output, show_none);\n\n    if (run_command(iptables_command + \"-F \" + chain[i], output, show_none) != 0)\n        mylog(log_warn, \"iptables -F failed %d\\n\", i);\n\n    if (run_command(iptables_command + \"-I \" + chain[i] + \" -j DROP\", output, show_none) != 0)\n        mylog(log_warn, \"iptables -I failed %d\\n\", i);\n\n    if (run_command(rule_keep_del[i], output, show_none) != 0)\n        mylog(log_warn, \"rule_keep_del failed %d\\n\", i);\n\n    run_command(rule_keep_del[i], output, show_none);  // do it twice,incase it fails for unknown random reason\n\n    if (run_command(rule_keep_add[i], output, show_log) != 0)\n        mylog(log_warn, \"rule_keep_del failed %d\\n\", i);\n\n    mylog(log_debug, \"keep_iptables_rule end %llu\\n\", get_current_time());\n    return 0;\n}\n\nint clear_iptables_rule() {\n    char *output;\n    string dummy = \"\";\n    if (!iptables_rule_added) return 0;\n\n    for (int i = 0; i <= iptables_rule_keeped; i++) {\n        run_command(rule_keep_del[i], output);\n        run_command(iptables_command + \"-F \" + chain[i], output);\n        run_command(iptables_command + \"-X \" + chain[i], output);\n    }\n    return 0;\n}\n#endif\n\n#ifdef UDP2RAW_MP\nvoid iptables_rule()  // handles -a -g --gen-add  --keep-rule --clear --wait-lock\n{\n    if (generate_iptables_rule) {\n        if (raw_mode == mode_faketcp && use_tcp_dummy_socket == 1) {\n            mylog(log_fatal, \"failed,-g doesnt work with easy-faketcp mode\\n\");\n            myexit(-1);\n        }\n        if (raw_mode == mode_udp) {\n            mylog(log_warn, \"It not necessary to use iptables/firewall rule in udp mode\\n\");\n        }\n        log_bare(log_warn, \"for linux, use:\\n\");\n        if (raw_ip_version == AF_INET) {\n            if (raw_mode == mode_faketcp)\n                printf(\"iptables -I INPUT -s %s -p tcp -m tcp --sport %d -j DROP\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            if (raw_mode == mode_udp)\n                printf(\"iptables -I INPUT -s %s -p udp -m udp --sport %d -j DROP\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            if (raw_mode == mode_icmp)\n                printf(\"iptables -I INPUT -s %s -p icmp --icmp-type 0 -j DROP\\n\", remote_addr.get_ip());\n            printf(\"\\n\");\n        } else {\n            assert(raw_ip_version == AF_INET6);\n            if (raw_mode == mode_faketcp)\n                printf(\"ip6tables -I INPUT -s %s -p tcp -m tcp --sport %d -j DROP\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            if (raw_mode == mode_udp)\n                printf(\"ip6tables -I INPUT -s %s -p udp -m udp --sport %d -j DROP\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            if (raw_mode == mode_icmp)\n                printf(\"ip6tables -I INPUT -s %s -p -p icmpv6 --icmpv6-type 129 -j DROP\\n\", remote_addr.get_ip());\n            printf(\"\\n\");\n        }\n\n        log_bare(log_warn, \"for mac/bsd use:\\n\");\n        if (raw_ip_version == AF_INET) {\n            if (raw_mode == mode_faketcp)\n                printf(\"echo 'block drop inet proto tcp from %s port %d to any' > ./1.conf\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            if (raw_mode == mode_udp)\n                printf(\"echo 'block drop inet proto udp from %s port %d to any' > ./1.conf\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            if (raw_mode == mode_icmp)\n                printf(\"echo 'block drop inet proto icmp from %s to any' > ./1.conf\\n\", remote_addr.get_ip());\n        } else {\n            assert(raw_ip_version == AF_INET6);\n            if (raw_mode == mode_faketcp)\n                printf(\"echo 'block drop inet6 proto tcp from %s port %d to any' > ./1.conf\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            if (raw_mode == mode_udp)\n                printf(\"echo 'block drop inet6 proto udp from %s port %d to any' > ./1.conf\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            if (raw_mode == mode_icmp)\n                printf(\"echo 'block drop inet6 proto icmp6 from %s to any' > ./1.conf\\n\", remote_addr.get_ip());\n        }\n        printf(\"pfctl -f ./1.conf\\n\");\n        printf(\"pfctl -e\\n\");\n        printf(\"\\n\");\n\n        log_bare(log_warn, \"for windows vista and above use:\\n\");\n        if (raw_ip_version == AF_INET) {\n            if (raw_mode == mode_faketcp) {\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=TCP dir=in remoteip=%s remoteport=%d action=block\\n\", remote_addr.get_ip(), remote_addr.get_port());\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=TCP dir=out remoteip=%s remoteport=%d action=block\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            }\n            if (raw_mode == mode_udp) {\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=UDP dir=in remoteip=%s remoteport=%d action=block\\n\", remote_addr.get_ip(), remote_addr.get_port());\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=UDP dir=out remoteip=%s remoteport=%d action=block\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            }\n\n            if (raw_mode == mode_icmp) {\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=ICMPV4 dir=in remoteip=%s action=block\\n\", remote_addr.get_ip());\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=ICMPV4 dir=out remoteip=%s action=block\\n\", remote_addr.get_ip());\n            }\n        } else {\n            assert(raw_ip_version == AF_INET6);\n            if (raw_mode == mode_faketcp) {\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=TCP dir=in remoteip=%s remoteport=%d action=block\\n\", remote_addr.get_ip(), remote_addr.get_port());\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=TCP dir=out remoteip=%s remoteport=%d action=block\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            }\n            if (raw_mode == mode_udp) {\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=UDP dir=in remoteip=%s remoteport=%d action=block\\n\", remote_addr.get_ip(), remote_addr.get_port());\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=UDP dir=out remoteip=%s remoteport=%d action=block\\n\", remote_addr.get_ip(), remote_addr.get_port());\n            }\n\n            if (raw_mode == mode_icmp) {\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=ICMPV6 dir=in remoteip=%s action=block\\n\", remote_addr.get_ip());\n                printf(\"netsh advfirewall firewall add rule name=udp2raw protocol=ICMPV6 dir=out remoteip=%s action=block\\n\", remote_addr.get_ip());\n            }\n        }\n\n        myexit(0);\n    }\n}\n#endif\n\nvoid signal_handler(int sig) {\n    about_to_exit = 1;\n    // myexit(0);\n}\n"
  },
  {
    "path": "misc.h",
    "content": "/*\n * misc.h\n *\n *  Created on: Sep 23, 2017\n *      Author: root\n */\n\n#ifndef MISC_H_\n#define MISC_H_\n\n#include \"common.h\"\n#include \"log.h\"\n#include \"network.h\"\n\nextern int hb_mode;\nextern int hb_len;\nextern char hb_buf[buf_len];\n\nextern int mtu_warn;\n\nextern int max_rst_allowed;\nextern int max_rst_to_show;\n\nextern int enable_dns_resolve;\n\nextern int ttl_value;\n\nconst u32_t max_handshake_conn_num = 10000;\nconst u32_t max_ready_conn_num = 1000;\nconst u32_t anti_replay_window_size = 4000;\nconst int max_conv_num = 10000;\n\nconst u32_t client_handshake_timeout = 5000;  // unit ms\nconst u32_t client_retry_interval = 1000;     // ms\n\nconst u32_t server_handshake_timeout = client_handshake_timeout + 5000;  // this should be longer than clients. client retry initially ,server retry passtively\n\nconst int conv_clear_ratio = 30;  // conv grabage collecter check 1/30 of all conv one time\nconst int conn_clear_ratio = 50;\nconst int conv_clear_min = 1;\nconst int conn_clear_min = 1;\n\nconst u32_t conv_clear_interval = 1000;  // ms\nconst u32_t conn_clear_interval = 1000;  // ms\n\nconst i32_t max_fail_time = 0;  // disable\n\nconst u32_t heartbeat_interval = 600;  // ms\n\nconst u32_t timer_interval = 400;  // ms. this should be smaller than heartbeat_interval and retry interval;\n\nconst uint32_t conv_timeout = 180000;  // ms. 120 second\n// const u32_t conv_timeout=30000; //for test\n\nconst u32_t client_conn_timeout = 10000;                              // ms.\nconst u32_t client_conn_uplink_timeout = client_conn_timeout + 2000;  // ms\n\nconst uint32_t server_conn_timeout = conv_timeout + 60000;  // ms. this should be 60s+ longer than conv_timeout,so that conv_manager can destruct convs gradually,to avoid latency glicth\n// const u32_t server_conn_timeout=conv_timeout+10000;//for test\n\nconst u32_t iptables_rule_keep_interval = 20;  // unit: second;\n\nenum server_current_state_t { server_idle = 0,\n                              server_handshake1,\n                              server_ready };  // server state machine\nenum client_current_state_t { client_idle = 0,\n                              client_tcp_handshake,\n                              client_handshake1,\n                              client_handshake2,\n                              client_ready,\n                              client_tcp_handshake_dummy };  // client state machine\n\nenum raw_mode_t { mode_faketcp = 0,\n                  mode_udp,\n                  mode_icmp,\n                  mode_end };\nenum program_mode_t { unset_mode = 0,\n                      client_mode,\n                      server_mode };\n\nunion current_state_t {\n    server_current_state_t server_current_state;\n    client_current_state_t client_current_state;\n};\n\n// extern char remote_address[max_address_len];\n// extern char local_ip[100], remote_ip[100],source_ip[100];//local_ip is for -l option,remote_ip for -r option,source for --source-ip\n// extern u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.\n// extern int local_port , remote_port,source_port;//similiar to local_ip  remote_ip,buf for port.source_port=0 indicates --source-port is not enabled\n\nextern address_t local_addr, remote_addr, source_addr;\n\nextern my_ip_t bind_addr;\n\nextern int bind_addr_used;\nextern int force_source_ip;  // if --source-ip is enabled\nextern int force_source_port;\nextern int source_port;\n\nextern my_id_t const_id;  // an id used for connection recovery,its generated randomly,it never change since its generated\n\nextern int udp_fd;                 // for client only. client use this fd to listen and handle udp connection\nextern int bind_fd;                // bind only,never send or recv.  its just a dummy fd for bind,so that other program wont occupy the same port\nextern int epollfd;                // fd for epoll\nextern int timer_fd;               // the general timer fd for client and server.for server this is not the only timer find,every connection has a timer fd.\nextern int fail_time_counter;      // determine if the max_fail_time is reached\nextern int epoll_trigger_counter;  // for debug only\nextern int debug_flag;             // for debug only\n\nextern int simple_rule;                 // deprecated.\nextern int keep_rule;                   // whether to monitor the iptables rule periodly,re-add if losted\nextern int auto_add_iptables_rule;      // if -a is set\nextern int generate_iptables_rule;      // if -g is set\nextern int generate_iptables_rule_add;  // if --gen-add is set\nextern int retry_on_error;\nconst int retry_on_error_interval = 10;\n\nextern int debug_resend;  // debug only\n\nextern char key_string[1000];  // -k option\nextern char fifo_file[1000];\n\nextern raw_mode_t raw_mode;\nextern u32_t raw_ip_version;\n\nextern program_mode_t program_mode;\nextern unordered_map<int, const char *> raw_mode_tostring;\n\nextern int about_to_exit;\n\nextern int socket_buf_size;\n\nextern pthread_t keep_thread;\nextern int keep_thread_running;\n\nint process_lower_level_arg();\nvoid print_help();\nvoid iptables_rule();\nvoid pre_process_arg(int argc, char *argv[]);  // mainly for load conf file;\nint unit_test();\nint set_timer(int epollfd, int &timer_fd);\nint set_timer_server(int epollfd, int &timer_fd, fd64_t &fd64);\nint handle_lower_level(raw_info_t &raw_info);\n\nint add_iptables_rule(const char *);\n\nint clear_iptables_rule();\n\nint iptables_gen_add(const char *s, u32_t const_id);\nint iptables_rule_init(const char *s, u32_t const_id, int keep);\nint keep_iptables_rule();\n\nvoid signal_handler(int sig);\n\n#endif /* MISC_H_ */\n"
  },
  {
    "path": "my_ev.cpp",
    "content": "#pragma GCC diagnostic push\n\n#pragma GCC diagnostic ignored \"-Wextra\"\n#pragma GCC diagnostic ignored \"-Wsign-compare\"\n#pragma GCC diagnostic ignored \"-Wcomment\"\n#pragma GCC diagnostic ignored \"-Wparentheses\"\n#pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n#pragma GCC diagnostic ignored \"-Wunused-value\"\n\n#pragma GCC diagnostic ignored \"-Wall\"\n#pragma GCC diagnostic ignored \"-W\"\n\n#include \"my_ev_common.h\"\n#include \"ev.c\"\n\n#pragma GCC diagnostic pop\n"
  },
  {
    "path": "my_ev.h",
    "content": "#pragma once\n\n#include \"my_ev_common.h\"\n#include \"ev.h\"\n"
  },
  {
    "path": "my_ev_common.h",
    "content": "\n#define EV_STANDALONE 1\n#define EV_COMMON \\\n    void *data;   \\\n    unsigned long long u64;\n#define EV_COMPAT3 0\n\n//#include <wepoll.h>\n#if defined(__MINGW32__)\n//#define EV_USE_SELECT 1\n//#define EV_SELECT_IS_WINSOCKET 1\n\n#define EV_FD_TO_WIN32_HANDLE(fd) (fd)\n#define EV_WIN32_HANDLE_TO_FD(handle) (handle)\n#define EV_WIN32_CLOSE_FD(fd) closesocket(fd)\n#define FD_SETSIZE 4096\n\n#endif\n//#define EV_VERIFY 2\n"
  },
  {
    "path": "network.cpp",
    "content": "/*\n * network.cpp\n *\n *  Created on: Jul 29, 2017\n *      Author: wangyu\n */\n#include \"common.h\"\n#include \"network.h\"\n#include \"log.h\"\n#include \"misc.h\"\n\nint g_fix_gro = 0;\n\nint raw_recv_fd = -1;\nint raw_send_fd = -1;\nu32_t link_level_header_len = 0;  // set it to 14 if SOCK_RAW is used in socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));\nint use_tcp_dummy_socket = 0;\n\nint seq_mode = 3;\nint max_seq_mode = 4;\nint random_drop = 0;\n\nint filter_port = -1;\n\nint disable_bpf_filter = 0;  // for test only,most time no need to disable this\n\n// u32_t bind_address_uint32=0;\n\nint lower_level = 0;\nint lower_level_manual = 0;\nint ifindex = -1;\nchar if_name[100] = \"\";\n\nchar dev[100] = \"\";\n\nunsigned short g_ip_id_counter = 0;\n#ifdef UDP2RAW_LINUX\nunsigned char dest_hw_addr[sizeof(sockaddr_ll::sll_addr)] =\n    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0};\n#endif\n\n//{0x00,0x23,0x45,0x67,0x89,0xb9};\n\nconst u32_t receive_window_lower_bound = 40960;\nconst u32_t receive_window_random_range = 512;\nconst unsigned char wscale = 0x05;\n\nchar g_packet_buf[huge_buf_len];  // looks dirty but works well\nint g_packet_buf_len = -1;\nint g_packet_buf_cnt = 0;\n\n#ifdef UDP2RAW_LINUX\nunion {\n    sockaddr_ll ll;\n    sockaddr_in ipv4;\n    sockaddr_in6 ipv6;\n} g_sockaddr;\nsocklen_t g_sockaddr_len = -1;\n#endif\n\n#ifdef UDP2RAW_MP\n\n#ifndef NO_LIBNET\nlibnet_t *libnet_handle;\nlibnet_ptag_t g_ptag = 0;\nint send_with_pcap = 0;\n#else\nint send_with_pcap = 1;\n#endif\n\nint pcap_header_captured = 0;\nint pcap_header_buf[buf_len];\nint pcap_captured_full_len = -1;\n\npcap_t *pcap_handle;\nint pcap_link_header_len = -1;\n// int pcap_cnt=0;\nqueue_t my_queue;\n\npthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;\npthread_mutex_t pcap_mutex = PTHREAD_MUTEX_INITIALIZER;\nint use_pcap_mutex = 1;\n\nev_async async_watcher;\n\nstruct ev_loop *g_default_loop;\n\npthread_t pcap_recv_thread;\n\nstruct bpf_program g_filter;\nlong long g_filter_compile_cnt = 0;\n\n#endif\n\n#ifdef UDP2RAW_LINUX\n\nstruct sock_filter code_tcp_old[] = {\n    {0x28, 0, 0, 0x0000000c},   // 0\n    {0x15, 0, 10, 0x00000800},  // 1\n    {0x30, 0, 0, 0x00000017},   // 2\n    {0x15, 0, 8, 0x00000006},   // 3\n    {0x28, 0, 0, 0x00000014},   // 4\n    {0x45, 6, 0, 0x00001fff},   // 5\n    {0xb1, 0, 0, 0x0000000e},   // 6\n    {0x48, 0, 0, 0x0000000e},   // 7\n    {0x15, 2, 0, 0x0000ef32},   // 8\n    {0x48, 0, 0, 0x00000010},   // 9\n    {0x15, 0, 1, 0x0000ef32},   // 10\n    {0x6, 0, 0, 0x0000ffff},    // 11\n    {0x6, 0, 0, 0x00000000},    // 12\n};\nstruct sock_filter code_tcp[] = {\n    //{ 0x5, 0, 0, 0x00000001 },//0    //jump to 2,dirty hack from tcpdump -d's output\n    //{ 0x5, 0, 0, 0x00000000 },//1\n    {0x30, 0, 0, 0x00000009},  // 2\n    {0x15, 0, 6, 0x00000006},  // 3\n    {0x28, 0, 0, 0x00000006},  // 4\n    {0x45, 4, 0, 0x00001fff},  // 5\n    {0xb1, 0, 0, 0x00000000},  // 6\n    {0x48, 0, 0, 0x00000002},  // 7\n    {0x15, 0, 1, 0x0000fffe},  // 8   //modify this fffe to the port you listen on\n    {0x6, 0, 0, 0x0000ffff},   // 9\n    {0x6, 0, 0, 0x00000000},   // 10\n};\n/*\n{ 0x28, 0, 0, 0x0000000c },\n{ 0x15, 0, 8, 0x00000800 },\n{ 0x30, 0, 0, 0x00000017 },\n{ 0x15, 0, 6, 0x00000006 },\n{ 0x28, 0, 0, 0x00000014 },\n{ 0x45, 4, 0, 0x00001fff },\n{ 0xb1, 0, 0, 0x0000000e },\n{ 0x48, 0, 0, 0x00000010 },\n{ 0x15, 0, 1, 0x0000fffe },\n{ 0x6, 0, 0, 0x0000ffff },\n{ 0x6, 0, 0, 0x00000000 },\n*/\n\nint code_tcp_port_index = 6;\n\n// tcpdump -i ens33 ip6 and tcp and dst port 65534 -dd\nstruct sock_filter code_tcp6[] = {\n    //{ 0x28, 0, 0, 0x0000000c },//0\n    //{ 0x15, 0, 5, 0x000086dd },//1\n    {0x30, 0, 0, 0x00000006},  // 2\n    {0x15, 0, 3, 0x00000006},  // 3\n    {0x28, 0, 0, 0x0000002a},  // 4\n    {0x15, 0, 1, 0x0000fffe},  // 5\n    {0x6, 0, 0, 0x00040000},   // 6\n    {0x6, 0, 0, 0x00000000},   // 7\n};                             // note: this filter doesnt support extension headers\n/*\n { 0x30, 0, 0, 0x00000014 },//2\n{ 0x15, 0, 3, 0x00000006 },//3\n{ 0x28, 0, 0, 0x00000038 },//4\n{ 0x15, 0, 1, 0x0000fffe },//5\n{ 0x6, 0, 0, 0x00040000 },//6\n{ 0x6, 0, 0, 0x00000000 },//7\n*/\n\nint code_tcp6_port_index = 3;\n\nstruct sock_filter code_udp[] = {\n    //{ 0x5, 0, 0, 0x00000001 },\n    //{ 0x5, 0, 0, 0x00000000 },\n    {0x30, 0, 0, 0x00000009},\n    {0x15, 0, 6, 0x00000011},\n    {0x28, 0, 0, 0x00000006},\n    {0x45, 4, 0, 0x00001fff},\n    {0xb1, 0, 0, 0x00000000},\n    {0x48, 0, 0, 0x00000002},\n    {0x15, 0, 1, 0x0000fffe},  // modify this fffe to the port you listen on\n    {0x6, 0, 0, 0x0000ffff},\n    {0x6, 0, 0, 0x00000000},\n};\nint code_udp_port_index = 6;\n\nstruct sock_filter code_udp6[] = {\n    //\t\t{ 0x28, 0, 0, 0x0000000c },\n    //\t\t{ 0x15, 0, 5, 0x000086dd },\n    {0x30, 0, 0, 0x00000006},\n    {0x15, 0, 3, 0x00000011},\n    {0x28, 0, 0, 0x0000002a},\n    {0x15, 0, 1, 0x0000fffe},\n    {0x6, 0, 0, 0x00040000},\n    {0x6, 0, 0, 0x00000000},\n\n};\nint code_udp6_port_index = 3;\n\nstruct sock_filter code_icmp[] = {\n    //{ 0x5, 0, 0, 0x00000001 },\n    //{ 0x5, 0, 0, 0x00000000 },\n    {0x30, 0, 0, 0x00000009},\n    {0x15, 0, 1, 0x00000001},\n    {0x6, 0, 0, 0x0000ffff},\n    {0x6, 0, 0, 0x00000000},\n};\n\nstruct sock_filter code_icmp6[] = {\n    //\t\t{ 0x28, 0, 0, 0x0000000c },\n    //\t\t{ 0x15, 0, 6, 0x000086dd },\n    {0x30, 0, 0, 0x00000006},\n    {0x15, 3, 0, 0x0000003a},\n    {0x15, 0, 3, 0x0000002c},\n    {0x30, 0, 0, 0x00000028},\n    {0x15, 0, 1, 0x0000003a},\n    {0x6, 0, 0, 0x00040000},\n    {0x6, 0, 0, 0x00000000},\n\n};\n/*\n\ntcpdump -i eth1  ip and icmp -d\n(000) ldh      [12]\n(001) jeq      #0x800           jt 2    jf 5\n(002) ldb      [23]\n(003) jeq      #0x1             jt 4    jf 5\n(004) ret      #65535\n(005) ret      #0\n\ntcpdump -i eth1  ip and icmp -dd\n{ 0x28, 0, 0, 0x0000000c },\n{ 0x15, 0, 3, 0x00000800 },\n{ 0x30, 0, 0, 0x00000017 },\n{ 0x15, 0, 1, 0x00000001 },\n{ 0x6, 0, 0, 0x0000ffff },\n{ 0x6, 0, 0, 0x00000000 },\n\n\n */\n/*\n  tcpdump -i eth1 ip and tcp and dst port 65534 -dd\n\n{ 0x28, 0, 0, 0x0000000c },\n{ 0x15, 0, 8, 0x00000800 },\n{ 0x30, 0, 0, 0x00000017 },\n{ 0x15, 0, 6, 0x00000006 },\n{ 0x28, 0, 0, 0x00000014 },\n{ 0x45, 4, 0, 0x00001fff },\n{ 0xb1, 0, 0, 0x0000000e },\n{ 0x48, 0, 0, 0x00000010 },\n{ 0x15, 0, 1, 0x0000fffe },\n{ 0x6, 0, 0, 0x0000ffff },\n{ 0x6, 0, 0, 0x00000000 },\n\n (000) ldh      [12]\n(001) jeq      #0x800           jt 2    jf 10\n(002) ldb      [23]\n(003) jeq      #0x6             jt 4    jf 10\n(004) ldh      [20]\n(005) jset     #0x1fff          jt 10   jf 6\n(006) ldxb     4*([14]&0xf)\n(007) ldh      [x + 16]\n(008) jeq      #0xfffe          jt 9    jf 10\n(009) ret      #65535\n(010) ret      #0\n\n */\n#endif\n\npacket_info_t::packet_info_t() {\n    src_port = 0;\n    dst_port = 0;\n    if (raw_mode == mode_faketcp) {\n        protocol = IPPROTO_TCP;\n        ack_seq = get_true_random_number();\n        seq = get_true_random_number();\n        has_ts = 0;\n        ts_ack = 0;\n        syn = 0;\n        ack = 1;\n        ack_seq_counter = 0;\n\n        // mylog(log_info,\"<cons ,ts_ack= %u>\\n\",ts_ack);\n    } else if (raw_mode == mode_udp) {\n        protocol = IPPROTO_UDP;\n    } else if (raw_mode == mode_icmp) {\n        if (raw_ip_version == AF_INET) {\n            protocol = IPPROTO_ICMP;\n        } else {\n            assert(raw_ip_version == AF_INET6);\n            protocol = IPPROTO_ICMPV6;\n        }\n        my_icmp_seq = 0;\n    }\n}\n#ifdef UDP2RAW_MP\nvoid my_packet_handler(\n    u_char *args,\n    const struct pcap_pkthdr *packet_header,\n    const u_char *pkt_data) {\n    /*printf(\"<%d %d>\\n\",(int)packet_header->caplen,(int)packet_header->len );\n    for(int i=0;i<sizeof(pcap_pkthdr);i++)\n    {\n            char *p=(char *) packet_header;\n            printf(\"<%x>\",int( p[i] ));\n    }\n    printf(\"\\n\");*/\n    // mylog(log_debug,\"received a packet!\\n\");\n    assert(packet_header->caplen <= packet_header->len);\n    assert(packet_header->caplen <= huge_data_len);\n    // if(packet_header->caplen > max_data_len) return ;\n    if (g_fix_gro == 0 && packet_header->caplen < packet_header->len) return;\n\n    if ((int)packet_header->caplen < pcap_link_header_len) return;\n    // mylog(log_debug,\"and its vaild!\\n\");\n\n    pthread_mutex_lock(&queue_mutex);\n    if (!my_queue.full())\n        my_queue.push_back((char *)pkt_data, (int)(packet_header->caplen));\n    pthread_mutex_unlock(&queue_mutex);\n\n    // pcap_cnt++;\n\n    ev_async_send(g_default_loop, &async_watcher);\n    return;\n}\n\nvoid *pcap_recv_thread_entry(void *none) {\n    struct pcap_pkthdr *packet_header;\n    const u_char *pkt_data;\n\n    while (1) {\n        if (use_pcap_mutex) pthread_mutex_lock(&pcap_mutex);\n        int ret = pcap_loop(pcap_handle, -1, my_packet_handler, NULL);  // use -1 instead of 0 as cnt, since 0 is undefined in old versions\n        if (use_pcap_mutex) pthread_mutex_unlock(&pcap_mutex);\n        if (ret == -1)\n            mylog(log_warn, \"pcap_loop exited with value %d\\n\", ret);\n        else {\n            mylog(log_debug, \"pcap_loop exited with value %d\\n\", ret);\n        }\n        ev_sleep(1.0);\n        // myexit(-1);\n    }\n    /*\n    while(1)\n    {\n            //printf(\"!!!\\n\");\n            pthread_mutex_lock(&pcap_mutex);\n            int ret=pcap_next_ex(pcap_handle,&packet_header,&pkt_data);\n            pthread_mutex_unlock(&pcap_mutex);\n\n            switch (ret)\n            {\n                    case 0:\n                            continue;\n                    case 1:\n\n                            break;\n\n                    case -1:\n                            mylog(log_fatal,\"pcap_next_ex error [%s]\\n\",pcap_geterr(pcap_handle));\n                            myexit(-1);\n                            break;\n                    case -2:\n                            assert(0==1);//\n                            break;\n                    default:\n                            assert(0==1);//\n            }\n    }\n    myexit(-1);*/\n    return 0;\n}\n\nextern void async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents);\n#endif\n\n#ifdef UDP2RAW_LINUX\nint init_raw_socket() {\n    assert(raw_ip_version == AF_INET || raw_ip_version == AF_INET6);\n\n    g_ip_id_counter = get_true_random_number() % 65535;\n    if (lower_level == 0) {\n        raw_send_fd = socket(raw_ip_version, SOCK_RAW, IPPROTO_RAW);  // IPPROTO_TCP??\n\n        if (raw_send_fd == -1) {\n            mylog(log_fatal, \"Failed to create raw_send_fd\\n\");\n            // perror(\"Failed to create raw_send_fd\");\n            myexit(1);\n        }\n\n        /*ETH_P_IP\n        int one = 1;\n        const int *val = &one;\n        if (setsockopt (raw_send_fd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) {\n            mylog(log_fatal,\"Error setting IP_HDRINCL %d\\n\",errno);\n            //perror(\"Error setting IP_HDRINCL\");\n            myexit(2);\n        }*/\n\n    } else {\n        raw_send_fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));  // todo  how to create a recv only raw socket?\n\n        if (raw_send_fd == -1) {\n            mylog(log_fatal, \"Failed to create raw_send_fd\\n\");\n            // perror(\"Failed to create raw_send_fd\");\n            myexit(1);\n        }\n        // init_ifindex(if_name);\n    }\n\n    int opt = 0;\n    assert(setsockopt(raw_send_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) == 0);  // raw_send_fd is for send only, set its recv buffer to zero\n\n    if (force_socket_buf) {\n        if (setsockopt(raw_send_fd, SOL_SOCKET, SO_SNDBUFFORCE, &socket_buf_size, sizeof(socket_buf_size)) < 0) {\n            mylog(log_fatal, \"SO_SNDBUFFORCE fail  socket_buf_size=%d  errno=%s\\n\", socket_buf_size, strerror(errno));\n            myexit(1);\n        }\n    } else {\n        if (setsockopt(raw_send_fd, SOL_SOCKET, SO_SNDBUF, &socket_buf_size, sizeof(socket_buf_size)) < 0) {\n            mylog(log_fatal, \"SO_SNDBUF fail  socket_buf_size=%d  errno=%s\\n\", socket_buf_size, strerror(errno));\n            myexit(1);\n        }\n    }\n\n    // raw_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));\n\n    if (raw_ip_version == AF_INET)\n        raw_recv_fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));\n    else\n        raw_recv_fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));\n    // ETH_P_IP doesnt read outgoing packets\n    //    https://stackoverflow.com/questions/20264895/eth-p-ip-is-not-working-as-expected-i-can-only-receive-incoming-packets\n    //    to capture both incoming and outgoing packets use ETH_P_ALL\n\n    if (raw_recv_fd == -1) {\n        mylog(log_fatal, \"Failed to create raw_recv_fd\\n\");\n        // perror(\"\");\n        myexit(1);\n    }\n    if (strlen(dev) != 0) {\n        struct sockaddr_ll bind_address;\n        memset(&bind_address, 0, sizeof(bind_address));\n\n        int index = -1;\n        assert(init_ifindex(dev, raw_recv_fd, index) == 0);\n\n        bind_address.sll_family = AF_PACKET;\n        if (raw_ip_version == AF_INET)\n            bind_address.sll_protocol = htons(ETH_P_IP);\n        else\n            bind_address.sll_protocol = htons(ETH_P_IPV6);\n        bind_address.sll_ifindex = index;\n\n        if (bind(raw_recv_fd, (struct sockaddr *)&bind_address, sizeof(bind_address)) == -1) {\n            mylog(log_fatal, \"bind to dev [%s] failed\\n\", dev);\n            myexit(1);\n        }\n    }\n\n    if (force_socket_buf) {\n        if (setsockopt(raw_recv_fd, SOL_SOCKET, SO_RCVBUFFORCE, &socket_buf_size, sizeof(socket_buf_size)) < 0) {\n            mylog(log_fatal, \"SO_RCVBUFFORCE fail  socket_buf_size=%d  errno=%s\\n\", socket_buf_size, strerror(errno));\n            myexit(1);\n        }\n    } else {\n        if (setsockopt(raw_recv_fd, SOL_SOCKET, SO_RCVBUF, &socket_buf_size, sizeof(socket_buf_size)) < 0) {\n            mylog(log_fatal, \"SO_RCVBUF fail  socket_buf_size=%d  errno=%s\\n\", socket_buf_size, strerror(errno));\n            myexit(1);\n        }\n    }\n\n    // IP_HDRINCL to tell the kernel that headers are included in the packet\n\n    setnonblocking(raw_send_fd);  // not really necessary\n    setnonblocking(raw_recv_fd);\n\n    return 0;\n}\n#endif\n#ifdef UDP2RAW_MP\nint init_raw_socket() {\n#ifndef NO_LIBNET\n    char libnet_errbuf[LIBNET_ERRBUF_SIZE];\n\n    if (raw_ip_version == AF_INET) {\n        libnet_handle = libnet_init(LIBNET_RAW4, dev, libnet_errbuf);\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        libnet_handle = libnet_init(LIBNET_RAW6, dev, libnet_errbuf);\n    }\n\n    if (libnet_handle == 0) {\n        mylog(log_fatal, \"libnet_init failed bc of [%s]\\n\", libnet_errbuf);\n        myexit(-1);\n    }\n    g_ptag = 0;\n    libnet_clear_packet(libnet_handle);\n#endif\n\n    char pcap_errbuf[PCAP_ERRBUF_SIZE];\n\n    // pcap_handle=pcap_open_live(dev,max_data_len,0,1000,pcap_errbuf);\n\n    pcap_handle = pcap_create(dev, pcap_errbuf);\n\n    if (pcap_handle == 0) {\n        mylog(log_fatal, \"pcap_create failed bc of [%s]\\n\", pcap_errbuf);\n        myexit(-1);\n    }\n\n    assert(pcap_set_snaplen(pcap_handle, huge_data_len) == 0);\n    assert(pcap_set_promisc(pcap_handle, 0) == 0);\n    assert(pcap_set_timeout(pcap_handle, 1) == 0);\n    assert(pcap_set_immediate_mode(pcap_handle, 1) == 0);\n\n    int ret = pcap_activate(pcap_handle);\n    if (ret < 0) {\n        printf(\"pcap_activate failed  %s\\n\", pcap_geterr(pcap_handle));\n        myexit(-1);\n    }\n\n    if (send_with_pcap) {\n        ret = pcap_setdirection(pcap_handle, PCAP_D_INOUT);  // must be used after being actived\n        if (ret != 0) mylog(log_debug, \"pcap_setdirection(pcap_handle,PCAP_D_INOUT) failed with value %d, %s\\n\", ret, pcap_geterr(pcap_handle));\n    } else {\n        ret = pcap_setdirection(pcap_handle, PCAP_D_IN);\n        if (ret != 0) mylog(log_debug, \"pcap_setdirection(pcap_handle,PCAP_D_IN) failed with value %d, %s\\n\", ret, pcap_geterr(pcap_handle));\n    }\n\n    ret = pcap_datalink(pcap_handle);\n\n    if (ret == DLT_EN10MB) {\n        pcap_link_header_len = 14;\n    } else if (ret == DLT_NULL) {\n        pcap_link_header_len = 4;\n    } else if (ret == DLT_LINUX_SLL) {\n        pcap_link_header_len = 16;\n    } else {\n        mylog(log_fatal, \"unknown pcap link type : %d\\n\", ret);\n        myexit(-1);\n    }\n\n    char filter_exp[1000];\n\n    address_t tmp_addr;\n    if (get_src_adress2(tmp_addr, remote_addr) != 0) {\n        mylog(log_error, \"get_src_adress() failed, maybe you dont have internet\\n\");\n        myexit(-1);\n    }\n\n    string src = tmp_addr.get_ip();\n    string dst = remote_addr.get_ip();\n    if (raw_ip_version == AF_INET) {\n        // sprintf(filter_exp,\"ip and src %s and dst %s and (tcp or udp or icmp)\",my_ntoa(source_ip_uint32),dst.c_str());\n        sprintf(filter_exp, \"ip and src %s and dst %s and (tcp or udp or icmp)\", src.c_str(), dst.c_str());\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        sprintf(filter_exp, \"ip6 and src %s and dst %s and (tcp or udp or icmp6)\", src.c_str(), dst.c_str());\n    }\n\n    if (pcap_compile(pcap_handle, &g_filter, filter_exp, 0, PCAP_NETMASK_UNKNOWN) == -1) {\n        printf(\"Bad filter - %s\\n\", pcap_geterr(pcap_handle));\n        myexit(-1);\n    }\n    g_filter_compile_cnt++;\n\n    if (pcap_setfilter(pcap_handle, &g_filter) == -1) {\n        printf(\"Error setting filter - %s\\n\", pcap_geterr(pcap_handle));\n        myexit(-1);\n    }\n\n    ///////////////////////////////////////////////////////////////new thread created here\n    if (pthread_create(&pcap_recv_thread, NULL, pcap_recv_thread_entry, 0)) {\n        mylog(log_fatal, \"Error creating thread\\n\");\n        myexit(-1);\n    }\n    ////////////////////////////////////////////////////////////////////////////////\n\n    g_ip_id_counter = get_true_random_number() % 65535;\n\n    /*\n    if(lower_level==0)\n    {\n            raw_send_fd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);\n\n        if(raw_send_fd == -1) {\n            mylog(log_fatal,\"Failed to create raw_send_fd\\n\");\n            //perror(\"Failed to create raw_send_fd\");\n            myexit(1);\n        }\n\n        int one = 1;\n        const int *val = &one;\n        if (setsockopt (raw_send_fd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) {\n            mylog(log_fatal,\"Error setting IP_HDRINCL %d\\n\",errno);\n            //perror(\"Error setting IP_HDRINCL\");\n            myexit(2);\n        }\n\n\n    }\n    else\n    {\n            raw_send_fd = socket(PF_PACKET , SOCK_DGRAM , htons(ETH_P_IP));\n\n        if(raw_send_fd == -1) {\n            mylog(log_fatal,\"Failed to create raw_send_fd\\n\");\n            //perror(\"Failed to create raw_send_fd\");\n            myexit(1);\n        }\n            //init_ifindex(if_name);\n\n    }\n\n    if(force_socket_buf)\n    {\n            if(setsockopt(raw_send_fd, SOL_SOCKET, SO_SNDBUFFORCE, &socket_buf_size, sizeof(socket_buf_size))<0)\n            {\n                    mylog(log_fatal,\"SO_SNDBUFFORCE fail  socket_buf_size=%d  errno=%s\\n\",socket_buf_size,strerror(errno));\n                    myexit(1);\n            }\n    }\n    else\n    {\n            if(setsockopt(raw_send_fd, SOL_SOCKET, SO_SNDBUF, &socket_buf_size, sizeof(socket_buf_size))<0)\n            {\n                    mylog(log_fatal,\"SO_SNDBUF fail  socket_buf_size=%d  errno=%s\\n\",socket_buf_size,strerror(errno));\n                    myexit(1);\n            }\n    }\n\n\n\n    //raw_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));\n\n    raw_recv_fd= socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));\n\nif(raw_recv_fd == -1) {\n    mylog(log_fatal,\"Failed to create raw_recv_fd\\n\");\n    //perror(\"\");\n    myexit(1);\n}\n\n    if(force_socket_buf)\n    {\n            if(setsockopt(raw_recv_fd, SOL_SOCKET, SO_RCVBUFFORCE, &socket_buf_size, sizeof(socket_buf_size))<0)\n            {\n                    mylog(log_fatal,\"SO_RCVBUFFORCE fail  socket_buf_size=%d  errno=%s\\n\",socket_buf_size,strerror(errno));\n                    myexit(1);\n            }\n    }\n    else\n    {\n            if(setsockopt(raw_recv_fd, SOL_SOCKET, SO_RCVBUF, &socket_buf_size, sizeof(socket_buf_size))<0)\n            {\n                    mylog(log_fatal,\"SO_RCVBUF fail  socket_buf_size=%d  errno=%s\\n\",socket_buf_size,strerror(errno));\n                    myexit(1);\n            }\n    }\n\n//IP_HDRINCL to tell the kernel that headers are included in the packet\n\n\n\nsetnonblocking(raw_send_fd); //not really necessary\nsetnonblocking(raw_recv_fd);*/\n\n    return 0;\n}\n#endif\n#ifdef UDP2RAW_LINUX\nvoid init_filter(int port) {\n    sock_fprog bpf;\n    assert(raw_ip_version == AF_INET || raw_ip_version == AF_INET6);\n    if (raw_mode == mode_faketcp || raw_mode == mode_udp) {\n        filter_port = port;\n    }\n    if (disable_bpf_filter) return;\n    // if(raw_mode==mode_icmp) return ;\n    // code_tcp[8].k=code_tcp[10].k=port;\n    if (raw_mode == mode_faketcp) {\n        if (raw_ip_version == AF_INET) {\n            bpf.len = sizeof(code_tcp) / sizeof(code_tcp[0]);\n            code_tcp[code_tcp_port_index].k = port;\n            bpf.filter = code_tcp;\n        } else {\n            bpf.len = sizeof(code_tcp6) / sizeof(code_tcp6[0]);\n            code_tcp6[code_tcp6_port_index].k = port;\n            bpf.filter = code_tcp6;\n        }\n    } else if (raw_mode == mode_udp) {\n        if (raw_ip_version == AF_INET) {\n            bpf.len = sizeof(code_udp) / sizeof(code_udp[0]);\n            code_udp[code_udp_port_index].k = port;\n            bpf.filter = code_udp;\n        } else {\n            bpf.len = sizeof(code_udp6) / sizeof(code_udp6[0]);\n            code_udp6[code_udp6_port_index].k = port;\n            bpf.filter = code_udp6;\n        }\n    } else if (raw_mode == mode_icmp) {\n        if (raw_ip_version == AF_INET) {\n            bpf.len = sizeof(code_icmp) / sizeof(code_icmp[0]);\n            bpf.filter = code_icmp;\n        } else {\n            bpf.len = sizeof(code_icmp6) / sizeof(code_icmp6[0]);\n            bpf.filter = code_icmp6;\n        }\n    }\n\n    int dummy=0;\n\n    int ret = setsockopt(raw_recv_fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy));  // in case i forgot to remove\n    if (ret != 0) {\n        mylog(log_debug, \"error remove fiter\\n\");\n        // perror(\"filter\");\n        // exit(-1);\n    }\n    ret = setsockopt(raw_recv_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));\n    if (ret != 0) {\n        mylog(log_fatal, \"error set fiter\\n\");\n        // perror(\"filter\");\n        myexit(-1);\n    }\n}\n#endif\n\n#ifdef UDP2RAW_MP\nvoid init_filter(int port) {\n    /*\n    sock_fprog bpf;*/\n    if (raw_mode == mode_faketcp || raw_mode == mode_udp) {\n        filter_port = port;\n    }\n\n    char filter_exp[1000];\n\n    if (raw_ip_version == AF_INET) {\n        if (raw_mode == mode_faketcp) {\n            sprintf(filter_exp, \"ip and tcp and src %s and src port %d and dst port %d\", remote_addr.get_ip(), remote_addr.get_port(), port);\n        } else if (raw_mode == mode_udp) {\n            sprintf(filter_exp, \"ip and udp and src %s and src port %d and dst port %d\", remote_addr.get_ip(), remote_addr.get_port(), port);\n        } else if (raw_mode == mode_icmp) {\n            sprintf(filter_exp, \"ip and icmp and src %s\", remote_addr.get_ip());\n        } else {\n            mylog(log_fatal, \"unknow raw mode\\n\");\n            myexit(-1);\n        }\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        if (raw_mode == mode_faketcp) {\n            sprintf(filter_exp, \"ip6 and tcp and src %s and src port %d and dst port %d\", remote_addr.get_ip(), remote_addr.get_port(), port);\n        } else if (raw_mode == mode_udp) {\n            sprintf(filter_exp, \"ip6 and udp and src %s and src port %d and dst port %d\", remote_addr.get_ip(), remote_addr.get_port(), port);\n        } else if (raw_mode == mode_icmp) {\n            sprintf(filter_exp, \"ip6 and icmp6 and src %s\", remote_addr.get_ip());\n        } else {\n            mylog(log_fatal, \"unknow raw mode\\n\");\n            myexit(-1);\n        }\n    }\n\n    mylog(log_info, \"filter expression is [%s]\\n\", filter_exp);\n\n    // pthread_mutex_lock(&pcap_mutex);//not sure if mutex is needed here\n\n    long long tmp_cnt = 0;\n    if (use_pcap_mutex) {\n        while (pthread_mutex_trylock(&pcap_mutex) != 0) {\n            tmp_cnt++;\n            pcap_breakloop(pcap_handle);\n            if (tmp_cnt == 100) {\n                mylog(log_warn, \"%lld attempts of pcap_breakloop()\\n\", tmp_cnt);\n            }\n            if (tmp_cnt % 1000 == 0) {\n                mylog(log_warn, \"%lld attempts of pcap_breakloop()\\n\", tmp_cnt);\n                if (tmp_cnt > 5000) {\n                    mylog(log_fatal, \"we might have already run into a deadlock\\n\");\n                }\n            }\n            ev_sleep(0.001);\n        }\n        mylog(log_info, \"breakloop() succeed after %lld attempt(s)\\n\", tmp_cnt);\n    }\n\n    if (1) {\n        int ret = pcap_setdirection(pcap_handle, PCAP_D_IN);\n        if (ret != 0) mylog(log_debug, \"pcap_setdirection(pcap_handle,PCAP_D_IN) failed with value %d, %s\\n\", ret, pcap_geterr(pcap_handle));\n    }\n\n    assert(g_filter_compile_cnt != 0);\n    pcap_freecode(&g_filter);\n\n    if (pcap_compile(pcap_handle, &g_filter, filter_exp, 0, PCAP_NETMASK_UNKNOWN) == -1) {\n        mylog(log_fatal, \"Bad filter - %s\\n\", pcap_geterr(pcap_handle));\n        myexit(-1);\n    }\n    g_filter_compile_cnt++;\n\n    if (pcap_setfilter(pcap_handle, &g_filter) == -1) {\n        mylog(log_fatal, \"Error setting filter - %s\\n\", pcap_geterr(pcap_handle));\n        myexit(-1);\n    }\n\n    if (use_pcap_mutex) pthread_mutex_unlock(&pcap_mutex);\n    /*\n    if(disable_bpf_filter) return;\n    //if(raw_mode==mode_icmp) return ;\n    //code_tcp[8].k=code_tcp[10].k=port;\n    if(raw_mode==mode_faketcp)\n    {\n            bpf.len = sizeof(code_tcp)/sizeof(code_tcp[0]);\n            code_tcp[code_tcp_port_index].k=port;\n            bpf.filter = code_tcp;\n    }\n    else if(raw_mode==mode_udp)\n    {\n            bpf.len = sizeof(code_udp)/sizeof(code_udp[0]);\n            code_udp[code_udp_port_index].k=port;\n            bpf.filter = code_udp;\n    }\n    else if(raw_mode==mode_icmp)\n    {\n            bpf.len = sizeof(code_icmp)/sizeof(code_icmp[0]);\n            bpf.filter = code_icmp;\n    }\n\n    int dummy;\n\n    int ret=setsockopt(raw_recv_fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy)); //in case i forgot to remove\n    if (ret != 0)\n    {\n            mylog(log_debug,\"error remove fiter\\n\");\n            //perror(\"filter\");\n            //exit(-1);\n    }\n    ret = setsockopt(raw_recv_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));\n    if (ret != 0)\n    {\n            mylog(log_fatal,\"error set fiter\\n\");\n            //perror(\"filter\");\n            myexit(-1);\n    }*/\n}\n#endif\n\nvoid remove_filter() {\n    filter_port = 0;\n#ifdef UDP2RAW_LINUX\n    int dummy=0;\n    int ret = setsockopt(raw_recv_fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy));\n    if (ret != 0) {\n        mylog(log_debug, \"error remove fiter\\n\");\n        // perror(\"filter\");\n        // exit(-1);\n    }\n#endif\n}\n\nint init_ifindex(const char *if_name, int fd, int &index) {\n#ifdef UDP2RAW_LINUX\n    struct ifreq ifr;\n    size_t if_name_len = strlen(if_name);\n    if (if_name_len < sizeof(ifr.ifr_name)) {\n        memcpy(ifr.ifr_name, if_name, if_name_len);\n        ifr.ifr_name[if_name_len] = 0;\n    } else {\n        mylog(log_fatal, \"interface name is too long\\n\");\n        myexit(-1);\n    }\n    if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {\n        mylog(log_fatal, \"SIOCGIFINDEX fail ,%s\\n\", strerror(errno));\n        myexit(-1);\n    }\n    index = ifr.ifr_ifindex;\n    mylog(log_info, \"ifname:%s  ifindex:%d\\n\", if_name, index);\n#endif\n    return 0;\n}\n\n#ifdef UDP2RAW_LINUX\nbool interface_has_arp(const char *interface) {\n    struct ifreq ifr;\n    // int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);\n    int sock = raw_send_fd;\n    memset(&ifr, 0, sizeof(ifr));\n    strcpy(ifr.ifr_name, interface);\n    if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {\n        // perror(\"SIOCGIFFLAGS\");\n        mylog(log_fatal, \"ioctl(sock, SIOCGIFFLAGS, &ifr) failed for interface %s,errno %s\\n\", interface, strerror(errno));\n        myexit(-1);\n    }\n    // close(sock);\n    return !(ifr.ifr_flags & IFF_NOARP);\n}\nstruct route_info_t {\n    string if_name;\n    u32_t dest;\n    u32_t mask;\n    u32_t gw;\n    u32_t flag;\n};\nint dest_idx = 1;\nint gw_idx = 2;\nint if_idx = 0;\nint mask_idx = 7;\nint flag_idx = 3;\nvector<int> find_route_entry(const vector<route_info_t> &route_info_vec, u32_t ip) {\n    vector<int> res;\n    for (u32_t i = 0; i <= 32; i++) {\n        u32_t mask = 0xffffffff;\n        // mask >>=i;\n        // if(i==32) mask=0;  //why 0xffffffff>>32  equals 0xffffffff??\n\n        mask <<= i;\n        if (i == 32) mask = 0;\n        log_bare(log_debug, \"(mask:%x)\", mask);\n        for (u32_t j = 0; j < route_info_vec.size(); j++) {\n            const route_info_t &info = route_info_vec[j];\n            if (info.mask != mask)\n                continue;\n            log_bare(log_debug, \"<<%d,%d>>\", i, j);\n            if ((info.dest & mask) == (ip & mask)) {\n                log_bare(log_debug, \"found!\");\n                res.push_back(j);\n            }\n        }\n        if (res.size() != 0) {\n            return res;\n        }\n    }\n    return res;\n}\nint find_direct_dest(const vector<route_info_t> &route_info_vec, u32_t ip, u32_t &dest_ip, string &if_name) {\n    vector<int> res;\n    for (int i = 0; i < 1000; i++) {\n        res = find_route_entry(route_info_vec, ip);\n        log_bare(log_debug, \"<entry:%u>\", (u32_t)res.size());\n        if (res.size() == 0) {\n            mylog(log_error, \"cant find route entry\\n\");\n            return -1;\n        }\n        if (res.size() > 1) {\n            mylog(log_error, \"found duplicated entries\\n\");\n            return -1;\n        }\n        if ((route_info_vec[res[0]].flag & 2) == 0) {\n            dest_ip = ip;\n            if_name = route_info_vec[res[0]].if_name;\n            return 0;\n        } else {\n            ip = route_info_vec[res[0]].gw;\n        }\n    }\n    mylog(log_error, \"dead loop in find_direct_dest\\n\");\n    return -1;\n}\nstruct arp_info_t {\n    u32_t ip;\n    string hw;\n    string if_name;\n};\nint arp_ip_idx = 0;\nint arp_hw_idx = 3;\nint arp_if_idx = 5;\n\nint find_arp(const vector<arp_info_t> &arp_info_vec, u32_t ip, string if_name, string &hw) {\n    int pos = -1;\n    int count = 0;\n    for (u32_t i = 0; i < arp_info_vec.size(); i++) {\n        const arp_info_t &info = arp_info_vec[i];\n        if (info.if_name != if_name) continue;\n        if (info.ip == ip) {\n            count++;\n            pos = i;\n        }\n    }\n    if (count == 0) {\n        // mylog(log_warn,\"cant find arp entry for %s %s,using 00:00:00:00:00:00\\n\",my_ntoa(ip),if_name.c_str());\n        // hw=\"00:00:00:00:00:00\";\n        mylog(log_error, \"cant find arp entry for %s %s\\n\", my_ntoa(ip), if_name.c_str());\n        return -1;\n    }\n    if (count > 1) {\n        mylog(log_error, \"find multiple arp entry for %s %s\\n\", my_ntoa(ip), if_name.c_str());\n        return -1;\n    }\n    hw = arp_info_vec[pos].hw;\n    return 0;\n}\nint find_lower_level_info(u32_t ip, u32_t &dest_ip, string &if_name, string &hw) {\n    ip = htonl(ip);\n    if (ip == htonl(inet_addr(\"127.0.0.1\"))) {\n        dest_ip = ntohl(ip);\n        if_name = \"lo\";\n        hw = \"00:00:00:00:00:00\";\n        return 0;\n    }\n\n    string route_file;\n    if (read_file(\"/proc/net/route\", route_file) != 0) return -1;\n    string arp_file;\n    if (read_file(\"/proc/net/arp\", arp_file) != 0) return -1;\n\n    log_bare(log_debug, \"/proc/net/route:<<%s>>\\n\", route_file.c_str());\n    log_bare(log_debug, \"/proc/net/arp:<<%s>>\\n\", route_file.c_str());\n\n    auto route_vec2 = string_to_vec2(route_file.c_str());\n    vector<route_info_t> route_info_vec;\n    for (u32_t i = 1; i < route_vec2.size(); i++) {\n        log_bare(log_debug, \"<size:%u>\", (u32_t)route_vec2[i].size());\n        if (route_vec2[i].size() != 11) {\n            mylog(log_error, \"route coloum %d !=11 \\n\", int(route_vec2[i].size()));\n            return -1;\n        }\n        route_info_t tmp;\n        tmp.if_name = route_vec2[i][if_idx];\n        if (hex_to_u32_with_endian(route_vec2[i][dest_idx], tmp.dest) != 0) return -1;\n        if (hex_to_u32_with_endian(route_vec2[i][gw_idx], tmp.gw) != 0) return -1;\n        if (hex_to_u32_with_endian(route_vec2[i][mask_idx], tmp.mask) != 0) return -1;\n        if (hex_to_u32(route_vec2[i][flag_idx], tmp.flag) != 0) return -1;\n        route_info_vec.push_back(tmp);\n        for (u32_t j = 0; j < route_vec2[i].size(); j++) {\n            log_bare(log_debug, \"<%s>\", route_vec2[i][j].c_str());\n        }\n        log_bare(log_debug, \"%s dest:%x mask:%x gw:%x flag:%x\", tmp.if_name.c_str(), tmp.dest, tmp.mask, tmp.gw, tmp.flag);\n        log_bare(log_debug, \"\\n\");\n    }\n\n    if (find_direct_dest(route_info_vec, ip, dest_ip, if_name) != 0) {\n        mylog(log_error, \"find_direct_dest failed for ip %s\\n\", my_ntoa(ntohl(ip)));\n        return -1;\n    }\n\n    log_bare(log_debug, \"========\\n\");\n    auto arp_vec2 = string_to_vec2(arp_file.c_str());\n    vector<arp_info_t> arp_info_vec;\n    for (u32_t i = 1; i < arp_vec2.size(); i++) {\n        log_bare(log_debug, \"<<arp_vec2[i].size(): %d>>\", (int)arp_vec2[i].size());\n\n        for (u32_t j = 0; j < arp_vec2[i].size(); j++) {\n            log_bare(log_debug, \"<%s>\", arp_vec2[i][j].c_str());\n        }\n        if (arp_vec2[i].size() != 6) {\n            mylog(log_error, \"arp coloum %d !=11 \\n\", int(arp_vec2[i].size()));\n            return -1;\n        }\n        arp_info_t tmp;\n        tmp.if_name = arp_vec2[i][arp_if_idx];\n        tmp.hw = arp_vec2[i][arp_hw_idx];\n        tmp.ip = htonl(inet_addr(arp_vec2[i][arp_ip_idx].c_str()));\n        arp_info_vec.push_back(tmp);\n        log_bare(log_debug, \"\\n\");\n    }\n    if (!interface_has_arp(if_name.c_str())) {\n        mylog(log_info, \"%s is a noarp interface,using 00:00:00:00:00:00\\n\", if_name.c_str());\n        hw = \"00:00:00:00:00:00\";\n    } else if (find_arp(arp_info_vec, dest_ip, if_name, hw) != 0) {\n        mylog(log_error, \"find_arp failed for dest_ip %s ,if_name %s\\n\", my_ntoa(ntohl(ip)), if_name.c_str());\n        return -1;\n    }\n    // printf(\"%s\\n\",hw.c_str());\n\n    dest_ip = ntohl(dest_ip);\n    return 0;\n}\n#endif\n\n#ifdef UDP2RAW_LINUX\nint send_raw_packet(raw_info_t &raw_info, const char *packet, int len) {\n    const packet_info_t &send_info = raw_info.send_info;\n    const packet_info_t &recv_info = raw_info.recv_info;\n\n    int ret;\n    if (lower_level == 0) {\n        if (raw_ip_version == AF_INET) {\n            struct sockaddr_in sin = {0};\n            sin.sin_family = raw_ip_version;\n            // sin.sin_port = htons(info.dst_port); //dont need this\n            sin.sin_addr.s_addr = send_info.new_dst_ip.v4;\n            ret = sendto(raw_send_fd, packet, len, 0, (struct sockaddr *)&sin, sizeof(sin));\n        } else if (raw_ip_version == AF_INET6) {\n            struct sockaddr_in6 sin = {0};\n            sin.sin6_family = raw_ip_version;\n            // sin.sin_port = htons(info.dst_port); //dont need this\n            sin.sin6_addr = send_info.new_dst_ip.v6;\n            ret = sendto(raw_send_fd, packet, len, 0, (struct sockaddr *)&sin, sizeof(sin));\n        } else {\n            assert(0 == 1);\n        }\n\n    } else {\n        struct sockaddr_ll addr = {0};  //={0} not necessary\n        memcpy(&addr, &send_info.addr_ll, sizeof(addr));\n\n        ret = sendto(raw_send_fd, packet, len, 0, (struct sockaddr *)&addr, sizeof(addr));\n    }\n    if (ret == -1) {\n        mylog(log_trace, \"sendto failed\\n\");\n        // perror(\"why?\");\n        return -1;\n    } else {\n        // mylog(log_info,\"sendto succ\\n\");\n    }\n    return 0;\n}\n#endif\n\n#ifdef UDP2RAW_MP\n\nint send_raw_packet(raw_info_t &raw_info, const char *packet, int len) {\n    const packet_info_t &send_info = raw_info.send_info;\n    const packet_info_t &recv_info = raw_info.recv_info;\n\n    if (!send_with_pcap) {\n#ifndef NO_LIBNET\n\n        // g_ptag=libnet_build_ipv4(ip_tot_len, iph->tos, ntohs(iph->id), ntohs(iph->frag_off),\n        //\tiph->ttl , iph->protocol , iph->check , iph->saddr, iph->daddr,\n        //\t(const unsigned char *)payload, payloadlen, libnet_handle, g_ptag);\n\n        // assert(g_ptag!=-1 &&g_ptag!=0);\n\n        // int ret;\n        // ret= libnet_write(libnet_handle);\n\n        // assert(ret!=-1);\n\n        // iph->tot_len=htons(ip_tot_len);\n        // iph->check =csum ((unsigned short *) send_raw_ip_buf, iph->ihl*4);\n        if (raw_ip_version == AF_INET) {\n            libnet_write_raw_ipv4(libnet_handle, (const unsigned char *)packet, len);  // todo, this api is marked as internal, maybe we should avoid using it.\n        } else {\n            assert(raw_ip_version == AF_INET6);\n            libnet_write_raw_ipv6(libnet_handle, (const unsigned char *)packet, len);\n        }\n#endif\n    } else {\n        char buf[buf_len];\n        assert(pcap_header_captured == 1);\n        assert(pcap_link_header_len != -1);\n        memcpy(buf, pcap_header_buf, pcap_link_header_len);\n        memcpy(buf + pcap_link_header_len, packet, len);\n        // pthread_mutex_lock(&pcap_mutex); looks like this is not necessary, and it harms performance\n        int ret = pcap_sendpacket(pcap_handle, (const unsigned char *)buf, len + pcap_link_header_len);\n        if (ret != 0) {\n            mylog(log_warn, \"pcap_sendpcaket failed with vaule %d,%s, data_len=%d\\n\", ret, pcap_geterr(pcap_handle), len);\n            // pthread_mutex_unlock(&pcap_mutex);\n            // myexit(-1);\n        }\n        // pthread_mutex_unlock(&pcap_mutex);\n        /*\nunsigned char *p=(unsigned char *)send_raw_ip_buf0;\nfor(int i=0;i<ip_tot_len+pcap_link_header_len;i++)\n        printf(\"<%02x>\",int(p[i]));\nprintf(\"\\n\");\nassert(pcap_sendpacket(pcap_handle,(const unsigned char *)pcap_header_buf,cap_len)==0);\np=(unsigned char *)pcap_header_buf;\nfor(int i=0;i<cap_len;i++)\n        printf(\"<%02x>\",int(p[i]));\nprintf(\"\\n\");\nprintf(\"pcap send!\\n\");*/\n    }\n    return 0;\n}\n#endif\n\nint send_raw_ip(raw_info_t &raw_info, const char *payload, int payloadlen) {\n    const packet_info_t &send_info = raw_info.send_info;\n    const packet_info_t &recv_info = raw_info.recv_info;\n    char send_raw_ip_buf[buf_len];\n\n    if (raw_info.disabled) {\n        mylog(log_debug, \"[%s,%d]connection disabled, no packet will be sent\\n\", recv_info.new_src_ip.get_str1(), recv_info.src_port);\n        assert(max_rst_allowed >= 0);\n        return 0;\n    }\n\n    uint16_t ip_tot_len;\n    if (raw_ip_version == AF_INET) {\n        struct my_iphdr *iph = (struct my_iphdr *)send_raw_ip_buf;\n        memset(iph, 0, sizeof(my_iphdr));\n\n        iph->ihl = sizeof(my_iphdr) / 4;  // we dont use ip options,so the length is just sizeof(iphdr)\n        iph->version = 4;\n        iph->tos = 0;\n\n        if (lower_level) {\n            // iph->id=0;\n            iph->id = htons(g_ip_id_counter++);  // Id of this packet\n        } else                                   // no need to else?\n        {\n            iph->id = htons(g_ip_id_counter++);  // Id of this packet\n            // iph->id = 0; //Id of this packet  ,kernel will auto fill this if id is zero  ,or really?????// todo //seems like there is a problem\n        }\n\n        iph->frag_off = htons(0x4000);  // DF set,others are zero\n        // iph->frag_off = htons(0x0000); //DF set,others are zero\n        iph->ttl = (unsigned char)ttl_value;\n        iph->protocol = send_info.protocol;\n        iph->check = 0;                        // Set to 0 before calculating checksum\n        iph->saddr = send_info.new_src_ip.v4;  // Spoof the source ip address\n        iph->daddr = send_info.new_dst_ip.v4;\n\n        ip_tot_len = sizeof(struct my_iphdr) + payloadlen;\n#ifdef UDP2RAW_LINUX\n        if (lower_level)\n            iph->tot_len = htons(ip_tot_len);  // this is not necessary ,kernel will always auto fill this  //http://man7.org/linux/man-pages/man7/raw.7.html\n        else\n            iph->tot_len = 0;\n#endif\n\n#ifdef UDP2RAW_MP\n        iph->tot_len = htons(ip_tot_len);  // always fill for mp version\n#endif\n\n        memcpy(send_raw_ip_buf + sizeof(my_iphdr), payload, payloadlen);\n\n#ifdef UDP2RAW_LINUX\n        if (lower_level)\n            iph->check =\n                csum((unsigned short *)send_raw_ip_buf, iph->ihl * 4);  // this is not necessary ,kernel will always auto fill this\n        else\n            iph->check = 0;\n#endif\n\n#ifdef UDP2RAW_MP\n        iph->check = csum((unsigned short *)send_raw_ip_buf, iph->ihl * 4);  // always cal checksum for mp version\n#endif\n    } else {\n        assert(raw_ip_version == AF_INET6);\n\n        struct my_ip6hdr *ip6h = (struct my_ip6hdr *)send_raw_ip_buf;\n        memset(ip6h, 0, sizeof(my_ip6hdr));\n\n        ip6h->version = 6;\n        ip6h->payload_len = htons(payloadlen);\n        ip6h->next_header = send_info.protocol;\n        ip6h->hop_limit = (unsigned char)ttl_value;\n        ip6h->src = send_info.new_src_ip.v6;\n        ip6h->dst = send_info.new_dst_ip.v6;\n\n        ip_tot_len = sizeof(struct my_ip6hdr) + payloadlen;\n        memcpy(send_raw_ip_buf + sizeof(my_ip6hdr), payload, payloadlen);\n    }\n\n    return send_raw_packet(raw_info, send_raw_ip_buf, ip_tot_len);\n}\n\nint pre_recv_raw_packet() {\n#ifdef UDP2RAW_LINUX\n    assert(g_packet_buf_cnt == 0);\n\n    g_sockaddr_len = sizeof(g_sockaddr.ll);\n    g_packet_buf_len = recvfrom(raw_recv_fd, g_packet_buf, huge_data_len + 1, 0, (sockaddr *)&g_sockaddr, &g_sockaddr_len);\n    // assert(g_sockaddr_len==sizeof(g_sockaddr.ll)); //g_sockaddr_len=18, sizeof(g_sockaddr.ll)=20, why its not equal? maybe its bc sll_halen is 6?\n\n    // assert(g_addr_ll_size==sizeof(g_addr_ll));\n\n    if (g_packet_buf_len == huge_data_len + 1) {\n        if (g_fix_gro == 0) {\n            mylog(log_warn, \"huge packet, data_len %d > %d,dropped\\n\", g_packet_buf_len, huge_data_len);\n            return -1;\n        } else {\n            mylog(log_debug, \"huge packet, data_len %d > %d,not dropped\\n\", g_packet_buf_len, huge_data_len);\n            g_packet_buf_len = huge_data_len;\n        }\n    }\n\n    if (g_packet_buf_len >= max_data_len + 1) {\n        if (g_fix_gro == 0) {\n            mylog(log_warn, \"huge packet, data_len %d > %d(max_data_len) dropped, maybe you need to turn down mtu at upper level, or you may take a look at --fix-gro\\n\", g_packet_buf_len,\n                  max_data_len);\n            return -1;\n        } else {\n            mylog(log_debug, \"huge packet, data_len %d > %d(max_data_len) not dropped\\n\", g_packet_buf_len,\n                  max_data_len);\n            // return -1;\n        }\n    }\n\n    if (g_packet_buf_len < 0) {\n        mylog(log_trace, \"recv_len %d\\n\", g_packet_buf_len);\n        return -1;\n    }\n    g_packet_buf_cnt++;\n#endif\n    return 0;\n}\nint discard_raw_packet() {\n    assert(g_packet_buf_cnt == 1);\n    g_packet_buf_cnt--;\n    return 0;\n}\n#ifdef UDP2RAW_LINUX\nint recv_raw_packet(char *&packet, int &len, int peek) {\n    assert(g_packet_buf_cnt == 1);\n    if (!peek)\n        g_packet_buf_cnt--;\n\n    if (g_packet_buf_len < int(link_level_header_len)) {\n        mylog(log_trace, \"packet len %d shorter than link_level_header_len %d\\n\", g_packet_buf_len, int(link_level_header_len));\n        return -1;\n    }\n\n    if (link_level_header_len == 14) {\n        unsigned char a = g_packet_buf[12];\n        unsigned char b = g_packet_buf[13];\n\n        if (!((a == 0x08 && b == 0x00) || (a == 0x86 && b == 0xdd))) {\n            mylog(log_trace, \"not an ipv4 or ipv6 packet!\\n\");\n            return -1;\n        }\n    }\n    packet = g_packet_buf + int(link_level_header_len);\n    len = g_packet_buf_len - int(link_level_header_len);\n    return 0;\n}\n#endif\n#ifdef UDP2RAW_MP\nint recv_raw_packet(char *&packet, int &len, int peek) {\n    assert(g_packet_buf_cnt == 1);\n    if (!peek)\n        g_packet_buf_cnt--;\n\n    packet = g_packet_buf;\n    len = g_packet_buf_len;\n    return 0;\n}\n#endif\nint recv_raw_ip(raw_info_t &raw_info, char *&payload, int &payloadlen) {\n    char *raw_packet_buf;\n    // static char recv_raw_ip_buf[buf_len];\n    int raw_packet_len;\n\n    if (recv_raw_packet(raw_packet_buf, raw_packet_len, raw_info.peek) != 0) return -1;\n\n    // const packet_info_t &send_info=raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    my_iphdr *iph;\n    my_ip6hdr *ip6h;\n    int flag = 0;\n    // int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len+1, flag ,(sockaddr*)&saddr , &saddr_size);\n\n    char *ip_begin = raw_packet_buf;  // 14 is eth net header\n\n    if (raw_packet_len < 1) {\n        mylog(log_trace, \"raw_packet_len <1, dropped\\n\");\n        return -1;\n    }\n    iph = (struct my_iphdr *)(ip_begin);\n    ip6h = (struct my_ip6hdr *)(ip_begin);\n    if (raw_ip_version == AF_INET) {\n        if (iph->version != 4) {\n            mylog(log_trace, \"expect ipv4 packet, but got something else: %02x\\n\", iph->version);\n            return -1;\n        }\n        if (raw_packet_len < (int)sizeof(my_iphdr)) {\n            mylog(log_trace, \"raw_packet_len<sizeof(iphdr)\\n\");\n            return -1;\n        }\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        if (ip6h->version != 6) {\n            mylog(log_trace, \"expect ipv6 packet, but got something else: %02x\\n\", ip6h->version);\n            return -1;\n        }\n        if (raw_packet_len < (int)sizeof(my_ip6hdr)) {\n            mylog(log_trace, \"raw_packet_len<sizeof(ip6_hdr)\\n\");\n            return -1;\n        }\n    }\n#ifdef UDP2RAW_LINUX\n    if (lower_level) {\n        memcpy(&recv_info.addr_ll, &g_sockaddr.ll, sizeof(recv_info.addr_ll));\n    }\n#endif\n\n    unsigned short iphdrlen;\n    int ip_len;\n    if (raw_ip_version == AF_INET) {\n        recv_info.new_src_ip.v4 = iph->saddr;\n        recv_info.new_dst_ip.v4 = iph->daddr;\n        recv_info.protocol = iph->protocol;\n        iphdrlen = iph->ihl * 4;\n        ip_len = ntohs(iph->tot_len);\n    } else {\n        // todo flow id\n        assert(raw_ip_version == AF_INET6);\n        recv_info.new_src_ip.v6 = ip6h->src;\n        recv_info.new_dst_ip.v6 = ip6h->dst;\n        iphdrlen = 40;\n        recv_info.protocol = ip6h->next_header;  // todo handle extension headers;\n        ip_len = ntohs(ip6h->payload_len) + iphdrlen;\n    }\n\n    if (bind_addr_used && !recv_info.new_dst_ip.equal(bind_addr)) {\n        mylog(log_trace, \"bind adress doenst match %s %s, dropped\\n\", recv_info.new_dst_ip.get_str1(), bind_addr.get_str2());\n        // printf(\" bind adress doenst match, dropped\\n\");\n        return -1;\n    }\n\n    // if (!(iph->ihl > 0 && iph->ihl <=60)) {\n    //\tmylog(log_trace,\"iph ihl error\\n\");\n    //    return -1;\n    //  }\n\n    if (raw_packet_len < ip_len) {\n        mylog(log_debug, \"incomplete packet\\n\");\n        return -1;\n    }\n\n    if (raw_ip_version == AF_INET) {\n        if (raw_info.peek == 0)  // avoid cal it twice\n        {\n            u32_t ip_chk = csum((unsigned short *)ip_begin, iphdrlen);\n\n            if (ip_chk != 0) {\n                mylog(log_debug, \"ip header error %x\\n\", ip_chk);\n                return -1;\n            }\n        }\n    } else {\n        // do nothing\n    }\n\n    payload = ip_begin + iphdrlen;\n\n    payloadlen = ip_len - iphdrlen;\n\n    if (payloadlen < 0) {\n        mylog(log_warn, \"error payload len\\n\");\n        return -1;\n    }\n\n    return 0;\n}\n\nint peek_raw(raw_info_t &raw_info) {\n    // static char peek_raw_buf[buf_len];\n    // assert(g_packet_buf_cnt==1);\n    // g_packet_buf_cnt--;\n    // char * peek_raw_buf=g_packet_buf;\n    // int recv_len=g_packet_buf_len;\n\n    // char *ip_begin=peek_raw_buf+link_level_header_len;\n    // struct sockaddr saddr={0};\n    // socklen_t saddr_size=sizeof(saddr);\n    // int recv_len = recvfrom(raw_recv_fd, peek_raw_buf,max_data_len, MSG_PEEK ,&saddr , &saddr_size);//change max_data_len to something smaller,we only need header here\n    // iphdr * iph = (struct iphdr *) (ip_begin);\n    // mylog(log_info,\"recv_len %d\\n\",recv_len);\n    // if(recv_len<int(sizeof(iphdr)))\n    //{\n    //\tmylog(log_trace,\"failed here %d %d\\n\",recv_len,int(sizeof(iphdr)));\n    //\tmylog(log_trace,\"%s\\n \",strerror(errno));\n    //\treturn -1;\n    // }\n    // peek_info.new_src_ip.v4=iph->saddr;\n    // unsigned short iphdrlen =iph->ihl*4;\n    // char *payload=ip_begin+iphdrlen;\n\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    char *payload;\n    int payload_len;\n    if (recv_raw_ip(raw_info, payload, payload_len) != 0)\n        return -1;\n    // mylog(log_info,\"protocol %d\\n\",iph->protocol);\n    switch (raw_mode) {\n        case mode_faketcp: {\n            if (recv_info.protocol != IPPROTO_TCP) {\n                mylog(log_trace, \"failed here\");\n                return -1;\n            }\n            struct my_tcphdr *tcph = (my_tcphdr *)payload;\n            if (payload_len < int(sizeof(my_tcphdr))) {\n                mylog(log_trace, \"failed here\");\n                return -1;\n            }\n            recv_info.src_port = ntohs(tcph->source);\n            recv_info.syn = tcph->syn;\n            break;\n        }\n        case mode_udp: {\n            if (recv_info.protocol != IPPROTO_UDP) return -1;\n            struct my_udphdr *udph = (my_udphdr *)payload;\n            if (payload_len < int(sizeof(my_udphdr)))\n                return -1;\n            recv_info.src_port = ntohs(udph->source);\n            break;\n        }\n        case mode_icmp: {\n            if (raw_ip_version == AF_INET) {\n                if (recv_info.protocol != IPPROTO_ICMP) return -1;\n            } else {\n                assert(raw_ip_version == AF_INET6);\n                if (recv_info.protocol != IPPROTO_ICMPV6) return -1;\n            }\n            struct my_icmphdr *icmph = (my_icmphdr *)payload;\n            if (payload_len < int(sizeof(my_udphdr)))\n                return -1;\n            recv_info.src_port = ntohs(icmph->id);\n            break;\n        }\n        default:\n            return -1;\n    }\n    return 0;\n}\nint send_raw_icmp(raw_info_t &raw_info, const char *payload, int payloadlen) {\n    const packet_info_t &send_info = raw_info.send_info;\n    const packet_info_t &recv_info = raw_info.recv_info;\n\n    char send_raw_icmp_buf[buf_len];\n    my_icmphdr *icmph = (struct my_icmphdr *)(send_raw_icmp_buf);\n    memset(icmph, 0, sizeof(my_icmphdr));\n    if (raw_ip_version == AF_INET) {\n        if (program_mode == client_mode) {\n            icmph->type = 8;\n        } else {\n            icmph->type = 0;\n        }\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        if (program_mode == client_mode) {\n            icmph->type = 128;\n        } else {\n            icmph->type = 129;\n        }\n    }\n    icmph->code = 0;\n    icmph->id = htons(send_info.src_port);\n\n    icmph->seq = htons(send_info.my_icmp_seq);  /////////////modify\n\n    memcpy(send_raw_icmp_buf + sizeof(my_icmphdr), payload, payloadlen);\n\n    if (raw_ip_version == AF_INET) {\n        icmph->check_sum = csum((unsigned short *)send_raw_icmp_buf, sizeof(my_icmphdr) + payloadlen);\n    } else {\n        assert(raw_ip_version == AF_INET6);\n\n        pseudo_header6 v6;\n        struct pseudo_header6 *psh = &v6;\n\n        psh->src = send_info.new_src_ip.v6;\n        psh->dst = send_info.new_dst_ip.v6;\n        psh->next_header = IPPROTO_ICMPV6;\n        psh->tcp_length = htons(sizeof(my_icmphdr) + payloadlen);\n        psh->placeholder1 = 0;\n        psh->placeholder2 = 0;\n\n        icmph->check_sum = csum_with_header((char *)psh, sizeof(pseudo_header6), (unsigned short *)send_raw_icmp_buf, sizeof(my_icmphdr) + payloadlen);\n    }\n    if (send_raw_ip(raw_info, send_raw_icmp_buf, sizeof(my_icmphdr) + payloadlen) != 0) {\n        return -1;\n    }\n\n    /*if(program_mode==client_mode)\n    {\n            send_info.icmp_seq++;\n    }*/\n\n    return 0;\n}\n\nint send_raw_udp(raw_info_t &raw_info, const char *payload, int payloadlen) {\n    const packet_info_t &send_info = raw_info.send_info;\n    const packet_info_t &recv_info = raw_info.recv_info;\n\n    char send_raw_udp_buf[buf_len];\n\n    my_udphdr *udph = (struct my_udphdr *)(send_raw_udp_buf);\n\n    memset(udph, 0, sizeof(my_udphdr));\n\n    udph->source = htons(send_info.src_port);\n    udph->dest = htons(send_info.dst_port);\n\n    int udp_tot_len = payloadlen + sizeof(my_udphdr);\n\n    if (udp_tot_len > 65535) {\n        mylog(log_debug, \"invalid len\\n\");\n        return -1;\n    }\n    mylog(log_trace, \"udp_len:%d %d\\n\", udp_tot_len, udph->len);\n    udph->len = htons(uint16_t(udp_tot_len));\n\n    memcpy(send_raw_udp_buf + sizeof(my_udphdr), payload, payloadlen);\n\n    if (raw_ip_version == AF_INET) {\n        pseudo_header v4;\n        struct pseudo_header *psh = &v4;\n\n        psh->source_address = send_info.new_src_ip.v4;\n        psh->dest_address = send_info.new_dst_ip.v4;\n        psh->placeholder = 0;\n        psh->protocol = IPPROTO_UDP;\n        psh->tcp_length = htons(udp_tot_len);\n\n        udph->check = csum_with_header((char *)psh, sizeof(pseudo_header), (unsigned short *)send_raw_udp_buf, udp_tot_len);\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        pseudo_header6 v6;\n        struct pseudo_header6 *psh = &v6;\n\n        psh->src = send_info.new_src_ip.v6;\n        psh->dst = send_info.new_dst_ip.v6;\n        psh->next_header = IPPROTO_UDP;\n        psh->tcp_length = htons(udp_tot_len);\n\n        psh->placeholder1 = 0;\n        psh->placeholder2 = 0;\n\n        udph->check = csum_with_header((char *)psh, sizeof(pseudo_header6), (unsigned short *)send_raw_udp_buf, udp_tot_len);\n    }\n\n    if (send_raw_ip(raw_info, send_raw_udp_buf, udp_tot_len) != 0) {\n        return -1;\n    }\n    return 0;\n}\n\nint send_raw_tcp(raw_info_t &raw_info, const char *payload, int payloadlen) {  // TODO seq increase\n\n    const packet_info_t &send_info = raw_info.send_info;\n    const packet_info_t &recv_info = raw_info.recv_info;\n\n    // mylog(log_debug,\"syn %d\\n\",send_info.syn);\n\n    char send_raw_tcp_buf[buf_len];\n    // char *send_raw_tcp_buf=send_raw_tcp_buf0;\n\n    struct my_tcphdr *tcph = (struct my_tcphdr *)(send_raw_tcp_buf);\n\n    memset(tcph, 0, sizeof(my_tcphdr));\n\n    // TCP Header\n    tcph->source = htons(send_info.src_port);\n    tcph->dest = htons(send_info.dst_port);\n\n    tcph->seq = htonl(send_info.seq);\n    tcph->ack_seq = htonl(send_info.ack_seq);\n\n    tcph->fin = 0;\n    tcph->syn = send_info.syn;\n    tcph->rst = 0;\n    tcph->psh = send_info.psh;\n    tcph->ack = send_info.ack;\n\n    if (tcph->syn == 1) {\n        tcph->doff = 10;  // tcp header size\n        int i = sizeof(my_tcphdr);\n        send_raw_tcp_buf[i++] = 0x02;  // mss\n        send_raw_tcp_buf[i++] = 0x04;\n        send_raw_tcp_buf[i++] = 0x05;\n        send_raw_tcp_buf[i++] = (char)0xb4;\n\n        // raw_send_buf[i++]=0x01;\n        // raw_send_buf[i++]=0x01;\n        send_raw_tcp_buf[i++] = 0x04;  // sack ok\n        send_raw_tcp_buf[i++] = 0x02;  // sack ok\n\n        send_raw_tcp_buf[i++] = 0x08;  // ts   i=6\n        send_raw_tcp_buf[i++] = 0x0a;  // i=7\n\n        //*(u32_t*) (&send_raw_tcp_buf[i]) = htonl(\n        //\t(u32_t) get_current_time());\n\n        u32_t ts = htonl((u32_t)get_current_time());\n        memcpy(&send_raw_tcp_buf[i], &ts, sizeof(ts));\n\n        i += 4;\n\n        // mylog(log_info,\"[syn]<send_info.ts_ack= %u>\\n\",send_info.ts_ack);\n\n        //*(u32_t*) (&send_raw_tcp_buf[i]) = htonl(send_info.ts_ack);\n        u32_t ts_ack = htonl(send_info.ts_ack);\n        memcpy(&send_raw_tcp_buf[i], &ts_ack, sizeof(ts_ack));\n\n        i += 4;\n\n        send_raw_tcp_buf[i++] = 0x01;\n        send_raw_tcp_buf[i++] = 0x03;\n        send_raw_tcp_buf[i++] = 0x03;\n        send_raw_tcp_buf[i++] = wscale;\n    } else {\n        tcph->doff = 8;\n        int i = sizeof(my_tcphdr);\n\n        send_raw_tcp_buf[i++] = 0x01;\n        send_raw_tcp_buf[i++] = 0x01;\n\n        send_raw_tcp_buf[i++] = 0x08;  // ts   //i=2\n        send_raw_tcp_buf[i++] = 0x0a;  // i=3;\n\n        //*(u32_t*) (&send_raw_tcp_buf[i]) = htonl(\n        //\t(u32_t) get_current_time());\n\n        u32_t ts = htonl((u32_t)get_current_time());\n        memcpy(&send_raw_tcp_buf[i], &ts, sizeof(ts));\n\n        i += 4;\n\n        // mylog(log_info,\"<send_info.ts_ack= %u>\\n\",send_info.ts_ack);\n\n        //*(u32_t*) (&send_raw_tcp_buf[i]) = htonl(send_info.ts_ack);\n        u32_t ts_ack = htonl(send_info.ts_ack);\n        memcpy(&send_raw_tcp_buf[i], &ts_ack, sizeof(ts_ack));\n        i += 4;\n    }\n\n    tcph->urg = 0;\n    // tcph->window = htons((uint16_t)(1024));\n    tcph->window = htons((uint16_t)(receive_window_lower_bound + get_true_random_number() % receive_window_random_range));\n\n    tcph->check = 0;  // leave checksum 0 now, filled later by pseudo header\n    tcph->urg_ptr = 0;\n\n    char *tcp_data = send_raw_tcp_buf + +tcph->doff * 4;\n\n    memcpy(tcp_data, payload, payloadlen);\n    int tcp_totlen = tcph->doff * 4 + payloadlen;\n\n    if (raw_ip_version == AF_INET) {\n        pseudo_header v4;\n        struct pseudo_header *psh = &v4;\n\n        psh->source_address = send_info.new_src_ip.v4;\n        psh->dest_address = send_info.new_dst_ip.v4;\n        psh->placeholder = 0;\n        psh->protocol = IPPROTO_TCP;\n        psh->tcp_length = htons(tcp_totlen);\n\n        tcph->check = csum_with_header((char *)psh, sizeof(pseudo_header), (unsigned short *)send_raw_tcp_buf, tcp_totlen);\n    } else {\n        assert(raw_ip_version == AF_INET6);\n\n        pseudo_header6 v6;\n        struct pseudo_header6 *psh = &v6;\n\n        psh->src = send_info.new_src_ip.v6;\n        psh->dst = send_info.new_dst_ip.v6;\n        psh->next_header = IPPROTO_TCP;\n        psh->tcp_length = htons(tcp_totlen);\n        psh->placeholder1 = 0;\n        psh->placeholder2 = 0;\n\n        tcph->check = csum_with_header((char *)psh, sizeof(pseudo_header6), (unsigned short *)send_raw_tcp_buf, tcp_totlen);\n    }\n\n    if (send_raw_ip(raw_info, send_raw_tcp_buf, tcp_totlen) != 0) {\n        return -1;\n    }\n\n    raw_info.send_info.data_len = payloadlen;\n    return 0;\n}\n/*\nint send_raw_tcp_deprecated(const packet_info_t &info,const char * payload,int payloadlen)\n{\n        static uint16_t ip_id=1;\n        char raw_send_buf[buf_len];\n        char raw_send_buf2[buf_len];\n\n        //if((prog_mode==client_mode&& payloadlen!=9)  ||(prog_mode==server_mode&& payloadlen!=5 )  )\n        mylog(log_trace,\"send raw from to %d %d %d %d\\n\",info.src_ip,info.src_port,info.dst_ip,info.dst_port);\n\n        char *data;\n\n    memset(raw_send_buf,0,payloadlen+100);\n\n    struct iphdr *iph = (struct iphdr *) raw_send_buf;\n\n    //TCP header\n    struct tcphdr *tcph = (struct tcphdr *) (raw_send_buf + sizeof (struct ip));\n\n    struct sockaddr_in sin;\n    struct pseudo_header psh;\n\n    //some address resolution\n    sin.sin_family = AF_INET;\n    sin.sin_port = htons(info.dst_port);\n    sin.sin_addr.s_addr = info.dst_ip;\n\n    //Fill in the IP Header\n    iph->ihl = 5;\n    iph->version = 4;\n    iph->tos = 0;\n\n    iph->id = htonl (ip_id++); //Id of this packet\n    iph->frag_off = htons(0x4000); //DF set,others are zero\n    iph->ttl = (unsigned char)ttl_value;\n    iph->protocol = IPPROTO_TCP;\n    iph->check = 0; //Set to 0 before calculating checksum\n    iph->saddr = info.src_ip;    //Spoof the source ip address\n    iph->daddr = info.dst_ip;\n\n    //TCP Header\n    tcph->source = htons(info.src_port);\n    tcph->dest = htons(info.dst_port);\n\n    tcph->seq =htonl(info.seq);\n    tcph->ack_seq = htonl(info.ack_seq);\n\n    tcph->fin=0;\n    tcph->syn=info.syn;\n    tcph->rst=0;\n    tcph->psh=info.psh;\n    tcph->ack=info.ack;\n\n    if(tcph->syn==1)\n    {\n        tcph->doff = 10;  //tcp header size\n        int i=sizeof (struct iphdr)+20;\n        raw_send_buf[i++]=0x02;//mss\n        raw_send_buf[i++]=0x04;\n        raw_send_buf[i++]=0x05;\n        raw_send_buf[i++]=0xb4;\n\n        //raw_send_buf[i++]=0x01;\n        //raw_send_buf[i++]=0x01;\n        raw_send_buf[i++]=0x04; //sack ok\n        raw_send_buf[i++]=0x02; //sack ok\n\n\n        raw_send_buf[i++]=0x08;   //i=6;\n        raw_send_buf[i++]=0x0a;\n\n        *(uint32_t*)(& raw_send_buf[i])=htonl((uint32_t)get_current_time());\n\n        i+=4;\n\n        *(uint32_t*)(& raw_send_buf[i])=htonl(info.ts_ack);\n        i+=4;\n\n        raw_send_buf[i++]=0x01;\n        raw_send_buf[i++]=0x03;\n        raw_send_buf[i++]=0x03;\n        raw_send_buf[i++]=0x05;\n    }\n    else\n    {\n        tcph->doff=8;\n        int i=sizeof (struct iphdr)+20;\n\n        raw_send_buf[i++]=0x01;\n        raw_send_buf[i++]=0x01;\n\n        raw_send_buf[i++]=0x08;   //i=0;\n        raw_send_buf[i++]=0x0a;\n\n        *(uint32_t*)(& raw_send_buf[i])=htonl((uint32_t)get_current_time());\n\n        i+=4;\n\n        *(uint32_t*)(& raw_send_buf[i])=htonl(info.ts_ack);\n        i+=4;\n\n\n    }\n\n\n\n    tcph->urg=0;\n    //tcph->window = htons((uint16_t)(1024));\n    tcph->window = htons((uint16_t)(10240+random()%100));\n\n\n    tcph->check = 0; //leave checksum 0 now, filled later by pseudo header\n    tcph->urg_ptr = 0;\n\n\n    //Data part\n    data = raw_send_buf + sizeof(struct iphdr) + tcph->doff*4;\n\n    iph->tot_len = sizeof (struct iphdr) + tcph->doff*4 + payloadlen;\n\n    memcpy(data , payload, payloadlen);\n\n    psh.source_address = info.src_ip;\n    psh.dest_address = sin.sin_addr.s_addr;\n    psh.placeholder = 0;\n    psh.protocol = IPPROTO_TCP;\n    psh.tcp_length = htons(tcph->doff*4 + payloadlen );\n\n    int psize = sizeof(struct pseudo_header) + tcph->doff*4 + payloadlen;\n\n     memcpy(raw_send_buf2 , (char*) &psh , sizeof (struct pseudo_header));\n     memcpy(raw_send_buf2 + sizeof(struct pseudo_header) , tcph , tcph->doff*4 + payloadlen);\n\n     tcph->check = csum( (unsigned short*) raw_send_buf2, psize);\n\n     //Ip checksum\n     iph->check = csum ((unsigned short *) raw_send_buf, iph->tot_len);\n\n     mylog(log_trace,\"sent seq  ack_seq len<%u %u %d>\\n\",g_packet_info_send.seq,g_packet_info_send.ack_seq,payloadlen);\n\n     int ret = sendto(raw_send_fd, raw_send_buf, iph->tot_len ,  0, (struct sockaddr *) &sin, sizeof (sin));\n\n     if(g_packet_info_send.syn==0&&g_packet_info_send.ack==1&&payloadlen!=0)\n     {\n         if(seq_mode==0)\n         {\n\n\n         }\n         else if(seq_mode==1)\n         {\n                 g_packet_info_send.seq+=payloadlen;\n         }\n         else if(seq_mode==2)\n         {\n                 if(random()% 5==3 )\n                         g_packet_info_send.seq+=payloadlen;\n         }\n     }\n     mylog(log_trace,\"<ret:%d>\\n\",ret);\n         if(ret<0)\n     {\n                mylog(log_fatal,\"\");\n         perror(\"raw send error\\n\");\n         //printf(\"send error\\n\");\n     }\n     return 0;\n}\n*/\n\nint recv_raw_icmp(raw_info_t &raw_info, char *&payload, int &payloadlen) {\n    const packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n    static char recv_raw_icmp_buf[buf_len];\n\n    char *ip_payload;\n    int ip_payloadlen;\n\n    if (recv_raw_ip(raw_info, ip_payload, ip_payloadlen) != 0) {\n        mylog(log_debug, \"recv_raw_ip error\\n\");\n        return -1;\n    }\n    mylog(log_trace, \"ip_payloadlen=%d\\n\", ip_payloadlen);\n    if (raw_ip_version == AF_INET) {\n        if (recv_info.protocol != IPPROTO_ICMP) {\n            // printf(\"not udp protocol\\n\");\n            return -1;\n        }\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        if (recv_info.protocol != IPPROTO_ICMPV6) {\n            // printf(\"not udp protocol\\n\");\n            return -1;\n        }\n    }\n\n    if (ip_payloadlen < int(sizeof(my_icmphdr))) {\n        mylog(log_debug, \"too short to hold icmp header\\n\");\n        return -1;\n    }\n\n    my_icmphdr *icmph = (struct my_icmphdr *)(ip_payload);\n\n    if (ntohs(icmph->id) != send_info.src_port) {\n        mylog(log_debug, \"icmp id mis-match,ignored\\n\");\n        return -1;\n    }\n\n    recv_info.src_port = recv_info.dst_port = ntohs(icmph->id);\n    recv_info.my_icmp_seq = ntohs(icmph->seq);\n\n    if (icmph->code != 0)\n        return -1;\n\n    unsigned short check;\n    if (raw_ip_version == AF_INET) {\n        if (program_mode == client_mode) {\n            if (icmph->type != 0)\n                return -1;\n        } else {\n            if (icmph->type != 8)\n                return -1;\n        }\n        check = csum((unsigned short *)ip_payload, ip_payloadlen);\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        if (program_mode == client_mode) {\n            if (icmph->type != 129)\n                return -1;\n        } else {\n            if (icmph->type != 128)\n                return -1;\n        }\n\n        pseudo_header6 tmp_header;\n        struct pseudo_header6 *psh = &tmp_header;\n\n        psh->src = recv_info.new_src_ip.v6;\n        psh->dst = recv_info.new_dst_ip.v6;\n        psh->placeholder1 = 0;\n        psh->placeholder2 = 0;\n        psh->next_header = IPPROTO_ICMPV6;\n        psh->tcp_length = htons(ip_payloadlen);\n\n        check = csum_with_header((char *)psh, sizeof(pseudo_header6), (unsigned short *)ip_payload, ip_payloadlen);\n    }\n\n    if (check != 0) {\n        mylog(log_debug, \"icmp checksum fail %x\\n\", check);\n        return -1;\n    }\n    // mylog(log_info,\"program_mode=%d\\n\",program_mode);\n    /*\n            if(program_mode==server_mode)\n            {\n                    send_info.icmp_seq=ntohs(icmph->seq);\n                    //mylog(log_info,\"send_info.seq=%d\\n\",send_info.seq);\n            }*/\n\n    payload = ip_payload + sizeof(my_icmphdr);\n    payloadlen = ip_payloadlen - sizeof(my_icmphdr);\n    mylog(log_trace, \"get a packet len=%d\\n\", payloadlen);\n\n    return 0;\n}\n\nint recv_raw_udp(raw_info_t &raw_info, char *&payload, int &payloadlen) {\n    const packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n    // static char recv_raw_udp_buf[buf_len];\n    char *ip_payload;\n    int ip_payloadlen;\n\n    if (recv_raw_ip(raw_info, ip_payload, ip_payloadlen) != 0) {\n        mylog(log_debug, \"recv_raw_ip error\\n\");\n        return -1;\n    }\n    if (recv_info.protocol != IPPROTO_UDP) {\n        // printf(\"not udp protocol\\n\");\n        return -1;\n    }\n    if (ip_payloadlen < int(sizeof(my_udphdr))) {\n        mylog(log_debug, \"too short to hold udpheader\\n\");\n        return -1;\n    }\n    my_udphdr *udph = (struct my_udphdr *)ip_payload;\n\n    if (int(ntohs(udph->len)) != ip_payloadlen) {\n        mylog(log_debug, \"udp length error %d %d \\n\", ntohs(udph->len), ip_payloadlen);\n        return -1;\n    }\n\n    if (udph->dest != ntohs(uint16_t(filter_port))) {\n        // printf(\"%x %x\",tcph->dest,);\n        return -1;\n    }\n\n    // memcpy(recv_raw_udp_buf+ sizeof(struct pseudo_header) , ip_payload , ip_payloadlen);\n\n    /*\n    pseudo_header tmp_header={0};\n    struct pseudo_header *psh=&tmp_header ;\n\n    psh->source_address = recv_info.new_src_ip.v4;\n    psh->dest_address = recv_info.new_dst_ip.v4;\n    psh->placeholder = 0;\n    psh->protocol = IPPROTO_UDP;\n    psh->tcp_length = htons(ip_payloadlen);\n\n    int csum_len=ip_payloadlen;\n    uint16_t udp_chk = csum_with_header((char *)psh,sizeof(pseudo_header), (unsigned short*) ip_payload, csum_len);\n    */\n    uint16_t udp_chk;\n    int csum_len = ip_payloadlen;\n    if (raw_ip_version == AF_INET) {\n        pseudo_header tmp_header;\n        struct pseudo_header *psh = &tmp_header;\n\n        psh->source_address = recv_info.new_src_ip.v4;\n        psh->dest_address = recv_info.new_dst_ip.v4;\n        psh->placeholder = 0;\n        psh->protocol = IPPROTO_UDP;\n        psh->tcp_length = htons(ip_payloadlen);\n\n        udp_chk = csum_with_header((char *)psh, sizeof(pseudo_header), (unsigned short *)ip_payload, csum_len);\n    } else {\n        assert(raw_ip_version == AF_INET6);\n\n        pseudo_header6 tmp_header;\n        struct pseudo_header6 *psh = &tmp_header;\n\n        psh->src = recv_info.new_src_ip.v6;\n        psh->dst = recv_info.new_dst_ip.v6;\n        psh->placeholder1 = 0;\n        psh->placeholder2 = 0;\n        psh->next_header = IPPROTO_UDP;\n        psh->tcp_length = htons(ip_payloadlen);\n\n        udp_chk = csum_with_header((char *)psh, sizeof(pseudo_header6), (unsigned short *)ip_payload, csum_len);\n    }\n\n    if (udp_chk != 0) {\n        mylog(log_debug, \"udp_chk:%x\\n\", udp_chk);\n        mylog(log_debug, \"udp header error\\n\");\n        return -1;\n    }\n\n    char *udp_begin = ip_payload;\n\n    recv_info.src_port = ntohs(udph->source);\n    recv_info.dst_port = ntohs(udph->dest);\n\n    payloadlen = ip_payloadlen - sizeof(my_udphdr);\n\n    payload = udp_begin + sizeof(my_udphdr);\n\n    return 0;\n}\nint parse_tcp_option(char *option_begin, char *option_end, packet_info_t &recv_info) {\n    recv_info.has_ts = 0;\n    recv_info.ts = 0;\n\n    char *ptr = option_begin;\n    // char *option_end=tcp_begin+tcp_hdr_len;\n    while (ptr < option_end) {\n        if (*ptr == 0) {\n            return 0;\n        } else if (*ptr == 1) {\n            ptr++;\n        } else if (*ptr == 8) {\n            if (ptr + 1 >= option_end) {\n                mylog(log_trace, \"invaild option ptr+1==option_end,for ts\\n\");\n                return -1;\n            }\n            if (*(ptr + 1) != 10) {\n                mylog(log_trace, \"invaild ts len\\n\");\n                return -1;\n            }\n            if (ptr + 10 > option_end) {\n                mylog(log_trace, \"ptr+10>option_end for ts\\n\");\n                return -1;\n            }\n\n            recv_info.has_ts = 1;\n\n            recv_info.ts = read_u32(ptr + 2);\n            recv_info.ts_ack = read_u32(ptr + 6);\n\n            // printf(\"<%d %d>!\\n\",recv_info.ts,recv_info.ts_ack);\n\n            // return 0;//we currently only parse ts, so just return after its found\n            ptr += 10;\n        } else {\n            if (ptr + 1 >= option_end) {\n                mylog(log_trace, \"invaild option ptr+1==option_end\\n\");\n                return -1;\n            } else {\n                int len = (unsigned char)*(ptr + 1);\n                if (len <= 1) {\n                    mylog(log_trace, \"invaild option len %d\\n\", len);\n                    return -1;\n                }\n                // omit check\n                ptr += len;\n            }\n        }\n        // printf(\"!\");\n    }\n    // printf(\"\\n\");\n\n    return 0;\n}\nint recv_raw_tcp(raw_info_t &raw_info, char *&payload, int &payloadlen) {\n    const packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    // static char recv_raw_tcp_buf[buf_len];\n\n    char *ip_payload;\n    int ip_payloadlen;\n\n    if (recv_raw_ip(raw_info, ip_payload, ip_payloadlen) != 0) {\n        mylog(log_debug, \"recv_raw_ip error\\n\");\n        return -1;\n    }\n\n    if (recv_info.protocol != IPPROTO_TCP) {\n        // printf(\"not tcp protocol\\n\");\n        return -1;\n    }\n\n    my_tcphdr *tcph = (struct my_tcphdr *)ip_payload;\n\n    unsigned short tcphdrlen = tcph->doff * 4;\n\n    if (!(tcphdrlen > 0 && tcphdrlen <= 60)) {\n        mylog(log_debug, \"tcph error\\n\");\n        return 0;\n    }\n\n    if (tcphdrlen > ip_payloadlen) {\n        mylog(log_debug, \"error,tcphdrlen >ip_payloadlen\\n\");\n        return 0;\n    }\n\n    if (tcph->dest != ntohs(uint16_t(filter_port))) {\n        // printf(\"%x %x\",tcph->dest,);\n        return -1;\n    }\n\n    // memcpy(recv_raw_tcp_buf+ sizeof(struct pseudo_header) , ip_payload , ip_payloadlen);\n    uint16_t tcp_chk;\n    int csum_len = ip_payloadlen;\n    if (raw_ip_version == AF_INET) {\n        pseudo_header tmp_header;\n        struct pseudo_header *psh = &tmp_header;\n\n        psh->source_address = recv_info.new_src_ip.v4;\n        psh->dest_address = recv_info.new_dst_ip.v4;\n        psh->placeholder = 0;\n        psh->protocol = IPPROTO_TCP;\n        psh->tcp_length = htons(ip_payloadlen);\n\n        tcp_chk = csum_with_header((char *)psh, sizeof(pseudo_header), (unsigned short *)ip_payload, csum_len);\n    } else {\n        assert(raw_ip_version == AF_INET6);\n\n        pseudo_header6 tmp_header;\n        struct pseudo_header6 *psh = &tmp_header;\n\n        psh->src = recv_info.new_src_ip.v6;\n        psh->dst = recv_info.new_dst_ip.v6;\n        psh->placeholder1 = 0;\n        psh->placeholder2 = 0;\n        psh->next_header = IPPROTO_TCP;\n        psh->tcp_length = htons(ip_payloadlen);\n\n        tcp_chk = csum_with_header((char *)psh, sizeof(pseudo_header6), (unsigned short *)ip_payload, csum_len);\n    }\n    /*for(int i=0;i<csum_len;i++)\n    {\n        printf(\"<%d>\",int(ip_payload[i]));\n    }\n    printf(\"\\n\");*/\n\n    if (tcp_chk != 0) {\n        mylog(log_debug, \"tcp_chk:%x, tcp checksum failed, ignored\\n\", tcp_chk);\n        // return -1;\n    }\n\n    char *tcp_begin = ip_payload;  // ip packet's data part\n\n    char *tcp_option = ip_payload + sizeof(my_tcphdr);\n    char *option_end = ip_payload + tcphdrlen;\n\n    /*\n    //old ts parse code\n    recv_info.has_ts=0;\n    recv_info.ts=0;\n    if(tcph->doff==10)\n    {\n        if(tcp_option[6]==0x08 &&tcp_option[7]==0x0a)\n        {\n                recv_info.has_ts=1;\n                //recv_info.ts=ntohl(*(u32_t*)(&tcp_option[8]));\n                memcpy(&recv_info.ts,&tcp_option[8],sizeof(recv_info.ts));\n                recv_info.ts=ntohl(recv_info.ts);\n\n                //recv_info.ts_ack=ntohl(*(u32_t*)(&tcp_option[12]));\n                memcpy(&recv_info.ts_ack,&tcp_option[12],sizeof(recv_info.ts_ack));\n                recv_info.ts_ack=ntohl(recv_info.ts_ack);\n\n                //g_packet_info_send.ts_ack= ntohl(*(uint32_t*)(&tcp_option[8]));\n        }\n        else\n        {\n        //\tmylog(log_info,\"\\n\");\n        }\n    }\n    else if(tcph->doff==8)\n    {\n        if(tcp_option[2]==0x08 &&tcp_option[3]==0x0a)\n        {\n                recv_info.has_ts=1;\n                //recv_info.ts=ntohl(*(u32_t*)(&tcp_option[4]));\n                memcpy(&recv_info.ts,&tcp_option[4],sizeof(recv_info.ts));\n                recv_info.ts=ntohl(recv_info.ts);\n                //recv_info.ts_ack=ntohl(*(u32_t*)(&tcp_option[8]));\n                memcpy(&recv_info.ts_ack,&tcp_option[8],sizeof(recv_info.ts_ack));\n                recv_info.ts_ack=ntohl(recv_info.ts_ack);\n                //g_packet_info_send.ts_ack= ntohl(*(uint32_t*)(&tcp_option[0]));\n        }\n        else\n        {\n                //mylog(log_info,\"!!!\\n\");\n        }\n    }\n    else\n    {\n        //mylog(log_info,\"tcph->doff= %u\\n\",tcph->doff);\n    }\n    printf(\"<%d %d>\\n\",recv_info.ts,recv_info.ts_ack);\n    */\n    parse_tcp_option(tcp_option, option_end, recv_info);\n\n    recv_info.ack = tcph->ack;\n    recv_info.syn = tcph->syn;\n    recv_info.rst = tcph->rst;\n    recv_info.src_port = ntohs(tcph->source);\n    recv_info.dst_port = ntohs(tcph->dest);\n\n    recv_info.seq = ntohl(tcph->seq);\n\n    // recv_info.last_last_ack_seq=recv_info.last_ack_seq;\n    // recv_info.last_ack_seq=recv_info.ack_seq;\n    u32_t last_ack_seq = recv_info.ack_seq;\n    recv_info.ack_seq = ntohl(tcph->ack_seq);\n    if (recv_info.ack_seq == last_ack_seq) {\n        recv_info.ack_seq_counter++;\n    } else {\n        recv_info.ack_seq_counter = 0;\n    }\n\n    recv_info.psh = tcph->psh;\n\n    if (tcph->rst == 1) {\n        raw_info.rst_received++;\n\n        if (max_rst_to_show > 0) {\n            if (raw_info.rst_received < max_rst_to_show) {\n                mylog(log_warn, \"[%s,%d]rst==1,cnt=%d\\n\", recv_info.new_src_ip.get_str1(), recv_info.src_port, (int)raw_info.rst_received);\n            } else if (raw_info.rst_received == max_rst_to_show) {\n                mylog(log_warn, \"[%s,%d]rst==1,cnt=%d >=max_rst_to_show, this log will be muted for current connection\\n\", recv_info.new_src_ip.get_str1(), recv_info.src_port, (int)raw_info.rst_received);\n            } else {\n                mylog(log_debug, \"[%s,%d]rst==1,cnt=%d\\n\", recv_info.new_src_ip.get_str1(), recv_info.src_port, (int)raw_info.rst_received);\n            }\n        } else if (max_rst_to_show == 0) {\n            mylog(log_debug, \"[%s,%d]rst==1,cnt=%d\\n\", recv_info.new_src_ip.get_str1(), recv_info.src_port, (int)raw_info.rst_received);\n        } else {\n            mylog(log_warn, \"[%s,%d]rst==1,cnt=%d\\n\", recv_info.new_src_ip.get_str1(), recv_info.src_port, (int)raw_info.rst_received);\n        }\n\n        if (max_rst_allowed >= 0 && raw_info.rst_received == max_rst_allowed + 1) {\n            mylog(log_warn, \"[%s,%d]connection disabled because of rst_received=%d > max_rst_allow=%d\\n\", recv_info.new_src_ip.get_str1(), recv_info.src_port, (int)raw_info.rst_received, (int)max_rst_allowed);\n            raw_info.disabled = 1;\n        }\n    }\n\n    /* if(recv_info.has_ts)\n     {\n         send_info.ts_ack=recv_info.ts;   //////////////////////////////////////////////modify\n     }*/\n\n    payloadlen = ip_payloadlen - tcphdrlen;\n\n    payload = tcp_begin + tcphdrlen;\n\n    /*if (recv_info.syn == 0 && recv_info.ack == 1&& payloadlen != 0)   //only modify   send_info when the packet is not part of handshake\n    {\n            send_info.ack_seq=recv_info.seq;\n    }*/\n    raw_info.recv_info.data_len = payloadlen;\n    return 0;\n}\n/*\nint recv_raw_tcp_deprecated(packet_info_t &info,char * &payload,int &payloadlen)\n{\n        static char buf[buf_len];\n\n        char raw_recv_buf[buf_len];\n        char raw_recv_buf2[buf_len];\n        char raw_recv_buf3[buf_len];\n\n        iphdr *  iph;\n        tcphdr * tcph;\n        int size;\n        struct sockaddr saddr;\n        socklen_t saddr_size;\n        saddr_size = sizeof(saddr);\n\n        mylog(log_trace,\"raw!\\n\");\n\n        size = recvfrom(raw_recv_fd, buf, max_data_len, 0 ,&saddr , &saddr_size);\n\n        if(buf[12]!=8||buf[13]!=0)\n        {\n                mylog(log_debug,\"not an ipv4 packet!\\n\");\n                return -1;\n        }\n\n        char *ip_begin=buf+14;\n\n        iph = (struct iphdr *) (ip_begin);\n\n\n    if (!(iph->ihl > 0 && iph->ihl <=60)) {\n        mylog(log_debug,\"iph ihl error\");\n        return -1;\n    }\n\n    if (iph->protocol != IPPROTO_TCP) {\n        mylog(log_debug,\"iph protocal != tcp\\n\");\n        return -1;\n    }\n\n\n        int ip_len=ntohs(iph->tot_len);\n\n    unsigned short iphdrlen =iph->ihl*4;\n    tcph=(struct tcphdr*)(ip_begin+ iphdrlen);\n    unsigned short tcphdrlen = tcph->doff*4;\n\n    if (!(tcph->doff > 0 && tcph->doff <=60)) {\n        mylog(log_debug,\"tcph error\");\n        return 0;\n    }\n\n\n    if(tcph->dest!=ntohs(uint16_t(filter_port)))\n    {\n        //printf(\"%x %x\",tcph->dest,);\n        return -1;\n    }\n    /////ip\n    uint32_t ip_chk=csum ((unsigned short *) ip_begin, iphdrlen);\n\n    int psize = sizeof(struct pseudo_header) + ip_len-iphdrlen;\n    /////ip end\n\n\n    ///tcp\n    struct pseudo_header psh;\n\n    psh.source_address = iph->saddr;\n    psh.dest_address = iph->daddr;\n    psh.placeholder = 0;\n    psh.protocol = IPPROTO_TCP;\n    psh.tcp_length = htons(ip_len-iphdrlen);\n\n    memcpy(raw_recv_buf2 , (char*) &psh , sizeof (struct pseudo_header));\n    memcpy(raw_recv_buf2 + sizeof(struct pseudo_header) , ip_begin+ iphdrlen , ip_len-iphdrlen);\n\n    uint16_t tcp_chk = csum( (unsigned short*) raw_recv_buf2, psize);\n\n\n   if(ip_chk!=0)\n    {\n           mylog(log_debug,\"ip header error %d\\n\",ip_chk);\n        return -1;\n    }\n    if(tcp_chk!=0)\n    {\n        mylog(log_debug,\"tcp_chk:%x\\n\",tcp_chk);\n        mylog(log_debug,\"tcp header error\\n\");\n        return -1;\n\n    }\n    char *tcp_begin=raw_recv_buf2+sizeof(struct pseudo_header);  //ip packet's data part\n\n    char *tcp_option=raw_recv_buf2+sizeof(struct pseudo_header)+sizeof(tcphdr);\n\n    info.has_ts=0;\n\n    if(tcph->doff==10)\n    {\n        if(tcp_option[6]==0x08 &&tcp_option[7]==0x0a)\n        {\n                info.has_ts=1;\n                info.ts=ntohl(*(uint32_t*)(&tcp_option[8]));\n                info.ts_ack=ntohl(*(uint32_t*)(&tcp_option[12]));\n                //g_packet_info_send.ts_ack= ntohl(*(uint32_t*)(&tcp_option[8]));\n        }\n    }\n    else if(tcph->doff==8)\n    {\n        if(tcp_option[3]==0x08 &&tcp_option[4]==0x0a)\n        {\n                info.has_ts=1;\n                info.ts=ntohl(*(uint32_t*)(&tcp_option[0]));\n                info.ts_ack=ntohl(*(uint32_t*)(&tcp_option[4]));\n                //g_packet_info_send.ts_ack= ntohl(*(uint32_t*)(&tcp_option[0]));\n        }\n    }\n\n    if(tcph->rst==1)\n    {\n        mylog(log_warn,\"%%%%%%%%%%rst==1%%%%%%%%%%%%%\\n\");\n    }\n\n\n    info.ack=tcph->ack;\n    info.syn=tcph->syn;\n    info.rst=tcph->rst;\n    info.src_port=ntohs(tcph->source);\n    info.src_ip=iph->saddr;\n    info.seq=ntohl(tcph->seq);\n    info.ack_seq=ntohl(tcph->ack_seq);\n    info.psh=tcph->psh;\n    if(info.has_ts)\n    {\n        g_packet_info_send.ts_ack=info.ts;\n    }\n    ////tcp end\n\n\n    payloadlen = ip_len-tcphdrlen-iphdrlen;\n\n    payload=ip_begin+tcphdrlen+iphdrlen;\n\n    if(payloadlen>0&&payload[0]=='h')\n    {\n        mylog(log_debug,\"recvd <%u %u %d>\\n\",ntohl(tcph->seq ),ntohl(tcph->ack_seq), payloadlen);\n    }\n\n    if(payloadlen>0&&tcph->syn==0&&tcph->ack==1)\n    {\n        //if(seq_increse)\n                g_packet_info_send.ack_seq=ntohl(tcph->seq)+(uint32_t)payloadlen;\n    }\n\n\n    //printf(\"%d\\n\",ip_len);\n\n    mylog(log_trace,\"<%u,%u,%u,%u,%d>\\n\",(unsigned int)iphdrlen,(unsigned int)tcphdrlen,(unsigned int)tcph->syn,(unsigned int)tcph->ack,payloadlen);\n\n\n        return 0;\n}*/\nint send_raw0(raw_info_t &raw_info, const char *payload, int payloadlen) {\n    if (random_drop != 0) {\n        if (get_true_random_number() % 10000 < (u32_t)random_drop) {\n            return 0;\n        }\n    }\n\n    packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n    mylog(log_trace, \"send_raw : from %s %d  to %s %d\\n\", send_info.new_src_ip.get_str1(), send_info.src_port, send_info.new_dst_ip.get_str2(), send_info.dst_port);\n    switch (raw_mode) {\n        case mode_faketcp:\n            return send_raw_tcp(raw_info, payload, payloadlen);\n        case mode_udp:\n            return send_raw_udp(raw_info, payload, payloadlen);\n        case mode_icmp:\n            return send_raw_icmp(raw_info, payload, payloadlen);\n        default:\n            return -1;\n    }\n}\nint recv_raw0(raw_info_t &raw_info, char *&payload, int &payloadlen) {\n    packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n    switch (raw_mode) {\n        case mode_faketcp:\n            return recv_raw_tcp(raw_info, payload, payloadlen);\n        case mode_udp:\n            return recv_raw_udp(raw_info, payload, payloadlen);\n        case mode_icmp:\n            return recv_raw_icmp(raw_info, payload, payloadlen);\n        default:\n            return -1;\n    }\n}\n\nint after_send_raw0(raw_info_t &raw_info) {\n    packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    if (raw_mode == mode_faketcp) {\n        if (send_info.syn == 0 && send_info.ack == 1 && raw_info.send_info.data_len != 0)  // only modify   send_info when the packet is not part of handshake\n        {\n            if (seq_mode == 0) {\n            } else if (seq_mode == 1) {\n                send_info.seq += raw_info.send_info.data_len;  //////////////////modify\n            } else if (seq_mode == 2) {\n                if (get_true_random_number() % 5 == 3)\n                    send_info.seq += raw_info.send_info.data_len;  //////////////////modify\n            } else if (seq_mode == 3 || seq_mode == 4) {\n                send_info.seq += raw_info.send_info.data_len;\n\n                u32_t window_size;\n\n                if (seq_mode == 3) {\n                    window_size = (u32_t)((u32_t)receive_window_lower_bound << (u32_t)wscale);\n                } else  // seq_mode==4\n                {\n                    window_size = (u32_t)((u32_t)receive_window_lower_bound);\n                }\n\n                if (larger_than_u32(send_info.seq + max_data_len, recv_info.ack_seq + window_size)) {\n                    send_info.seq = raw_info.recv_info.ack_seq;\n                }\n                if (recv_info.ack_seq_counter >= 3)  // simulate tcp fast re-transmit\n                {\n                    recv_info.ack_seq_counter = 0;\n                    send_info.seq = raw_info.recv_info.ack_seq;\n                }\n                if (larger_than_u32(raw_info.recv_info.ack_seq, send_info.seq))  // for further use,currently no effect.\n                {\n                    send_info.seq = raw_info.recv_info.ack_seq;\n                }\n            }\n        }\n    }\n    if (raw_mode == mode_icmp) {\n        if (program_mode == client_mode) {\n            send_info.my_icmp_seq++;\n        }\n    }\n    return 0;\n}\nint after_recv_raw0(raw_info_t &raw_info) {\n    packet_info_t &send_info = raw_info.send_info;\n    packet_info_t &recv_info = raw_info.recv_info;\n\n    if (raw_mode == mode_faketcp) {\n        if (recv_info.has_ts)\n            send_info.ts_ack = recv_info.ts;\n        if (recv_info.syn == 0 && recv_info.ack == 1 && raw_info.recv_info.data_len != 0)  // only modify   send_info when the packet is not part of handshake\n        {\n            if (seq_mode == 0 || seq_mode == 1 || seq_mode == 2) {\n                if (larger_than_u32(recv_info.seq + raw_info.recv_info.data_len, send_info.ack_seq))\n                    send_info.ack_seq = recv_info.seq + raw_info.recv_info.data_len;  // TODO only update if its larger\n            } else if (seq_mode == 3 || seq_mode == 4) {\n                if (recv_info.seq == send_info.ack_seq) {\n                    send_info.ack_seq = recv_info.seq + raw_info.recv_info.data_len;  // currently we dont remembr tcp segments,this is the simplest way\n                    // TODO implement tcp segment remembering and SACK.\n                }\n            }\n        }\n    }\n    if (raw_mode == mode_icmp) {\n        if (program_mode == server_mode) {\n            if (larger_than_u16(recv_info.my_icmp_seq, send_info.my_icmp_seq))\n                send_info.my_icmp_seq = recv_info.my_icmp_seq;  // TODO only update if its larger\n        }\n    }\n    return 0;\n}\n\n/*\nint send_raw(raw_info_t &raw_info,const char * payload,int payloadlen)\n{\n        packet_info_t &send_info=raw_info.send_info;\n        packet_info_t &recv_info=raw_info.recv_info;\n        int ret=send_raw0(raw_info,payload,payloadlen);\n        if(ret<0) return ret;\n        else\n        {\n                after_send_raw0(raw_info);\n                return ret;\n        }\n}\n\nint recv_raw(raw_info_t &raw_info,char *& payload,int & payloadlen)\n{\n        packet_info_t &send_info=raw_info.send_info;\n        packet_info_t &recv_info=raw_info.recv_info;\n        int ret=recv_raw0(raw_info,payload,payloadlen);\n        if(ret<0) return ret;\n        else\n        {\n                after_recv_raw0(raw_info);\n                return ret;\n        }\n}*/\n\n/*\nint get_src_adress(u32_t &ip,u32_t remote_ip_uint32,int remote_port)  //a trick to get src adress for a dest adress,so that we can use the src address in raw socket as source ip\n{\n        struct sockaddr_in remote_addr_in={0};\n\n        socklen_t slen = sizeof(sockaddr_in);\n        //memset(&remote_addr_in, 0, sizeof(remote_addr_in));\n        remote_addr_in.sin_family = AF_INET;\n        remote_addr_in.sin_port = htons(remote_port);\n        remote_addr_in.sin_addr.s_addr = remote_ip_uint32;\n\n\n        int new_udp_fd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n        if(new_udp_fd<0)\n        {\n                mylog(log_warn,\"create udp_fd error\\n\");\n                return -1;\n        }\n        //set_buf_size(new_udp_fd);\n\n        mylog(log_debug,\"created new udp_fd %d\\n\",new_udp_fd);\n        int ret = connect(new_udp_fd, (struct sockaddr *) &remote_addr_in, slen);\n        if(ret!=0)\n        {\n                mylog(log_warn,\"udp fd connect fail\\n\");\n                close(new_udp_fd);\n                return -1;\n        }\n\n        struct sockaddr_in my_addr={0};\n        socklen_t len=sizeof(my_addr);\n\n    if(getsockname(new_udp_fd, (struct sockaddr *) &my_addr, &len)!=0){close(new_udp_fd); return -1;}\n\n    ip=my_addr.sin_addr.s_addr;\n\n    close(new_udp_fd);\n\n    return 0;\n}*/\n\nint get_src_adress2(address_t &output_addr, address_t remote_addr) {\n    int new_udp_fd = remote_addr.new_connected_udp_fd();\n    if (new_udp_fd < 0) {\n        mylog(log_warn, \"create udp_fd error\\n\");\n        return -1;\n    }\n\n    socklen_t len = sizeof(output_addr.inner);\n\n    if (getsockname(new_udp_fd, (struct sockaddr *)&output_addr.inner, &len) != 0) {\n        close(new_udp_fd);\n        return -1;\n    }\n\n    assert(output_addr.get_type() == remote_addr.get_type());\n\n    close(new_udp_fd);\n\n    return 0;\n}\n/*\nint try_to_list_and_bind(int &fd,u32_t local_ip_uint32,int port)  //try to bind to a port,may fail.\n{\n         int old_bind_fd=fd;\n\n         if(raw_mode==mode_faketcp)\n         {\n                 fd=socket(AF_INET,SOCK_STREAM,0);\n         }\n         else  if(raw_mode==mode_udp||raw_mode==mode_icmp)\n         {\n                 fd=socket(AF_INET,SOCK_DGRAM,0);\n         }\n     if(old_bind_fd!=-1)\n     {\n         close(old_bind_fd);\n     }\n\n         struct sockaddr_in temp_bind_addr={0};\n     //bzero(&temp_bind_addr, sizeof(temp_bind_addr));\n\n     temp_bind_addr.sin_family = AF_INET;\n     temp_bind_addr.sin_port = htons(port);\n     temp_bind_addr.sin_addr.s_addr = local_ip_uint32;\n\n     if (bind(fd, (struct sockaddr*)&temp_bind_addr, sizeof(temp_bind_addr)) !=0)\n     {\n         mylog(log_debug,\"bind fail\\n\");\n         return -1;\n     }\n         if(raw_mode==mode_faketcp)\n         {\n\n                if (listen(fd, SOMAXCONN) != 0) {\n                        mylog(log_warn,\"listen fail\\n\");\n                        return -1;\n                }\n         }\n     return 0;\n}*/\nint try_to_list_and_bind2(int &fd, address_t address)  // try to bind to a port,may fail.\n{\n    if (fd != -1) {\n        close(fd);\n    }\n    if (raw_mode == mode_faketcp) {\n        fd = socket(address.get_type(), SOCK_STREAM, 0);\n    } else if (raw_mode == mode_udp || raw_mode == mode_icmp) {\n        fd = socket(address.get_type(), SOCK_DGRAM, 0);\n    }\n\n    if (fd == -1) {\n        mylog(log_debug, \"create fd fail\\n\");\n        return -1;\n    }\n    /*struct sockaddr_in temp_bind_addr={0};\n    //bzero(&temp_bind_addr, sizeof(temp_bind_addr));\n\n    temp_bind_addr.sin_family = AF_INET;\n    temp_bind_addr.sin_port = htons(port);\n    temp_bind_addr.sin_addr.s_addr = local_ip_uint32;*/\n\n    if (::bind(fd, (struct sockaddr *)&address.inner, address.get_len()) != 0) {\n        mylog(log_debug, \"bind fail\\n\");\n        return -1;\n    }\n    if (raw_mode == mode_faketcp && !use_tcp_dummy_socket) {\n        if (listen(fd, SOMAXCONN) != 0) {\n            mylog(log_warn, \"listen fail\\n\");\n            return -1;\n        }\n    }\n    return 0;\n}\n/*\nint client_bind_to_a_new_port(int &fd,u32_t local_ip_uint32)//find a free port and bind to it.\n{\n        int raw_send_port=10000+get_true_random_number()%(65535-10000);\n        for(int i=0;i<1000;i++)//try 1000 times at max,this should be enough\n        {\n                if (try_to_list_and_bind(fd,local_ip_uint32,raw_send_port)==0)\n                {\n                        return raw_send_port;\n                }\n        }\n        mylog(log_fatal,\"bind port fail\\n\");\n        myexit(-1);\n        return -1;////for compiler check\n}*/\n\nint client_bind_to_a_new_port2(int &fd, const address_t &address)  // find a free port and bind to it.\n{\n    address_t tmp = address;\n    for (int i = 0; i < 1000; i++)  // try 1000 times at max,this should be enough\n    {\n        int raw_send_port = 10000 + get_true_random_number() % (65535 - 10000);\n        tmp.set_port(raw_send_port);\n        if (try_to_list_and_bind2(fd, tmp) == 0) {\n            return raw_send_port;\n        }\n    }\n    mylog(log_fatal, \"bind port fail\\n\");\n    myexit(-1);\n    return -1;  ////for compiler check\n}\n"
  },
  {
    "path": "network.h",
    "content": "/*\n * network.h\n *\n *  Created on: Jul 29, 2017\n *      Author: wangyu\n */\n\n#ifndef UDP2RAW_NETWORK_H_\n#define UDP2RAW_NETWORK_H_\n\nextern int raw_recv_fd;\nextern int raw_send_fd;\nextern int use_tcp_dummy_socket;\nextern int seq_mode;\nextern int max_seq_mode;\nextern int filter_port;\n// extern u32_t bind_address_uint32;\nextern int disable_bpf_filter;\n\nextern int lower_level;\nextern int lower_level_manual;\nextern char if_name[100];\nextern char dev[100];\nextern unsigned char dest_hw_addr[];\n\nextern int random_drop;\n\nextern int ifindex;\n\nextern char g_packet_buf[huge_buf_len];\nextern int g_packet_buf_len;\nextern int g_packet_buf_cnt;\n#ifdef UDP2RAW_MP\nextern queue_t my_queue;\n\nextern ev_async async_watcher;\nextern struct ev_loop *g_default_loop;\n\nextern pthread_mutex_t queue_mutex;\nextern int use_pcap_mutex;\n\nextern int pcap_cnt;\n\nextern int pcap_link_header_len;\n\nextern int send_with_pcap;\nextern int pcap_header_captured;\nextern int pcap_header_buf[buf_len];\n\nstruct icmphdr {\n    uint8_t type;\n    uint8_t code;\n    uint16_t check_sum;\n    uint16_t id;\n    uint16_t seq;\n};\n#endif\n\nstruct my_iphdr {\n#ifdef UDP2RAW_LITTLE_ENDIAN\n    unsigned char ihl : 4;\n    unsigned char version : 4;\n#else\n    unsigned char version : 4;\n    unsigned char ihl : 4;\n#endif\n    u_int8_t tos;\n    u_int16_t tot_len;\n    u_int16_t id;\n    u_int16_t frag_off;\n    u_int8_t ttl;\n    u_int8_t protocol;\n    u_int16_t check;\n    u_int32_t saddr;\n    u_int32_t daddr;\n    /*The options start here. */\n};\n\nstruct my_udphdr {\n    /*__extension__*/ union {\n        struct\n        {\n            u_int16_t uh_sport; /* source port */\n            u_int16_t uh_dport; /* destination port */\n            u_int16_t uh_ulen;  /* udp length */\n            u_int16_t uh_sum;   /* udp checksum */\n        };\n        struct\n        {\n            u_int16_t source;\n            u_int16_t dest;\n            u_int16_t len;\n            u_int16_t check;\n        };\n    };\n};\n\nstruct my_tcphdr {\n    /*__extension__*/ union {\n        struct\n        {\n            u_int16_t th_sport; /* source port */\n            u_int16_t th_dport; /* destination port */\n            u_int32_t th_seq;   /* sequence number */\n            u_int32_t th_ack;   /* acknowledgement number */\n#ifdef UDP2RAW_LITTLE_ENDIAN\n            u_int8_t th_x2 : 4;  /* (unused) */\n            u_int8_t tc_off : 4; /* data offset */\n#else\n            u_int8_t th_off : 4; /* data offset */\n            u_int8_t th_x2 : 4;  /* (unused) */\n#endif\n            u_int8_t th_flags;\n#define TH_FIN 0x01\n#define TH_SYN 0x02\n#define TH_RST 0x04\n#define TH_PUSH 0x08\n#define TH_ACK 0x10\n#define TH_URG 0x20\n            u_int16_t th_win; /* window */\n            u_int16_t th_sum; /* checksum */\n            u_int16_t th_urp; /* urgent pointer */\n        };\n        struct\n        {\n            u_int16_t source;\n            u_int16_t dest;\n            u_int32_t seq;\n            u_int32_t ack_seq;\n#ifdef UDP2RAW_LITTLE_ENDIAN\n            u_int16_t res1 : 4;\n            u_int16_t doff : 4;\n            u_int16_t fin : 1;\n            u_int16_t syn : 1;\n            u_int16_t rst : 1;\n            u_int16_t psh : 1;\n            u_int16_t ack : 1;\n            u_int16_t urg : 1;\n            u_int16_t res2 : 2;\n#else\n            u_int16_t doff : 4;\n            u_int16_t res1 : 4;\n            u_int16_t res2 : 2;\n            u_int16_t urg : 1;\n            u_int16_t ack : 1;\n            u_int16_t psh : 1;\n            u_int16_t rst : 1;\n            u_int16_t syn : 1;\n            u_int16_t fin : 1;\n#endif\n            u_int16_t window;\n            u_int16_t check;\n            u_int16_t urg_ptr;\n        };\n    };\n};\n\nstruct my_ip6hdr {\n#ifdef UDP2RAW_LITTLE_ENDIAN\n    uint8_t traffic_class_high : 4;\n    uint8_t version : 4;\n    uint8_t flow_label_high : 4;\n    uint8_t traffic_class_low : 4;\n#else\n    uint8_t version : 4;\n    uint8_t traffic_class_high : 4;\n    uint8_t traffic_class_low : 4;\n    uint8_t flow_label_high : 4;\n#endif\n    u_int16_t flow_label_low;\n    u_int16_t payload_len;\n    uint8_t next_header;\n    uint8_t hop_limit;\n\n    struct in6_addr src;\n    struct in6_addr dst;\n};\n\nstruct my_icmphdr {\n    uint8_t type;\n    uint8_t code;\n    uint16_t check_sum;\n    uint16_t id;\n    uint16_t seq;\n};\n\nstruct pseudo_header {\n    u_int32_t source_address;\n    u_int32_t dest_address;\n    u_int8_t placeholder;\n    u_int8_t protocol;\n    u_int16_t tcp_length;\n};\n\nstruct pseudo_header6 {\n    struct in6_addr src;\n    struct in6_addr dst;\n    u_int32_t tcp_length;\n    u_int16_t placeholder1;\n    u_int8_t placeholder2;\n    u_int8_t next_header;\n};\n\nstruct packet_info_t  // todo change this to union\n{\n    uint8_t protocol;\n\n    // u32_t src_ip;\n    // u32_t dst_ip;\n    my_ip_t new_src_ip;\n    my_ip_t new_dst_ip;\n\n    uint16_t src_port;\n    uint16_t dst_port;\n\n    // tcp_part:\n    bool syn, ack, psh, rst;\n\n    u32_t seq, ack_seq;\n\n    u32_t ack_seq_counter;\n\n    u32_t ts, ts_ack;\n\n    uint16_t my_icmp_seq;\n\n    bool has_ts;\n\n    i32_t data_len;\n\n#ifdef UDP2RAW_LINUX\n    sockaddr_ll addr_ll;\n#endif\n\n    packet_info_t();\n};\n\nstruct raw_info_t {\n    packet_info_t send_info;\n    packet_info_t recv_info;\n    // int last_send_len;\n    // int last_recv_len;\n    bool peek = 0;\n    // bool csum=1;\n    u32_t reserved_send_seq;\n    // uint32_t first_seq,first_ack_seq;\n    int rst_received = 0;\n    bool disabled = 0;\n\n};  // g_raw_info;\n\nint init_raw_socket();\n\nvoid init_filter(int port);\n\nvoid remove_filter();\n\n#ifdef UDP2RAW_LINUX\nint init_ifindex(const char *if_name, int fd, int &index);\n#endif\n\n#ifdef UDP2RAW_MP\nint init_ifindex(const char *if_name, int &index);\n#endif\n\nint find_lower_level_info(u32_t ip, u32_t &dest_ip, string &if_name, string &hw);\n\nint get_src_adress(u32_t &ip, u32_t remote_ip_uint32, int remote_port);  // a trick to get src adress for a dest adress,so that we can use the src address in raw socket as source ip\nint get_src_adress2(address_t &output_addr, address_t remote_addr);\n\nint try_to_list_and_bind(int &bind_fd, u32_t local_ip_uint32, int port);  // try to bind to a port,may fail.\nint try_to_list_and_bind2(int &fd, address_t address);\n\nint client_bind_to_a_new_port(int &bind_fd, u32_t local_ip_uint32);  // find a free port and bind to it.\nint client_bind_to_a_new_port2(int &fd, const address_t &address);\n\nint discard_raw_packet();\nint pre_recv_raw_packet();\n\nint send_raw_ip(raw_info_t &raw_info, const char *payload, int payloadlen);\n\nint peek_raw(raw_info_t &peek_info);\n\nint recv_raw_ip(raw_info_t &raw_info, char *&payload, int &payloadlen);\n\nint send_raw_icmp(raw_info_t &raw_info, const char *payload, int payloadlen);\n\nint send_raw_udp(raw_info_t &raw_info, const char *payload, int payloadlen);\n\nint send_raw_tcp(raw_info_t &raw_info, const char *payload, int payloadlen);\n\nint recv_raw_icmp(raw_info_t &raw_info, char *&payload, int &payloadlen);\n\nint recv_raw_udp(raw_info_t &raw_info, char *&payload, int &payloadlen);\n\nint recv_raw_tcp(raw_info_t &raw_info, char *&payload, int &payloadlen);\n\n// int send_raw(raw_info_t &raw_info,const char * payload,int payloadlen);\n\n// int recv_raw(raw_info_t &raw_info,char * &payload,int &payloadlen);\n\nint send_raw0(raw_info_t &raw_info, const char *payload, int payloadlen);\n\nint recv_raw0(raw_info_t &raw_info, char *&payload, int &payloadlen);\n\nint after_send_raw0(raw_info_t &raw_info);\n\nint after_recv_raw0(raw_info_t &raw_info);\n\n#endif /* NETWORK_H_ */\n"
  },
  {
    "path": "pcap_wrapper.cpp",
    "content": "#include <windows.h>\n#include <pcap_wrapper.h>\n#include <assert.h>\n#include <stdio.h>\nint (*pcap_loop)(pcap_t *, int, pcap_handler, u_char *);\nint (*pcap_breakloop)(pcap_t *);\n\npcap_t *(*pcap_create)(const char *, char *);\n\nint (*pcap_set_snaplen)(pcap_t *, int) = 0;\nint (*pcap_set_promisc)(pcap_t *, int) = 0;\nint (*pcap_can_set_rfmon)(pcap_t *) = 0;\nint (*pcap_set_rfmon)(pcap_t *, int) = 0;\nint (*pcap_set_timeout)(pcap_t *, int) = 0;\nint (*pcap_set_buffer_size)(pcap_t *, int) = 0;\nint (*pcap_activate)(pcap_t *) = 0;\n\nint (*pcap_setfilter)(pcap_t *, struct bpf_program *) = 0;\nint (*pcap_setdirection)(pcap_t *, pcap_direction_t) = 0;\n\nint (*pcap_datalink)(pcap_t *) = 0;\n\nvoid (*pcap_freecode)(struct bpf_program *) = 0;\n\nint (*pcap_compile)(pcap_t *, struct bpf_program *, const char *, int,\n                    bpf_u_int32) = 0;\n\nchar *(*pcap_geterr)(pcap_t *) = 0;\nint (*pcap_sendpacket)(pcap_t *, const u_char *, int) = 0;\n\nchar *(*pcap_lookupdev)(char *) = 0;\n\nint (*pcap_findalldevs)(pcap_if_t **, char *) = 0;\n\nstruct init_pcap_t {\n    init_pcap_t() {\n        init_pcap();\n    }\n\n} do_it;\n\nstatic void init_npcap_dll_path() {\n    BOOL(WINAPI * SetDllDirectory)\n    (LPCTSTR);\n    char sysdir_name[512];\n    int len;\n\n    SetDllDirectory = (BOOL(WINAPI *)(LPCTSTR))GetProcAddress(GetModuleHandle(\"kernel32.dll\"), \"SetDllDirectoryA\");\n    if (SetDllDirectory == NULL) {\n        printf(\"Error in SetDllDirectory\\n\");\n    } else {\n        len = GetSystemDirectory(sysdir_name, 480);  //\tbe safe\n        if (!len)\n            printf(\"Error in GetSystemDirectory (%d)\\n\", (int)GetLastError());\n        strcat(sysdir_name, \"\\\\Npcap\");\n        if (SetDllDirectory(sysdir_name) == 0)\n            printf(\"Error in SetDllDirectory(\\\"System32\\\\Npcap\\\")\\n\");\n    }\n}\n\n#define EXPORT_FUN(XXX)                                     \\\n    do {                                                    \\\n        XXX = (__typeof__(XXX))GetProcAddress(wpcap, #XXX); \\\n    } while (0)\nint init_pcap() {\n    HMODULE wpcap = LoadLibrary(\"wpcap.dll\");\n    if (wpcap != 0) {\n        printf(\"using system32/wpcap.dll\\n\");\n    } else {\n        init_npcap_dll_path();\n        // SetDllDirectory(\"C:\\\\Windows\\\\System32\\\\Npcap\\\\\");\n        wpcap = LoadLibrary(\"wpcap.dll\");\n        if (wpcap != 0)\n            printf(\"using system32/npcap/wpcap.dll\\n\");\n    }\n    if (wpcap == 0) {\n        printf(\"cant not open wpcap.dll, make sure winpcap/npcap is installed\\n\");\n        exit(-1);\n    }\n    assert(wpcap != 0);\n\n    EXPORT_FUN(pcap_loop);\n    EXPORT_FUN(pcap_breakloop);\n    EXPORT_FUN(pcap_create);\n    EXPORT_FUN(pcap_set_snaplen);\n    EXPORT_FUN(pcap_set_promisc);\n    EXPORT_FUN(pcap_set_timeout);\n    EXPORT_FUN(pcap_activate);\n    EXPORT_FUN(pcap_setfilter);\n    EXPORT_FUN(pcap_setdirection);\n    EXPORT_FUN(pcap_datalink);\n    EXPORT_FUN(pcap_freecode);\n    EXPORT_FUN(pcap_compile);\n    EXPORT_FUN(pcap_geterr);\n    EXPORT_FUN(pcap_sendpacket);\n    EXPORT_FUN(pcap_lookupdev);\n    EXPORT_FUN(pcap_findalldevs);\n    /*\n    pcap_loop = (__typeof__(pcap_loop))GetProcAddress(wpcap, \"pcap_loop\");\n    pcap_create = (__typeof__(pcap_create))GetProcAddress(wpcap, \"pcap_create\");\n    pcap_set_snaplen = (__typeof__(pcap_set_snaplen))GetProcAddress(wpcap, \"pcap_set_snaplen\");\n    pcap_set_promisc = (__typeof__(pcap_set_promisc))GetProcAddress(wpcap, \"pcap_set_promisc\");\n    pcap_set_timeout = (__typeof__(pcap_set_timeout))GetProcAddress(wpcap, \"pcap_set_timeout\");\n    pcap_activate = (__typeof__(pcap_activate))GetProcAddress(wpcap, \"pcap_activate\");\n    pcap_setfilter = (__typeof__(pcap_setfilter))GetProcAddress(wpcap, \"pcap_setfilter\");\n    pcap_setdirection = (__typeof__(pcap_setdirection))GetProcAddress(wpcap, \"pcap_setdirection\");\n    pcap_datalink = (__typeof__(pcap_datalink))GetProcAddress(wpcap, \"pcap_datalink\");\n    pcap_freecode = (__typeof__(pcap_freecode))GetProcAddress(wpcap, \"pcap_freecode\");\n    pcap_compile = (__typeof__(pcap_compile))GetProcAddress(wpcap, \"pcap_compile\");\n    pcap_geterr = (__typeof__(pcap_geterr))GetProcAddress(wpcap, \"pcap_geterr\");\n    pcap_sendpacket = (__typeof__(pcap_sendpacket))GetProcAddress(wpcap, \"pcap_sendpacket\");\n    pcap_lookupdev = (__typeof__(pcap_lookupdev))GetProcAddress(wpcap, \"pcap_lookupdev\");\n    pcap_findalldevs = (__typeof__(pcap_findalldevs))GetProcAddress(wpcap, \"pcap_findalldevs\");\n    //pcap_loop = (__typeof__(pcap_loop))GetProcAddress(wpcap, \"pcap_loop\");\n    //pcap_loop = (__typeof__(pcap_loop))GetProcAddress(wpcap, \"pcap_loop\");\n    //pcap_loop = (__typeof__(pcap_loop))GetProcAddress(wpcap, \"pcap_loop\");\n    */\n    return 0;\n}\n"
  },
  {
    "path": "pcap_wrapper.h",
    "content": "#pragma once\n\n//#ifdef __cplusplus\n// extern \"C\" {\n//#endif\n\n//#include <sys/time.h>\n//#include <stdint.h>\n\nstruct bpf_program {\n    char a[4096];\n};\n\nstruct pcap_t {\n    char a[4096];\n};\n\ntypedef unsigned int bpf_u_int32;\n\ntypedef struct my_timeval {\n    int tv_sec;\n    int tv_usec;\n} my_timeval;\n\nstruct pcap_pkthdr {\n    struct my_timeval ts; /* time stamp */\n    bpf_u_int32 caplen;   /* length of portion present */\n    bpf_u_int32 len;      /* length this packet (off wire) */\n};\n\ntypedef enum {\n    PCAP_D_INOUT = 0,\n    PCAP_D_IN,\n    PCAP_D_OUT\n} pcap_direction_t;\n\nstruct pcap_addr {\n    struct pcap_addr *next;\n    struct sockaddr *addr;      /* address */\n    struct sockaddr *netmask;   /* netmask for that address */\n    struct sockaddr *broadaddr; /* broadcast address for that address */\n    struct sockaddr *dstaddr;   /* P2P destination address for that address */\n};\n\nstruct pcap_if {\n    struct pcap_if *next;\n    char *name;        /* name to hand to \"pcap_open_live()\" */\n    char *description; /* textual description of interface, or NULL */\n    struct pcap_addr *addresses;\n    bpf_u_int32 flags; /* PCAP_IF_ interface flags */\n};\n\ntypedef struct pcap_if pcap_if_t;\ntypedef struct pcap_addr pcap_addr_t;\n\ntypedef unsigned char u_char;\n\n#define PCAP_ERRBUF_SIZE 256\n\n#define DLT_NULL 0    /* BSD loopback encapsulation */\n#define DLT_EN10MB 1  /* Ethernet (10Mb) */\n#define DLT_EN3MB 2   /* Experimental Ethernet (3Mb) */\n#define DLT_AX25 3    /* Amateur Radio AX.25 */\n#define DLT_PRONET 4  /* Proteon ProNET Token Ring */\n#define DLT_CHAOS 5   /* Chaos */\n#define DLT_IEEE802 6 /* 802.5 Token Ring */\n#define DLT_ARCNET 7  /* ARCNET, with BSD-style header */\n#define DLT_SLIP 8    /* Serial Line IP */\n#define DLT_PPP 9     /* Point-to-point Protocol */\n#define DLT_FDDI 10   /* FDDI */\n#define DLT_LINUX_SLL 113\n\n#define PCAP_NETMASK_UNKNOWN 0xffffffff\n\ntypedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,\n                             const u_char *);\n\nextern int (*pcap_loop)(pcap_t *, int, pcap_handler, u_char *);\n\nextern int (*pcap_breakloop)(pcap_t *);\n\nextern pcap_t *(*pcap_create)(const char *, char *);\n\nextern int (*pcap_set_snaplen)(pcap_t *, int);\nextern int (*pcap_set_promisc)(pcap_t *, int);\nextern int (*pcap_can_set_rfmon)(pcap_t *);\nextern int (*pcap_set_rfmon)(pcap_t *, int);\nextern int (*pcap_set_timeout)(pcap_t *, int);\nextern int (*pcap_set_buffer_size)(pcap_t *, int);\nextern int (*pcap_activate)(pcap_t *);\n\nextern int (*pcap_setfilter)(pcap_t *, struct bpf_program *);\nextern int (*pcap_setdirection)(pcap_t *, pcap_direction_t);\n\nextern int (*pcap_datalink)(pcap_t *);\n\nextern void (*pcap_freecode)(struct bpf_program *);\n\nextern int (*pcap_compile)(pcap_t *, struct bpf_program *, const char *, int,\n                           bpf_u_int32);\n\nextern char *(*pcap_geterr)(pcap_t *);\nextern int (*pcap_sendpacket)(pcap_t *, const u_char *, int);\n\nextern char *(*pcap_lookupdev)(char *);\n\nextern int (*pcap_findalldevs)(pcap_if_t **, char *);\n\ninline int pcap_set_immediate_mode(pcap_t *, int) {\n    return 0;\n}\n\n//#ifdef __cplusplus\n//}\n//#endif\n\nint init_pcap();\n"
  },
  {
    "path": "server.cpp",
    "content": "/*\n * server.cpp\n *\n *  Created on: Aug 29, 2018\n *      Author: root\n */\n\n#ifndef UDP2RAW_MP\n\n#include \"common.h\"\n#include \"network.h\"\n#include \"connection.h\"\n#include \"misc.h\"\n#include \"log.h\"\n#include \"lib/md5.h\"\n#include \"encrypt.h\"\n#include \"fd_manager.h\"\n\nint server_on_timer_multi(conn_info_t &conn_info)  // for server. called when a timer is ready in epoll.for server,there will be one timer for every connection\n// there is also a global timer for server,but its not handled here\n{\n    char ip_port[max_addr_len];\n    // u32_t ip=conn_info.raw_info.send_info.dst_ip;\n    // u32_t port=conn_info.raw_info.send_info.dst_port;\n\n    address_t tmp_addr;\n    tmp_addr.from_ip_port_new(raw_ip_version, &conn_info.raw_info.send_info.new_dst_ip, conn_info.raw_info.send_info.dst_port);\n    // sprintf(ip_port,\"%s:%d\",my_ntoa(ip),port);\n    tmp_addr.to_str(ip_port);\n\n    // keep_iptables_rule();\n    mylog(log_trace, \"server timer!\\n\");\n    raw_info_t &raw_info = conn_info.raw_info;\n\n    assert(conn_info.state.server_current_state == server_ready);\n\n    if (conn_info.state.server_current_state == server_ready) {\n        conn_info.blob->conv_manager.s.clear_inactive(ip_port);\n        /*\n        if( get_current_time()-conn_info.last_hb_recv_time>heartbeat_timeout )\n        {\n                mylog(log_trace,\"%lld %lld\\n\",get_current_time(),conn_info.last_state_time);\n                conn_info.server_current_state=server_nothing;\n\n                //conn_manager.current_ready_ip=0;\n                //conn_manager.current_ready_port=0;\n\n                mylog(log_info,\"changed state to server_nothing\\n\");\n                return 0;\n        }*/\n        // dont need to do this at server,conn_manger will clear expired connections\n\n        if (get_current_time() - conn_info.last_hb_sent_time < heartbeat_interval) {\n            return 0;\n        }\n\n        if (hb_mode == 0)\n            send_safer(conn_info, 'h', hb_buf, 0);  /////////////send\n        else\n            send_safer(conn_info, 'h', hb_buf, hb_len);\n        conn_info.last_hb_sent_time = get_current_time();\n\n        mylog(log_debug, \"heart beat sent<%x,%x>\\n\", conn_info.my_id, conn_info.oppsite_id);\n    } else {\n        mylog(log_fatal, \"this shouldnt happen!\\n\");\n        myexit(-1);\n    }\n    return 0;\n}\nint server_on_raw_recv_ready(conn_info_t &conn_info, char *ip_port, char type, char *data, int data_len)  // called while the state for a connection is server_ready\n// receives data and heart beat by recv_safer.\n{\n    raw_info_t &raw_info = conn_info.raw_info;\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n    // char ip_port[40];\n\n    // sprintf(ip_port,\"%s:%d\",my_ntoa(recv_info.src_ip),recv_info.src_port);\n\n    /*\n            if (recv_info.src_ip != send_info.dst_ip\n                            || recv_info.src_port != send_info.dst_port) {\n                    mylog(log_debug, \"unexpected adress\\n\");\n                    return 0;\n            }*/\n\n    if (type == 'h' && data_len >= 0) {\n        // u32_t tmp = ntohl(*((u32_t *) &data[sizeof(u32_t)]));\n        mylog(log_debug, \"[%s][hb]received hb \\n\", ip_port);\n        conn_info.last_hb_recv_time = get_current_time();\n        return 0;\n    } else if (type == 'd' && data_len >= int(sizeof(u32_t))) {\n        // u32_t tmp_conv_id = ntohl(*((u32_t *) &data[0]));\n        my_id_t tmp_conv_id;\n        memcpy(&tmp_conv_id, &data[0], sizeof(tmp_conv_id));\n        tmp_conv_id = ntohl(tmp_conv_id);\n\n        if (hb_mode == 0)\n            conn_info.last_hb_recv_time = get_current_time();\n\n        mylog(log_trace, \"conv:%u\\n\", tmp_conv_id);\n        if (!conn_info.blob->conv_manager.s.is_conv_used(tmp_conv_id)) {\n            if (conn_info.blob->conv_manager.s.get_size() >= max_conv_num) {\n                mylog(log_warn,\n                      \"[%s]ignored new conv %x connect bc max_conv_num exceed\\n\", ip_port,\n                      tmp_conv_id);\n                return 0;\n            }\n\n            /*\n            struct sockaddr_in remote_addr_in={0};\n\n            socklen_t slen = sizeof(sockaddr_in);\n            //memset(&remote_addr_in, 0, sizeof(remote_addr_in));\n            remote_addr_in.sin_family = AF_INET;\n            remote_addr_in.sin_port = htons(remote_port);\n            remote_addr_in.sin_addr.s_addr = remote_ip_uint32;\n\n\n\n            int new_udp_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n\n\n            if (new_udp_fd < 0) {\n                    mylog(log_warn, \"[%s]create udp_fd error\\n\",ip_port);\n                    return -1;\n            }\n            setnonblocking(new_udp_fd);\n            set_buf_size(new_udp_fd,socket_buf_size);\n\n            mylog(log_debug, \"[%s]created new udp_fd %d\\n\",ip_port, new_udp_fd);\n            int ret = connect(new_udp_fd, (struct sockaddr *) &remote_addr_in,\n                            slen);\n            if (ret != 0) {\n                    mylog(log_warn, \"udp fd connect fail\\n\");\n                    close(new_udp_fd);\n                    return -1;\n            }*/\n\n            int new_udp_fd = remote_addr.new_connected_udp_fd();\n            if (new_udp_fd < 0) {\n                mylog(log_warn, \"[%s]new_connected_udp_fd() failed\\n\", ip_port);\n                return -1;\n            }\n\n            struct epoll_event ev;\n\n            fd64_t new_udp_fd64 = fd_manager.create(new_udp_fd);\n            fd_manager.get_info(new_udp_fd64).p_conn_info = &conn_info;\n\n            mylog(log_trace, \"[%s]u64: %lld\\n\", ip_port, new_udp_fd64);\n            ev.events = EPOLLIN;\n\n            ev.data.u64 = new_udp_fd64;\n\n            int ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, new_udp_fd, &ev);\n\n            if (ret != 0) {\n                mylog(log_warn, \"[%s]add udp_fd error\\n\", ip_port);\n                close(new_udp_fd);\n                return -1;\n            }\n\n            conn_info.blob->conv_manager.s.insert_conv(tmp_conv_id, new_udp_fd64);\n\n            // assert(conn_manager.udp_fd_mp.find(new_udp_fd)==conn_manager.udp_fd_mp.end());\n\n            // conn_manager.udp_fd_mp[new_udp_fd] = &conn_info;\n\n            // pack_u64(conn_info.raw_info.recv_info.src_ip,conn_info.raw_info.recv_info.src_port);\n\n            mylog(log_info, \"[%s]new conv conv_id=%x, assigned fd=%d\\n\", ip_port,\n                  tmp_conv_id, new_udp_fd);\n        }\n\n        fd64_t fd64 = conn_info.blob->conv_manager.s.find_data_by_conv(tmp_conv_id);\n\n        conn_info.blob->conv_manager.s.update_active_time(tmp_conv_id);\n\n        int fd = fd_manager.to_fd(fd64);\n\n        mylog(log_trace, \"[%s]received a data from fake tcp,len:%d\\n\", ip_port, data_len);\n        int ret = send(fd, data + sizeof(u32_t),\n                       data_len - (sizeof(u32_t)), 0);\n\n        mylog(log_trace, \"[%s]%d byte sent  ,fd :%d\\n \", ip_port, ret, fd);\n        if (ret < 0) {\n            mylog(log_warn, \"send returned %d\\n\", ret);\n            // perror(\"what happened????\");\n        }\n        return 0;\n    }\n    return 0;\n}\n\nint server_on_raw_recv_pre_ready(conn_info_t &conn_info, char *ip_port, u32_t tmp_oppsite_const_id)  // do prepare work before state change to server ready for a specifc connection\n// connection recovery is also handle here\n{\n    // u32_t ip;uint16_t port;\n    // ip=conn_info.raw_info.recv_info.src_ip;\n    // port=conn_info.raw_info.recv_info.src_port;\n    // char ip_port[40];\n    // sprintf(ip_port,\"%s:%d\",my_ntoa(ip),port);\n\n    mylog(log_info, \"[%s]received handshake oppsite_id:%x  my_id:%x\\n\", ip_port, conn_info.oppsite_id, conn_info.my_id);\n\n    mylog(log_info, \"[%s]oppsite const_id:%x \\n\", ip_port, tmp_oppsite_const_id);\n    if (conn_manager.const_id_mp.find(tmp_oppsite_const_id) == conn_manager.const_id_mp.end()) {\n        // conn_manager.const_id_mp=\n\n        if (conn_manager.ready_num >= max_ready_conn_num) {\n            mylog(log_info, \"[%s]max_ready_conn_num,cant turn to ready\\n\", ip_port);\n            conn_info.state.server_current_state = server_idle;\n            return 0;\n        }\n\n        conn_info.prepare();\n        conn_info.state.server_current_state = server_ready;\n        conn_info.oppsite_const_id = tmp_oppsite_const_id;\n        conn_manager.ready_num++;\n        conn_manager.const_id_mp[tmp_oppsite_const_id] = &conn_info;\n\n        // conn_info.last_state_time=get_current_time(); //dont change this!!!!!!!!!!!!!!!!!!!!!!!!!\n\n        // conn_manager.current_ready_ip=ip;\n        // conn_manager.current_ready_port=port;\n\n        // my_id=conn_info.my_id;\n        // oppsite_id=conn_info.oppsite_id;\n        conn_info.last_hb_recv_time = get_current_time();\n\n        conn_info.last_hb_sent_time = conn_info.last_hb_recv_time;  //=get_current_time()\n\n        if (hb_mode == 0)\n            send_safer(conn_info, 'h', hb_buf, 0);  /////////////send\n        else\n            send_safer(conn_info, 'h', hb_buf, hb_len);\n\n        mylog(log_info, \"[%s]changed state to server_ready\\n\", ip_port);\n        conn_info.blob->anti_replay.re_init();\n\n        // g_conn_info=conn_info;\n        int new_timer_fd;\n        set_timer_server(epollfd, new_timer_fd, conn_info.timer_fd64);\n\n        fd_manager.get_info(conn_info.timer_fd64).p_conn_info = &conn_info;\n        // assert(conn_manager.timer_fd_mp.find(new_timer_fd)==conn_manager.timer_fd_mp.end());\n        // conn_manager.timer_fd_mp[new_timer_fd] = &conn_info;//pack_u64(ip,port);\n\n        // timer_fd_mp[new_timer_fd]\n        /*\n         if(oppsite_const_id!=0&&tmp_oppsite_const_id!=oppsite_const_id)  //TODO MOVE TO READY\n         {\n         mylog(log_info,\"cleared all conv bc of const id doesnt match\\n\");\n         conv_manager.clear();\n         }*/\n        // oppsite_const_id=tmp_oppsite_const_id;\n    } else {\n        conn_info_t &ori_conn_info = *conn_manager.const_id_mp[tmp_oppsite_const_id];\n\n        if (ori_conn_info.state.server_current_state == server_ready) {\n            if (conn_info.last_state_time < ori_conn_info.last_state_time) {\n                mylog(log_info, \"[%s]conn_info.last_state_time<ori_conn_info.last_state_time. ignored new handshake\\n\", ip_port);\n                conn_info.state.server_current_state = server_idle;\n                conn_info.oppsite_const_id = 0;\n                return 0;\n            }\n            address_t addr1;\n            addr1.from_ip_port_new(raw_ip_version, &ori_conn_info.raw_info.recv_info.new_src_ip, ori_conn_info.raw_info.recv_info.src_port);\n            if (!conn_manager.exist(addr1))  // TODO remove this\n            {\n                mylog(log_fatal, \"[%s]this shouldnt happen\\n\", ip_port);\n                myexit(-1);\n            }\n            address_t addr2;\n            addr2.from_ip_port_new(raw_ip_version, &conn_info.raw_info.recv_info.new_src_ip, conn_info.raw_info.recv_info.src_port);\n            if (!conn_manager.exist(addr2))  // TODO remove this\n            {\n                mylog(log_fatal, \"[%s]this shouldnt happen2\\n\", ip_port);\n                myexit(-1);\n            }\n            conn_info_t *&p_ori = conn_manager.find_insert_p(addr1);\n            conn_info_t *&p = conn_manager.find_insert_p(addr2);\n            conn_info_t *tmp = p;\n            p = p_ori;\n            p_ori = tmp;\n\n            mylog(log_info, \"[%s]grabbed a connection\\n\", ip_port);\n\n            // ori_conn_info.state.server_current_state=server_ready;\n            ori_conn_info.recover(conn_info);\n\n            // send_safer(ori_conn_info, 'h',hb_buf, hb_len);\n            // ori_conn_info.blob->anti_replay.re_init();\n            if (hb_mode == 0)\n                send_safer(ori_conn_info, 'h', hb_buf, 0);  /////////////send\n            else\n                send_safer(ori_conn_info, 'h', hb_buf, hb_len);\n\n            ori_conn_info.last_hb_recv_time = get_current_time();\n\n            conn_info.state.server_current_state = server_idle;\n            conn_info.oppsite_const_id = 0;\n\n        } else {\n            mylog(log_fatal, \"[%s]this should never happen\\n\", ip_port);\n            myexit(-1);\n        }\n        return 0;\n    }\n    return 0;\n}\nint server_on_raw_recv_handshake1(conn_info_t &conn_info, char *ip_port, char *data, int data_len)  // called when server received a handshake1 packet from client\n{\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n    raw_info_t &raw_info = conn_info.raw_info;\n\n    // u32_t ip=conn_info.raw_info.recv_info.src_ip;\n    // uint16_t port=conn_info.raw_info.recv_info.src_port;\n\n    // char ip_port[40];\n    // sprintf(ip_port,\"%s:%d\",my_ntoa(ip),port);\n\n    if (data_len < int(3 * sizeof(my_id_t))) {\n        mylog(log_debug, \"[%s] data_len=%d too short to be a handshake\\n\", ip_port, data_len);\n        return -1;\n    }\n    // id_t tmp_oppsite_id=  ntohl(* ((u32_t *)&data[0]));\n    my_id_t tmp_oppsite_id;\n    memcpy(&tmp_oppsite_id, (u32_t *)&data[0], sizeof(tmp_oppsite_id));\n    tmp_oppsite_id = ntohl(tmp_oppsite_id);\n\n    // id_t tmp_my_id=ntohl(* ((u32_t *)&data[sizeof(id_t)]));\n    my_id_t tmp_my_id;\n    memcpy(&tmp_my_id, &data[sizeof(my_id_t)], sizeof(tmp_my_id));\n    tmp_my_id = ntohl(tmp_my_id);\n\n    if (tmp_my_id == 0)  // received  init handshake again\n    {\n        if (raw_mode == mode_faketcp) {\n            send_info.seq = recv_info.ack_seq;\n            send_info.ack_seq = recv_info.seq + raw_info.recv_info.data_len;\n            send_info.ts_ack = recv_info.ts;\n        }\n        if (raw_mode == mode_icmp) {\n            send_info.my_icmp_seq = recv_info.my_icmp_seq;\n        }\n        send_handshake(raw_info, conn_info.my_id, tmp_oppsite_id, const_id);  //////////////send\n\n        mylog(log_info, \"[%s]changed state to server_handshake1,my_id is %x\\n\", ip_port, conn_info.my_id);\n    } else if (tmp_my_id == conn_info.my_id) {\n        conn_info.oppsite_id = tmp_oppsite_id;\n        // id_t tmp_oppsite_const_id=ntohl(* ((u32_t *)&data[sizeof(id_t)*2]));\n\n        my_id_t tmp_oppsite_const_id;\n        memcpy(&tmp_oppsite_const_id, &data[sizeof(my_id_t) * 2], sizeof(tmp_oppsite_const_id));\n        tmp_oppsite_const_id = ntohl(tmp_oppsite_const_id);\n\n        if (raw_mode == mode_faketcp) {\n            send_info.seq = recv_info.ack_seq;\n            send_info.ack_seq = recv_info.seq + raw_info.recv_info.data_len;\n            send_info.ts_ack = recv_info.ts;\n        }\n\n        if (raw_mode == mode_icmp) {\n            send_info.my_icmp_seq = recv_info.my_icmp_seq;\n        }\n\n        server_on_raw_recv_pre_ready(conn_info, ip_port, tmp_oppsite_const_id);\n\n    } else {\n        mylog(log_debug, \"[%s]invalid my_id %x,my_id is %x\\n\", ip_port, tmp_my_id, conn_info.my_id);\n    }\n    return 0;\n}\nint server_on_recv_safer_multi(conn_info_t &conn_info, char type, char *data, int data_len) {\n    return 0;\n}\nint server_on_raw_recv_multi()  // called when server received an raw packet\n{\n    char dummy_buf[buf_len];\n    raw_info_t peek_raw_info;\n    peek_raw_info.peek = 1;\n    packet_info_t &peek_info = peek_raw_info.recv_info;\n    mylog(log_trace, \"got a packet\\n\");\n    if (pre_recv_raw_packet() < 0) return -1;\n    if (peek_raw(peek_raw_info) < 0) {\n        discard_raw_packet();\n        // recv(raw_recv_fd, 0,0, 0  );//\n        // struct sockaddr saddr;\n        // socklen_t saddr_size=sizeof(saddr);\n        /// recvfrom(raw_recv_fd, 0,0, 0 ,&saddr , &saddr_size);//\n        mylog(log_trace, \"peek_raw failed\\n\");\n        return -1;\n    } else {\n        mylog(log_trace, \"peek_raw success\\n\");\n    }\n    // u32_t ip=peek_info.src_ip;uint16_t port=peek_info.src_port;\n\n    int data_len;\n    char *data;\n\n    address_t addr;\n    addr.from_ip_port_new(raw_ip_version, &peek_info.new_src_ip, peek_info.src_port);\n\n    char ip_port[max_addr_len];\n    addr.to_str(ip_port);\n    // sprintf(ip_port,\"%s:%d\",my_ntoa(ip),port);\n    mylog(log_trace, \"[%s]peek_raw\\n\", ip_port);\n\n    if (raw_mode == mode_faketcp && peek_info.syn == 1) {\n        if (!conn_manager.exist(addr) || conn_manager.find_insert(addr).state.server_current_state != server_ready) {  // reply any syn ,before state become ready\n\n            raw_info_t tmp_raw_info;\n            if (recv_raw0(tmp_raw_info, data, data_len) < 0) {\n                return 0;\n            }\n            if (data_len >= max_data_len + 1) {\n                mylog(log_debug, \"data_len=%d >= max_data_len+1,ignored\", data_len);\n                return -1;\n            }\n            if (use_tcp_dummy_socket != 0)\n                return 0;\n            raw_info_t &raw_info = tmp_raw_info;\n            packet_info_t &send_info = raw_info.send_info;\n            packet_info_t &recv_info = raw_info.recv_info;\n\n            send_info.new_src_ip = recv_info.new_dst_ip;\n            send_info.src_port = recv_info.dst_port;\n\n            send_info.dst_port = recv_info.src_port;\n            send_info.new_dst_ip = recv_info.new_src_ip;\n\n            if (lower_level) {\n                handle_lower_level(raw_info);\n            }\n\n            if (data_len == 0 && raw_info.recv_info.syn == 1 && raw_info.recv_info.ack == 0) {\n                send_info.ack_seq = recv_info.seq + 1;\n\n                send_info.psh = 0;\n                send_info.syn = 1;\n                send_info.ack = 1;\n                send_info.ts_ack = recv_info.ts;\n\n                mylog(log_info, \"[%s]received syn,sent syn ack back\\n\", ip_port);\n                send_raw0(raw_info, 0, 0);\n                return 0;\n            }\n        } else {\n            discard_raw_packet();\n            // recv(raw_recv_fd, 0,0,0);\n        }\n        return 0;\n    }\n    if (!conn_manager.exist(addr)) {\n        if (conn_manager.mp.size() >= max_handshake_conn_num) {\n            mylog(log_info, \"[%s]reached max_handshake_conn_num,ignored new handshake\\n\", ip_port);\n            discard_raw_packet();\n            // recv(raw_recv_fd, 0,0, 0  );//\n            return 0;\n        }\n\n        raw_info_t tmp_raw_info;\n\n        if (raw_mode == mode_icmp) {\n            tmp_raw_info.send_info.dst_port = tmp_raw_info.send_info.src_port = addr.get_port();\n        }\n        if (recv_bare(tmp_raw_info, data, data_len) < 0) {\n            return 0;\n        }\n        if (data_len < int(3 * sizeof(my_id_t))) {\n            mylog(log_debug, \"[%s]too short to be a handshake\\n\", ip_port);\n            return -1;\n        }\n\n        // id_t zero=ntohl(* ((u32_t *)&data[sizeof(id_t)]));\n        my_id_t zero;\n        memcpy(&zero, &data[sizeof(my_id_t)], sizeof(zero));\n        zero = ntohl(zero);\n\n        if (zero != 0) {\n            mylog(log_debug, \"[%s]not a invalid initial handshake\\n\", ip_port);\n            return -1;\n        }\n\n        mylog(log_info, \"[%s]got packet from a new ip\\n\", ip_port);\n\n        conn_info_t &conn_info = conn_manager.find_insert(addr);\n        conn_info.raw_info = tmp_raw_info;\n        raw_info_t &raw_info = conn_info.raw_info;\n\n        packet_info_t &send_info = conn_info.raw_info.send_info;\n        packet_info_t &recv_info = conn_info.raw_info.recv_info;\n\n        // conn_info.ip_port.ip=ip;\n        // conn_info.ip_port.port=port;\n\n        send_info.new_src_ip = recv_info.new_dst_ip;\n        send_info.src_port = recv_info.dst_port;\n\n        send_info.dst_port = recv_info.src_port;\n        send_info.new_dst_ip = recv_info.new_src_ip;\n\n        if (lower_level) {\n            handle_lower_level(raw_info);\n        }\n\n        // id_t tmp_oppsite_id=  ntohl(* ((u32_t *)&data[0]));\n        // mylog(log_info,\"[%s]handshake1 received %x\\n\",ip_port,tmp_oppsite_id);\n\n        conn_info.my_id = get_true_random_number_nz();\n\n        mylog(log_info, \"[%s]created new conn,state: server_handshake1,my_id is %x\\n\", ip_port, conn_info.my_id);\n\n        conn_info.state.server_current_state = server_handshake1;\n        conn_info.last_state_time = get_current_time();\n\n        server_on_raw_recv_handshake1(conn_info, ip_port, data, data_len);\n        return 0;\n    }\n\n    conn_info_t &conn_info = conn_manager.find_insert(addr);  // insert if not exist\n    packet_info_t &send_info = conn_info.raw_info.send_info;\n    packet_info_t &recv_info = conn_info.raw_info.recv_info;\n    raw_info_t &raw_info = conn_info.raw_info;\n\n    if (conn_info.state.server_current_state == server_handshake1) {\n        if (recv_bare(raw_info, data, data_len) != 0) {\n            return -1;\n        }\n        return server_on_raw_recv_handshake1(conn_info, ip_port, data, data_len);\n    }\n    if (conn_info.state.server_current_state == server_ready) {\n        vector<char> type_vec;\n        vector<string> data_vec;\n        recv_safer_multi(conn_info, type_vec, data_vec);\n        if (data_vec.empty()) {\n            mylog(log_debug, \"recv_safer failed!\\n\");\n            return -1;\n        }\n\n        for (int i = 0; i < (int)type_vec.size(); i++) {\n            char type = type_vec[i];\n            char *data = (char *)data_vec[i].c_str();  // be careful, do not append data to it\n            int data_len = data_vec[i].length();\n            server_on_raw_recv_ready(conn_info, ip_port, type, data, data_len);\n        }\n        return 0;\n    }\n\n    if (conn_info.state.server_current_state == server_idle) {\n        discard_raw_packet();\n        // recv(raw_recv_fd, 0,0, 0  );//\n        return 0;\n    }\n    mylog(log_fatal, \"we should never run to here\\n\");\n    myexit(-1);\n    return -1;\n}\n\nint server_on_udp_recv(conn_info_t &conn_info, fd64_t fd64) {\n    char buf[buf_len];\n\n    if (conn_info.state.server_current_state != server_ready)  // TODO remove this for peformance\n    {\n        mylog(log_fatal, \"p_conn_info->state.server_current_state!=server_ready!!!this shouldnt happen\\n\");\n        myexit(-1);\n    }\n\n    // conn_info_t &conn_info=*p_conn_info;\n\n    assert(conn_info.blob->conv_manager.s.is_data_used(fd64));\n\n    u32_t conv_id = conn_info.blob->conv_manager.s.find_conv_by_data(fd64);\n\n    int fd = fd_manager.to_fd(fd64);\n\n    int recv_len = recv(fd, buf, max_data_len + 1, 0);\n\n    mylog(log_trace, \"received a packet from udp_fd,len:%d\\n\", recv_len);\n\n    if (recv_len == max_data_len + 1) {\n        mylog(log_warn, \"huge packet, data_len > %d,dropped\\n\", max_data_len);\n        return -1;\n    }\n\n    if (recv_len < 0) {\n        mylog(log_debug, \"udp fd,recv_len<0 continue,%s\\n\", strerror(errno));\n        return -1;\n    }\n\n    if (recv_len >= mtu_warn) {\n        mylog(log_warn, \"huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\\n \", recv_len, mtu_warn);\n    }\n\n    // conn_info.conv_manager->update_active_time(conv_id);  server dosnt update from upd side,only update from raw side.  (client updates at both side)\n\n    if (conn_info.state.server_current_state == server_ready) {\n        send_data_safer(conn_info, buf, recv_len, conv_id);\n        // send_data(g_packet_info_send,buf,recv_len,my_id,oppsite_id,conv_id);\n        mylog(log_trace, \"send_data_safer ,sent !!\\n\");\n    }\n\n    return 0;\n}\n\nint server_event_loop() {\n    char buf[buf_len];\n\n    int i, j, k;\n    int ret;\n\n    if (raw_ip_version == AF_INET) {\n        if (local_addr.inner.ipv4.sin_addr.s_addr != 0) {\n            bind_addr_used = 1;\n            bind_addr.v4 = local_addr.inner.ipv4.sin_addr.s_addr;\n        }\n    } else {\n        assert(raw_ip_version == AF_INET6);\n        char zero_arr[16] = {0};\n        if (memcmp(&local_addr.inner.ipv6.sin6_addr, zero_arr, 16) != 0) {\n            bind_addr_used = 1;\n            bind_addr.v6 = local_addr.inner.ipv6.sin6_addr;\n        }\n    }\n    // bind_address_uint32=local_ip_uint32;//only server has bind adress,client sets it to zero\n\n    if (lower_level) {\n        if (lower_level_manual) {\n            init_ifindex(if_name, raw_send_fd, ifindex);\n            mylog(log_info, \"we are running at lower-level (manual) mode\\n\");\n        } else {\n            mylog(log_info, \"we are running at lower-level (auto) mode\\n\");\n        }\n    }\n\n    if (raw_mode == mode_faketcp) {\n        bind_fd = socket(local_addr.get_type(), SOCK_STREAM, 0);\n    } else if (raw_mode == mode_udp || raw_mode == mode_icmp)  // bind an adress to avoid collision,for icmp,there is no port,just bind a udp port\n    {\n        bind_fd = socket(local_addr.get_type(), SOCK_DGRAM, 0);\n    }\n\n    // struct sockaddr_in temp_bind_addr={0};\n    // bzero(&temp_bind_addr, sizeof(temp_bind_addr));\n\n    // temp_bind_addr.sin_family = AF_INET;\n    // temp_bind_addr.sin_port = local_addr.get_port();\n    // temp_bind_addr.sin_addr.s_addr = local_addr.inner.ipv4.sin_addr.s_addr;\n\n    if (bind(bind_fd, (struct sockaddr *)&local_addr.inner, local_addr.get_len()) != 0) {\n        mylog(log_fatal, \"bind fail\\n\");\n        myexit(-1);\n    }\n\n    if (raw_mode == mode_faketcp) {\n        if (listen(bind_fd, SOMAXCONN) != 0) {\n            mylog(log_fatal, \"listen fail\\n\");\n            myexit(-1);\n        }\n    }\n\n    // init_raw_socket();\n    init_filter(local_addr.get_port());  // bpf filter\n\n    epollfd = epoll_create1(0);\n    const int max_events = 4096;\n\n    struct epoll_event ev, events[max_events];\n    if (epollfd < 0) {\n        mylog(log_fatal, \"epoll return %d\\n\", epollfd);\n        myexit(-1);\n    }\n\n    ev.events = EPOLLIN;\n    ev.data.u64 = raw_recv_fd;\n\n    ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, raw_recv_fd, &ev);\n    if (ret != 0) {\n        mylog(log_fatal, \"add raw_fd error\\n\");\n        myexit(-1);\n    }\n    int timer_fd;\n\n    set_timer(epollfd, timer_fd);\n\n    u64_t begin_time = 0;\n    u64_t end_time = 0;\n\n    mylog(log_info, \"now listening at %s\\n\", local_addr.get_str());\n\n    int fifo_fd = -1;\n\n    if (fifo_file[0] != 0) {\n        fifo_fd = create_fifo(fifo_file);\n        ev.events = EPOLLIN;\n        ev.data.u64 = fifo_fd;\n\n        ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, fifo_fd, &ev);\n        if (ret != 0) {\n            mylog(log_fatal, \"add fifo_fd to epoll error %s\\n\", strerror(errno));\n            myexit(-1);\n        }\n        mylog(log_info, \"fifo_file=%s\\n\", fifo_file);\n    }\n\n    while (1)  ////////////////////////\n    {\n        if (about_to_exit) myexit(0);\n\n        int nfds = epoll_wait(epollfd, events, max_events, 180 * 1000);\n        if (nfds < 0) {  // allow zero\n            if (errno == EINTR) {\n                mylog(log_info, \"epoll interrupted by signal,continue\\n\");\n                // myexit(0);\n            } else {\n                mylog(log_fatal, \"epoll_wait return %d,%s\\n\", nfds, strerror(errno));\n                myexit(-1);\n            }\n        }\n        int idx;\n        for (idx = 0; idx < nfds; ++idx) {\n            // mylog(log_debug,\"ndfs:  %d \\n\",nfds);\n            epoll_trigger_counter++;\n            // printf(\"%d %d %d %d\\n\",timer_fd,raw_recv_fd,raw_send_fd,n);\n            if ((events[idx].data.u64) == (u64_t)timer_fd) {\n                if (debug_flag) begin_time = get_current_time();\n                conn_manager.clear_inactive();\n                u64_t dummy;\n                int unused = read(timer_fd, &dummy, 8);\n                // current_time_rough=get_current_time();\n                if (debug_flag) {\n                    end_time = get_current_time();\n                    mylog(log_debug, \"timer_fd,%llu,%llu,%llu\\n\", begin_time, end_time, end_time - begin_time);\n                }\n\n                mylog(log_trace, \"epoll_trigger_counter:  %d \\n\", epoll_trigger_counter);\n                epoll_trigger_counter = 0;\n\n            } else if (events[idx].data.u64 == (u64_t)raw_recv_fd) {\n                if (debug_flag) begin_time = get_current_time();\n                server_on_raw_recv_multi();\n                if (debug_flag) {\n                    end_time = get_current_time();\n                    mylog(log_debug, \"raw_recv_fd,%llu,%llu,%llu  \\n\", begin_time, end_time, end_time - begin_time);\n                }\n            } else if (events[idx].data.u64 == (u64_t)fifo_fd) {\n                int len = read(fifo_fd, buf, sizeof(buf));\n                if (len < 0) {\n                    mylog(log_warn, \"fifo read failed len=%d,errno=%s\\n\", len, strerror(errno));\n                    continue;\n                }\n                // assert(len>=0);\n                buf[len] = 0;\n                while (len >= 1 && buf[len - 1] == '\\n')\n                    buf[len - 1] = 0;\n                mylog(log_info, \"got data from fifo,len=%d,s=[%s]\\n\", len, buf);\n                mylog(log_info, \"unknown command\\n\");\n            } else if (events[idx].data.u64 > u32_t(-1)) {\n                fd64_t fd64 = events[idx].data.u64;\n                if (!fd_manager.exist(fd64)) {\n                    mylog(log_trace, \"fd64 no longer exist\\n\");\n                    return -1;\n                }\n                assert(fd_manager.exist_info(fd64));\n                conn_info_t *p_conn_info = fd_manager.get_info(fd64).p_conn_info;\n                conn_info_t &conn_info = *p_conn_info;\n                if (fd64 == conn_info.timer_fd64)  //////////timer_fd64\n                {\n                    if (debug_flag) begin_time = get_current_time();\n                    int fd = fd_manager.to_fd(fd64);\n                    u64_t dummy;\n                    int unused = read(fd, &dummy, 8);\n                    assert(conn_info.state.server_current_state == server_ready);  // TODO remove this for peformance\n                    server_on_timer_multi(conn_info);\n                    if (debug_flag) {\n                        end_time = get_current_time();\n                        mylog(log_debug, \"(events[idx].data.u64 >>32u) == 2u ,%llu,%llu,%llu  \\n\", begin_time, end_time, end_time - begin_time);\n                    }\n                } else  // udp_fd64\n                {\n                    if (debug_flag) begin_time = get_current_time();\n                    server_on_udp_recv(conn_info, fd64);\n                    if (debug_flag) {\n                        end_time = get_current_time();\n                        mylog(log_debug, \"(events[idx].data.u64 >>32u) == 1u,%lld,%lld,%lld  \\n\", begin_time, end_time, end_time - begin_time);\n                    }\n                }\n            } else {\n                mylog(log_fatal, \"unknown fd,this should never happen\\n\");\n                myexit(-1);\n            }\n        }\n    }\n    return 0;\n}\n\n#endif\n"
  },
  {
    "path": "third-party/luci-app-udp2raw/moved_to_new_repo",
    "content": "https://github.com/sensec/luci-app-udp2raw\n"
  },
  {
    "path": "third-party/udp2raw-cmake-makefile/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.7)\nproject(udp2raw_tunnel)\n\nset(CMAKE_CXX_STANDARD 11)\nset_source_files_properties(lib/aes_faster_c/aes.c lib/aes_faster_c/wrapper.c lib/md5.c PROPERTIES LANGUAGE CXX )\n\nset(SOURCE_FILES\n        lib/aes_faster_c/aes.c\n\tlib/aes_faster_c/wrapper.c\n        lib/md5.c\n        common.cpp\n        encrypt.cpp\n        log.cpp\n        main.cpp\n        network.cpp\n        )\nset(CMAKE_CXX_FLAGS \"-Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers  -static\")\n#set(CMAKE_LINK_LIBRARY_FLAG \"-lrt\")\nadd_executable(udp2raw_cmake ${SOURCE_FILES})\ntarget_link_libraries(udp2raw_cmake rt)\ntarget_link_libraries(udp2raw_cmake pthread)\n"
  },
  {
    "path": "third-party/udp2raw-openwrt-makefile/moved_to_new_repo",
    "content": "https://github.com/sensec/openwrt-udp2raw\n"
  }
]