logwang 2017-04-21 18:43:26 +08:00
parent 08d6a8500a
commit a9643ea85c
7717 changed files with 4051144 additions and 1 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*~
*.a
*.core
*.lo
*.la
*.o
*.so

BIN
F-Stack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

216
LICENSE Normal file
View File

@ -0,0 +1,216 @@
Main code of F-Stack is BSD 2-Clause licensed.
Copyright (C) 2017 THL A29 Limited, a Tencent company.
All rights reserved.
Other Dependencies:
------------------------------------------------------------------------------
This work contains some softwares from:
DPDK(http://dpdk.org/),
FreeBSD(https://www.freebsd.org/),
Nginx(http://nginx.org),
Redis(https://github.com/antirez/redis),
Microthread framework(https://github.com/Tencent/MSEC/tree/master/spp_rpc/src/sync_frame/micro_thread).
This work uses some codes from:
Libplebnet(https://gitorious.org/freebsd/kmm-sandbox/commit/fa8a11970bc0ed092692736f175925766bebf6af?p=freebsd:kmm-sandbox.git;a=tree;f=lib/libplebnet;h=ae446dba0b4f8593b69b339ea667e12d5b709cfb;hb=refs/heads/work/svn_trunk_libplebnet),
Libuinet(https://github.com/pkelsey/libuinet),
inih(https://github.com/benhoyt/inih).
1.DPDK
BSD 3-Clause, Copyright(c) 2010-2017 Intel Corporation.All rights reserved.
2.FreeBSD
BSD 2-Clause, Copyright 1992-2016 The FreeBSD Project. All rights reserved.
3.Libplebnet
BSD 2-Clause, Copyright (c) 2010-2011 Kip Macy.All rights reserved.
4.Libuinet
BSD 2-Clause, Copyright (c) 2015 Patrick Kelsey.All rights reserved.
5.inih(a simple .INI file parser)
BSD 3-Clause, Copyright (c) 2009, Ben Hoyt.All rights reserved.
6.Nginx
BSD 2-Clause, Copyright (C) 2002-2017 Igor Sysoev.
Copyright (C) 2011-2017 Nginx, Inc.All rights reserved.
7.Redis
BSD 2-Clause, Copyright (c) 2006-2015, Salvatore Sanfilippo.All rights reserved.
8.Microthread framework
GPL-2.0, Copyright (C) 2016 THL A29 Limited, a Tencent company.All rights reserved.
Terms of the BSD 2-Clause License:
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Terms of the BSD 3-Clause License:
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Terms of the GPL-2.0 License:
-------------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
One line to give the program's name and a brief idea of what it does.
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.

106
README.md
View File

@ -1,2 +1,106 @@
# F-Stack
Since the F-Stack project involves a large number of third party code, there are many open source licenses, copyrights need to be reviewed. So, the project is closed temporarily, and when this work is completed, we will reopen the project before April 24th.
![](F-Stack.png)
## Introduction
With the rapid development of NIC, the poor performance of data packets processing with Linux kernel has become the bottleneck. However, the rapid development of the Internet needs high performance of network processing, kernel bypass has caught more and more attention. There are various similar technologies appear, such as DPDK, NETMAP and PF_RING. The main idea of kernel bypass is that Linux is only used to deal with control flow, all data streams are processed in user space. Therefore, kernel bypass can avoid performance bottlenecks caused by kernel packet copy, thread scheduling, system calls and interrupt. Furthermore, kernel bypass can achieve higher performance with multi optimizing methods. Within various techniques, DPDK has been widely used because of its more thorough isolation from kernel scheduling and active community support.
[F-Stack](http://www.f-stack.org/?from=github) is an open source network framework with high performance based on DPDK. With follow characteristics
1. Ultra high network performance which can achieve network card under full load, 10 million concurrent connection, 5 million RPS, 1 million CPS.
2. Transplant FreeBSD 11.01 user space stack, provides a complete stack function, cut a great amount of irrelevant features. Therefore greatly enhance the performance.
3. Support Nginx, Redis and other mature applications, service can easily use F-Stack
4. With Multi-process architecture, easy to extend
5. Provide micro thread interface. Various applications with stateful app can easily use F-Stack to get high performance without processing complex asynchronous logic.
6. Provide Epoll/Kqueue interface that allow many kinds of applications easily use F-Stack
## History
In order to deal with the increasingly severe DDoS attacks, authorized DNS server of Tencent Cloud DNSPod switched from Gigabit Ethernet to 10-Gigabit at the end of 2012. We faced several options, one is to continue to use the original model another is to use kernel bypass technology. After several rounds of investigation, we finally chose to develop our next generation of DNS server based on DPDK. The reason is DPDK provides ultra-high performance and can be seamlessly extended to 40G, or even 100G NIC in the future.
After several months of development and testing, DKDNS, high-performance DNS server based on DPDK officially released in October 2013. It's capable of achieving up to 11 million QPS with a single 10GE port and 18.2 million QPS with two 10GE ports. And then we developed a user-space TCP/IP stack called F-Stack that can process 0.6 million RPS with a single 10GE port.
With the fast growth of Tencent Cloud, more and more services need higher network access performance. Meanwhile, F-Stack was continuous improving driven by the business growth, and ultimately developed into a general network access framework. But this TCP/IP stack couldn't meet the needs of these services while continue to develop and maintain a complete network stack will cost high, we've tried several plans and finally determined to port FreeBSD(11.0 stable) TCP/IP stack into F-Stack. Thus, we can reduce the cost of maintenance and follow up the improvement from community quickly.Thanks to [libplebnet](https://gitorious.org/freebsd/kmm-sandbox/commit/fa8a11970bc0ed092692736f175925766bebf6af?p=freebsd:kmm-sandbox.git;a=tree;f=lib/libplebnet;h=ae446dba0b4f8593b69b339ea667e12d5b709cfb;hb=refs/heads/work/svn_trunk_libplebnet) and [libuinet](https://github.com/pkelsey/libuinet), this work becomes a lot easier.
With the rapid development of all kinds of application, in order to help different APPs quick and easily use F-Stack, F-Stack has integrated Nginx, Redis and other commonly used APPs, and a micro thread framework, and provides a standard Epoll/Kqueue interface.
Currently, besides authorized DNS server of DNSPod, there are various products in Tencent Cloud has used the F-Stack, such as HttpDNS (D+), COS access module, CDN access module, etc..
## Quick Start
#clone F-Stack
mkdir /data/f-stack
git clone https://github.com/F-Stack/f-stack.git /data/f-stack
cd f-stack
# compile DPDK
cd dpdk/tools
./dpdk-setup.sh # compile with x86_64-native-linuxapp-gcc
# Set hugepage
# single-node system
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# or NUMA
echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
# Using Hugepage with the DPDK
mkdir /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
# offload NIC
modprobe uio
insmod /data/f-stack/dpdk/x86_64-native-linuxapp-gcc/build/kmod/igb_uio.ko
insmod /data/f-stack/dpdk/x86_64-native-linuxapp-gcc/build/kmod/rte_kni.ko
python dpdk-devbind.py --status
ifconfig eth0 down
python dpdk-devbind.py --bind=igb_uio eth0 # assuming that use 10GE NIC and eth0
# Compile F-Stack
cd ../../lib/
make
export FF_PATH=/data/f-stack
export FF_DPDK=/data/f-stack/dpdk/x86_64-native-linuxapp-gcc/lib
#### Nginx
cd app/nginx-1.11.10
./configure --prefix=/usr/local/nginx_fstack --with-ff_module
make
make install
cd ../..
./start.sh -b /usr/local/nginx_fstack/sbin/nginx -c config.ini
#### Redis
cd app/redis-3.2.8/
make
make install
## Nginx Testing Result
Test environment
NIC:Intel Corporation Ethernet Controller XL710 for 40GbE QSFP+
CPU:Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz
Memory128G
OS:CentOS Linux release 7.2 (Final)
Kernel3.10.104-1-tlinux2-0041.tl2
Nginx uses linux kernel's default config, all soft interrupts are working in the first CPU core.
Nginx si means modify the smp_affinity of every IRQ, so that the decision to service an interrupt with a particular CPU is made at the hardware level, with no intervention from the kernel.
CPS (Connection:close, Small data packet) test result
![](http://i.imgur.com/PvCRmXR.png)
RPS (Connection:Keep-Alive, Small data packet) test data
![](http://i.imgur.com/CTDPx3a.png)
Bandwidth (Connection:Keep-Alive, 3.7k bytes data packet) test data
![](http://i.imgur.com/1ZM6yT9.png)
## Licenses
See [LICENSE](LICENSE)

95
app/micro_thread/Makefile Normal file
View File

@ -0,0 +1,95 @@
#
# Tencent is pleased to support the open source community by making MSEC available.
#
# Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
#
# Licensed under the GNU General Public License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. You may
# obtain a copy of the License at
#
# https://opensource.org/licenses/GPL-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the
# License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific language governing permissions
# and limitations under the License.
#
########MAKEFILE##########
ifeq ($(FF_PATH),)
$(error variable FF_PATH is not set)
endif
DEBUG= -g
BINARY = libmt.a
FF_LIB=$(FF_PATH)/libfstack.a
DPDK_LIBS = $(shell pkg-config --define-variable=TOPDIR=${FF_PATH} --libs f-stack.pc)
# Comment the following line if you are not using the gnu c compiler
#C_ARGS = -Wall -g -fPIC -D_DEBUG
C_ARGS = -Wall -g -fPIC -O0 -DMT_REAL_TIME
#.SUFFIXES: .o .cpp
ifeq ($(ARCH),32)
C_ARGS += -march=pentium4 -m32 -DSUS_LINUX -pthread
else
C_ARGS += -m64 -DSUS_LINUX -pthread
endif
# You might have to change this if your c compiler is not cc
CC = g++
# You shouldn't need to make any more changes below this line.
INCCOMM=-I./valgrind -I$(FF_PATH)/lib
#.c.o:
# $(CC) -c $*.c
all: $(BINARY)
### shell color config
RED = \\e[1m\\e[31m
DARKRED = \\e[31m
GREEN = \\e[1m\\e[32m
DARKGREEN = \\e[32m
BLUE = \\e[1m\\e[34m
DARKBLUE = \\e[34m
YELLOW = \\e[1m\\e[33m
DARKYELLOW = \\e[33m
MAGENTA = \\e[1m\\e[35m
DARKMAGENTA = \\e[35m
CYAN = \\e[1m\\e[36m
DARKCYAN = \\e[36m
RESET = \\e[m
CRESET = ;echo -ne \\e[m; test -s $@
%.o: %.cpp
@echo -e Compiling $(GREEN)$<$(RESET) ...$(RED)
@$(CC) $(C_ARGS) -c -o $@ $< $(INCCOMM) $(CRESET)
%.o: %.c
@echo -e Compiling $(GREEN)$<$(RESET) ...$(RED)
@$(CC) $(C_ARGS) -c -o $@ $< $(INCCOMM) $(CRESET)
%.o: %.S
@echo -e Compiling $(GREEN)$<$(RESET) ...$(RED)
@$(CC) $(C_ARGS) -c -o $@ $< $(INCCOMM) $(CRESET)
clean:
@rm -f $(BINARY) *.a *.o echo
LIB_OBJ = micro_thread.o kqueue_proxy.o arch_ctx.o mt_session.o mt_notify.o mt_action.o mt_mbuf_pool.o mt_api.o\
mt_connection.o mt_concurrent.o mt_sys_hook.o ff_hook.o heap_timer.o mt_cache.o mt_net.o
libmt.a: $(LIB_OBJ)
@echo -e Linking $(CYAN)$@$(RESET) ...$(RED)
@-rm -f $@
@ar crs $@ $^ $(FST_LIB) $(CRESET)
@chmod +x $@
echo: echo.o libmt.a
@echo -e Compile $(CYAN)$@$(RESET) ...$(RED)
@$(CC) -O -gdwarf-2 -o $@ $^ -lstdc++ -ldl -lm $(DPDK_LIBS) $(CRESET)

157
app/micro_thread/arch_ctx.S Normal file
View File

@ -0,0 +1,157 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
#
# context x86 or x86_64 save and restore
#
# x86_64 x86
# 0 %rbx %ebx
# 1 %rsp %esp
# 2 %rbp %ebp
# 3 %r12 %esi
# 4 %r13 %edi
# 5 %r14 %eip
# 6 %r15
# 7 %rip
#if defined(__amd64__) || defined(__x86_64__)
##
# @brief save_context
##
.text
.align 4
.globl save_context
.type save_context, @function
save_context:
pop %rsi
xorl %eax,%eax
movq %rbx,(%rdi)
movq %rsp,8(%rdi)
push %rsi
movq %rbp,16(%rdi)
movq %r12,24(%rdi)
movq %r13,32(%rdi)
movq %r14,40(%rdi)
movq %r15,48(%rdi)
movq %rsi,56(%rdi)
ret
.size save_context,.-save_context
##
# @brief restore_context
##
.text
.align 4
.globl restore_context
.type restore_context, @function
restore_context:
movl %esi,%eax
movq (%rdi),%rbx
movq 8(%rdi),%rsp
movq 16(%rdi),%rbp
movq 24(%rdi),%r12
movq 32(%rdi),%r13
movq 40(%rdi),%r14
movq 48(%rdi),%r15
jmp *56(%rdi)
.size restore_context,.-restore_context
##
# @brief replace_esp
##
.text
.align 4
.globl replace_esp
.type replace_esp, @function
replace_esp:
movq %rsi,8(%rdi)
ret
.size replace_esp,.-replace_esp
#elif defined(__i386__)
##
# @brief save_context
##
.text
.align 4
.globl save_context
.type save_context, @function
save_context:
movl 4(%esp),%edx
popl %ecx
xorl %eax,%eax
movl %ebx,(%edx)
movl %esp,4(%edx)
pushl %ecx
movl %ebp,8(%edx)
movl %esi,12(%edx)
movl %edi,16(%edx)
movl %ecx,20(%edx)
ret
.size save_context,.-save_context
##
# @brief restore_context
##
.text
.align 4
.globl restore_context
.type restore_context, @function
restore_context:
movl 4(%esp),%edx
movl 8(%esp),%eax
movl (%edx),%ebx
movl 4(%edx),%esp
movl 8(%edx),%ebp
movl 12(%edx),%esi
movl 16(%edx),%edi
jmp *20(%edx)
.size restore_context,.-restore_context
##
# @brief replace_esp
##
.text
.align 4
.globl replace_esp
.type replace_esp, @function
replace_esp:
movl 4(%esp),%edx
movl 8(%esp),%eax
movl %eax,4(%edx)
ret
.size replace_esp,.-replace_esp
#else
#error "Linux cpu arch not supported"
#endif

102
app/micro_thread/echo.cpp Normal file
View File

@ -0,0 +1,102 @@
#include <stdio.h>
#include <stdlib.h>
#include "mt_incl.h"
#include "micro_thread.h"
using namespace NS_MICRO_THREAD;
int set_fd_nonblock(int fd)
{
int nonblock = 1;
return ioctl(fd, FIONBIO, &nonblock);
}
int create_tcp_sock()
{
int fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
fprintf(stderr, "create tcp socket failed, error: %m\n");
return -1;
}
if (set_fd_nonblock(fd) == -1) {
fprintf(stderr, "set tcp socket nonblock failed\n");
return -1;
}
return fd;
}
void echo(void *arg)
{
int ret;
int *p = (int *)arg;
int clt_fd = *p;
delete p;
char buf[64 * 1024];
while (true) {
ret = mt_recv(clt_fd, (void *)buf, 64 * 1024, 0, -1);
if (ret < 0) {
printf("recv from client error\n");
break;
}
ret = mt_send(clt_fd, (void *)buf, ret, 0, 1000);
if (ret < 0) {
//printf("send data to client error\n");
break;
}
}
close(clt_fd);
}
int echo_server()
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(80);
int fd = create_tcp_sock();
if (fd < 0) {
fprintf(stderr, "create listen socket failed\n");
return -1;
}
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(fd);
fprintf(stderr, "bind failed [%m]\n");
return -1;
}
if (listen(fd, 1024) < 0) {
close(fd);
fprintf(stderr, "listen failed [%m]\n");
return -1;
}
int clt_fd = 0;
int *p;
while (true) {
struct sockaddr_in client_addr;
int addr_len = sizeof(client_addr);
clt_fd = mt_accept(fd, (struct sockaddr*)&client_addr, (socklen_t*)&addr_len, -1);
if (clt_fd < 0) {
mt_sleep(1);
continue;
}
if (set_fd_nonblock(clt_fd) == -1) {
fprintf(stderr, "set clt_fd nonblock failed [%m]\n");
break;
}
p = new int(clt_fd);
mt_start_thread((void *)echo, (void *)p);
}
return 0;
}
int main(int argc, char *argv[])
{
mt_init_frame("./config.ini", argc, argv);
echo_server();
}

View File

@ -0,0 +1,561 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename epoll_proxy.cpp
* @info epoll for micro thread manage
*/
#include "epoll_proxy.h"
#include "micro_thread.h"
using namespace NS_MICRO_THREAD;
/**
* @brief
*/
EpollProxy::EpollProxy()
{
_maxfd = EpollProxy::DEFAULT_MAX_FD_NUM;
_epfd = -1;
_evtlist = NULL;
_eprefs = NULL;
}
/**
* @brief epoll,
*/
int EpollProxy::InitEpoll(int max_num)
{
int rc = 0;
if (max_num > _maxfd) // 如果设置的数目较大, 则调整最大fd数目
{
_maxfd = max_num;
}
_epfd = epoll_create(_maxfd);
if (_epfd < 0)
{
rc = -1;
goto EXIT_LABEL;
}
fcntl(_epfd, F_SETFD, FD_CLOEXEC);
_eprefs = new FdRef[_maxfd];
if (NULL == _eprefs)
{
rc = -2;
goto EXIT_LABEL;
}
_evtlist = (EpEvent*)calloc(_maxfd, sizeof(EpEvent));
if (NULL == _evtlist)
{
rc = -3;
goto EXIT_LABEL;
}
struct rlimit rlim;
memset(&rlim, 0, sizeof(rlim));
if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
{
if ((int)rlim.rlim_max < _maxfd)
{
rlim.rlim_cur = rlim.rlim_max;
setrlimit(RLIMIT_NOFILE, &rlim);
rlim.rlim_cur = _maxfd;
rlim.rlim_max = _maxfd;
setrlimit(RLIMIT_NOFILE, &rlim);
}
}
EXIT_LABEL:
if (rc < 0)
{
TermEpoll();
}
return rc;
}
/**
* @brief epoll
*/
void EpollProxy::TermEpoll()
{
if (_epfd > 0)
{
close(_epfd);
_epfd = -1;
}
if (_evtlist != NULL)
{
free(_evtlist);
_evtlist = NULL;
}
if (_eprefs != NULL)
{
delete []_eprefs;
_eprefs = NULL;
}
}
/**
* @brief 线socketepoll
* @param fdset 线socket
* @return true , false , ,
*/
bool EpollProxy::EpollAdd(EpObjList& obj_list)
{
bool ret = true;
EpollerObj *epobj = NULL;
EpollerObj *epobj_error = NULL;
TAILQ_FOREACH(epobj, &obj_list, _entry)
{
if (!EpollAddObj(epobj))
{
MTLOG_ERROR("epobj add failed, fd: %d", epobj->GetOsfd());
epoll_assert(0);
epobj_error = epobj;
ret = false;
goto EXIT_LABEL;
}
}
EXIT_LABEL:
if (!ret)
{
TAILQ_FOREACH(epobj, &obj_list, _entry)
{
if (epobj == epobj_error)
{
break;
}
EpollDelObj(epobj);
}
}
return ret;
}
/**
* @brief 线socketepoll
* @param fdset 线socket
* @return true , false
*/
bool EpollProxy::EpollDel(EpObjList& obj_list)
{
bool ret = true;
EpollerObj *epobj = NULL;
TAILQ_FOREACH(epobj, &obj_list, _entry)
{
if (!EpollDelObj(epobj)) // failed also need continue, be sure ref count ok
{
MTLOG_ERROR("epobj del failed, fd: %d", epobj->GetOsfd());
epoll_assert(0);
ret = false;
}
}
return ret;
}
/**
* @brief epfdepctrl,
*/
bool EpollProxy::EpollCtrlAdd(int fd, int events)
{
FdRef* item = FdRefGet(fd);
if (NULL == item)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("epfd ref not find, failed, fd: %d", fd);
epoll_assert(0);
return false;
}
// 更新引用计数, 部分流程会依赖该计数, 失败要回滚
item->AttachEvents(events);
int old_events = item->GetListenEvents();
int new_events = old_events | events;
if (old_events == new_events) {
return true;
}
int op = old_events ? EPOLL_CTL_MOD : EPOLL_CTL_ADD;
EpEvent ev;
ev.events = new_events;
ev.data.fd = fd;
if ((epoll_ctl(_epfd, op, fd, &ev) < 0) && !(op == EPOLL_CTL_ADD && errno == EEXIST))
{
MT_ATTR_API(320850, 1); // epoll error
MTLOG_ERROR("epoll ctrl failed, fd: %d, op: %d, errno: %d", fd, op, errno);
item->DetachEvents(events);
epoll_assert(0);
return false;
}
item->SetListenEvents(new_events);
return true;
}
/**
* @brief epfdepctrl,
*/
bool EpollProxy::EpollCtrlDel(int fd, int events)
{
return EpollCtrlDelRef(fd, events, false);
}
/**
* @brief epfdepctrl, , , epollctl
*/
bool EpollProxy::EpollCtrlDelRef(int fd, int events, bool use_ref)
{
FdRef* item = FdRefGet(fd);
if (NULL == item)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("epfd ref not find, failed, fd: %d", fd);
epoll_assert(0);
return false;
}
item->DetachEvents(events); // delete 失败不回滚处理
int old_events = item->GetListenEvents();
int new_events = old_events &~ events; // 默认情况
// 如果要按引用删除, 需要核查是否满足删除条件
if (use_ref)
{
new_events = old_events;
if (0 == item->ReadRefCnt()) {
new_events = new_events & ~EPOLLIN;
}
if (0 == item->WriteRefCnt()) {
new_events = new_events & ~EPOLLOUT;
}
}
if (old_events == new_events)
{
return true;
}
int op = new_events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL;
EpEvent ev;
ev.events = new_events;
ev.data.fd = fd;
if ((epoll_ctl(_epfd, op, fd, &ev) < 0) && !(op == EPOLL_CTL_DEL && errno == ENOENT))
{
MT_ATTR_API(320850, 1); // epoll error
MTLOG_ERROR("epoll ctrl failed, fd: %d, op: %d, errno: %d", fd, op, errno);
epoll_assert(0);
return false;
}
item->SetListenEvents(new_events);
return true;
}
/**
* @brief epfdepctrl, , 退
*/
bool EpollProxy::EpollAddObj(EpollerObj* obj)
{
if (NULL == obj)
{
MTLOG_ERROR("epobj input invalid, %p", obj);
return false;
}
FdRef* item = FdRefGet(obj->GetOsfd());
if (NULL == item)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("epfd ref not find, failed, fd: %d", obj->GetOsfd());
epoll_assert(0);
return false;
}
// 不同的回调状态, 不同的方式处理 del 事件, 屏蔽连接复用方式的处理复杂性
int ret = obj->EpollCtlAdd(item);
if (ret < 0)
{
MTLOG_ERROR("epoll ctrl callback failed, fd: %d, obj: %p", obj->GetOsfd(), obj);
epoll_assert(0);
return false;
}
return true;
}
/**
* @brief 线socketepoll
* @param fdset 线socket
* @return true , false
*/
bool EpollProxy::EpollDelObj(EpollerObj* obj)
{
if (NULL == obj)
{
MTLOG_ERROR("fdobj input invalid, %p", obj);
return false;
}
FdRef* item = FdRefGet(obj->GetOsfd());
if (NULL == item)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("epfd ref not find, failed, fd: %d", obj->GetOsfd());
epoll_assert(0);
return false;
}
// 不同的回调状态, 不同的方式处理 del 事件, 屏蔽连接复用方式的处理复杂性
int ret = obj->EpollCtlDel(item);
if (ret < 0)
{
MTLOG_ERROR("epoll ctrl callback failed, fd: %d, obj: %p", obj->GetOsfd(), obj);
epoll_assert(0);
return false;
}
return true;
}
/**
* @brief socket
* @param evtfdnum fd
*/
void EpollProxy::EpollRcvEventList(int evtfdnum)
{
int ret = 0;
int osfd = 0;
int revents = 0;
FdRef* item = NULL;
EpollerObj* obj = NULL;
for (int i = 0; i < evtfdnum; i++)
{
osfd = _evtlist[i].data.fd;
item = FdRefGet(osfd);
if (NULL == item)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("epfd ref not find, failed, fd: %d", osfd);
epoll_assert(0);
continue;
}
revents = _evtlist[i].events;
obj = item->GetNotifyObj();
if (NULL == obj)
{
MTLOG_ERROR("fd notify obj null, failed, fd: %d", osfd);
EpollCtrlDel(osfd, (revents & (EPOLLIN | EPOLLOUT)));
continue;
}
obj->SetRcvEvents(revents);
// 1. 错误处理, 完毕后直接跳出
if (revents & (EPOLLERR | EPOLLHUP))
{
obj->HangupNotify();
continue;
}
// 2. 可读事件, 非0返回值会跳出
if (revents & EPOLLIN) {
ret = obj->InputNotify();
if (ret != 0) {
continue;
}
}
// 3. 可写事件, 非0返回值会跳出
if (revents & EPOLLOUT) {
ret = obj->OutputNotify();
if (ret != 0) {
continue;
}
}
}
}
/**
* @brief epoll_wait
*/
void EpollProxy::EpollDispath()
{
int wait_time = EpollGetTimeout();
int nfd = epoll_wait(_epfd, _evtlist, _maxfd, wait_time);
if (nfd <= 0) {
return;
}
EpollRcvEventList(nfd);
}
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
int EpollerObj::InputNotify()
{
MicroThread* thread = this->GetOwnerThread();
if (NULL == thread)
{
epoll_assert(0);
MTLOG_ERROR("Epoll fd obj, no thread ptr, wrong");
return -1;
}
// 多个事件同时到达, 防重复操作
if (thread->HasFlag(MicroThread::IO_LIST))
{
MtFrame* frame = MtFrame::Instance();
frame->RemoveIoWait(thread);
frame->InsertRunable(thread);
}
return 0;
}
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
int EpollerObj::OutputNotify()
{
MicroThread* thread = this->GetOwnerThread();
if (NULL == thread)
{
epoll_assert(0);
MTLOG_ERROR("Epoll fd obj, no thread ptr, wrong");
return -1;
}
// 多个事件同时到达, 防重复操作
if (thread->HasFlag(MicroThread::IO_LIST))
{
MtFrame* frame = MtFrame::Instance();
frame->RemoveIoWait(thread);
frame->InsertRunable(thread);
}
return 0;
}
/**
* @brief , fd, thread
* @return ,
*/
int EpollerObj::HangupNotify()
{
MtFrame* frame = MtFrame::Instance();
frame->EpollCtrlDel(this->GetOsfd(), this->GetEvents());
return 0;
}
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
int EpollerObj::EpollCtlAdd(void* args)
{
MtFrame* frame = MtFrame::Instance();
FdRef* fd_ref = (FdRef*)args;
epoll_assert(fd_ref != NULL);
int osfd = this->GetOsfd();
int new_events = this->GetEvents();
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
EpollerObj* old_obj = fd_ref->GetNotifyObj();
if ((old_obj != NULL) && (old_obj != this))
{
MTLOG_ERROR("epfd ref conflict, fd: %d, old: %p, now: %p", osfd, old_obj, this);
return -1;
}
fd_ref->SetNotifyObj(this);
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
if (!frame->EpollCtrlAdd(osfd, new_events))
{
MTLOG_ERROR("epfd ref add failed, log");
fd_ref->SetNotifyObj(old_obj);
return -2;
}
return 0;
}
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
int EpollerObj::EpollCtlDel(void* args)
{
MtFrame* frame = MtFrame::Instance();
FdRef* fd_ref = (FdRef*)args;
epoll_assert(fd_ref != NULL);
int osfd = this->GetOsfd();
int events = this->GetEvents();
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
EpollerObj* old_obj = fd_ref->GetNotifyObj();
if (old_obj != this)
{
MTLOG_ERROR("epfd ref conflict, fd: %d, old: %p, now: %p", osfd, old_obj, this);
return -1;
}
fd_ref->SetNotifyObj(NULL);
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
if (!frame->EpollCtrlDelRef(osfd, events, false)) // 引用有风险, 弊大于利, 关闭掉
{
MTLOG_ERROR("epfd ref del failed, log");
fd_ref->SetNotifyObj(old_obj);
return -2;
}
return 0;
}

View File

@ -0,0 +1,434 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename epoll_proxy.h
* @info epoll for micro thread manage
*/
#ifndef _EPOLL_PROXY___
#define _EPOLL_PROXY___
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/epoll.h>
#include <assert.h>
#include <set>
#include <vector>
using std::set;
using std::vector;
#define epoll_assert(statement)
//#define epoll_assert(statement) assert(statement)
namespace NS_MICRO_THREAD {
/******************************************************************************/
/* 操作系统头文件适配定义 */
/******************************************************************************/
/**
* @brief add more detail for linux <sys/queue.h>, freebsd and University of California
* @info queue.h version 8.3 (suse) diff version 8.5 (tlinux)
*/
#ifndef TAILQ_CONCAT
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_CONCAT(head1, head2, field) \
do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
} \
} while (0)
#endif
#ifndef TAILQ_FOREACH_SAFE // tlinux no this define
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#endif
/******************************************************************************/
/* Epoll proxy 定义与实现部分 */
/******************************************************************************/
class EpollProxy;
class MicroThread;
/**
* @brief epoll
*/
class EpollerObj
{
protected:
int _fd; ///< 系统FD 或 socket
int _events; ///< 监听的事件类型
int _revents; ///< 收到的事件类型
int _type; ///< 工厂类别定义
MicroThread* _thread; ///< 关联线程指针对象
public:
TAILQ_ENTRY(EpollerObj) _entry; ///< 关联微线程的管理入口
/**
* @brief
*/
explicit EpollerObj(int fd = -1) {
_fd = fd;
_events = 0;
_revents = 0;
_type = 0;
_thread = NULL;
};
virtual ~EpollerObj(){};
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int InputNotify();
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int OutputNotify();
/**
* @brief
* @return ,
*/
virtual int HangupNotify();
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
virtual int EpollCtlAdd(void* args);
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
virtual int EpollCtlDel(void* args);
/**
* @brief fd
*/
void EnableInput() { _events |= EPOLLIN; };
/**
* @brief fd
*/
void EnableOutput() { _events |= EPOLLOUT; };
/**
* @brief fd
*/
void DisableInput() { _events &= ~EPOLLIN; };
/**
* @brief fd
*/
void DisableOutput() { _events &= ~EPOLLOUT; };
/**
* @brief socket
*/
int GetOsfd() { return _fd; };
void SetOsfd(int fd) { _fd = fd; };
/**
* @brief 访
*/
int GetEvents() { return _events; };
void SetRcvEvents(int revents) { _revents = revents; };
int GetRcvEvents() { return _revents; };
/**
* @brief ,
*/
int GetNtfyType() { return _type; };
virtual void Reset() {
_fd = -1;
_events = 0;
_revents = 0;
_type = 0;
_thread = NULL;
};
/**
* @brief 线
* @param thread 线
*/
void SetOwnerThread(MicroThread* thread) { _thread = thread; };
MicroThread* GetOwnerThread() { return _thread; };
};
typedef TAILQ_HEAD(__EpFdList, EpollerObj) EpObjList; ///< 高效的双链管理
typedef struct epoll_event EpEvent; ///< 重定义一下epoll event
/**
* @brief EPOLLFD线, ,
* @info , , , 20150623
*/
class FdRef
{
private:
int _wr_ref; ///< 监听写的引用计数
int _rd_ref; ///< 监听读的引用计数
int _events; ///< 当前正在侦听的事件列表
int _revents; ///< 当前该fd收到的事件信息, 仅在epoll_wait后处理中有效
EpollerObj* _epobj; ///< 单独注册调度器对象一个fd关联一个对象
public:
/**
* @brief
*/
FdRef() {
_wr_ref = 0;
_rd_ref = 0;
_events = 0;
_revents = 0;
_epobj = NULL;
};
~FdRef(){};
/**
* @brief
*/
void SetListenEvents(int events) {
_events = events;
};
int GetListenEvents() {
return _events;
};
/**
* @brief
*/
void SetNotifyObj(EpollerObj* ntfy) {
_epobj = ntfy;
};
EpollerObj* GetNotifyObj() {
return _epobj;
};
/**
* @brief
*/
void AttachEvents(int event) {
if (event & EPOLLIN) {
_rd_ref++;
}
if (event & EPOLLOUT){
_wr_ref++;
}
};
void DetachEvents(int event) {
if (event & EPOLLIN) {
if (_rd_ref > 0) {
_rd_ref--;
} else {
_rd_ref = 0;
}
}
if (event & EPOLLOUT){
if (_wr_ref > 0) {
_wr_ref--;
} else {
_wr_ref = 0;
}
}
};
/**
* @brief
*/
int ReadRefCnt() { return _rd_ref; };
int WriteRefCnt() { return _wr_ref; };
};
/**
* @brief EPOLL, epollepoll
*/
class EpollProxy
{
public:
static const int DEFAULT_MAX_FD_NUM = 100000; ///< 默认最大监控的fd
private:
int _epfd; ///< epoll 主句柄
int _maxfd; ///< 最大的文件句柄数
EpEvent* _evtlist; ///< epoll返回给用户的事件列表指针
FdRef* _eprefs; ///< 用户监听的事件本地管理数组
public:
/**
* @brief
*/
EpollProxy();
virtual ~EpollProxy(){};
/**
* @brief epoll,
* @param max_num fd
*/
int InitEpoll(int max_num);
void TermEpoll(void);
/**
* @brief epoll_wait
* @return , MS
*/
virtual int EpollGetTimeout(void) { return 0;};
/**
* @brief epoll
* @param fdlist , socket
* @param fd socket,
* @param timeout ,
* @return true , false
*/
virtual bool EpollSchedule(EpObjList* fdlist, EpollerObj* fd, int timeout) { return false;};
/**
* @brief 线socketepoll
* @param fdset 线socket
* @return true , false
*/
bool EpollAdd(EpObjList& fdset);
/**
* @brief 线socketepoll
* @param fdset 线socket
* @return true , false
*/
bool EpollDel(EpObjList& fdset);
/**
* @brief epoll_wait
*/
void EpollDispath(void);
/**
* @brief fd,
* @param fd
* @param obj epoll
*/
bool EpollAddObj(EpollerObj* obj);
/**
* @brief fd,
* @param fd
* @param obj epoll
*/
bool EpollDelObj(EpollerObj* obj);
/**
* @brief epoll ctl,
* @param fd
* @param new_events
*/
bool EpollCtrlAdd(int fd, int new_events);
/**
* @brief epoll ctl,
* @param fd
* @param new_events
*/
bool EpollCtrlDel(int fd, int new_events);
bool EpollCtrlDelRef(int fd, int new_events, bool use_ref);
/**
* @brief fd, fd,
* @param fd
* @return , NULL
*/
FdRef* FdRefGet(int fd) {
return ((fd >= _maxfd) || (fd < 0)) ? (FdRef*)NULL : &_eprefs[fd];
};
/**
* @brief ,
* @param fd
* @param obj
*/
void EpollNtfyReg(int fd, EpollerObj* obj) {
FdRef* ref = FdRefGet(fd);
if (ref) {
ref->SetNotifyObj(obj);
}
};
protected:
/**
* @brief socket
* @param evtfdnum fd
*/
void EpollRcvEventList(int evtfdnum);
};
}//NAMESPCE
#endif

View File

@ -0,0 +1,7 @@
DPDK = ${TOPDIR}/dpdk/x86_64-native-linuxapp-gcc
Name: F-Stack
Description: F-Stack pkg-config pc
Version: 1.0
Libs: -L${TOPDIR}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive -Wl,--no-as-needed -fvisibility=default -pthread -lm -lrt -L${DPDK}/lib -Wl,--whole-archive -lrte_pmd_vmxnet3_uio -lrte_pmd_i40e -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ring -Wl,--whole-archive -lrte_hash -lrte_kvargs -Wl,-lrte_mbuf -lethdev -lrte_eal -Wl,-lrte_mempool -lrte_ring -lrte_cmdline -lrte_cfgfile -lrte_kni -lrte_timer -Wl,-lrte_pmd_virtio -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto
Cflags: -Wall -Werror -include ${DPDK}/include/rte_config.h -I${DPDK}/include -march=native -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3 -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2

View File

@ -0,0 +1,222 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sched.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdarg.h>
#include "ff_api.h"
#include "mt_sys_hook.h"
#include "ff_hook.h"
/*
void ff_hook_new_fd(int fd)
{
if (fd < 0 || fd >= ff_HOOK_MAX_FD) {
return;
}
g_ff_hook_fd_tab[fd] = 1;
}
bool ff_hook_find_fd(int fd) {
if (fd < 0 || fd >= ff_HOOK_MAX_FD) {
return false;
}
if (g_ff_hook_fd_tab[fd] == 1) {
return true;
} else {
return false;
}
}
void ff_hook_free_fd(int fd)
{
if (fd < 0 || fd >= ff_HOOK_MAX_FD) {
return;
}
g_ff_hook_fd_tab[fd] = 0;
}
*/
int ff_hook_socket(int domain, int type, int protocol)
{
if (!ff_hook_active() || (AF_INET != domain) || (SOCK_STREAM != type && SOCK_DGRAM != type)) {
return mt_real_func(socket)(domain, type, protocol);
}
int fd = ff_socket(domain, type, protocol);
if (fd >= 0) {
fd |= 1 << FF_FD_BITS;
}
return fd;
}
int ff_hook_close(int fd)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_close(fd);
} else {
return mt_real_func(close)(fd);
}
}
int ff_hook_connect(int fd, const struct sockaddr *address, socklen_t addrlen_len)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_connect(fd, (struct linux_sockaddr *)address, addrlen_len);
} else {
return mt_real_func(connect)(fd, address, addrlen_len);
}
}
ssize_t ff_hook_read(int fd, void *buf, size_t nbyte)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_read(fd, buf, nbyte);
} else {
return mt_real_func(read)(fd, buf, nbyte);
}
}
ssize_t ff_hook_write(int fd, const void *buf, size_t nbyte)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_write(fd, buf, nbyte);
} else {
return mt_real_func(write)(fd, buf, nbyte);
}
}
ssize_t ff_hook_sendto(int fd, const void *message, size_t length, int flags,
const struct sockaddr *dest_addr, socklen_t dest_len)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_sendto(fd, message, length, flags, (struct linux_sockaddr *)dest_addr, dest_len);
} else {
return mt_real_func(sendto)(fd, message, length, flags, dest_addr, dest_len);
}
}
ssize_t ff_hook_recvfrom(int fd, void *buffer, size_t length, int flags,
struct sockaddr *address, socklen_t *address_len)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_recvfrom(fd, buffer, length, flags, (struct linux_sockaddr *)address, address_len);
} else {
return mt_real_func(recvfrom)(fd, buffer, length, flags, address, address_len);
}
}
ssize_t ff_hook_recv(int fd, void *buffer, size_t length, int flags)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_recv(fd, buffer, length, flags);
} else {
return mt_real_func(recv)(fd, buffer, length, flags);
}
}
ssize_t ff_hook_send(int fd, const void *buf, size_t nbyte, int flags)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_send(fd, buf, nbyte, flags);
} else {
return mt_real_func(send)(fd, buf, nbyte, flags);
}
}
int ff_hook_setsockopt(int fd, int level, int option_name, const void *option_value, socklen_t option_len)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_setsockopt(fd, level, option_name, option_value, option_len);
} else {
return mt_real_func(setsockopt)(fd, level, option_name, option_value, option_len);
}
}
int ff_hook_ioctl(int fd, int cmd, void *arg)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_ioctl(fd, cmd, arg);
} else {
return mt_real_func(ioctl)(fd, cmd, arg);
}
}
int ff_hook_fcntl(int fd, int cmd, void *arg)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_fcntl(fd, cmd, arg);
} else {
return mt_real_func(fcntl)(fd, cmd, arg);
}
}
int ff_hook_listen(int fd, int backlog)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_listen(fd, backlog);
} else {
return mt_real_func(listen)(fd, backlog);
}
}
int ff_hook_bind(int fd, const struct sockaddr *addr, socklen_t addrlen)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
return ff_bind(fd, (struct linux_sockaddr *)addr, addrlen);
} else {
return mt_real_func(bind)(fd, addr, addrlen);
}
}
int ff_hook_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
{
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
int c = ff_accept(fd, (struct linux_sockaddr *)addr, addrlen);
if (c < 0) {
return c;
}
c |= 1 << FF_FD_BITS;
return c;
} else {
return mt_real_func(accept)(fd, addr, addrlen);
}
}

View File

@ -0,0 +1,56 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
#ifndef __FF_HOOK_H__
#define __FF_HOOK_H__
#include <stdint.h>
#define FF_FD_BITS 16
#define CHK_FD_BIT(fd) (fd & (1 << FF_FD_BITS))
#define CLR_FD_BIT(fd) (fd & ~(1 << FF_FD_BITS))
void ff_hook_new_fd(int fd);
bool ff_hook_find_fd(int fd);
void ff_hook_free_fd(int fd);
int ff_hook_socket(int domain, int type, int protocol);
int ff_hook_close(int fd);
int ff_hook_connect(int fd, const struct sockaddr *address, socklen_t addrlen_len);
ssize_t ff_hook_read(int fd, void *buf, size_t nbyte);
ssize_t ff_hook_write(int fd, const void *buf, size_t nbyte);
ssize_t ff_hook_sendto(int fd, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
ssize_t ff_hook_recvfrom(int fd, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len);
ssize_t ff_hook_recv(int fd, void *buffer, size_t length, int flags);
ssize_t ff_hook_send(int fd, const void *buf, size_t nbyte, int flags);
int ff_hook_setsockopt(int fd, int level, int option_name, const void *option_value, socklen_t option_len);
int ff_hook_ioctl(int fd, int cmd, void *arg);
int ff_hook_fcntl(int fd, int cmd, void *arg);
int ff_hook_listen(int fd, int backlog);
int ff_hook_bind(int fd, const struct sockaddr *addr, socklen_t addrlen);
int ff_hook_accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
#endif

View File

@ -0,0 +1,290 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename hash_list.h
* @info hash, hash; hash,
* , , ,
* @time 2013-06-11
*/
#ifndef __HASH_LIST_FILE__
#define __HASH_LIST_FILE__
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
namespace NS_MICRO_THREAD {
/**
* @brief Hash,
*/
class HashKey
{
private:
HashKey* _next_entry; ///< 开链hash的链接元素
uint32_t _hash_value; ///< hash value信息, 节约比较的时间
void* _data_ptr; ///< hash data数据指针, 可key - value 聚合存储
public:
friend class HashList; ///< hash表可以直接访问next指针
/**
* @brief
*/
HashKey():_next_entry(NULL), _hash_value(0), _data_ptr(NULL) {};
virtual ~HashKey(){};
/**
* @brief hash, keyhash
* @return hash
*/
virtual uint32_t HashValue() = 0;
/**
* @brief cmp, ID, key
* @return hash
*/
virtual int HashCmp(HashKey* rhs) = 0;
/**
* @brief , , ,
*/
virtual void HashIterate() {
return;
};
/**
* @brief
*/
void* GetDataPtr() {
return _data_ptr;
};
void SetDataPtr(void* data) {
_data_ptr = data;
};
};
/**
* @brief Hash, hash, hash,
*/
class HashList
{
public:
/**
* @brief
*/
explicit HashList(int max = 100000) {
_max = GetMaxPrimeNum((max > 2) ? max : 100000);
_buckets = (HashKey**)calloc(_max, sizeof(HashKey*));
_count = 0;
};
virtual ~HashList() {
if (_buckets) {
free(_buckets);
_buckets = NULL;
}
_count = 0;
};
/**
* @brief hash
* @return
*/
int HashSize() {
return _count;
};
/**
* @brief hash, , remove
* @param key , ,
* @return 0 , -1 , -2
*/
int HashInsert(HashKey* key) {
if (!key || !_buckets) {
return -1;
}
if ((key->_hash_value != 0) || (key->_next_entry != NULL)) {
return -2;
}
key->_hash_value = key->HashValue();
int idx = (key->_hash_value) % _max;
HashKey* next_item = _buckets[idx];
_buckets[idx] = key;
key->_next_entry = next_item;
_count++;
return 0;
}
/**
* @brief hash
* @param key key
* @return , NULL
*/
HashKey* HashFind(HashKey* key) {
if (!key || !_buckets) {
return NULL;
}
uint32_t hash = key->HashValue();
int idx = hash % _max;
HashKey* item = _buckets[idx];
for (; item != NULL; item = item->_next_entry) {
if (item->_hash_value != hash) {
continue;
}
if (item->HashCmp(key) == 0) {
break;
}
}
return item;
}
/**
* @brief hash
* @param key key
* @return , NULL
*/
void* HashFindData(HashKey* key) {
HashKey* item = HashFind(key);
if (!item) {
return NULL;
} else {
return item->_data_ptr;
}
};
/**
* @brief hash
* @param key key
*/
void HashRemove(HashKey* key) {
if (!key || !_buckets) {
return;
}
uint32_t hash = key->HashValue();
int idx = hash % _max;
HashKey* item = _buckets[idx];
HashKey* prev = NULL;
for (; item != NULL; prev = item, item = item->_next_entry) {
if ((item->_hash_value == hash) && (item->HashCmp(key) == 0)){
if (prev == NULL) {
_buckets[idx] = item->_next_entry;
} else {
prev->_next_entry = item->_next_entry;
}
item->_hash_value = 0;
item->_next_entry = NULL;
_count--;
break;
}
}
}
/**
* @brief hash,
*/
void HashForeach() {
if (!_buckets) {
return;
}
for (int i = 0; i < _max; i++) {
HashKey* item = _buckets[i];
for (; item != NULL; item = item->_next_entry) {
item->HashIterate();
}
}
}
/**
* @brief hash, ,
*/
HashKey* HashGetFirst() {
if (!_buckets) {
return NULL;
}
for (int i = 0; i < _max; i++) {
if (_buckets[i]) {
return _buckets[i];
}
}
return NULL;
}
private:
/**
* @brief
*/
int GetMaxPrimeNum(int num)
{
int sqrt_value = (int)sqrt(num);
for (int i = num; i > 0; i--)
{
int flag = 1;
for (int k = 2; k <= sqrt_value; k++)
{
if (i % k == 0)
{
flag = 0;
break;
}
}
if (flag == 1)
{
return i;
}
}
return 0;
};
private:
HashKey** _buckets; ///< 桶指针
int _count; ///< 有效元素个数
int _max; ///< 最大节点个数
};
}
#endif

441
app/micro_thread/heap.h Normal file
View File

@ -0,0 +1,441 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename heap.h
* @info , , std::make_heap
* @time 2013-06-11
*/
#ifndef __HEAP_ENTRY_FILE__
#define __HEAP_ENTRY_FILE__
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define heap_assert(statement)
//#define heap_assert(statement) assert(statement)
namespace NS_MICRO_THREAD {
class HeapEntry; // 堆元素类, 继承实现扩展
class HeapList; // 堆管理类, 通用
/**
* @brief , ,
*/
class HeapEntry
{
private:
int _index; ///< 堆元素下标, 利于快速索引删除操作
public:
friend class HeapList;
/**
* @brief
*/
HeapEntry():_index(0){};
virtual ~HeapEntry(){};
/**
* @brief , , ,
* @return
*/
virtual unsigned long long HeapValue() = 0;
/**
* @brief , , ,
*/
virtual void HeapIterate() {
return;
};
/**
* @brief
* @param list
* @return 0 ; -1 ; -2
*/
inline int InsertIntoHeap(HeapList* list);
/**
* @brief
* @param list
* @return 0 ; -1 ; -2
*/
inline int DeleteFromHeap(HeapList* list);
/**
* @brief , 使
* @return
*/
inline int GetIndex() {
return _index;
};
private:
inline int HeapValueCmp(HeapEntry* rhs) {
if (this->HeapValue() == rhs->HeapValue()) {
return 0;
} else if (this->HeapValue() > rhs->HeapValue()) {
return 1;
} else {
return -1;
}
};
inline void SetIndex(int index) {
_index = index;
};
};
/**
* @brief ,
*/
class HeapList
{
private:
HeapEntry** _list; // 堆元素的指针数组, 目前定长
int _max; // 堆可管理最大元素个数
int _count; // 堆已经管理的元素个数
public:
/**
* @brief
*/
explicit HeapList(int max = 100000) {
_max = (max > 0) ? max : 100000;
_list = (HeapEntry**)malloc (sizeof(HeapEntry*) * (_max+1));
heap_assert(_list);
memset(_list, 0, sizeof(HeapEntry*) * (_max+1));
_count = 0;
};
virtual ~HeapList() {
if (_list) {
free(_list);
_list = NULL;
}
_max = 0;
_count = 0;
};
/**
* @brief heap,
* @param size
* @return 0 ; -1
*/
int HeapResize(int size) {
if (_max >= size) {
return 0;
}
HeapEntry** new_list = (HeapEntry**)malloc(sizeof(HeapEntry*) * (size+1));
if (NULL == new_list) {
return -1;
}
memset(new_list, 0, sizeof(HeapEntry*) * (size+1));
memcpy(new_list, _list, sizeof(HeapEntry*) * (_max+1));
free(_list);
_list = new_list;
_max = size;
return 0;
};
/**
* @brief
* @param entry
* @return 0 ; -1 ; -2
*/
int HeapPush(HeapEntry* entry);
/**
* @brief ,
* @return , NULL
*/
HeapEntry* HeapPop();
/**
* @brief
* @param entry
* @return 0 ; -1 ; -2
*/
int HeapDelete(HeapEntry* entry);
/**
* @brief , 2,
*/
void HeapForeach();
/**
* @brief
* @return
*/
int HeapSize() {
return _count;
};
/**
* @brief ,
* @return , NULL
*/
HeapEntry* HeapTop() {
return (_count > 0) ? _list[1] : NULL;
};
private:
/**
* @brief
* @return true
*/
bool HeapFull() {
return (_count >= _max);
};
/**
* @brief
* @return true
*/
bool HeapEmpty() {
return (_count == 0);
};
/**
* @brief ,
*/
void HeapUp();
/**
* @brief ,
*/
void HeapDown(int index);
};
/**
* @brief ,
*/
inline void HeapList::HeapUp()
{
for (int pos = _count; pos > 0; pos = pos/2)
{
if (pos/2 < 1) // pos == 1 已经到顶, 0 属于保留
{
break;
}
if (_list[pos]->HeapValueCmp(_list[pos/2]) < 0)
{
HeapEntry* tmp = _list[pos/2];
_list[pos/2] = _list[pos];
_list[pos] = tmp;
_list[pos]->SetIndex(pos);
_list[pos/2]->SetIndex(pos/2);
}
else
{
break;
}
}
}
/**
* @brief ,
* @param index
*/
inline void HeapList::HeapDown(int index)
{
int min_son;
for (int pos = index; pos <= _count; pos = min_son)
{
if (pos*2 > _count) // pos是叶子节点了
{
break;
}
else if (pos*2 == _count)
{
min_son = pos*2;
}
else
{
if (_list[pos*2+1]->HeapValueCmp(_list[pos*2]) < 0)
{
min_son = pos*2+1;
}
else
{
min_son = pos*2;
}
}
if (_list[pos]->HeapValueCmp(_list[min_son]) > 0)
{
HeapEntry* tmp = _list[min_son];
_list[min_son] = _list[pos];
_list[pos] = tmp;
_list[pos]->SetIndex(pos);
_list[min_son]->SetIndex(min_son);
}
else
{
break;
}
}
}
/**
* @brief
* @param entry
* @return 0 ; -1 ; -2
*/
inline int HeapList::HeapPush(HeapEntry* item)
{
if (HeapFull()) {
heap_assert(0); // 满, 理论上是可能的, 实际运行不太可能过10W
return -1;
}
if (item->GetIndex() != 0) {
heap_assert(0); // 重复插入
return -2;
}
_count++;
_list[_count] = item;
item->SetIndex(_count);
HeapUp();
return 0;
}
/**
* @brief ,
* @return , NULL
*/
inline HeapEntry* HeapList::HeapPop()
{
if (HeapEmpty()) {
return NULL;
}
HeapEntry* top = _list[1]; // 0 保留
_list[1] = _list[_count];
_list[1]->SetIndex(1);
_list[_count] = 0;
_count--;
HeapDown(1);
heap_assert(top->GetIndex() == 1);
top->SetIndex(0);
return top;
}
/**
* @brief
* @param entry
* @return 0 ; -1 ; -2
*/
inline int HeapList::HeapDelete(HeapEntry* item)
{
if (HeapEmpty()) {
return -1;
}
int pos = item->GetIndex() ;
if ((pos > _count) ||(pos <= 0))
{
heap_assert(0); // 非法数据或重复删除
return -2;
}
HeapEntry* del = _list[pos];
_list[pos] = _list[_count];
_list[pos]->SetIndex(pos);
_list[_count] = 0;
_count--;
HeapDown(pos);
heap_assert(pos == del->GetIndex());
del->SetIndex(0);
return 0;
}
/**
* @brief , 2,
*/
inline void HeapList::HeapForeach()
{
int per = 1;
for (int i = 1; i <= _count; i++)
{
if (i >= per*2)
{
printf("\n");
per *=2;
}
printf("%llu ", _list[i]->HeapValue());
_list[i]->HeapIterate();
}
}
/**
* @brief
* @param list
* @return 0 ; -1 ; -2
*/
inline int HeapEntry::InsertIntoHeap(HeapList* list) {
return list->HeapPush(this);
};
/**
* @brief
* @param list
* @return 0 ; -1 ; -2
*/
inline int HeapEntry::DeleteFromHeap(HeapList* list) {
return list->HeapDelete(this);
};
} // namespace end
#endif

View File

@ -0,0 +1,115 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file heap_timer.cpp
*/
#include "heap_timer.h"
#include "micro_thread.h"
using namespace NS_MICRO_THREAD;
/**
* @brief
*/
CTimerMng::CTimerMng(uint32_t max_item)
{
#define TIMER_MIN 100000
if (max_item < TIMER_MIN)
{
max_item = TIMER_MIN;
}
_heap = new HeapList(max_item);
}
/**
* @brief
*/
CTimerMng::~CTimerMng()
{
if (_heap) {
delete _heap;
_heap = NULL;
}
}
/**
* @brief
* @param timerable
* @param interval ms
* @return true,
*/
bool CTimerMng::start_timer(CTimerNotify* timerable, uint32_t interval)
{
if (!_heap || !timerable) {
return false;
}
utime64_t now_ms = MtFrame::Instance()->GetLastClock();
timerable->set_expired_time(now_ms + interval);
int32_t ret = _heap->HeapPush(timerable);
if (ret < 0) {
MTLOG_ERROR("timer start failed(%p), ret(%d)", timerable, ret);
return false;
}
return true;
}
/**
* @brief
* @param timerable
*/
void CTimerMng::stop_timer(CTimerNotify* timerable)
{
if (!_heap || !timerable) {
return;
}
_heap->HeapDelete(timerable);
return;
}
/**
* @brief
*/
void CTimerMng::check_expired()
{
if (!_heap) {
return;
}
utime64_t now = MtFrame::Instance()->GetLastClock();
CTimerNotify* timer = dynamic_cast<CTimerNotify*>(_heap->HeapTop());
while (timer && (timer->get_expired_time() <= now))
{
_heap->HeapDelete(timer);
timer->timer_notify();
timer = dynamic_cast<CTimerNotify*>(_heap->HeapTop());
}
};

View File

@ -0,0 +1,131 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file heap_timer.h
*/
#ifndef _MICRO_THREAD_TIMER_H_
#define _MICRO_THREAD_TIMER_H_
#include <stdint.h>
#include "heap.h"
namespace NS_MICRO_THREAD
{
/**
* @brief
*/
class CTimerNotify : public HeapEntry
{
public:
/**
* @brief ,
*/
virtual void timer_notify() { return;};
/**
* @brief , , ,
* @return
*/
virtual unsigned long long HeapValue() {
return (unsigned long long)_time_expired;
};
/**
* @brief
*/
CTimerNotify() : _time_expired(0) {};
/**
* @brief
*/
virtual ~CTimerNotify(){};
/**
* @brief , ms
* @param expired ms
*/
void set_expired_time(uint64_t expired) {
_time_expired = expired;
};
/**
* @brief , ms
* @return ms
*/
uint64_t get_expired_time() {
return _time_expired;
};
private:
uint64_t _time_expired; // 绝对的超时时间ms单位
};
/**
* @brief
*/
class CTimerMng
{
public:
/**
* @brief
* @param max_item ()
*/
explicit CTimerMng(uint32_t max_item = 100000);
/**
* @brief
*/
~CTimerMng();
/**
* @brief
* @param timerable
* @param interval ms
* @return true,
*/
bool start_timer(CTimerNotify* timerable, uint32_t interval);
/**
* @brief
* @param timerable
*/
void stop_timer(CTimerNotify* timerable);
/**
* @brief
*/
void check_expired();
private:
HeapList* _heap; // 最小堆指针
};
}
#endif

View File

@ -0,0 +1,561 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename kqueue_proxy.cpp
* @info kqueue for micro thread manage
*/
#include "kqueue_proxy.h"
#include "micro_thread.h"
#include "ff_hook.h"
using namespace NS_MICRO_THREAD;
KqueueProxy::KqueueProxy()
{
_maxfd = KqueueProxy::DEFAULT_MAX_FD_NUM;
_kqfd = -1;
_evtlist = NULL;
_kqrefs = NULL;
}
int KqueueProxy::InitKqueue(int max_num)
{
int rc = 0;
if (max_num > _maxfd)
{
_maxfd = max_num;
}
_kqfd = ff_kqueue();
if (_kqfd < 0)
{
rc = -1;
goto EXIT_LABEL;
}
ff_fcntl(_kqfd, F_SETFD, FD_CLOEXEC);
_kqrefs = new KqFdRef[_maxfd];
if (_kqrefs == NULL)
{
rc = -2;
goto EXIT_LABEL;
}
_evtlist = (KqEvent*)calloc(_maxfd, sizeof(KqEvent));
if (_evtlist == NULL)
{
rc = -3;
goto EXIT_LABEL;
}
struct rlimit rlim;
memset(&rlim, 0, sizeof(rlim));
if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
{
if ((int)rlim.rlim_max < _maxfd)
{
rlim.rlim_cur = rlim.rlim_max;
setrlimit(RLIMIT_NOFILE, &rlim);
rlim.rlim_cur = _maxfd;
rlim.rlim_max = _maxfd;
setrlimit(RLIMIT_NOFILE, &rlim);
}
}
EXIT_LABEL:
if (rc < 0)
{
TermKqueue();
}
return rc;
}
void KqueueProxy::TermKqueue()
{
if (_kqfd > 0)
{
close(_kqfd);
_kqfd = -1;
}
if (_evtlist != NULL)
{
free(_evtlist);
_evtlist = NULL;
}
if (_kqrefs != NULL)
{
delete []_kqrefs;
_kqrefs = NULL;
}
}
bool KqueueProxy::KqueueAdd(KqObjList& obj_list)
{
bool ret = true;
KqueuerObj *kqobj = NULL;
KqueuerObj *kqobj_error = NULL;
TAILQ_FOREACH(kqobj, &obj_list, _entry)
{
if (!KqueueAddObj(kqobj))
{
MTLOG_ERROR("kqobj add failed, fd: %d", kqobj->GetOsfd());
kqueue_assert(0);
kqobj_error = kqobj;
ret = false;
goto EXIT_LABEL;
}
}
EXIT_LABEL:
if (!ret)
{
TAILQ_FOREACH(kqobj, &obj_list, _entry)
{
if (kqobj == kqobj_error)
{
break;
}
KqueueDelObj(kqobj);
}
}
return ret;
}
bool KqueueProxy::KqueueDel(KqObjList& obj_list)
{
bool ret = true;
KqueuerObj *kqobj = NULL;
TAILQ_FOREACH(kqobj, &obj_list, _entry)
{
if (!KqueueDelObj(kqobj)) // failed also need continue, be sure ref count ok
{
MTLOG_ERROR("epobj del failed, fd: %d", kqobj->GetOsfd());
kqueue_assert(0);
ret = false;
}
}
return ret;
}
bool KqueueProxy::KqueueCtrlAdd(int fd, int events)
{
KqFdRef* item = KqFdRefGet(fd);
if (item == NULL)
{
MT_ATTR_API(320851, 1); // fd error, wtf?
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", fd);
kqueue_assert(0);
return false;
}
item->AttachEvents(events);
int old_events = item->GetListenEvents();
int new_events = old_events | events;
if (old_events == new_events)
{
return true;
}
KqEvent ke;
int ret;
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
}
if (old_events & KQ_EVENT_WRITE) {
EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
if (ret == -1) {
// TODO, error check
item->DetachEvents(events);
kqueue_assert(0);
return false;
}
}
if (old_events & KQ_EVENT_READ) {
EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
if (ret == -1) {
// TODO, error check
item->DetachEvents(events);
kqueue_assert(0);
return false;
}
}
if (events & KQ_EVENT_WRITE) {
EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
if (ret == -1) {
// TODO, error check
item->DetachEvents(events);
kqueue_assert(0);
return false;
}
}
if (events & KQ_EVENT_READ) {
EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
if (ret == -1) {
// TODO, error check
item->DetachEvents(events);
kqueue_assert(0);
return false;
}
}
item->SetListenEvents(new_events);
return true;
}
bool KqueueProxy::KqueueCtrlDel(int fd, int events)
{
return KqueueCtrlDelRef(fd, events, false);
}
bool KqueueProxy::KqueueCtrlDelRef(int fd, int events, bool use_ref)
{
KqFdRef* item = KqFdRefGet(fd);
if (item == NULL)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", fd);
kqueue_assert(0);
return false;
}
item->DetachEvents(events);
int old_events = item->GetListenEvents();
int new_events = old_events &~ events;
if (use_ref) {
new_events = old_events;
if (item->ReadRefCnt() == 0) {
new_events = new_events & ~KQ_EVENT_READ;
}
if (item->WriteRefCnt() == 0) {
new_events = new_events & ~KQ_EVENT_WRITE;
}
}
if (old_events == new_events)
{
return true;
}
KqEvent ke;
int ret;
if (CHK_FD_BIT(fd)) {
fd = CLR_FD_BIT(fd);
}
if (old_events & KQ_EVENT_WRITE) {
EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
if (ret == -1) {
kqueue_assert(0);
return false;
}
}
if (old_events & KQ_EVENT_READ) {
EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
if (ret == -1) {
kqueue_assert(0);
return false;
}
}
if (new_events & KQ_EVENT_WRITE) {
EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
if (ret == -1) {
kqueue_assert(0);
return false;
}
}
if (new_events & KQ_EVENT_READ) {
EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
if (ret == -1) {
kqueue_assert(0);
return false;
}
}
item->SetListenEvents(new_events);
return true;
}
bool KqueueProxy::KqueueAddObj(KqueuerObj* obj)
{
if (obj == NULL)
{
MTLOG_ERROR("kqobj input invalid, %p", obj);
return false;
}
KqFdRef* item = KqFdRefGet(obj->GetOsfd());
if (item == NULL)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", obj->GetOsfd());
kqueue_assert(0);
return false;
}
int ret = obj->KqueueCtlAdd(item);
if (ret < 0) {
MTLOG_ERROR("kqueue ctrl callback failed, fd: %d, obj: %p", obj->GetOsfd(), obj);
kqueue_assert(0);
return false;
}
return true;
}
bool KqueueProxy::KqueueDelObj(KqueuerObj* obj)
{
if (obj == NULL)
{
MTLOG_ERROR("kqobj input invalid, %p", obj);
return false;
}
KqFdRef* item = KqFdRefGet(obj->GetOsfd());
if (item == NULL)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", obj->GetOsfd());
kqueue_assert(0);
return false;
}
int ret = obj->KqueueCtlDel(item);
if (ret < 0) {
MTLOG_ERROR("kqueue ctrl callback failed, fd: %d, obj: %p", obj->GetOsfd(), obj);
kqueue_assert(0);
return false;
}
return true;
}
void KqueueProxy::KqueueRcvEventList(int evtfdnum)
{
int ret = 0;
int osfd = 0;
int revents = 0;
int tmp_evts = 0;
KqFdRef* item = NULL;
KqueuerObj* obj = NULL;
for (int i = 0; i < evtfdnum; i++)
{
osfd = _evtlist[i].ident |= 1 << FF_FD_BITS;
item = KqFdRefGet(osfd);
if (item == NULL)
{
MT_ATTR_API(320851, 1); // fd error
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", osfd);
kqueue_assert(0);
continue;
}
tmp_evts = _evtlist[i].filter;
if (tmp_evts == EVFILT_READ) {
revents |= KQ_EVENT_READ;
}
if (tmp_evts == EVFILT_WRITE) {
revents |= KQ_EVENT_WRITE;
}
obj = item->GetNotifyObj();
if (obj == NULL)
{
MTLOG_ERROR("fd notify obj null, failed, fd: %d", osfd);
KqueueCtrlDel(osfd, (revents & (KQ_EVENT_READ | KQ_EVENT_WRITE)));
continue;
}
obj->SetRcvEvents(revents);
if (tmp_evts == EV_ERROR)
{
obj->HangupNotify();
continue;
}
if (revents & KQ_EVENT_READ)
{
ret = obj->InputNotify();
if (ret != 0)
{
continue;
}
}
if (revents & KQ_EVENT_WRITE)
{
ret = obj->OutputNotify();
if (ret != 0)
{
continue;
}
}
}
}
void KqueueProxy::KqueueDispatch()
{
int nfd;
int wait_time = KqueueGetTimeout();
if (wait_time) {
struct timespec ts;
ts.tv_sec = wait_time / 1000;
ts.tv_nsec = 0;
nfd = ff_kevent(_kqfd, NULL, 0, _evtlist, _maxfd, &ts);
} else {
nfd = ff_kevent(_kqfd, NULL, 0, _evtlist, _maxfd, NULL);
}
if (nfd <= 0)
{
return;
}
KqueueRcvEventList(nfd);
}
int KqueuerObj::InputNotify()
{
MicroThread* thread = this->GetOwnerThread();
if (thread == NULL)
{
kqueue_assert(0);
MTLOG_ERROR("kqueue fd obj, no thread ptr, wrong");
return -1;
}
if (thread->HasFlag(MicroThread::IO_LIST))
{
MtFrame* frame = MtFrame::Instance();
frame->RemoveIoWait(thread);
frame->InsertRunable(thread);
}
return 0;
}
int KqueuerObj::OutputNotify()
{
MicroThread* thread = this->GetOwnerThread();
if (NULL == thread)
{
kqueue_assert(0);
MTLOG_ERROR("kqueue fd obj, no thread ptr, wrong");
return -1;
}
// 多个事件同时到达, 防重复操作
if (thread->HasFlag(MicroThread::IO_LIST))
{
MtFrame* frame = MtFrame::Instance();
frame->RemoveIoWait(thread);
frame->InsertRunable(thread);
}
return 0;
}
int KqueuerObj::HangupNotify()
{
MtFrame* frame = MtFrame::Instance();
frame->KqueueCtrlDel(this->GetOsfd(), this->GetEvents());
return 0;
}
int KqueuerObj::KqueueCtlAdd(void* args)
{
MtFrame* frame = MtFrame::Instance();
KqFdRef* fd_ref = (KqFdRef*)args;
kqueue_assert(fd_ref != NULL);
int osfd = this->GetOsfd();
int new_events = this->GetEvents();
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
KqueuerObj* old_obj = fd_ref->GetNotifyObj();
if ((old_obj != NULL) && (old_obj != this))
{
MTLOG_ERROR("kqfd ref conflict, fd: %d, old: %p, now: %p", osfd, old_obj, this);
return -1;
}
fd_ref->SetNotifyObj(this);
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
if (!frame->KqueueCtrlAdd(osfd, new_events))
{
MTLOG_ERROR("kqfd ref add failed, log");
fd_ref->SetNotifyObj(old_obj);
return -2;
}
return 0;
}
int KqueuerObj::KqueueCtlDel(void* args)
{
MtFrame* frame = MtFrame::Instance();
KqFdRef* fd_ref = (KqFdRef*)args;
kqueue_assert(fd_ref != NULL);
int osfd = this->GetOsfd();
int events = this->GetEvents();
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
KqueuerObj* old_obj = fd_ref->GetNotifyObj();
if (old_obj != this)
{
MTLOG_ERROR("kqfd ref conflict, fd: %d, old: %p, now: %p", osfd, old_obj, this);
return -1;
}
fd_ref->SetNotifyObj(NULL);
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
if (!frame->KqueueCtrlDelRef(osfd, events, false)) // 引用有风险, 弊大于利, 关闭掉
{
MTLOG_ERROR("kqfd ref del failed, log");
fd_ref->SetNotifyObj(old_obj);
return -2;
}
return 0;
}

View File

@ -0,0 +1,320 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename kqueue.h
* @info kqueue for micro thread manage
*/
#ifndef _KQUEUE_PROXY___
#define _KQUEUE_PROXY___
#include <stdlib.h>
#include <unistd.h>
#include <sys/queue.h>
#include "ff_api.h"
#include <set>
#include <vector>
using std::set;
using std::vector;
#define kqueue_assert(statement)
//#define kqueue_assert(statement) assert(statement)
namespace NS_MICRO_THREAD {
#define KQ_EVENT_NONE 0
#define KQ_EVENT_READ 1
#define KQ_EVENT_WRITE 2
/******************************************************************************/
/* 操作系统头文件适配定义 */
/******************************************************************************/
/**
* @brief add more detail for linux <sys/queue.h>, freebsd and University of California
* @info queue.h version 8.3 (suse) diff version 8.5 (tlinux)
*/
#ifndef TAILQ_CONCAT
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_CONCAT(head1, head2, field) \
do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
} \
} while (0)
#endif
#ifndef TAILQ_FOREACH_SAFE // tlinux no this define
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#endif
/******************************************************************************/
/* Kqueue proxy 定义与实现部分 */
/******************************************************************************/
class KqueueProxy;
class MicroThread;
/**
* @brief kqueue
*/
class KqueuerObj
{
protected:
int _fd;
int _events;
int _revents;
int _type;
MicroThread* _thread;
public:
TAILQ_ENTRY(KqueuerObj) _entry;
explicit KqueuerObj(int fd = -1) {
_fd = fd;
_events = 0;
_revents = 0;
_type = 0;
_thread = NULL;
};
virtual ~KqueuerObj(){};
virtual int InputNotify();
virtual int OutputNotify();
virtual int HangupNotify();
virtual int KqueueCtlAdd(void* args);
virtual int KqueueCtlDel(void* args);
/**
* @brief fd
*/
void EnableInput() { _events |= KQ_EVENT_READ; };
/**
* @brief fd
*/
void EnableOutput() { _events |= KQ_EVENT_WRITE; };
/**
* @brief fd
*/
void DisableInput() { _events &= ~KQ_EVENT_READ; };
/**
* @brief fd
*/
void DisableOutput() { _events &= ~KQ_EVENT_WRITE; };
/**
* @brief socket
*/
int GetOsfd() { return _fd; };
void SetOsfd(int fd) { _fd = fd; };
/**
* @brief 访
*/
int GetEvents() { return _events; };
void SetRcvEvents(int revents) { _revents = revents; };
int GetRcvEvents() { return _revents; };
/**
* @brief ,
*/
int GetNtfyType() { return _type; };
virtual void Reset() {
_fd = -1;
_events = 0;
_revents = 0;
_type = 0;
_thread = NULL;
};
/**
* @brief 线
* @param thread 线
*/
void SetOwnerThread(MicroThread* thread) { _thread = thread; };
MicroThread* GetOwnerThread() { return _thread; };
};
typedef TAILQ_HEAD(__KqFdList, KqueuerObj) KqObjList; ///< 高效的双链管理
typedef struct kevent KqEvent; ///< 重定义一下kqueue event
/**
* @brief EPOLLFD线, ,
* @info , , , 20150623
*/
class KqFdRef
{
private:
int _wr_ref; ///< 监听写的引用计数
int _rd_ref; ///< 监听读的引用计数
int _events; ///< 当前正在侦听的事件列表
int _revents; ///< 当前该fd收到的事件信息, 仅在epoll_wait后处理中有效
KqueuerObj* _kqobj; ///< 单独注册调度器对象一个fd关联一个对象
public:
/**
* @brief
*/
KqFdRef() {
_wr_ref = 0;
_rd_ref = 0;
_events = 0;
_revents = 0;
_kqobj = NULL;
};
~KqFdRef(){};
/**
* @brief
*/
void SetListenEvents(int events) {
_events = events;
};
int GetListenEvents() {
return _events;
};
/**
* @brief
*/
void SetNotifyObj(KqueuerObj* ntfy) {
_kqobj = ntfy;
};
KqueuerObj* GetNotifyObj() {
return _kqobj;
};
/**
* @brief
*/
void AttachEvents(int event) {
if (event & KQ_EVENT_READ) {
_rd_ref++;
}
if (event & KQ_EVENT_WRITE){
_wr_ref++;
}
};
void DetachEvents(int event) {
if (event & KQ_EVENT_READ) {
if (_rd_ref > 0) {
_rd_ref--;
} else {
_rd_ref = 0;
}
}
if (event & KQ_EVENT_WRITE){
if (_wr_ref > 0) {
_wr_ref--;
} else {
_wr_ref = 0;
}
}
};
/**
* @brief
*/
int ReadRefCnt() { return _rd_ref; };
int WriteRefCnt() { return _wr_ref; };
};
class KqueueProxy
{
public:
static const int DEFAULT_MAX_FD_NUM = 100000;
private:
int _kqfd;
int _maxfd;
KqEvent* _evtlist;
KqFdRef* _kqrefs;
public:
KqueueProxy();
virtual ~KqueueProxy(){};
int InitKqueue(int max_num);
void TermKqueue(void);
virtual int KqueueGetTimeout(void) { return 0; };
virtual bool KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout) { return false; };
bool KqueueAdd(KqObjList& fdset);
bool KqueueDel(KqObjList& fdset);
void KqueueDispatch(void);
bool KqueueAddObj(KqueuerObj* obj);
bool KqueueDelObj(KqueuerObj* obj);
bool KqueueCtrlAdd(int fd, int new_events);
bool KqueueCtrlDel(int fd, int new_events);
bool KqueueCtrlDelRef(int fd, int new_events, bool use_ref);
KqFdRef* KqFdRefGet(int fd) {
return ((fd >= _maxfd) || (fd < 0)) ? (KqFdRef*)NULL : &_kqrefs[fd];
}
void KqueueNtfyReg(int fd, KqueuerObj* obj) {
KqFdRef* ref = KqFdRefGet(fd);
if (ref) {
ref->SetNotifyObj(obj);
}
};
protected:
void KqueueRcvEventList(int evtfdnum);
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,925 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename micro_thread.h
* @info micro thread manager
*/
#ifndef ___MICRO_THREAD_H__
#define ___MICRO_THREAD_H__
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/queue.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include <set>
#include <vector>
#include <queue>
#include "heap.h"
#include "kqueue_proxy.h"
#include "heap_timer.h"
using std::vector;
using std::set;
using std::queue;
namespace NS_MICRO_THREAD {
#define STACK_PAD_SIZE 128 ///< 栈上下隔离区域的大小
#define MEM_PAGE_SIZE 4096 ///< 内存页默认大小
#define DEFAULT_STACK_SIZE 128*1024 ///< 默认栈大小128K
#define DEFAULT_THREAD_NUM 2000 ///< 默认2000个初始线程
typedef unsigned long long utime64_t; ///< 64位的时间定义
typedef void (*ThreadStart)(void*); ///< 微线程入口函数定义
/**
* @brief 线,
*/
class ScheduleObj
{
public:
/**
* @brief 访
*/
static ScheduleObj* Instance (void);
/**
* @brief ,
*/
utime64_t ScheduleGetTime(void);
/**
* @brief 线
*/
void ScheduleThread(void);
/**
* @brief 线sleep
*/
void ScheduleSleep(void);
/**
* @brief 线pend
*/
void SchedulePend(void);
/**
* @brief 线pend,
*/
void ScheduleUnpend(void* thread);
/**
* @brief 线,
*/
void ScheduleReclaim(void);
/**
* @brief
*/
void ScheduleStartRun(void);
private:
static ScheduleObj* _instance; // 私有句柄
};
/**
* @brief 线
*/
struct MtStack
{
int _stk_size; ///< 栈的大小, 有效使用空间
int _vaddr_size; ///< 申请的buff总大小
char *_vaddr; ///< 申请的内存基地址
void *_esp; ///< 栈的esp寄存器
char *_stk_bottom; ///< 栈最低的地址空间
char *_stk_top; ///< 栈最高的地址空间
void *_private; ///< 线程私有数据
int valgrind_id; ///< valgrind id
};
/**
* @brief 线
*/
class Thread : public HeapEntry
{
public:
/**
* @brief
*/
explicit Thread(int stack_size = 0);
virtual ~Thread(){};
/**
* @brief 线
*/
virtual void Run(void){};
/**
* @brief 线,
*/
bool Initial(void);
/**
* @brief 线,
*/
void Destroy(void);
/**
* @brief 线,
*/
void Reset(void);
/**
* @brief 线,
* @param ms
*/
void sleep(int ms);
/**
* @brief 线, 线
*/
void Wait();
/**
* @brief , ,
*/
void SwitchContext(void);
/**
* @brief ,
*/
void RestoreContext(void);
/**
* @brief
* @return 线
*/
utime64_t GetWakeupTime(void) {
return _wakeup_time;
};
/**
* @brief
* @param waketime 线
*/
void SetWakeupTime(utime64_t waketime) {
_wakeup_time = waketime;
};
/**
* @brief 线
* @param data 线使
*/
void SetPrivate(void *data)
{
_stack->_private = data;
}
/**
* @brief 线
*/
void* GetPrivate()
{
return _stack->_private;
}
/**
* @brief ,,
*/
bool CheckStackHealth(char *esp);
protected:
/**
* @brief 线,
*/
virtual void CleanState(void){};
/**
* @brief
*/
virtual bool InitStack(void);
/**
* @brief
*/
virtual void FreeStack(void);
/**
* @brief ,,
*/
virtual void InitContext(void);
private:
MtStack* _stack; ///< 私有栈指针
jmp_buf _jmpbuf; ///< 上下文jmpbuff
int _stack_size; ///< 栈大小字段
utime64_t _wakeup_time; ///< 睡眠唤醒时间
};
/**
* @brief 线
*/
class MicroThread : public Thread
{
public:
enum ThreadType
{
NORMAL = 0, ///< 默认普通线程, 没有动态申请的栈信息
PRIMORDIAL = 1, ///< 原生线程, main函数开启
DAEMON = 2, ///< 守护线程, 底层IO EPOLL管理与调度触发
SUB_THREAD = 3, ///< 二级线程, 仅执行简单工作
};
enum ThreadFlag
{
NOT_INLIST = 0x0, ///< 无队列状态
FREE_LIST = 0x1, ///< 空闲队列中
IO_LIST = 0x2, ///< IO等待队列中
SLEEP_LIST = 0x4, ///< 主动SLEEP中
RUN_LIST = 0x8, ///< 可运行队列中
PEND_LIST = 0x10, ///< 阻塞队列中
SUB_LIST = 0x20, ///< 二级线程队列中
};
enum ThreadState
{
INITIAL = 0, ///< 初始化状态
RUNABLE = 1, ///< 可运行状态
RUNNING = 2, ///< 正在运行中
SLEEPING = 3, ///< IO等待或SLEEP中
PENDING = 4, ///< 阻塞状态中, 等待子线程OK等
};
typedef TAILQ_ENTRY(MicroThread) ThreadLink; ///< 微线程链接
typedef TAILQ_HEAD(__ThreadSubTailq, MicroThread) SubThreadList; ///< 微线程队列定义
public:
/**
* @brief 线
*/
MicroThread(ThreadType type = NORMAL);
~MicroThread(){};
ThreadLink _entry; ///< 状态队列入口
ThreadLink _sub_entry; ///< 子线程队列入口
/**
* @brief 线,
* @return 线
*/
virtual utime64_t HeapValue() {
return GetWakeupTime();
};
/**
* @brief 线
*/
virtual void Run(void);
/**
* @breif fd
*/
void ClearAllFd(void) {
TAILQ_INIT(&_fdset);
};
void AddFd(KqueuerObj* efpd) {
TAILQ_INSERT_TAIL(&_fdset, efpd, _entry);
};
void AddFdList(KqObjList* fdset) {
TAILQ_CONCAT(&_fdset, fdset, _entry);
};
KqObjList& GetFdSet(void) {
return _fdset;
};
/**
* @breif 线
*/
void SetType(ThreadType type) {
_type = type;
};
ThreadType GetType(void) {
return _type;
};
/**
* @breif 线
*/
bool IsDaemon(void) {
return (DAEMON == _type);
};
bool IsPrimo(void) {
return (PRIMORDIAL == _type);
};
bool IsSubThread(void) {
return (SUB_THREAD == _type);
};
/**
* @brief 线
*/
void SetParent(MicroThread* parent) {
_parent = parent;
};
MicroThread* GetParent() {
return _parent;
};
void WakeupParent();
/**
* @brief 线
*/
void AddSubThread(MicroThread* sub);
void RemoveSubThread(MicroThread* sub);
bool HasNoSubThread();
/**
* @brief 线
*/
void SetState(ThreadState state) {
_state = state;
};
ThreadState GetState(void) {
return _state;
}
/**
* @breif 线
*/
void SetFlag(ThreadFlag flag) {
_flag = (ThreadFlag)(_flag | flag);
};
void UnsetFlag(ThreadFlag flag) {
_flag = (ThreadFlag)(_flag & ~flag);
};
bool HasFlag(ThreadFlag flag) {
return _flag & flag;
};
ThreadFlag GetFlag() {
return _flag;
};
/**
* @breif 线
*/
void SetSartFunc(ThreadStart func, void* args) {
_start = func;
_args = args;
};
void* GetThreadArgs() {
return _args;
}
protected:
/**
* @breif 线
*/
virtual void CleanState(void);
private:
ThreadState _state; ///< 微线程当前状态
ThreadType _type; ///< 微线程类型
ThreadFlag _flag; ///< 微线程标记位
KqObjList _fdset; ///< 微线程关注的socket列表
SubThreadList _sub_list; ///< 二级线程的队列
MicroThread* _parent; ///< 二级线程的父线程
ThreadStart _start; ///< 微线程注册函数
void* _args; ///< 微线程注册参数
};
typedef std::set<MicroThread*> ThreadSet; ///< 微线程set管理结构
typedef std::queue<MicroThread*> ThreadList; ///< 微线程queue管理结构
/**
* @brief 线, ,
*/
class LogAdapter
{
public:
/**
* @brief
*/
LogAdapter(){};
virtual ~LogAdapter(){};
/**
* @brief ,
* @return true , false
*/
virtual bool CheckDebug(){ return true;};
virtual bool CheckTrace(){ return true;};
virtual bool CheckError(){ return true;};
/**
* @brief
*/
virtual void LogDebug(char* fmt, ...){};
virtual void LogTrace(char* fmt, ...){};
virtual void LogError(char* fmt, ...){};
/**
* @brief
*/
virtual void AttrReportAdd(int attr, int iValue){};
virtual void AttrReportSet(int attr, int iValue){};
};
/**
* @brief 线
*/
class ThreadPool
{
public:
static unsigned int default_thread_num; ///< 默认2000微线程待命
static unsigned int default_stack_size; ///< 默认128K栈大小
/**
* @brief 线
*/
static void SetDefaultThreadNum(unsigned int num) {
default_thread_num = num;
};
/**
* @brief 线,
*/
static void SetDefaultStackSize(unsigned int size) {
default_stack_size = (size + MEM_PAGE_SIZE - 1) / MEM_PAGE_SIZE * MEM_PAGE_SIZE;
};
/**
* @brief 线
*/
bool InitialPool(int max_num);
/**
* @brief 线
*/
void DestroyPool (void);
/**
* @brief 线
* @return 线
*/
MicroThread* AllocThread(void);
/**
* @brief 线
* @param thread 线
*/
void FreeThread(MicroThread* thread);
/**
* @brief 线
* @param thread 线
*/
int GetUsedNum(void);
private:
ThreadList _freelist; ///< 空闲待命的微线程队列
int _total_num; ///< 目前总的微线程数目,后续按需控制上限
int _use_num; ///< 当前正在使用的微线程数目
int _max_num; ///< 最大并发限制数, 放置内存过度使用
};
typedef TAILQ_HEAD(__ThreadTailq, MicroThread) ThreadTailq; ///< 微线程队列定义
/**
* @brief 线,
*/
class MtFrame : public KqueueProxy, public ThreadPool
{
private:
static MtFrame* _instance; ///< 单例指针
LogAdapter* _log_adpt; ///< 日志接口
ThreadList _runlist; ///< 可运行queue, 无优先级
ThreadTailq _iolist; ///< 等待队列,可随机脱离队列
ThreadTailq _pend_list; ///< 等待队列,可随机脱离队列
HeapList _sleeplist; ///< 等待超时的堆, 可随机脱离, 且随时获取最小堆首
MicroThread* _daemon; ///< 守护线程, 执行epoll wait, 超时检测
MicroThread* _primo; ///< 原生线程, 使用的是原生堆栈
MicroThread* _curr_thread; ///< 当前运行线程
utime64_t _last_clock; ///< 全局时间戳, 每次idle获取一次
int _waitnum; ///< 等待运行的总线程数, 可调节调度的节奏
CTimerMng* _timer; ///< TCP保活专用的timer定时器
int _realtime; /// < 使用实时时间0, 未设置
public:
friend class ScheduleObj; ///< 调度器对象, 是框架类的门面模式, 友元处理
public:
/**
* @brief 线,
*/
static MtFrame* Instance (void);
/**
* @brief 线IO sendto
* @param fd socket
* @param msg
* @param len
* @param to
* @param tolen
* @param timeout ,
* @return >0 , <0
*/
static int sendto(int fd, const void *msg, int len, int flags, const struct sockaddr *to, int tolen, int timeout);
/**
* @brief 线IO recvfrom
* @param fd socket
* @param buf
* @param len
* @param from
* @param fromlen
* @param timeout ,
* @return >0 , <0
*/
static int recvfrom(int fd, void *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, int timeout);
/**
* @brief 线IO connect
* @param fd socket
* @param addr server
* @param addrlen
* @param timeout ,
* @return >0 , <0
*/
static int connect(int fd, const struct sockaddr *addr, int addrlen, int timeout);
/**
* @brief 线IO accept
* @param fd
* @param addr
* @param addrlen
* @param timeout ,
* @return >=0 acceptsocket, <0
*/
static int accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int timeout);
/**
* @brief 线IO read
* @param fd socket
* @param buf
* @param nbyte
* @param timeout ,
* @return >0 , <0
*/
static ssize_t read(int fd, void *buf, size_t nbyte, int timeout);
/**
* @brief 线IO write
* @param fd socket
* @param buf
* @param nbyte
* @param timeout ,
* @return >0 , <0
*/
static ssize_t write(int fd, const void *buf, size_t nbyte, int timeout);
/**
* @brief 线IO recv
* @param fd socket
* @param buf
* @param len
* @param timeout ,
* @return >0 , <0
*/
static int recv(int fd, void *buf, int len, int flags, int timeout);
/**
* @brief 线IO send
* @param fd socket
* @param buf
* @param nbyte
* @param timeout ,
* @return >0 , <0
*/
static ssize_t send(int fd, const void *buf, size_t nbyte, int flags, int timeout);
/**
* @brief 线sleep, ms
*/
static void sleep(int ms);
/**
* @brief 线,
* @param fd socket
* @param events EPOLLIN or EPOLLOUT
* @param timeout ,
* @return >0 , <0
*/
static int WaitEvents(int fd, int events, int timeout);
/**
* @brief 线
* @param entry 线
* @param args 线
* @return 线, NULL
*/
static MicroThread* CreateThread(ThreadStart entry, void *args, bool runable = true);
/**
* @brief 线, static
* @param args 线
*/
static void DaemonRun(void* args);
static int Loop(void* args);
/**
* @brief 线线
*/
MicroThread *GetRootThread();
/**
* @brief ,
*/
bool InitFrame(LogAdapter* logadpt = NULL, int max_thread_num = 50000);
/**
* @brief HOOKapi
*/
void SetHookFlag();
/**
* @brief
*/
void Destroy (void);
/**
* @brief 线
*/
char* Version(void);
/**
* @brief
*/
utime64_t GetLastClock(void) {
if(_realtime)
{
return GetSystemMS();
}
return _last_clock;
};
/**
* @brief 线
*/
MicroThread* GetActiveThread(void) {
return _curr_thread;
};
/**
* @brief 线, ,
* @return 线
*/
int RunWaitNum(void) {
return _waitnum;
};
/**
* @brief 访
*/
LogAdapter* GetLogAdpt(void) {
return _log_adpt;
};
/**
* @brief
*/
CTimerMng* GetTimerMng(void) {
return _timer;
};
/**
* @brief epoll wait,
*/
virtual int KqueueGetTimeout(void);
/**
* @brief 线, cpu,
* @param fdlist socket
* @param fd fd
* @param timeout ,
* @return true , false
*/
virtual bool KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout);
/**
* @brief 线, 线
* @param timeout ,
*/
void WaitNotify(utime64_t timeout);
/**
* @brief 线, IO,
* @param thread 线
*/
void RemoveIoWait(MicroThread* thread);
/**
* @brief 线, ,
* @param thread 线
*/
void InsertRunable(MicroThread* thread);
/**
* @brief 线, pend
* @param thread 线
*/
void InsertPend(MicroThread* thread);
/**
* @brief 线, PEND
* @param thread 线
*/
void RemovePend(MicroThread* thread);
void SetRealTime(int realtime_)
{
_realtime =realtime_;
}
private:
/**
* @brief 线
*/
MtFrame():_realtime(1){ _curr_thread = NULL; };
/**
* @brief 线线
*/
MicroThread* DaemonThread(void){
return _daemon;
};
/**
* @brief 线
*/
void ThreadSchdule(void);
/**
* @brief
*/
void CheckExpired();
/**
* @brief , 线
*/
void WakeupTimeout(void);
/**
* @brief
*/
void SetLastClock(utime64_t clock) {
_last_clock = clock;
};
/**
* @brief 线
*/
void SetActiveThread(MicroThread* thread) {
_curr_thread = thread;
};
/**
* @brief ,
*/
utime64_t GetSystemMS(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL);
};
/**
* @brief 线, IO
* @param thread 线
*/
void InsertSleep(MicroThread* thread);
/**
* @brief 线, IO
* @param thread 线
*/
void RemoveSleep(MicroThread* thread);
/**
* @brief 线, IO
* @param thread 线
*/
void InsertIoWait(MicroThread* thread);
/**
* @brief 线,
* @param thread 线
*/
void RemoveRunable(MicroThread* thread);
};
/**
* @brief
*/
#define MTLOG_DEBUG(fmt, args...) \
do { \
register NS_MICRO_THREAD::MtFrame *fm = NS_MICRO_THREAD::MtFrame::Instance(); \
if (fm && fm->GetLogAdpt() && fm->GetLogAdpt()->CheckDebug()) \
{ \
fm->GetLogAdpt()->LogDebug((char*)"[%-10s][%-4d][%-10s]"fmt, \
__FILE__, __LINE__, __FUNCTION__, ##args); \
} \
} while (0)
#define MTLOG_TRACE(fmt, args...) \
do { \
register NS_MICRO_THREAD::MtFrame *fm = NS_MICRO_THREAD::MtFrame::Instance(); \
if (fm && fm->GetLogAdpt() && fm->GetLogAdpt()->CheckTrace()) \
{ \
fm->GetLogAdpt()->LogTrace((char*)"[%-10s][%-4d][%-10s]"fmt, \
__FILE__, __LINE__, __FUNCTION__, ##args); \
} \
} while (0)
#define MTLOG_ERROR(fmt, args...) \
do { \
register NS_MICRO_THREAD::MtFrame *fm = NS_MICRO_THREAD::MtFrame::Instance(); \
if (fm && fm->GetLogAdpt() && fm->GetLogAdpt()->CheckError()) \
{ \
fm->GetLogAdpt()->LogError((char*)"[%-10s][%-4d][%-10s]"fmt, \
__FILE__, __LINE__, __FUNCTION__, ##args); \
} \
} while (0)
#define MT_ATTR_API(ATTR, VALUE) \
do { \
register NS_MICRO_THREAD::MtFrame *fm = NS_MICRO_THREAD::MtFrame::Instance(); \
if (fm && fm->GetLogAdpt()) \
{ \
fm->GetLogAdpt()->AttrReportAdd(ATTR, VALUE); \
} \
} while (0)
#define MT_ATTR_API_SET(ATTR, VALUE) \
do { \
register NS_MICRO_THREAD::MtFrame *fm = NS_MICRO_THREAD::MtFrame::Instance(); \
if (fm && fm->GetLogAdpt()) \
{ \
fm->GetLogAdpt()->AttrReportSet(ATTR, VALUE); \
} \
} while (0)
}// NAMESPACE NS_MICRO_THREAD
#endif

View File

@ -0,0 +1,255 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_action.cpp
* @info 线ACTION
* @time 20130924
**/
#include "micro_thread.h"
#include "mt_notify.h"
#include "mt_connection.h"
#include "mt_session.h"
#include "mt_action.h"
using namespace std;
using namespace NS_MICRO_THREAD;
/**
* @brief item
*/
void IMtAction::Init()
{
_flag = MULTI_FLAG_UNDEF;
_proto = MT_UDP;
_conn_type = CONN_TYPE_SHORT;
_errno = ERR_NONE;
_time_cost = 0;
_buff_size = 0;
_msg = NULL;
_conn = NULL;
_ntfy_name = 0;
memset(&_addr, 0, sizeof(_addr));
}
/**
* @brief , item
*/
void IMtAction::Reset()
{
// 长连接, 处理成功才复用, 否则强制关闭
bool force_free = false;
if (_errno != ERR_NONE) {
force_free = true;
}
if (_conn) {
ConnectionMgr::Instance()->FreeConnection(_conn, force_free);
_conn = NULL;
}
}
/**
* @brief , ,
*/
KqueuerObj* IMtAction::GetNtfyObj() {
IMtConnection* conn = GetIConnection();
if (conn) {
return conn->GetNtfyObj();
} else {
return NULL;
}
};
/**
* @brief
*/
int IMtAction::InitConnEnv()
{
MtFrame* mtframe = MtFrame::Instance();
ConnectionMgr* connmgr = ConnectionMgr::Instance();
MsgBuffPool* msgmgr = MsgBuffPool::Instance();
NtfyObjMgr* ntfymgr = NtfyObjMgr::Instance();
SessionMgr* sessionmgr = SessionMgr::Instance();
if (_conn != NULL) {
MTLOG_ERROR("Action init failed, maybe action reused in actionlist, check it!!");
return -100;
}
// 1. 分类获取conn句柄
CONN_OBJ_TYPE conn_obj_type = OBJ_CONN_UNDEF;
NTFY_OBJ_TYPE ntfy_obj_type = NTFY_OBJ_UNDEF;
MULTI_PROTO proto = this->GetProtoType();
MULTI_CONNECT type = this->GetConnType();
if ((MT_UDP == proto) && (CONN_TYPE_SESSION == type)) // UDP session模式
{
conn_obj_type = OBJ_UDP_SESSION;
ntfy_obj_type = NTFY_OBJ_SESSION;
}
else if (MT_UDP == proto) // UDP 其它模式
{
conn_obj_type = OBJ_SHORT_CONN;
ntfy_obj_type = NTFY_OBJ_THREAD;
}
else // TCP 模式
{
conn_obj_type = OBJ_TCP_KEEP;
ntfy_obj_type = NTFY_OBJ_THREAD;
}
_conn = connmgr->GetConnection(conn_obj_type, this->GetMsgDstAddr());
if (!_conn) {
MTLOG_ERROR("Get conn failed, type: %d", conn_obj_type);
return -1;
}
_conn->SetIMtActon(this);
// 2. 获取msg buff句柄
int max_len = this->GetMsgBuffSize();
MtMsgBuf* msg_buff = msgmgr->GetMsgBuf(max_len);
if (!msg_buff) {
MTLOG_ERROR("Maybe no memory, buffsize: %d, get failed", max_len);
return -2;
}
msg_buff->SetBuffType(BUFF_SEND);
_conn->SetMtMsgBuff(msg_buff);
// 3. 获取 ntfy 对象句柄
KqueuerObj* ntfy_obj = ntfymgr->GetNtfyObj(ntfy_obj_type, _ntfy_name);
if (!ntfy_obj) {
MTLOG_ERROR("Maybe no memory, ntfy type: %d, get failed", ntfy_obj_type);
return -3;
}
_conn->SetNtfyObj(ntfy_obj);
// 4. SESSION模型, 建立session
MicroThread* thread = mtframe->GetActiveThread();
ntfy_obj->SetOwnerThread(thread);
this->SetIMsgPtr((IMtMsg*)thread->GetThreadArgs());
if (conn_obj_type == OBJ_UDP_SESSION)
{
this->SetOwnerThread(thread);
this->SetSessionConn(_conn);
this->SetSessionId(sessionmgr->GetSessionId());
sessionmgr->InsertSession(this);
}
return 0;
}
/**
* @brief ,
*/
int IMtAction::DoEncode()
{
MtMsgBuf* msg_buff = NULL;
if (_conn) {
msg_buff = _conn->GetMtMsgBuff();
}
if (!_conn || !msg_buff) {
MTLOG_ERROR("conn(%p) or msgbuff(%p) null", _conn, msg_buff);
return -100;
}
int msg_len = msg_buff->GetMaxLen();
int ret = this->HandleEncode(msg_buff->GetMsgBuff(), msg_len, _msg);
if (ret < 0)
{
MTLOG_DEBUG("handleecode failed, ret %d", ret);
return ret;
}
msg_buff->SetMsgLen(msg_len);
return 0;
}
/**
* @brief ,
*/
int IMtAction::DoInput()
{
MtMsgBuf* msg_buff = NULL;
if (_conn) {
msg_buff = _conn->GetMtMsgBuff();
}
if (!_conn || !msg_buff) {
MTLOG_ERROR("conn(%p) or msgbuff(%p) null", _conn, msg_buff);
return -100;
}
int msg_len = msg_buff->GetHaveRcvLen();
int ret = this->HandleInput(msg_buff->GetMsgBuff(), msg_len, _msg);
if (ret < 0)
{
MTLOG_DEBUG("HandleInput failed, ret %d", ret);
return ret;
}
return ret;
}
int IMtAction::DoProcess()
{
MtMsgBuf* msg_buff = NULL;
if (_conn) {
msg_buff = _conn->GetMtMsgBuff();
}
if (!_conn || !msg_buff) {
MTLOG_ERROR("conn(%p) or msgbuff(%p) null", _conn, msg_buff);
return -100;
}
int ret = this->HandleProcess(msg_buff->GetMsgBuff(), msg_buff->GetMsgLen(), _msg);
if (ret < 0)
{
MTLOG_DEBUG("handleprocess failed, ret %d", ret);
return ret;
}
return 0;
}
int IMtAction::DoError()
{
return this->HandleError((int)_errno, _msg);
}
/**
* @brief
*/
IMtAction::IMtAction()
{
Init();
}
IMtAction::~IMtAction()
{
Reset();
Init();
}

View File

@ -0,0 +1,327 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_action.h
* @info 线ACTION
**/
#ifndef __MT_ACTION_H__
#define __MT_ACTION_H__
#include <netinet/in.h>
#include <queue>
#include "mt_msg.h"
#include "mt_session.h"
#include "mt_notify.h"
namespace NS_MICRO_THREAD {
/**
* @brief
*/
enum MULTI_STATE
{
MULTI_FLAG_UNDEF = 0x0, ///< 初始化, 未启动
MULTI_FLAG_INIT = 0x1, ///< socket创建已成功
MULTI_FLAG_OPEN = 0x2, ///< socket连接已打开
MULTI_FLAG_SEND = 0x4, ///< 请求报文已经发送
MULTI_FLAG_FIN = 0x8, ///< 应答报文已经接收到
};
/**
* @brief
*/
enum MULTI_CONNECT
{
CONN_UNKNOWN = 0,
CONN_TYPE_SHORT = 0x1, ///< 短连接, 一次交互后关闭
CONN_TYPE_LONG = 0x2, ///< 长连接,每次使用后, 可回收重复使用
CONN_TYPE_SESSION = 0x4, ///< 长连接按session id 复用, 防串包
};
/**
* @brief
*/
enum MULTI_ERROR
{
ERR_NONE = 0,
ERR_SOCKET_FAIL = -1, ///< 创建sock失败
ERR_CONNECT_FAIL = -2, ///< 连接失败
ERR_SEND_FAIL = -3, ///< 发送报文失败
ERR_RECV_FAIL = -4, ///< 接收失败
ERR_RECV_TIMEOUT = -5, ///< 接收超时
ERR_KQUEUE_FAIL = -6, ///< epoll失败
ERR_FRAME_ERROR = -7, ///< 框架失败
ERR_PEER_CLOSE = -8, ///< 对方关闭
ERR_PARAM_ERROR = -9, ///< 参数错误
ERR_MEMORY_ERROR = -10, ///< 内存申请失败
ERR_ENCODE_ERROR = -11, ///< 封包失败
ERR_DST_ADDR_ERROR = -12, ///< 目标地址获取失败
};
/**
* @brief 线
*/
class IMtAction : public ISession
{
public:
/**
* @brief 线
*/
IMtAction();
virtual ~IMtAction();
/**
* @brief (, 使inline)
* @param dst -
*/
void SetMsgDstAddr(struct sockaddr_in* dst) {
memcpy(&_addr, dst, sizeof(_addr));
};
/**
* @brief
* @return
*/
struct sockaddr_in* GetMsgDstAddr() {
return &_addr;
};
/**
* @brief buff, 使msgbuff
* @return 0
*/
void SetMsgBuffSize(int buff_size) {
_buff_size = buff_size;
};
/**
* @brief buff
* @return buff
*/
int GetMsgBuffSize() {
return (_buff_size > 0) ? _buff_size : 65535;
}
/**
* @brief sessionid
* @return 0
*/
void SetSessionName(int name) {
_ntfy_name = name;
};
/**
* @brief sessionid
* @return session
*/
int GetSessionName() {
return _ntfy_name;
}
/**
* @brief proto
*/
void SetProtoType(MULTI_PROTO proto) {
_proto = proto;
};
/**
* @brief proto
* @return proto type
*/
MULTI_PROTO GetProtoType() {
return _proto;
};
/**
* @brief
*/
void SetConnType(MULTI_CONNECT type) {
_conn_type = type;
};
/**
* @brief
* @return conn type
*/
MULTI_CONNECT GetConnType() {
return _conn_type;
};
/**
* @brief errno
*/
void SetErrno(MULTI_ERROR err) {
_errno = err;
};
/**
* @brief ERRNO
* @return ERRONO
*/
MULTI_ERROR GetErrno() {
return _errno;
};
/**
* @brief timecost
*/
void SetCost(int cost) {
_time_cost = cost;
};
/**
* @brief timecost
* @return timecost
*/
int GetCost() {
return _time_cost;
};
/**
* @brief
* @param flag -
*/
void SetMsgFlag(MULTI_STATE flag) {
_flag = flag;
};
/**
* @brief
* @return flag -
*/
MULTI_STATE GetMsgFlag() {
return _flag;
};
/**
* @brief
* @return IMtConn
*/
void SetIMsgPtr(IMtMsg* msg ) {
_msg = msg;
};
/**
* @brief
* @return IMtConn
*/
IMtMsg* GetIMsgPtr() {
return _msg;
};
/**
* @brief
* @return IMtConn
*/
void SetIConnection(IMtConnection* conn) {
_conn = conn;
};
/**
* @brief
* @return IMtConn
*/
IMtConnection* GetIConnection() {
return _conn;
};
/**
* @brief
*/
void Init();
/**
* @brief , Action
*/
void Reset();
/**
* @brief , ,
*/
KqueuerObj* GetNtfyObj();
/**
* @brief , ,
*/
int InitConnEnv();
/**
* @brief ,
*/
int DoEncode();
int DoInput();
int DoProcess();
int DoError();
public:
/**
* @brief
* @return >0 -, < 0
*/
virtual int HandleEncode(void* buf, int& len, IMtMsg* msg){return 0;};
/**
* @brief CHECK, TCP
* @return > 0 ,, =0 , <0 (-65535 UDP)
*/
virtual int HandleInput(void* buf, int len, IMtMsg* msg){return 0;};
/**
* @brief ,
* @return 0 ,
*/
virtual int HandleProcess(void* buf, int len, IMtMsg* msg){return 0;};
/**
* @brief , MULTI_ERROR
* @info handleprocess,
* @return 0 ,
*/
virtual int HandleError(int err, IMtMsg* msg){return 0;};
protected:
MULTI_STATE _flag; // 处理结束标记信息, 当前状态信息
MULTI_PROTO _proto; // 协议类型 UDP/TCP
MULTI_CONNECT _conn_type; // 连接类型 长短连接
MULTI_ERROR _errno; // 错误码信息, 0成功其他错误
struct sockaddr_in _addr; // 请求时填写指定发送的stAddr
int _time_cost; // 本次请求应答耗时, 毫秒
int _buff_size; // 本次请求最大请求与应答长度
int _ntfy_name; // 关联的session ntfy的名字, session模型适用
IMtMsg* _msg; // 消息指针, 上级指针
IMtConnection* _conn; // 连接器指针, 下级指针, 管理生存期
};
}
#endif

1329
app/micro_thread/mt_api.cpp Normal file

File diff suppressed because it is too large Load Diff

410
app/micro_thread/mt_api.h Normal file
View File

@ -0,0 +1,410 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename mt_api.h
* @info 线api, 线API
*/
#ifndef __MT_API_H__
#define __MT_API_H__
#include <netinet/in.h>
#include <vector>
using std::vector;
namespace NS_MICRO_THREAD {
/******************************************************************************/
/* 微线程用户接口定义: UDP短连接收发接口 */
/******************************************************************************/
/**
* @brief socket, socket,
* [] UDPbuff, static, []
* @param dst -
* @param pkg -
* @param len -
* @param rcv_buf -buff
* @param buf_size -modify-buff, ,
* @param timeout -, ms
* @return 0 , -1 socket, -2 , -3 , errno
*/
int mt_udpsendrcv(struct sockaddr_in* dst, void* pkg, int len, void* rcv_buf, int& buf_size, int timeout);
/******************************************************************************/
/* 微线程用户接口定义: TCP连接池收发接口 */
/******************************************************************************/
/**
* @brief TCP
* @param buf
* @param len
* @return >0 ; 0 ; <0
*/
typedef int (*MtFuncTcpMsgLen)(void* buf, int len);
/**
* @brief TCPIP/PORT, 10
* [] tcpbuff, static, []
* @param dst -
* @param pkg -
* @param len -
* @param rcv_buf -buff
* @param buf_size -modify-buff, ,
* @param timeout -, ms
* @param check_func -
* @return 0 , -1 socket, -2 , -3 ,
* -4 , -5 , -6 , -7 -10
*/
int mt_tcpsendrcv(struct sockaddr_in* dst, void* pkg, int len, void* rcv_buf, int& buf_size,
int timeout, MtFuncTcpMsgLen chek_func);
enum MT_TCP_CONN_TYPE
{
MT_TCP_SHORT = 1, /// 短连接
MT_TCP_LONG = 2, /// 长连接
MT_TCP_SHORT_SNDONLY = 3, /// 短连接只发
MT_TCP_LONG_SNDONLY = 4, /// 长连接只发
MT_TCP_BUTT
};
/**
* @brief TCP
* [] tcpbuff, static, []
* @param dst -
* @param pkg -
* @param len -
* @param rcv_buf -buffNULL
* @param buf_size -modify-buff, , NULL
* @param timeout -, ms
* @param check_func -
* @param type -
* MT_TCP_SHORT:
* MT_TCP_LONG :
* MT_TCP_LONG_SNDONLY :
* MT_TCP_SHORT_SNDONLY:
* @return 0 , -1 socket, -2 , -3 ,
* -4 , -5 , -6 , -7 , -10
*/
int mt_tcpsendrcv_ex(struct sockaddr_in* dst, void* pkg, int len, void* rcv_buf, int* buf_size,
int timeout, MtFuncTcpMsgLen func, MT_TCP_CONN_TYPE type = MT_TCP_LONG);
/**
* @brief TCP
* @param buf
* @param len
* @param closed
* @param msg_ctx
* mt_tcpsendrcv
* mt_tcpsendrcv使
* buf使
* @param msg_len_detected truefalsefalse
* true>0MtFuncTcpMsgCheckerMtFuncTcpMsgChecker
* @return >0 ; 0 ; <0
*
* 0:
* 1,
* 2bufbufrealloc buf
*
* 0bufrealloc bufbuf
* 0
*/
typedef int (*MtFuncTcpMsgChecker)(void* buf, int len, bool closed, void* msg_ctx, bool &msg_len_detected);
/**
* @brief TCP
* [] tcpbuff, static, []
* @param dst -
* @param pkg -
* @param len -
* @param rcv_buf - keep_rcv_bufmallocvoid* rcv_buf=NULL:
* @param recv_pkg_size -buff0
* @param timeout -, ms
* @param check_func -
* @param msg_ctx -
*
* @param type -
* MT_TCP_SHORT:
* MT_TCP_LONG :
* MT_TCP_LONG_SNDONLY :
* MT_TCP_SHORT_SNDONLY:
* @param keep_rcv_buf -true,rcv_bufbufbuf
* msg_ctxmalloc bufctx
* @return 0 , -1 socket, -2 , -3 ,
* -4 , -5 , -6 , -7 , -10 , -11,buf
*/
int mt_tcpsendrcv_ex(struct sockaddr_in* dst, void* pkg, int len, void*& rcv_buf, int& recv_pkg_size,
int timeout, MtFuncTcpMsgChecker check_func, void* msg_ctx=NULL,
MT_TCP_CONN_TYPE type = MT_TCP_LONG, bool keep_rcv_buf=false);
/**
* @brief TCPIP/PORT, 10
* [] tcpbuff, static, []
* @param dst -
* @param pkg -
* @param len -
* @param rcv_buf - keep_rcv_buf
* @param recv_pkg_size -buff0
* @param timeout -, ms
* @param check_func -
* @param msg_ctx -
* @param keep_rcv_buf -true,rcv_bufbufbuf
* msg_ctxmalloc
* @return 0 , -1 socket, -2 , -3 ,
* -4 , -5 , -6 , -7 , -10
*/
int mt_tcpsendrcv(struct sockaddr_in* dst, void* pkg, int len, void*& rcv_buf, int& recv_pkg_size,
int timeout, MtFuncTcpMsgChecker check_func, void* msg_ctx=NULL, bool keep_rcv_buf=false);
/******************************************************************************/
/* 微线程用户接口定义: 微线程Task多路并发模型接口定义 */
/******************************************************************************/
/**
* @brief 线
*/
class IMtTask
{
public:
/**
* @brief 线
* @return 0 -, < 0
*/
virtual int Process() { return -1; };
/**
* @brief task
* @info Process
*/
void SetResult(int rc)
{
_result = rc;
}
/**
* @brief task
* @info Process
*/
int GetResult(void)
{
return _result;
}
/**
* @brief task
*/
void SetTaskType(int type)
{
_type = type;
}
/**
* @brief task
* @info task使task
* @return task
*/
int GetTaskType(void)
{
return _type;
}
/**
* @brief 线
*/
IMtTask() {};
virtual ~IMtTask() {};
protected:
int _type; // task类型多种类型task业务可以自定义类型方便从基类转换
int _result; // task执行结果即Process返回值
};
typedef vector<IMtTask*> IMtTaskList;
/**
* @brief IO, Task-fork-wait
* @param req_list -task list apitask
* @return 0 , -1 线
*/
int mt_exec_all_task(IMtTaskList& req_list);
/******************************************************************************/
/* 微线程用户接口定义: 微线程封装系统接口 */
/******************************************************************************/
/**
* @brief 线sleep, ms
* @info CPU使
*/
void mt_sleep(int ms);
/**
* @brief 线ms
*/
unsigned long long mt_time_ms(void);
/******************************************************************************/
/* 微线程用户接口定义: 微线程用户私有数据接口 */
/******************************************************************************/
/**
* @brief IMtMsg
* @info
*/
void mt_set_msg_private(void *data);
/**
* @brief IMtMsg
* @return
*/
void* mt_get_msg_private();
/******************************************************************************/
/* 微线程用户接口定义: 微线程封装系统接口(不推荐使用) */
/******************************************************************************/
/**
* @brief 线
* @info 使spp线
* 使sppSyncFrame
* @return false: true:
*/
bool mt_init_frame(const char *conf=NULL, int argc=0, char * const argv[]=NULL);
/**
* @brief 线
* @info 128K
*/
void mt_set_stack_size(unsigned int bytes);
/**
* @brief 线IO recvfrom
* @param fd socket
* @param buf
* @param len
* @param from
* @param fromlen
* @param timeout ,
* @return >0 , <0
*/
int mt_recvfrom(int fd, void *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, int timeout);
/**
* @brief 线IO sendto
* @param fd socket
* @param msg
* @param len
* @param to
* @param tolen
* @param timeout ,
* @return >0 , <0
*/
int mt_sendto(int fd, const void *msg, int len, int flags, const struct sockaddr *to, int tolen, int timeout);
/**
* @brief 线IO connect
* @param fd socket
* @param addr server
* @param addrlen
* @param timeout ,
* @return >0 , <0
*/
int mt_connect(int fd, const struct sockaddr *addr, int addrlen, int timeout);
/**
* @brief 线IO accept
* @param fd
* @param addr
* @param addrlen
* @param timeout ,
* @return >=0 acceptsocket, <0
*/
int mt_accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int timeout);
/**
* @brief 线IO read
* @param fd socket
* @param buf
* @param nbyte
* @param timeout ,
* @return >0 , <0
*/
ssize_t mt_read(int fd, void *buf, size_t nbyte, int timeout);
/**
* @brief 线IO write
* @param fd socket
* @param buf
* @param nbyte
* @param timeout ,
* @return >0 , <0
*/
ssize_t mt_write(int fd, const void *buf, size_t nbyte, int timeout);
/**
* @brief 线IO recv
* @param fd socket
* @param buf
* @param len
* @param timeout ,
* @return >0 , <0
*/
ssize_t mt_recv(int fd, void *buf, int len, int flags, int timeout);
/**
* @brief 线IO send
* @param fd socket
* @param buf
* @param nbyte
* @param timeout ,
* @return >0 , <0
*/
ssize_t mt_send(int fd, const void *buf, size_t nbyte, int flags, int timeout);
/**
* @brief 线epoll
* @param fd socket
* @param events IN/OUT
* @param timeout ,
* @return >0 , <0
*/
int mt_wait_events(int fd, int events, int timeout);
void* mt_start_thread(void* entry, void* args);
}
#endif

View File

@ -0,0 +1,869 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename mt_cache.cpp
* @info TCPbuffer
*/
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include "mt_incl.h"
#include "kqueue_proxy.h"
#include "micro_thread.h"
#include "mt_sys_hook.h"
#include "ff_hook.h"
#include "mt_cache.h"
namespace NS_MICRO_THREAD {
/**
* @brief Buffer
* @param size buff
* @return NULL block,
*/
TSkBuffer* new_sk_buffer(uint32_t size)
{
uint32_t total = sizeof(TSkBuffer) + size;
total = (total + SK_DFLT_ALIGN_SIZE - 1) / SK_DFLT_ALIGN_SIZE * SK_DFLT_ALIGN_SIZE;
TSkBuffer* block = (TSkBuffer*)malloc(total);
if (block == NULL)
{
MTLOG_ERROR("malloc failed, no more memory[%u]", total);
return NULL;
}
block->last_time = 0;
block->size = size;
block->head = block->buff;
block->end = block->buff + size;
block->data = block->head;
block->data_len = 0;
return block;
}
/**
* @brief Buffer
* @param block -buff
*/
void delete_sk_buffer(TSkBuffer* block)
{
if (NULL == block) {
return;
}
free(block);
}
/**
* @brief (buff,)
* @param buff -buff
* @param size -
* @return buff
*/
TSkBuffer* reserve_sk_buffer(TSkBuffer* buff, uint32_t size)
{
if (NULL == buff) {
return new_sk_buffer(size);
}
if (buff->size >= size) {
return buff;
}
TSkBuffer* new_buff = new_sk_buffer(size);
if (NULL == new_buff) {
return buff;
}
memcpy(new_buff->data, buff->data, buff->data_len);
new_buff->data_len = buff->data_len;
delete_sk_buffer(buff);
return new_buff;
}
/**
* @brief cache
* @param mng -
* @param expired -,
* @param size -
*/
void sk_buffer_mng_init(TSkBuffMng* mng, uint32_t expired, uint32_t size)
{
TAILQ_INIT(&mng->free_list);
mng->expired = expired;
mng->count = 0;
mng->size = size;
}
/**
* @brief cache
* @param mng -
*/
void sk_buffer_mng_destroy(TSkBuffMng * mng)
{
TSkBuffer* item = NULL;
TSkBuffer* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &mng->free_list, entry, tmp)
{
TAILQ_REMOVE(&mng->free_list, item, entry);
delete_sk_buffer(item);
}
mng->count = 0;
}
/**
* @brief buff
* @param mng -
* @return NULLbuff
*/
TSkBuffer* alloc_sk_buffer(TSkBuffMng* mng)
{
if (NULL == mng) {
return NULL;
}
TSkBuffer* item = TAILQ_FIRST(&mng->free_list);
if (item != NULL)
{
TAILQ_REMOVE(&mng->free_list, item, entry);
mng->count--;
return item;
}
item = new_sk_buffer(mng->size);
if (NULL == item)
{
return NULL;
}
return item;
}
/**
* @brief buff
* @param mng -
* @param buff -buff
*/
void free_sk_buffer(TSkBuffMng* mng, TSkBuffer* buff)
{
if ((NULL == mng) || (NULL == buff)) {
return;
}
TAILQ_INSERT_TAIL(&mng->free_list, buff, entry);
mng->count++;
buff->last_time = (uint32_t)(mt_time_ms() / 1000);
buff->data = buff->head;
buff->data_len = 0;
}
/**
* @brief buff
* @param mng -
* @param now -,
*/
void recycle_sk_buffer(TSkBuffMng* mng, uint32_t now)
{
TSkBuffer* item = NULL;
TSkBuffer* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &mng->free_list, entry, tmp)
{
if ((now - item->last_time) < mng->expired)
{
break;
}
TAILQ_REMOVE(&mng->free_list, item, entry);
delete_sk_buffer(item);
mng->count--;
}
}
/**
* @brief Cache
* @param cache -
* @param pool -buff
*/
void rw_cache_init(TRWCache* cache, TSkBuffMng* pool)
{
TAILQ_INIT(&cache->list);
cache->len = 0;
cache->count = 0;
cache->pool = pool;
}
/**
* @brief Cache
* @param cache -
*/
void rw_cache_destroy(TRWCache* cache)
{
if ((cache == NULL) || (cache->pool == NULL)) {
return;
}
TSkBuffer* item = NULL;
TSkBuffer* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
{
TAILQ_REMOVE(&cache->list, item, entry);
free_sk_buffer(cache->pool, item);
}
cache->count = 0;
cache->len = 0;
cache->pool = NULL;
}
/**
* @brief Cache
* @param cache -
* @param buff -buff
* @param len -
* @return
*/
uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len)
{
if ((cache == NULL) || (cache->pool == NULL)) {
return 0;
}
char* out_buff = (char*)buff;
uint32_t left = len, skip_len = 0;
TSkBuffer* item = NULL;
TSkBuffer* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
{
// 1. 确认拷贝数据大小
skip_len = (item->data_len > left) ? left : item->data_len;
if (out_buff != NULL)
{
memcpy(out_buff, item->data, skip_len);
out_buff += skip_len;
}
left -= skip_len;
item->data_len -= skip_len;
item->data += skip_len;
if (item->data_len > 0)
{
break;
}
// 2. 移除一个block
if (cache->count > 0) {
cache->count--;
}
TAILQ_REMOVE(&cache->list, item, entry);
free_sk_buffer(cache->pool, item);
// 3. 循环变量控制
if (left == 0)
{
break;
}
}
// 整体考虑数据长度问题, 是否有足够的数据移除
skip_len = len - left;
if (cache->len > skip_len)
{
cache->len -= skip_len;
}
else
{
cache->len = 0;
}
return skip_len;
}
/**
* @brief Cache
* @param cache -
* @param len -
*/
void cache_skip_data(TRWCache* cache, uint32_t len)
{
cache_copy_out(cache, NULL, len);
}
/**
* @brief Cache
* @param cache -
* @param buff -
*/
void cache_append_buffer(TRWCache* cache, TSkBuffer* buff)
{
if ((NULL == cache) || (NULL == buff))
{
return;
}
TAILQ_INSERT_TAIL(&cache->list, buff, entry);
cache->len += buff->data_len;
cache->count++;
}
/**
* @brief Cache, free
* @param cache -
*/
TSkBuffer* cache_skip_first_buffer(TRWCache* cache)
{
TSkBuffer* buff = TAILQ_FIRST(&cache->list);
if ((NULL == cache) || (NULL == buff))
{
return NULL;
}
TAILQ_REMOVE(&cache->list, buff, entry);
if (cache->len >= buff->data_len)
{
cache->len -= buff->data_len;
}
if (cache->count > 0)
{
cache->count--;
}
return buff;
}
/**
* @brief Cache
* @param cache -
* @param data -
* @param len -
*/
int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len)
{
if ((NULL == data) || (NULL == cache) || (NULL == cache->pool))
{
return -1;
}
if (len == 0)
{
return 0;
}
uint32_t left = len;
uint32_t remain = 0;
// 1. 尾空间先进行append, 因为需要回滚, 前一部分先不拷贝
TSkBuffer* tail = TAILQ_LAST(&cache->list, __sk_buff_list);
if (tail != NULL)
{
if (tail->end > (tail->data + tail->data_len))
{
remain = tail->end - tail->data - tail->data_len;
}
if (remain >= len)
{
memcpy(tail->data + tail->data_len, data, len);
tail->data_len += len;
cache->len += len;
return (int32_t)len;
}
}
// 2. 有剩余buff待处理, 先申请剩余的buff, 在修改尾节点
TRWCache keep_list;
rw_cache_init(&keep_list, cache->pool);
left -= remain;
while (left > 0)
{
TSkBuffer* item = alloc_sk_buffer(cache->pool);
if (item == NULL)
{
rw_cache_destroy(&keep_list);
return -2;
}
cache_append_buffer(&keep_list, item);
if (left <= item->size)
{
memcpy(item->head, (char*)data + len - left, left);
item->data_len = left;
break;
}
memcpy(item->head, (char*)data + len - left, item->size);
item->data_len = item->size;
left -= item->size;
}
// 3. 尝试拷贝最初的buff, 这里不会回滚了
if ((tail != NULL) && (remain > 0))
{
memcpy(tail->data + tail->data_len, data, remain);
tail->data_len += remain;
}
cache->len += len;
cache->count += keep_list.count;
TAILQ_CONCAT(&cache->list, &keep_list.list, entry);
return (int32_t)len;
}
/**
* @brief CacheUDP, , 32使
* @param cache -
* @param fd - fd
* @param remote_addr -ip
* @return
*/
int32_t cache_udp_recv(TRWCache* cache, uint32_t fd, struct sockaddr_in* remote_addr)
{
if (NULL == cache)
{
return -1;
}
int32_t total = 0;
for (uint32_t i = 0; i < 100; i++)
{
TSkBuffer* item = alloc_sk_buffer(cache->pool);
if (NULL == item)
{
return -2;
}
socklen_t addr_len = sizeof(*remote_addr);
mt_hook_syscall(recvfrom);
int32_t rc = ff_hook_recvfrom(fd, item->data, item->size, 0, (struct sockaddr*)remote_addr, &addr_len);
if (rc <= 0)
{
free_sk_buffer(cache->pool, item);
if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
{
break;
}
else
{
MTLOG_ERROR("recvfrom failed, fd[%d] ret %d[%m]", fd, rc);
return -3;
}
}
item->data_len += rc;
cache_append_buffer(cache, item);
total += rc;
}
return total;
}
/**
* @brief CacheTCP
* @param cache -
* @param fd - fd
* @return
*/
int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd)
{
if (NULL == cache)
{
return -1;
}
int32_t total = 0;
for (uint32_t i = 0; i < 100; i++)
{
// 1. 每次检查尾空间, 空间满或初始状态, 申请新空间
TSkBuffer* item = TAILQ_LAST(&cache->list, __sk_buff_list);
if ((NULL == item)
|| ((item->data_len + item->data) >= item->end))
{
item = alloc_sk_buffer(cache->pool);
if (item == NULL)
{
return -2;
}
cache_append_buffer(cache, item);
}
// 2. 单次最多接收size大小, 默认64K
uint8_t* buff = item->data + item->data_len;
uint32_t remain = item->end - item->data - item->data_len;
mt_hook_syscall(recv);
int32_t recvd_len = ff_hook_recv(fd, buff, remain, 0);
if (recvd_len == 0)
{
MTLOG_DEBUG("remote close, socket: %d", fd);
return -SK_ERR_NEED_CLOSE;
}
else if (recvd_len < 0)
{
if (errno == EAGAIN)
{
return total;
}
else
{
MTLOG_ERROR("recv tcp socket failed, error: %d[%m]", errno);
return -2;
}
}
else
{
item->data_len += recvd_len;
cache->len += recvd_len;
total += recvd_len;
if (recvd_len < (int32_t)remain) // 收不满, 可认为本次OK
{
return total;
}
}
}
return total;
}
/**
* @brief CacheTCP
* @param cache -
* @param fd - fd
* @return
*/
int32_t cache_tcp_send(TRWCache* cache, uint32_t fd)
{
if ((NULL == cache) || (NULL == cache->pool))
{
return -1;
}
if (cache->len == 0)
{
return 0;
}
int32_t ret = 0, total = 0;
TSkBuffer* item = NULL;
TSkBuffer* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
{
mt_hook_syscall(send);
ret = ff_hook_send(fd, item->data, item->data_len, 0);
if (ret < 0)
{
break;
}
total += ret;
if (ret < (int32_t)item->data_len)
{
break;
}
}
cache_skip_data(cache, total);
if (ret < 0)
{
if (errno != EAGAIN)
{
MTLOG_ERROR("tcp socket send failed, error: %d[%m]", errno);
return -2;
}
}
return total;
}
/**
* @brief CacheTCP, 使IOVEC
* @param cache -
* @param fd - fd
* @param data -cache, buff
* @param len -buff
* @return
*/
int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint32_t len)
{
if ((NULL == cache) || (NULL == data))
{
return -1;
}
// 1. 优先发送CACHE数据
int32_t ret = cache_tcp_send(cache, fd);
if (ret < 0)
{
MTLOG_ERROR("tcp socket[%d] send cache data failed, rc: %d", fd, ret);
return ret;
}
// 2. CACHE已经无数据
int32_t send_len = 0;
if (cache->len == 0)
{
mt_hook_syscall(send);
ret = ff_hook_send(fd, data, len, 0);
if (ret >= 0)
{
send_len += ret;
}
else
{
if (errno != EAGAIN)
{
MTLOG_ERROR("tcp socket[%d] send failed, error: %d[%m]", fd, errno);
return -2;
}
}
}
int32_t rc = cache_append_data(cache, (char*)data + send_len, len - send_len);
if (rc < 0)
{
MTLOG_ERROR("tcp socket[%d] apend data failed, rc: %d", fd, rc);
return -3;
}
return send_len;
}
/**
* @brief cache
* @param multi -
* @return
*/
uint32_t get_data_len(TBuffVecPtr multi)
{
TRWCache* cache = (TRWCache*)multi;
if (NULL == cache) {
return 0;
} else {
return cache->len;
}
}
/**
* @brief cache
* @param multi -
* @return
*/
uint32_t get_block_count(TBuffVecPtr multi)
{
TRWCache* cache = (TRWCache*)multi;
if (NULL == cache) {
return 0;
} else {
return cache->count;
}
}
/**
* @brief cache
* @param multi -
* @return
*/
TBuffBlockPtr get_first_block(TBuffVecPtr multi)
{
TRWCache* cache = (TRWCache*)multi;
if (NULL == cache) {
return NULL;
} else {
return (TBuffBlockPtr)TAILQ_FIRST(&cache->list);
}
}
/**
* @brief cache
* @param multi -
* @param block -
* @return
*/
TBuffBlockPtr get_next_block(TBuffVecPtr multi, TBuffBlockPtr block)
{
TRWCache* cache = (TRWCache*)multi;
TSkBuffer* item = (TSkBuffer*)block;
if ((NULL == cache) || (NULL == item))
{
return NULL;
}
return (TBuffBlockPtr)TAILQ_NEXT(item, entry);
}
/**
* @brief
* @param block -
* @param data --modify
* @param len - modify
*/
void get_block_data(TBuffBlockPtr block, const void** data, int32_t* len)
{
TSkBuffer* item = (TSkBuffer*)block;
if (NULL == block)
{
return;
}
if (data != NULL)
{
*(uint8_t**)data = item->data;
}
if (len != NULL)
{
*len = (int32_t)item->data_len;
}
}
/**
* @brief
* @param multi -
* @param data -
* @param len -
* @return
*/
uint32_t read_cache_data(TBuffVecPtr multi, void* data, uint32_t len)
{
TRWCache* cache = (TRWCache*)multi;
if (NULL == cache) {
return 0;
}
uint32_t left_len = len;
uint32_t offset = 0;
TSkBuffer* item = NULL;
TSkBuffer* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
{
uint32_t copy_len = 0;
if (left_len <= item->data_len)
{
copy_len = left_len;
}
else
{
copy_len = item->data_len;
}
if (data != NULL)
{
memcpy((char*)data + offset, item->data, copy_len);
}
offset += copy_len;
left_len -= copy_len;
if (left_len <= 0)
{
break;
}
}
return offset;
}
/**
* @brief
* @param multi -
* @param data -
* @param len -
* @return
*/
uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_t len)
{
TRWCache* cache = (TRWCache*)multi;
if (NULL == cache) {
return 0;
}
if (begin >= cache->len) {
return 0;
}
uint32_t pos_left = begin;
uint32_t copy_left = len;
uint32_t offset = 0;
TSkBuffer* item = NULL;
TAILQ_FOREACH(item, &cache->list, entry)
{
// 1. 开始位置有剩余, 则跳过该部分
uint8_t* start_ptr = item->data;
uint32_t real_left = item->data_len;
if (pos_left > 0)
{
uint32_t skip_len = pos_left > real_left ? real_left : pos_left;
pos_left -= skip_len;
real_left -= skip_len;
start_ptr += skip_len;
}
// 2. 跳过后无长度剩余, 则等待下一块
if (real_left == 0)
{
continue;
}
// 3. 有剩余, 尽力拷贝最大长度
uint32_t copy_len = copy_left > real_left ? real_left : copy_left;
if (data != NULL)
{
memcpy((char*)data + offset, start_ptr, copy_len);
}
offset += copy_len;
copy_left -= copy_len;
if (copy_left == 0)
{
break;
}
}
return offset;
}
};

298
app/micro_thread/mt_cache.h Normal file
View File

@ -0,0 +1,298 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename mt_cache.h
* @info TCPbuffer
*/
#ifndef ___MT_BUFFER_CACHE_H
#define ___MT_BUFFER_CACHE_H
#include <stdint.h>
#include <sys/queue.h>
namespace NS_MICRO_THREAD {
// 默认的buff大小
#define SK_DFLT_BUFF_SIZE 64*1024
#define SK_DFLT_ALIGN_SIZE 8
#define SK_ERR_NEED_CLOSE 10000
/**
* @brief buffer
*/
typedef struct _sk_buffer_tag
{
TAILQ_ENTRY(_sk_buffer_tag) entry; // list entry buffer LRU等
uint32_t last_time; // 上次使用时间戳
uint32_t size; // buffer节点的空间大小
uint8_t* head; // buff数据区头指针
uint8_t* end; // buff数据区结束指针
uint8_t* data; // 有效数据的头指针
uint32_t data_len; // 有效的数据长度
uint8_t buff[0]; // 原始指针区域
} TSkBuffer;
typedef TAILQ_HEAD(__sk_buff_list, _sk_buffer_tag) TSkBuffList; // multi 事务命令队列
/**
* @brief buff
* @param size
* @return NULLbuff
*/
TSkBuffer* new_sk_buffer(uint32_t size = SK_DFLT_BUFF_SIZE);
/**
* @brief buff
* @param buff
*/
void delete_sk_buffer(TSkBuffer* buff);
/**
* @brief (buff,)
* @param buff -buff
* @param size -
* @return buff
*/
TSkBuffer* reserve_sk_buffer(TSkBuffer* buff, uint32_t size);
/**
* @brief buffer cache
*/
typedef struct _sk_buff_mng_tag
{
TSkBuffList free_list; // buff链表
uint32_t expired; // 超时时间
uint32_t size; // buff大小
uint32_t count; // 块个数
} TSkBuffMng;
/**
* @brief cache
* @param mng -
* @param expired -,
* @param size -
*/
void sk_buffer_mng_init(TSkBuffMng* mng, uint32_t expired, uint32_t size = SK_DFLT_BUFF_SIZE);
/**
* @brief cache
* @param mng -
*/
void sk_buffer_mng_destroy(TSkBuffMng * mng);
/**
* @brief buff
* @param mng -
* @return NULLbuff
*/
TSkBuffer* alloc_sk_buffer(TSkBuffMng* mng);
/**
* @brief buff
* @param mng -
* @param buff -buff
*/
void free_sk_buffer(TSkBuffMng* mng, TSkBuffer* buff);
/**
* @brief buff
* @param mng -
* @param now -,
*/
void recycle_sk_buffer(TSkBuffMng* mng, uint32_t now);
/**
* @brief buffer cache
*/
typedef struct _sk_rw_cache_tag
{
TSkBuffList list; // buff链表
uint32_t len; // 数据长度
uint32_t count; // 块个数
TSkBuffMng *pool; // 全局buff池指针
} TRWCache;
/**
* @brief Cache
* @param cache -
* @param pool -buff
*/
void rw_cache_init(TRWCache* cache, TSkBuffMng* pool);
/**
* @brief Cache
* @param cache -
*/
void rw_cache_destroy(TRWCache* cache);
/**
* @brief Cache
* @param cache -
* @param len -
*/
void cache_skip_data(TRWCache* cache, uint32_t len);
/**
* @brief Cache
* @param cache -
*/
TSkBuffer* cache_skip_first_buffer(TRWCache* cache);
/**
* @brief Cache
* @param cache -
* @param data -
* @param len -
*/
int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len);
/**
* @brief Cache
* @param cache -
* @param buff -
*/
void cache_append_buffer(TRWCache* cache, TSkBuffer* buff);
/**
* @brief Cache
* @param cache -
* @param buff -buff
* @param len -
* @return
*/
uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len);
/**
* @brief CacheUDP, , 32使
* @param cache -
* @param fd - fd
* @param remote_addr -ip
* @return
*/
int32_t cache_udp_recv(TRWCache* cache, uint32_t fd, struct sockaddr_in* remote_addr);
/**
* @brief CacheTCP
* @param cache -
* @param fd - fd
* @return
*/
int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd);
/**
* @brief CacheTCP
* @param cache -
* @param fd - fd
* @return
*/
int32_t cache_tcp_send(TRWCache* cache, uint32_t fd);
/**
* @brief CacheTCP, 使IOVEC
* @param cache -
* @param fd - fd
* @param data -cache, buff
* @param len -buff
* @return
*/
int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint32_t len);
// interface
typedef void* TBuffVecPtr; ///< 多个block的cache管理指针句柄
typedef void* TBuffBlockPtr; ///< 单个管理块指针句柄
/**
* @brief cache
* @param multi -
* @return
*/
uint32_t get_data_len(TBuffVecPtr multi);
/**
* @brief cache
* @param multi -
* @return
*/
uint32_t get_block_count(TBuffVecPtr multi);
/**
* @brief cache
* @param multi -
* @return
*/
TBuffBlockPtr get_first_block(TBuffVecPtr multi);
/**
* @brief cache
* @param multi -
* @param block -
* @return
*/
TBuffBlockPtr get_next_block(TBuffVecPtr multi, TBuffBlockPtr block);
/**
* @brief
* @param block -
* @param data --modify
* @param len - modify
*/
void get_block_data(TBuffBlockPtr block, const void** data, int32_t* len);
/**
* @brief
* @param multi -
* @param data -
* @param len -
* @return
*/
uint32_t read_cache_data(TBuffVecPtr multi, void* data, uint32_t len);
/**
* @brief
* @param multi -
* @param data -
* @param len -
* @return
*/
uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_t len);
};
#endif

View File

@ -0,0 +1,528 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_concurrent.c
* @info
* @time 20130924
**/
#include "micro_thread.h"
#include "mt_msg.h"
#include "mt_notify.h"
#include "mt_connection.h"
#include "mt_concurrent.h"
using namespace std;
using namespace NS_MICRO_THREAD;
/**
* @brief IO,
* @param req_list -
* @param how - EPOLLIN EPOLLOUT
* @param timeout -
* @return 0 , <0 -3
*/
int NS_MICRO_THREAD::mt_multi_netfd_poll(IMtActList& req_list, int how, int timeout)
{
KqObjList fdlist;
TAILQ_INIT(&fdlist);
KqueuerObj* obj = NULL;
IMtAction* action = NULL;
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
{
action = *it;
if (action) {
obj = action->GetNtfyObj();
}
if (!action || !obj)
{
action->SetErrno(ERR_FRAME_ERROR);
MTLOG_ERROR("input action %p, or ntify null, error", action);
return -1;
}
obj->SetRcvEvents(0);
if (how & KQ_EVENT_READ)
{
obj->EnableInput();
}
else
{
obj->DisableInput();
}
if (how & KQ_EVENT_WRITE)
{
obj->EnableOutput();
}
else
{
obj->DisableOutput();
}
TAILQ_INSERT_TAIL(&fdlist, obj, _entry);
}
MtFrame* mtframe = MtFrame::Instance();
if (!mtframe || !mtframe->KqueueSchedule(&fdlist, NULL, (int)timeout))
{
if (errno != ETIME)
{
action->SetErrno(ERR_KQUEUE_FAIL);
MTLOG_ERROR("Mtframe %p, epoll schedule failed, errno %d", mtframe, errno);
return -2;
}
return -3;
}
return 0;
}
/**
* @brief ITEMsocket
* @param req_list -
* @return 0 , <0
*/
int NS_MICRO_THREAD::mt_multi_newsock(IMtActList& req_list)
{
int sock = -1, has_ok = 0;
IMtAction* action = NULL;
IMtConnection* net_handler = NULL;
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
{
action = *it;
if (NULL == action)
{
action->SetErrno(ERR_PARAM_ERROR);
MTLOG_ERROR("Invalid param, conn %p null!!", action);
return -1;
}
if (action->GetErrno() != ERR_NONE) {
continue;
}
net_handler = action->GetIConnection();
if (NULL == net_handler)
{
action->SetErrno(ERR_FRAME_ERROR);
MTLOG_ERROR("Invalid param, conn %p null!!", net_handler);
return -2;
}
sock = net_handler->CreateSocket();
if (sock < 0)
{
action->SetErrno(ERR_SOCKET_FAIL);
MTLOG_ERROR("Get sock data failed, ret %d, errno %d!!", sock, errno);
return -3;
}
has_ok = 1;
if (action->GetProtoType() == MT_UDP)
{
action->SetMsgFlag(MULTI_FLAG_OPEN);
}
else
{
action->SetMsgFlag(MULTI_FLAG_INIT);
}
}
if (has_ok)
{
return 0;
}
else
{
return -4;
}
}
/**
* @brief IO,
* @param req_list -
* @param timeout -
* @return 0 , <0
*/
int NS_MICRO_THREAD::mt_multi_open(IMtActList& req_list, int timeout)
{
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
utime64_t end_ms = start_ms + timeout;
utime64_t curr_ms = 0;
int ret = 0, has_open = 0;
IMtAction* action = NULL;
IMtConnection* net_handler = NULL;
IMtActList::iterator it;
while (1)
{
IMtActList wait_list;
for (it = req_list.begin(); it != req_list.end(); ++it)
{
action = *it;
if (action->GetErrno() != ERR_NONE) {
continue;
}
if (action->GetMsgFlag() == MULTI_FLAG_OPEN) {
has_open = 1;
continue;
}
net_handler = action->GetIConnection();
if (NULL == net_handler)
{
action->SetErrno(ERR_FRAME_ERROR);
MTLOG_ERROR("Invalid param, conn %p null!!", net_handler);
return -1;
}
ret = net_handler->OpenCnnect();
if (ret < 0)
{
wait_list.push_back(action);
}
else
{
action->SetMsgFlag(MULTI_FLAG_OPEN);
}
}
curr_ms = MtFrame::Instance()->GetLastClock();
if (curr_ms > end_ms)
{
MTLOG_DEBUG("Open connect timeout, errno %d", errno);
for (IMtActList::iterator it = wait_list.begin(); it != wait_list.end(); ++it)
{
(*it)->SetErrno(ERR_CONNECT_FAIL);
}
if (!has_open)
{
return 0;
}
else
{
return -2;
}
}
if (!wait_list.empty())
{
mt_multi_netfd_poll(wait_list, KQ_EVENT_WRITE, end_ms - curr_ms);
}
else
{
return 0;
}
}
}
/**
* @brief IO,
* @param req_list -
* @param timeout -
* @return 0 , <0
*/
int NS_MICRO_THREAD::mt_multi_sendto(IMtActList& req_list, int timeout)
{
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
utime64_t end_ms = start_ms + timeout;
utime64_t curr_ms = 0;
int ret = 0, has_send = 0;
IMtAction* action = NULL;
IMtConnection* net_handler = NULL;
while (1)
{
IMtActList wait_list;
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
{
action = *it;
if (action->GetErrno() != ERR_NONE) {
continue;
}
if (action->GetMsgFlag() == MULTI_FLAG_SEND) {
has_send = 1;
continue;
}
net_handler = action->GetIConnection();
if (NULL == net_handler)
{
action->SetErrno(ERR_FRAME_ERROR);
MTLOG_ERROR("Invalid param, conn %p null!!", net_handler);
return -2;
}
// 0 -还要继续发送; -1 停止发送; > 0 发送OK
ret = net_handler->SendData();
if (ret == -1)
{
action->SetErrno(ERR_SEND_FAIL);
MTLOG_ERROR("MultiItem msg send error, %d", errno);
continue;
}
else if (ret == 0)
{
wait_list.push_back(action);
continue;
}
else
{
action->SetMsgFlag(MULTI_FLAG_SEND);
}
}
curr_ms = MtFrame::Instance()->GetLastClock();
if (curr_ms > end_ms)
{
MTLOG_DEBUG("send data timeout");
for (IMtActList::iterator it = wait_list.begin(); it != wait_list.end(); ++it)
{
(*it)->SetErrno(ERR_SEND_FAIL);
}
if (has_send)
{
return 0;
}
else
{
return -5;
}
}
if (!wait_list.empty())
{
mt_multi_netfd_poll(wait_list, KQ_EVENT_WRITE, end_ms - curr_ms);
}
else
{
return 0;
}
}
return 0;
}
/**
* @brief IO
*/
int NS_MICRO_THREAD::mt_multi_recvfrom(IMtActList& req_list, int timeout)
{
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
utime64_t end_ms = start_ms + timeout;
utime64_t curr_ms = 0;
int ret = 0;
IMtAction* action = NULL;
IMtConnection* net_handler = NULL;
while (1)
{
IMtActList wait_list;
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
{
action = *it;
if (action->GetErrno() != ERR_NONE) {
continue;
}
if (MULTI_FLAG_FIN == action->GetMsgFlag()) ///< 已处理完毕
{
continue;
}
net_handler = action->GetIConnection();
if (NULL == net_handler)
{
action->SetErrno(ERR_FRAME_ERROR);
MTLOG_ERROR("Invalid param, conn %p null!!", net_handler);
return -2;
}
// <0 失败, 0 继续收, >0 成功
ret = net_handler->RecvData();
if (ret < 0)
{
action->SetErrno(ERR_RECV_FAIL);
MTLOG_ERROR("MultiItem msg recv failed: %p", net_handler);
continue;
}
else if (ret == 0)
{
wait_list.push_back(action);
continue;
}
else
{
action->SetMsgFlag(MULTI_FLAG_FIN);
action->SetCost(MtFrame::Instance()->GetLastClock() - start_ms);
}
}
curr_ms = MtFrame::Instance()->GetLastClock();
if (curr_ms > end_ms)
{
MTLOG_DEBUG("Recv data timeout, curr %llu, start: %llu", curr_ms, start_ms);
for (IMtActList::iterator it = wait_list.begin(); it != wait_list.end(); ++it)
{
(*it)->SetErrno(ERR_RECV_TIMEOUT);
}
return -5;
}
if (!wait_list.empty())
{
mt_multi_netfd_poll(wait_list, KQ_EVENT_READ, end_ms - curr_ms);
}
else
{
return 0;
}
}
}
/**
* @brief IO
*/
int NS_MICRO_THREAD::mt_multi_sendrcv_ex(IMtActList& req_list, int timeout)
{
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
utime64_t curr_ms = 0;
int rc = mt_multi_newsock(req_list); // TODO, 可提取connect超时时间等
if (rc < 0)
{
MT_ATTR_API(320842, 1); // socket失败
MTLOG_ERROR("mt_multi_sendrcv new sock failed, ret: %d", rc);
return -1;
}
rc = mt_multi_open(req_list, timeout);
if (rc < 0)
{
MT_ATTR_API(320843, 1); // connect失败
MTLOG_ERROR("mt_multi_sendrcv open failed, ret: %d", rc);
return -2;
}
curr_ms = MtFrame::Instance()->GetLastClock();
rc = mt_multi_sendto(req_list, timeout - (curr_ms - start_ms));
if (rc < 0)
{
MT_ATTR_API(320844, 1); // 发送失败
MTLOG_ERROR("mt_multi_sendrcv send failed, ret: %d", rc);
return -3;
}
curr_ms = MtFrame::Instance()->GetLastClock();
rc = mt_multi_recvfrom(req_list, timeout - (curr_ms - start_ms));
if (rc < 0)
{
MT_ATTR_API(320845, 1); // 接收未完全成功
MTLOG_ERROR("mt_multi_sendrcv recv failed, ret: %d", rc);
return -4;
}
return 0;
}
/**
* @brief IO, ACTON, msg
* @param req_list -action list
* @param timeout -, ms
* @return 0 , -1 ,
*/
int NS_MICRO_THREAD::mt_msg_sendrcv(IMtActList& req_list, int timeout)
{
int iRet = 0;
// 第一步, 初始化action环境, 封装请求报文
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
{
IMtAction* pAction = *it;
if (!pAction || pAction->InitConnEnv() < 0)
{
MTLOG_ERROR("invalid action(%p) or int failed, error", pAction);
return -1;
}
iRet = pAction->DoEncode();
if (iRet < 0)
{
pAction->SetErrno(ERR_ENCODE_ERROR);
MTLOG_ERROR("pack action pkg failed, act %p, ret %d", pAction, iRet);
continue;
}
}
// 第二步, 同步收发消息, 失败也需要通知处理
mt_multi_sendrcv_ex(req_list, timeout);
// 第三步, 同步通知解包处理
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
{
IMtAction* pAction = *it;
if (pAction->GetMsgFlag() != MULTI_FLAG_FIN)
{
pAction->DoError();
MTLOG_DEBUG("send recv failed: %d", pAction->GetErrno());
continue;
}
iRet = pAction->DoProcess();
if (iRet < 0)
{
MTLOG_DEBUG("action process failed: %d", iRet);
continue;
}
}
// 第四步, 清理框架内部资源, 兼容各类用法
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
{
IMtAction* pAction = *it;
pAction->Reset();
}
return 0;
}

View File

@ -0,0 +1,103 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_concurrent.h
* @info 线
* @time 20130515
**/
#ifndef __MT_CONCURRENT_H__
#define __MT_CONCURRENT_H__
#include <netinet/in.h>
#include <vector>
namespace NS_MICRO_THREAD {
using std::vector;
class IMtAction;
typedef vector<IMtAction*> IMtActList;
/******************************************************************************/
/* 微线程用户接口定义: 微线程Action多路并发模型接口定义 */
/******************************************************************************/
/**
* @brief IO, ACTON, msg
* @param req_list -action list
* @param timeout -, ms
* @return 0 , -1 socket, -2 , -100 , errno
*/
int mt_msg_sendrcv(IMtActList& req_list, int timeout);
/******************************************************************************/
/* 内部实现定义部分 */
/******************************************************************************/
/**
* @brief IO,
* @param req_list -
* @param how - EPOLLIN EPOLLOUT
* @param timeout -
* @return 0 , <0 -3
*/
int mt_multi_netfd_poll(IMtActList& req_list, int how, int timeout);
/**
* @brief ITEMsocket
* @param req_list -
* @return 0 , <0
*/
int mt_multi_newsock(IMtActList& req_list);
/**
* @brief IO,
* @param req_list -
* @param timeout -
* @return 0 , <0
*/
int mt_multi_open(IMtActList& req_list, int timeout);
/**
* @brief IO,
* @param req_list -
* @param timeout -
* @return 0 , <0
*/
int mt_multi_sendto(IMtActList& req_list, int timeout);
/**
* @brief IO
*/
int mt_multi_recvfrom(IMtActList& req_list, int timeout);
/**
* @brief IO
*/
int mt_multi_sendrcv_ex(IMtActList& req_list, int timeout);
}
#endif

View File

@ -0,0 +1,921 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_connection.cpp
* @info 线
* @time 20130924
**/
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "micro_thread.h"
#include "mt_msg.h"
#include "mt_notify.h"
#include "mt_connection.h"
#include "mt_sys_hook.h"
#include "ff_hook.h"
using namespace std;
using namespace NS_MICRO_THREAD;
/**
* @brief 线
*/
IMtConnection::IMtConnection()
{
_type = OBJ_CONN_UNDEF;
_action = NULL;
_ntfy_obj = NULL;
_msg_buff = NULL;
}
IMtConnection::~IMtConnection()
{
if (_ntfy_obj) {
NtfyObjMgr::Instance()->FreeNtfyObj(_ntfy_obj);
_ntfy_obj = NULL;
}
if (_msg_buff) {
MsgBuffPool::Instance()->FreeMsgBuf(_msg_buff);
_msg_buff = NULL;
}
}
/**
* @brief
*/
void IMtConnection::Reset()
{
if (_ntfy_obj) {
NtfyObjMgr::Instance()->FreeNtfyObj(_ntfy_obj);
_ntfy_obj = NULL;
}
if (_msg_buff) {
MsgBuffPool::Instance()->FreeMsgBuf(_msg_buff);
_msg_buff = NULL;
}
_action = NULL;
_ntfy_obj = NULL;
_msg_buff = NULL;
}
/**
* @brief socket,
* @return >0 -, fd, < 0
*/
int UdpShortConn::CreateSocket()
{
// 1. UDP短连接, 每次新创SOCKET
_osfd = socket(AF_INET, SOCK_DGRAM, 0);
if (_osfd < 0)
{
MTLOG_ERROR("socket create failed, errno %d(%s)", errno, strerror(errno));
return -1;
}
// 2. 非阻塞设置
int flags = 1;
if (ioctl(_osfd, FIONBIO, &flags) < 0)
{
MTLOG_ERROR("socket unblock failed, errno %d(%s)", errno, strerror(errno));
close(_osfd);
_osfd = -1;
return -2;
}
// 3. 更新管理信息
if (_ntfy_obj) {
_ntfy_obj->SetOsfd(_osfd);
}
return _osfd;
}
/**
* @brief socket,
*/
int UdpShortConn::CloseSocket()
{
if (_osfd < 0)
{
return 0;
}
close(_osfd);
_osfd = -1;
return 0;
}
/**
* @brief ,
* @return 0 , . <0 . >0
*/
int UdpShortConn::SendData()
{
if (!_action || !_msg_buff) {
MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
return -100;
}
mt_hook_syscall(sendto);
int ret = ff_hook_sendto(_osfd, _msg_buff->GetMsgBuff(), _msg_buff->GetMsgLen(), 0,
(struct sockaddr*)_action->GetMsgDstAddr(), sizeof(struct sockaddr_in));
if (ret == -1)
{
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
{
return 0;
}
else
{
MTLOG_ERROR("socket send failed, fd %d, errno %d(%s)", _osfd,
errno, strerror(errno));
return -2;
}
}
else
{
_msg_buff->SetHaveSndLen(ret);
return ret;
}
}
/**
* @brief ,
* @param buff
* @return -1 . -2 . >0
*/
int UdpShortConn::RecvData()
{
if (!_action || !_msg_buff) {
MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
return -100;
}
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
mt_hook_syscall(recvfrom);
int ret = ff_hook_recvfrom(_osfd, _msg_buff->GetMsgBuff(), _msg_buff->GetMaxLen(),
0, (struct sockaddr*)&from, &fromlen);
if (ret < 0)
{
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
{
return 0;
}
else
{
MTLOG_ERROR("socket recv failed, fd %d, errno %d(%s)", _osfd,
errno, strerror(errno));
return -2; // 系统错误
}
}
else if (ret == 0)
{
return -1; // 对端关闭
}
else
{
_msg_buff->SetHaveRcvLen(ret);
}
// 上下文检查, >0 收包完整; =0 继续等待; <0(-65535串包)其它异常
ret = _action->DoInput();
if (ret > 0)
{
_msg_buff->SetMsgLen(ret);
return ret;
}
else if (ret == 0)
{
return 0;
}
else if (ret == -65535)
{
_msg_buff->SetHaveRcvLen(0);
return 0;
}
else
{
return -1;
}
}
/**
* @brief
*/
void UdpShortConn::Reset()
{
CloseSocket();
this->IMtConnection::Reset();
}
/**
* @brief , TCPconnect
* @return 0 -, < 0
*/
int TcpKeepConn::OpenCnnect()
{
if (!_action || !_msg_buff) {
MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
return -100;
}
int err = 0;
mt_hook_syscall(connect);
int ret = ff_hook_connect(_osfd, (struct sockaddr*)_action->GetMsgDstAddr(), sizeof(struct sockaddr_in));
if (ret < 0)
{
err = errno;
if (err == EISCONN)
{
return 0;
}
else
{
if ((err == EINPROGRESS) || (err == EALREADY) || (err == EINTR))
{
MTLOG_DEBUG("Open connect not ok, maybe first try, sock %d, errno %d", _osfd, err);
return -1;
}
else
{
MTLOG_ERROR("Open connect not ok, sock %d, errno %d", _osfd, err);
return -2;
}
}
}
else
{
return 0;
}
}
/**
* @brief sockTCP
*/
int TcpKeepConn::CreateSocket()
{
if (_osfd > 0) // 复用连接时, 可跳过创建处理; 不能跳过设置ntfyfd
{
if (_ntfy_obj) {
_ntfy_obj->SetOsfd(_osfd);
}
return _osfd;
}
// 第一次进入时, 创建socket
_osfd = socket(AF_INET, SOCK_STREAM, 0);
if (_osfd < 0)
{
MTLOG_ERROR("create tcp socket failed, error: %d", errno);
return -1;
}
// 非阻塞设置
int flags = 1;
if (ioctl(_osfd, FIONBIO, &flags) < 0)
{
MTLOG_ERROR("set tcp socket unblock failed, error: %d", errno);
close(_osfd);
_osfd = -1;
return -2;
}
// 更新管理信息
_keep_ntfy.SetOsfd(_osfd);
_keep_ntfy.DisableOutput();
_keep_ntfy.EnableInput();
if (_ntfy_obj) {
_ntfy_obj->SetOsfd(_osfd);
}
return _osfd;
}
/**
* @brief ,
* @param dst
* @param buff
* @param size
* @return 0 , . <0 . >0
*/
int TcpKeepConn::SendData()
{
if (!_action || !_msg_buff) {
MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
return -100;
}
char* msg_ptr = (char*)_msg_buff->GetMsgBuff();
int msg_len = _msg_buff->GetMsgLen();
int have_send_len = _msg_buff->GetHaveSndLen();
mt_hook_syscall(send);
int ret = ff_hook_send(_osfd, msg_ptr + have_send_len, msg_len - have_send_len, 0);
if (ret == -1)
{
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
{
return 0;
}
else
{
MTLOG_ERROR("send tcp socket failed, error: %d", errno);
return -1;
}
}
else
{
have_send_len += ret;
_msg_buff->SetHaveSndLen(have_send_len);
}
// 全部发送完毕, 返回成功, 否则继续等待
if (have_send_len >= msg_len)
{
return msg_len;
}
else
{
return 0;
}
}
/**
* @brief ,
* @param buff
* @return -1 . -2 . >0
*/
int TcpKeepConn::RecvData()
{
if (!_action || !_msg_buff) {
MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
return -100;
}
char* msg_ptr = (char*)_msg_buff->GetMsgBuff();
int max_len = _msg_buff->GetMaxLen();
int have_rcv_len = _msg_buff->GetHaveRcvLen();
mt_hook_syscall(recv);
int ret = ff_hook_recv(_osfd, (char*)msg_ptr + have_rcv_len, max_len - have_rcv_len, 0);
if (ret < 0)
{
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
{
return 0;
}
else
{
MTLOG_ERROR("recv tcp socket failed, error: %d", errno);
return -2; // 系统错误
}
}
else if (ret == 0)
{
MTLOG_ERROR("tcp remote close, address: %s[%d]",
inet_ntoa(_dst_addr.sin_addr), ntohs(_dst_addr.sin_port));
return -1; // 对端关闭
}
else
{
have_rcv_len += ret;
_msg_buff->SetHaveRcvLen(have_rcv_len);
}
// 上下文检查, >0 收包完整; =0 继续等待; <0(-65535串包)其它异常
ret = _action->DoInput();
if (ret > 0)
{
_msg_buff->SetMsgLen(have_rcv_len);
return ret;
}
else if (ret == 0)
{
return 0;
}
else
{
return -1;
}
}
/**
* @brief socket,
*/
int TcpKeepConn::CloseSocket()
{
if (_osfd < 0)
{
return 0;
}
_keep_ntfy.SetOsfd(-1);
close(_osfd);
_osfd = -1;
return 0;
}
/**
* @brief
*/
void TcpKeepConn::Reset()
{
memset(&_dst_addr, 0 ,sizeof(_dst_addr));
CloseSocket();
this->IMtConnection::Reset();
}
/**
* @brief
*/
void TcpKeepConn::ConnReuseClean()
{
this->IMtConnection::Reset();
}
/**
* @brief Idle, epoll
*/
bool TcpKeepConn::IdleAttach()
{
if (_osfd < 0) {
MTLOG_ERROR("obj %p attach failed, fd %d error", this, _osfd);
return false;
}
if (_keep_flag & TCP_KEEP_IN_KQUEUE) {
MTLOG_ERROR("obj %p repeat attach, error", this);
return true;
}
_keep_ntfy.DisableOutput();
_keep_ntfy.EnableInput();
// 保活定时器添加
CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
if ((NULL == timer) || !timer->start_timer(this, _keep_time))
{
MTLOG_ERROR("obj %p attach timer failed, error", this);
return false;
}
if (MtFrame::Instance()->KqueueAddObj(&_keep_ntfy))
{
_keep_flag |= TCP_KEEP_IN_KQUEUE;
return true;
}
else
{
MTLOG_ERROR("obj %p attach failed, error", this);
return false;
}
}
/**
* @brief Idle, 线
*/
bool TcpKeepConn::IdleDetach()
{
if (_osfd < 0) {
MTLOG_ERROR("obj %p detach failed, fd %d error", this, _osfd);
return false;
}
if (!(_keep_flag & TCP_KEEP_IN_KQUEUE)) {
MTLOG_DEBUG("obj %p repeat detach, error", this);
return true;
}
_keep_ntfy.DisableOutput();
_keep_ntfy.EnableInput();
// 保活定时器删除
CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
if (NULL != timer)
{
timer->stop_timer(this);
}
if (MtFrame::Instance()->KqueueDelObj(&_keep_ntfy))
{
_keep_flag &= ~TCP_KEEP_IN_KQUEUE;
return true;
}
else
{
MTLOG_ERROR("obj %p detach failed, error", this);
return false;
}
}
/**
* @brief ,
*/
void TcpKeepConn::timer_notify()
{
MTLOG_DEBUG("keep timeout[%u], fd %d, close connection", _keep_time, _osfd);
ConnectionMgr::Instance()->CloseIdleTcpKeep(this);
}
/**
* @brief
*/
TcpKeepMgr::TcpKeepMgr()
{
_keep_hash = new HashList(10000);
}
TcpKeepMgr::~TcpKeepMgr()
{
if (!_keep_hash) {
return;
}
HashKey* hash_item = _keep_hash->HashGetFirst();
while (hash_item)
{
delete hash_item;
hash_item = _keep_hash->HashGetFirst();
}
delete _keep_hash;
_keep_hash = NULL;
}
/**
* @brief IPTCP
*/
TcpKeepConn* TcpKeepMgr::GetTcpKeepConn(struct sockaddr_in* dst)
{
TcpKeepConn* conn = NULL;
if (NULL == dst)
{
MTLOG_ERROR("input param dst null, error");
return NULL;
}
TcpKeepKey key(dst);
TcpKeepKey* conn_list = (TcpKeepKey*)_keep_hash->HashFindData(&key);
if ((NULL == conn_list) || (NULL == conn_list->GetFirstConn()))
{
conn = _mem_queue.AllocPtr();
if (conn) {
conn->SetDestAddr(dst);
}
}
else
{
conn = conn_list->GetFirstConn();
conn_list->RemoveConn(conn);
conn->IdleDetach();
}
return conn;
}
/**
* @brief IPTCP
*/
bool TcpKeepMgr::RemoveTcpKeepConn(TcpKeepConn* conn)
{
struct sockaddr_in* dst = conn->GetDestAddr();
if ((dst->sin_addr.s_addr == 0) || (dst->sin_port == 0))
{
MTLOG_ERROR("sock addr, invalid, %x:%d", dst->sin_addr.s_addr, dst->sin_port);
return false;
}
TcpKeepKey key(dst);
TcpKeepKey* conn_list = (TcpKeepKey*)_keep_hash->HashFindData(&key);
if (!conn_list)
{
MTLOG_ERROR("no conn cache list, invalid, %x:%d", dst->sin_addr.s_addr, dst->sin_port);
return false;
}
conn->IdleDetach();
conn_list->RemoveConn(conn);
return true;
}
/**
* @brief IPTCP
*/
bool TcpKeepMgr::CacheTcpKeepConn(TcpKeepConn* conn)
{
struct sockaddr_in* dst = conn->GetDestAddr();
if ((dst->sin_addr.s_addr == 0) || (dst->sin_port == 0))
{
MTLOG_ERROR("sock addr, invalid, %x:%d", dst->sin_addr.s_addr, dst->sin_port);
return false;
}
TcpKeepKey key(dst);
TcpKeepKey* conn_list = (TcpKeepKey*)_keep_hash->HashFindData(&key);
if (!conn_list)
{
conn_list = new TcpKeepKey(conn->GetDestAddr());
if (!conn_list) {
MTLOG_ERROR("new conn list failed, error");
return false;
}
_keep_hash->HashInsert(conn_list);
}
if (!conn->IdleAttach())
{
MTLOG_ERROR("conn IdleAttach failed, error");
return false;
}
conn->ConnReuseClean();
conn_list->InsertConn(conn);
return true;
}
/**
* @brief tcp
*/
void TcpKeepMgr::FreeTcpKeepConn(TcpKeepConn* conn, bool force_free)
{
if (force_free)
{
conn->Reset();
_mem_queue.FreePtr(conn);
return;
}
else
{
if (!CacheTcpKeepConn(conn))
{
conn->Reset();
_mem_queue.FreePtr(conn);
return;
}
}
}
/**
* @brief socket,
* @return >0 -, fd, < 0
*/
int UdpSessionConn::CreateSocket()
{
// 1. session连接类, 由通知对象创建管理fd
if (!_action || !_ntfy_obj) {
MTLOG_ERROR("conn not set action %p, or _ntfy_obj %p, error", _action, _ntfy_obj);
return -100;
}
SessionProxy* proxy = dynamic_cast<SessionProxy*>(_ntfy_obj);
if (!proxy) {
MTLOG_ERROR("ntfy obj not match, _ntfy_obj %p, error", _ntfy_obj);
return -200;
}
ISessionNtfy* real_ntfy = proxy->GetRealNtfyObj();
if (!real_ntfy) {
MTLOG_ERROR("real ntfy obj not match, _ntfy_obj %p, error", _ntfy_obj);
return -300;
}
// 2. 委派创建, 更新句柄信息
int osfd = real_ntfy->GetOsfd();
if (osfd <= 0)
{
osfd = real_ntfy->CreateSocket();
if (osfd <= 0) {
MTLOG_ERROR("real ntfy obj create fd failed, _ntfy_obj %p, error", real_ntfy);
return -400;
}
}
_ntfy_obj->SetOsfd(osfd);
return osfd;
}
/**
* @brief socket,
*/
int UdpSessionConn::CloseSocket()
{
return 0;
}
/**
* @brief ,
* @return 0 , . <0 . >0
*/
int UdpSessionConn::SendData()
{
if (!_action || !_msg_buff || !_ntfy_obj) {
MTLOG_ERROR("conn not set action %p, or msg %p, ntfy %p error", _action, _msg_buff, _ntfy_obj);
return -100;
}
mt_hook_syscall(sendto);
int ret = ff_hook_sendto(_ntfy_obj->GetOsfd(), _msg_buff->GetMsgBuff(), _msg_buff->GetMsgLen(), 0,
(struct sockaddr*)_action->GetMsgDstAddr(), sizeof(struct sockaddr_in));
if (ret == -1)
{
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
{
return 0;
}
else
{
MTLOG_ERROR("socket send failed, fd %d, errno %d(%s)", _ntfy_obj->GetOsfd(),
errno, strerror(errno));
return -2;
}
}
else
{
_msg_buff->SetHaveSndLen(ret);
return ret;
}
}
/**
* @brief ,
* @param buff
* @return 0 -; >0 ; < 0
*/
int UdpSessionConn::RecvData()
{
if (!_ntfy_obj || !_msg_buff) {
MTLOG_ERROR("conn not set _ntfy_obj %p, or msg %p, error", _ntfy_obj, _msg_buff);
return -100;
}
if (_ntfy_obj->GetRcvEvents() <= 0) {
MTLOG_DEBUG("conn _ntfy_obj %p, no recv event, retry it", _ntfy_obj);
return 0;
}
// UDP Session 通知会替换msg buff, 通过type判定
int msg_len = _msg_buff->GetMsgLen();
if (BUFF_RECV == _msg_buff->GetBuffType())
{
return msg_len;
}
else
{
MTLOG_DEBUG("conn msg buff %p, no recv comm", _msg_buff);
return 0;
}
}
/**
* @brief session
* @return
*/
ConnectionMgr* ConnectionMgr::_instance = NULL;
ConnectionMgr* ConnectionMgr::Instance (void)
{
if (NULL == _instance)
{
_instance = new ConnectionMgr();
}
return _instance;
}
/**
* @brief session
*/
void ConnectionMgr::Destroy()
{
if( _instance != NULL )
{
delete _instance;
_instance = NULL;
}
}
/**
* @brief buff
*/
ConnectionMgr::ConnectionMgr()
{
}
/**
* @brief , ,
*/
ConnectionMgr::~ConnectionMgr()
{
}
/**
* @brief
*/
IMtConnection* ConnectionMgr::GetConnection(CONN_OBJ_TYPE type, struct sockaddr_in* dst)
{
switch (type)
{
case OBJ_SHORT_CONN:
return _udp_short_queue.AllocPtr();
break;
case OBJ_TCP_KEEP:
return _tcp_keep_mgr.GetTcpKeepConn(dst);
break;
case OBJ_UDP_SESSION:
return _udp_session_queue.AllocPtr();
break;
default:
return NULL;
break;
}
}
/**
* @brief
*/
void ConnectionMgr::FreeConnection(IMtConnection* conn, bool force_free)
{
if (!conn) {
return;
}
CONN_OBJ_TYPE type = conn->GetConnType();
switch (type)
{
case OBJ_SHORT_CONN:
conn->Reset();
return _udp_short_queue.FreePtr(dynamic_cast<UdpShortConn*>(conn));
break;
case OBJ_TCP_KEEP:
return _tcp_keep_mgr.FreeTcpKeepConn(dynamic_cast<TcpKeepConn*>(conn), force_free);
break;
case OBJ_UDP_SESSION:
conn->Reset();
return _udp_session_queue.FreePtr(dynamic_cast<UdpSessionConn*>(conn));
break;
default:
break;
}
delete conn;
return;
}
/**
* @brief idletcp
*/
void ConnectionMgr::CloseIdleTcpKeep(TcpKeepConn* conn)
{
_tcp_keep_mgr.RemoveTcpKeepConn(conn);
_tcp_keep_mgr.FreeTcpKeepConn(conn, true);
}

View File

@ -0,0 +1,563 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_connection.h
* @info 线
* @time 20130924
**/
#ifndef __MT_CONNECTION_H__
#define __MT_CONNECTION_H__
#include <netinet/in.h>
#include <queue>
#include "mt_mbuf_pool.h"
#include "hash_list.h"
#include "mt_action.h"
namespace NS_MICRO_THREAD {
using std::queue;
/**
* @brief
*/
enum CONN_OBJ_TYPE
{
OBJ_CONN_UNDEF = 0, ///< 未定义的连接对象
OBJ_SHORT_CONN = 1, ///< 短连接对象, fd关联会话, 每次用完CLOSE
OBJ_TCP_KEEP = 2, ///< TCP的复用模型, 每次每连接使用该fd, 用完可复用
OBJ_UDP_SESSION = 3, ///< UDP的session模型, 每连接可供任意线程使用
};
/**
* @brief 线,
*/
class IMtConnection
{
public:
/**
* @brief 线
*/
IMtConnection();
virtual ~IMtConnection();
/**
* @brief
*/
virtual void Reset();
/**
* @brief
*/
CONN_OBJ_TYPE GetConnType() {
return _type;
};
/**
* @brief ACTION
* @return IMtConn
*/
void SetIMtActon(IMtAction* action ) {
_action = action;
};
/**
* @brief ACTION
* @return IMtConn
*/
IMtAction* GetIMtActon() {
return _action;
};
/**
* @brief ACTION
* @return IMtConn
*/
void SetNtfyObj(KqueuerObj* obj ) {
_ntfy_obj = obj;
};
/**
* @brief ACTION
* @return IMtConn
*/
KqueuerObj* GetNtfyObj() {
return _ntfy_obj;
};
/**
* @brief msgbuff
* @return IMtConn
*/
void SetMtMsgBuff(MtMsgBuf* msg_buf) {
_msg_buff = msg_buf;
};
/**
* @brief msgbuff
* @return IMtConn
*/
MtMsgBuf* GetMtMsgBuff() {
return _msg_buff;
};
public:
/**
* @brief socket,
* @return >0 -, fd, < 0
*/
virtual int CreateSocket() {return 0;};
/**
* @brief , TCPconnect
* @return 0 -, < 0
*/
virtual int OpenCnnect() {return 0;};
/**
* @brief
* @return >0 -, , < 0
*/
virtual int SendData() {return 0;};
/**
* @brief
* @return >0 -, , < 0 (-1 ; -2 )
*/
virtual int RecvData() {return 0;};
/**
* @brief socket
* @return >0 -, fd, < 0
*/
virtual int CloseSocket() {return 0;};
protected:
CONN_OBJ_TYPE _type; // 预置的type, 可按type做工厂管理
IMtAction* _action; // 关联的action指针, 上级指针, 不关心资源生存期
KqueuerObj* _ntfy_obj; // EPOLL通知对象, 下级指针, 关心生存期
MtMsgBuf* _msg_buff; // 动态管理的buff字段, 下级指针, 关心生存期
};
/**
* @brief sock
*/
class UdpShortConn : public IMtConnection
{
public:
/**
* @brief socket
*/
UdpShortConn() {
_osfd = -1;
_type = OBJ_SHORT_CONN;
};
virtual ~UdpShortConn() {
CloseSocket();
};
/**
* @brief
*/
virtual void Reset();
/**
* @brief socket,
* @return >0 -, fd, < 0
*/
virtual int CreateSocket();
/**
* @brief
* @return >0 -, , < 0
*/
virtual int SendData();
/**
* @brief
* @return >0 -, , < 0 (-1 ; -2 )
*/
virtual int RecvData();
/**
* @brief socket
* @return >0 -, fd, < 0
*/
virtual int CloseSocket();
protected:
int _osfd; // 每次连接单独创建socket
};
enum TcpKeepFlag
{
TCP_KEEP_IN_LIST = 0x1,
TCP_KEEP_IN_KQUEUE = 0x2,
};
/**
* @brief sessionUDP
*/
class UdpSessionConn : public IMtConnection
{
public:
/**
* @brief socket
*/
UdpSessionConn() {
_type = OBJ_UDP_SESSION;
};
virtual ~UdpSessionConn() { };
/**
* @brief socket,
* @return >0 -, fd, < 0
*/
virtual int CreateSocket();
/**
* @brief
* @return >0 -, , < 0
*/
virtual int SendData();
/**
* @brief
* @return >0 -, , < 0 (-1 ; -2 )
*/
virtual int RecvData();
/**
* @brief socket
* @return >0 -, fd, < 0
*/
virtual int CloseSocket();
};
/**
* @brief sockTCP
*/
typedef TAILQ_ENTRY(TcpKeepConn) KeepConnLink;
typedef TAILQ_HEAD(__KeepConnTailq, TcpKeepConn) KeepConnList;
class TcpKeepConn : public IMtConnection, public CTimerNotify
{
public:
int _keep_flag; // 队列状态标记
KeepConnLink _keep_entry; // 队列管理入口
/**
* @brief socket
*/
TcpKeepConn() {
_osfd = -1;
_keep_time = 10*60*1000; // 默认10分钟, 可以按需调整
_keep_flag = 0;
_type = OBJ_TCP_KEEP;
_keep_ntfy.SetKeepNtfyObj(this);
};
virtual ~TcpKeepConn() {
CloseSocket();
};
/**
* @brief
*/
virtual void Reset();
/**
* @brief , TCPconnect
* @return 0 -, < 0
*/
virtual int OpenCnnect();
/**
* @brief socket,
* @return >0 -, fd, < 0
*/
virtual int CreateSocket();
/**
* @brief
* @return >0 -, , < 0
*/
virtual int SendData();
/**
* @brief
* @return >0 -, , < 0 (-1 ; -2 )
*/
virtual int RecvData();
/**
* @brief socket
* @return >0 -, fd, < 0
*/
virtual int CloseSocket();
/**
* @brief
*/
void ConnReuseClean();
/**
* @brief Idle, epoll
*/
bool IdleAttach();
/**
* @brief Idle, 线
*/
bool IdleDetach();
/**
* @brief ,
*/
void SetDestAddr(struct sockaddr_in* dst) {
memcpy(&_dst_addr, dst, sizeof(_dst_addr));
}
/**
* @brief
*/
struct sockaddr_in* GetDestAddr() {
return &_dst_addr;
}
/**
* @brief ,
*/
virtual void timer_notify();
/**
* @brief ,
*/
void SetKeepTime(unsigned int time) {
_keep_time = time;
};
protected:
int _osfd; // 每次连接单独创建socket
unsigned int _keep_time; // 设置保活的时间
TcpKeepNtfy _keep_ntfy; // 关联一个保活连接对象
struct sockaddr_in _dst_addr; // 远端地址信息
};
/**
* @brief hash
*/
class TcpKeepKey : public HashKey
{
public:
/**
* @brief
*/
TcpKeepKey() {
_addr_ipv4 = 0;
_net_port = 0;
TAILQ_INIT(&_keep_list);
this->SetDataPtr(this);
};
TcpKeepKey(struct sockaddr_in * dst) {
_addr_ipv4 = dst->sin_addr.s_addr;
_net_port = dst->sin_port;
TAILQ_INIT(&_keep_list);
this->SetDataPtr(this);
};
/**
* @brief conn
*/
~TcpKeepKey() {
TAILQ_INIT(&_keep_list);
};
/**
* @brief hash, keyhash
* @return hash
*/
virtual uint32_t HashValue(){
return _addr_ipv4 ^ ((_net_port << 16) | _net_port);
};
/**
* @brief cmp, ID, key
* @return hash
*/
virtual int HashCmp(HashKey* rhs){
TcpKeepKey* data = dynamic_cast<TcpKeepKey*>(rhs);
if (!data) {
return -1;
}
if (this->_addr_ipv4 != data->_addr_ipv4) {
return this->_addr_ipv4 - data->_addr_ipv4;
}
if (this->_net_port != data->_net_port) {
return this->_net_port - data->_net_port;
}
return 0;
};
/**
* @brief
*/
void InsertConn(TcpKeepConn* conn) {
if (conn->_keep_flag & TCP_KEEP_IN_LIST) {
return;
}
TAILQ_INSERT_TAIL(&_keep_list, conn, _keep_entry);
conn->_keep_flag |= TCP_KEEP_IN_LIST;
};
void RemoveConn(TcpKeepConn* conn) {
if (!(conn->_keep_flag & TCP_KEEP_IN_LIST)) {
return;
}
TAILQ_REMOVE(&_keep_list, conn, _keep_entry);
conn->_keep_flag &= ~TCP_KEEP_IN_LIST;
};
TcpKeepConn* GetFirstConn() {
return TAILQ_FIRST(&_keep_list);
};
private:
uint32_t _addr_ipv4; ///< ip地址
uint16_t _net_port; ///< port 网络序列
KeepConnList _keep_list; ///< 实际的空闲队列
};
/**
* @brief TCPcache
*/
class TcpKeepMgr
{
public:
typedef CPtrPool<TcpKeepConn> TcpKeepQueue; ///< 内存缓冲池
/**
* @brief
*/
TcpKeepMgr();
~TcpKeepMgr();
/**
* @brief IPTCP
*/
TcpKeepConn* GetTcpKeepConn(struct sockaddr_in* dst);
/**
* @brief IPTCP
*/
bool CacheTcpKeepConn(TcpKeepConn* conn);
/**
* @brief IPTCP, CACHE
*/
bool RemoveTcpKeepConn(TcpKeepConn* conn);
/**
* @brief tcp
*/
void FreeTcpKeepConn(TcpKeepConn* conn, bool force_free);
private:
HashList* _keep_hash; ///< hash表, 存储按IP索引的连接队列
TcpKeepQueue _mem_queue; ///< mem队列, 管理conn内存块
};
/**
* @brief
*/
class ConnectionMgr
{
public:
typedef CPtrPool<UdpShortConn> UdpShortQueue;
typedef CPtrPool<UdpSessionConn> UdpSessionQueue;
/**
* @brief buff
* @return
*/
static ConnectionMgr* Instance (void);
/**
* @brief
*/
static void Destroy(void);
/**
* @brief
*/
IMtConnection* GetConnection(CONN_OBJ_TYPE type, struct sockaddr_in* dst);
/**
* @brief
*/
void FreeConnection(IMtConnection* conn, bool force_free);
/**
* @brief idletcp
*/
void CloseIdleTcpKeep(TcpKeepConn* conn);
/**
* @brief buff
*/
~ConnectionMgr();
private:
/**
* @brief buff
*/
ConnectionMgr();
static ConnectionMgr * _instance; ///< 单例类句柄
UdpShortQueue _udp_short_queue; ///< 短连接的队列池
UdpSessionQueue _udp_session_queue; ///< udp session 连接池
TcpKeepMgr _tcp_keep_mgr; ///< tcp keep 管理器
};
}
#endif

View File

@ -0,0 +1,37 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_incl.h
* @info ΢Ïß³ÌÌṩ¸øspp_pluginµÄÍ·Îļþ
* @time 20130924
*/
#ifndef _MT_INCL_EX__
#define _MT_INCL_EX__
#include "mt_version.h"
#include "mt_msg.h"
#include "mt_api.h"
using namespace std;
using namespace NS_MICRO_THREAD;
#endif

View File

@ -0,0 +1,159 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_mbuf_pool.cpp
* @info 线buf
* @time 20130924
**/
#include "micro_thread.h"
#include "mt_mbuf_pool.h"
using namespace std;
using namespace NS_MICRO_THREAD;
/**
* @brief 访
* @return
*/
MsgBuffPool* MsgBuffPool::_instance = NULL;
MsgBuffPool* MsgBuffPool::Instance (void)
{
if (NULL == _instance)
{
_instance = new MsgBuffPool;
}
return _instance;
}
/**
* @brief
*/
void MsgBuffPool::Destroy()
{
if( _instance != NULL )
{
delete _instance;
_instance = NULL;
}
}
/**
* @brief buff
*/
MsgBuffPool::MsgBuffPool(int max_free)
{
_max_free = max_free;
_hash_map = new HashList(10000);
}
/**
* @brief buff
*/
MsgBuffPool::~MsgBuffPool()
{
if (!_hash_map) {
return;
}
MsgBufMap* msg_map = NULL;
HashKey* hash_item = _hash_map->HashGetFirst();
while (hash_item)
{
_hash_map->HashRemove(hash_item);
msg_map = dynamic_cast<MsgBufMap*>(hash_item);
delete msg_map;
hash_item = _hash_map->HashGetFirst();
}
delete _hash_map;
_hash_map = NULL;
}
/**
* @brief buff
* @return msgbuf, NULL
*/
MtMsgBuf* MsgBuffPool::GetMsgBuf(int max_size)
{
if (!_hash_map) {
MTLOG_ERROR("MsgBuffPoll not init! hash %p,", _hash_map);
return NULL;
}
MsgBufMap* msg_map = NULL;
MsgBufMap msg_key(max_size);
HashKey* hash_item = _hash_map->HashFind(&msg_key);
if (hash_item) {
msg_map = (MsgBufMap*)hash_item->GetDataPtr();
if (msg_map) {
return msg_map->GetMsgBuf();
} else {
MTLOG_ERROR("Hash item: %p, msg_map: %p impossible, clean it", hash_item, msg_map);
_hash_map->HashRemove(hash_item);
delete hash_item;
return NULL;
}
} else {
msg_map = new MsgBufMap(max_size, _max_free);
if (!msg_map) {
MTLOG_ERROR("maybe no more memory, failed. size: %d", max_size);
return NULL;
}
_hash_map->HashInsert(msg_map);
return msg_map->GetMsgBuf();
}
}
/**
* @brief buff
* @return msgbuf, NULL
*/
void MsgBuffPool::FreeMsgBuf(MtMsgBuf* msg_buf)
{
if (!_hash_map || !msg_buf) {
MTLOG_ERROR("MsgBuffPoll not init or input error! hash %p, msg_buf %p", _hash_map, msg_buf);
delete msg_buf;
return;
}
msg_buf->Reset();
MsgBufMap* msg_map = NULL;
MsgBufMap msg_key(msg_buf->GetMaxLen());
HashKey* hash_item = _hash_map->HashFind(&msg_key);
if (hash_item) {
msg_map = (MsgBufMap*)hash_item->GetDataPtr();
}
if (!hash_item || !msg_map) {
MTLOG_ERROR("MsgBuffPoll find no queue, maybe error: %d", msg_buf->GetMaxLen());
delete msg_buf;
return;
}
msg_map->FreeMsgBuf(msg_buf);
return;
}

View File

@ -0,0 +1,304 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_mbuf_pool.h
* @info 线buf
**/
#ifndef __MT_MBUF_POOL_H__
#define __MT_MBUF_POOL_H__
#include <netinet/in.h>
#include <queue>
#include "hash_list.h"
namespace NS_MICRO_THREAD {
using std::queue;
enum BUFF_TYPE
{
BUFF_UNDEF = 0, ///< 未定义类型
BUFF_RECV = 1, ///< 接收buff
BUFF_SEND = 2, ///< 发送buff
};
/**
* @brief buffer
*/
typedef TAILQ_ENTRY(MtMsgBuf) MsgBufLink;
typedef TAILQ_HEAD(__MtbuffTailq, MtMsgBuf) MsgBufQueue;
class MtMsgBuf
{
private:
int _max_len; // 最大的空间长度
int _msg_len; // 实际的消息长度
int _buf_type; // buff是发送还是接收
int _recv_len; // 已接收的消息长度
int _send_len; // 已发送的消息长度
void* _msg_buff; // buffer 实际头指针
public:
MsgBufLink _entry;
/**
* @brief , buff
*/
MtMsgBuf(int max_len) {
_max_len = max_len;
_msg_len = 0;
_buf_type = BUFF_UNDEF;
_recv_len = 0;
_send_len = 0;
_msg_buff = malloc(max_len);
};
~MtMsgBuf() {
if (_msg_buff) {
free(_msg_buff);
_msg_buff = NULL;
}
};
/**
* @brief
*/
void SetBuffType(BUFF_TYPE type) {
_buf_type = (int)type;
};
BUFF_TYPE GetBuffType() {
return (BUFF_TYPE)_buf_type;
};
/**
* @brief ,
*/
void Reset() {
_msg_len = 0;
_recv_len = 0;
_send_len = 0;
_buf_type = BUFF_UNDEF;
};
/**
* @brief
*/
void SetMsgLen(int msg_len) {
_msg_len = msg_len;
};
int GetMsgLen() {
return _msg_len;
};
/**
* @brief buffer
*/
int GetMaxLen() {
return _max_len;
};
void* GetMsgBuff() {
return _msg_buff;
};
/**
* @brief
*/
int GetHaveSndLen() {
return _send_len;
};
void SetHaveSndLen(int snd_len) {
_send_len = snd_len;
};
/**
* @brief
*/
int GetHaveRcvLen() {
return _recv_len;
};
void SetHaveRcvLen(int rcv_len) {
_recv_len = rcv_len;
};
};
/**
* @brief buffer,
*/
class MsgBufMap : public HashKey
{
public:
/**
* @brief buff
* @param buff_size mapbuff, buff
* @param max_free , free
*/
MsgBufMap(int buff_size, int max_free) {
_max_buf_size = buff_size;
_max_free = max_free;
this->SetDataPtr(this);
_queue_num = 0;
TAILQ_INIT(&_msg_queue);
};
/**
* @brief buff, , key
* @param buff_size mapbuff, buff
*/
explicit MsgBufMap(int buff_size) {
_max_buf_size = buff_size;
TAILQ_INIT(&_msg_queue);
};
/**
* @brief buff
*/
~MsgBufMap() {
MtMsgBuf* ptr = NULL;
MtMsgBuf* tmp = NULL;
TAILQ_FOREACH_SAFE(ptr, &_msg_queue, _entry, tmp)
{
TAILQ_REMOVE(&_msg_queue, ptr, _entry);
delete ptr;
_queue_num--;
}
TAILQ_INIT(&_msg_queue);
};
/**
* @brief buff
* @return msgbuf, NULL
*/
MtMsgBuf* GetMsgBuf(){
MtMsgBuf* ptr = NULL;
if (!TAILQ_EMPTY(&_msg_queue)) {
ptr = TAILQ_FIRST(&_msg_queue);
TAILQ_REMOVE(&_msg_queue, ptr, _entry);
_queue_num--;
} else {
ptr = new MtMsgBuf(_max_buf_size);
}
return ptr;
};
/**
* @brief buff
* @param msgbuf
*/
void FreeMsgBuf(MtMsgBuf* ptr){
if (_queue_num >= _max_free) {
delete ptr;
} else {
ptr->Reset();
TAILQ_INSERT_TAIL(&_msg_queue, ptr, _entry);
_queue_num++;
}
};
/**
* @brief hash, keyhash
* @return hash
*/
virtual uint32_t HashValue(){
return _max_buf_size;
};
/**
* @brief cmp, ID, key
* @return hash
*/
virtual int HashCmp(HashKey* rhs){
return this->_max_buf_size - (int)rhs->HashValue();
};
private:
int _max_free; ///< 最大空闲保留个数
int _max_buf_size; ///< 本队列最大的buffsize
int _queue_num; ///< 空闲队列个数
MsgBufQueue _msg_queue; ///< 实际的空闲队列
};
/**
* @brief buffer, buffer
*/
class MsgBuffPool
{
public:
/**
* @brief buff
* @return
*/
static MsgBuffPool* Instance (void);
/**
* @brief
*/
static void Destroy(void);
/**
* @brief buff
* @param max_free ,
*/
void SetMaxFreeNum(int max_free) {
_max_free = max_free;
};
/**
* @brief buff
* @return msgbuf, NULL
*/
MtMsgBuf* GetMsgBuf(int max_size);
/**
* @brief buff
* @param msgbuf
*/
void FreeMsgBuf(MtMsgBuf* msg_buf);
/**
* @brief buff
*/
~MsgBuffPool();
private:
/**
* @brief buff
*/
explicit MsgBuffPool(int max_free = 300);
static MsgBuffPool * _instance; ///< 单例类句柄
int _max_free; ///< 最大保留空闲数目
HashList* _hash_map; ///< 按size hashmap 保存空闲队列
};
}
#endif

54
app/micro_thread/mt_msg.h Normal file
View File

@ -0,0 +1,54 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_msg.h
* @info 线
**/
#ifndef __MT_MSG_H__
#define __MT_MSG_H__
namespace NS_MICRO_THREAD {
/**
* @brief 线
*/
class IMtMsg
{
public:
/**
* @brief 线
* @return 0 -, < 0
*/
virtual int HandleProcess() { return -1; };
/**
* @brief 线
*/
IMtMsg() {};
virtual ~IMtMsg() {};
};
}
#endif

1987
app/micro_thread/mt_net.cpp Normal file

File diff suppressed because it is too large Load Diff

718
app/micro_thread/mt_net.h Normal file
View File

@ -0,0 +1,718 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_net.h
* @info 线
**/
#ifndef __MT_NET_H__
#define __MT_NET_H__
#include "micro_thread.h"
#include "hash_list.h"
#include "mt_api.h"
#include "mt_cache.h"
#include "mt_net_api.h"
namespace NS_MICRO_THREAD {
/**
* @brief
*/
enum MT_CONN_TYPE
{
TYPE_CONN_UNKNOWN = 0,
TYPE_CONN_SHORT = 0x1, ///< 短连接, 一次交互后关闭
TYPE_CONN_POOL = 0x2, ///< 长连接,每次使用后, 可回收重复使用
TYPE_CONN_SESSION = 0x4, ///< 长连接按session id 复用, 防串包
TYPE_CONN_SENDONLY = 0x8, ///< 只发不收
};
/******************************************************************************/
/* 内部实现部分 */
/******************************************************************************/
class CSockLink;
/**
* @brief
* @info Listtailq, Type reset, releasetime, linkentry
*/
template <typename List, typename Type>
class CRecyclePool
{
public:
// 构造函数, 默认60s超时
CRecyclePool() {
_expired = 60 * 1000;
_count = 0;
TAILQ_INIT(&_free_list);
};
// 析构函数, 删除池中元素
~CRecyclePool() {
Type* item = NULL;
Type* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &_free_list, _link_entry, tmp)
{
TAILQ_REMOVE(&_free_list, item, _link_entry);
delete item;
}
_count = 0;
};
// 复用或新创建对象
Type* AllocItem() {
Type* item = TAILQ_FIRST(&_free_list);
if (item != NULL)
{
TAILQ_REMOVE(&_free_list, item, _link_entry);
_count--;
return item;
}
item = new Type();
if (NULL == item)
{
return NULL;
}
return item;
};
// 释放管理对象
void FreeItem(Type* obj) {
//obj->Reset();
TAILQ_INSERT_TAIL(&_free_list, obj, _link_entry);
obj->_release_time = mt_time_ms();
_count++;
};
// 回收句柄
void RecycleItem(uint64_t now) {
Type* item = NULL;
Type* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &_free_list, _link_entry, tmp)
{
if ((now - item->_release_time) < _expired) {
break;
}
TAILQ_REMOVE(&_free_list, item, _link_entry);
delete item;
_count--;
}
};
// 设置自定义的超时时间
void SetExpiredTime(uint64_t expired) {
_expired = expired;
};
private:
List _free_list; ///< 空闲链表
uint64_t _expired; ///< 超时时间
uint32_t _count; ///< 元素计数
};
/**
* @brief IO
*/
class CNetHandler : public HashKey
{
public:
// 句柄状态描述
enum {
STATE_IN_SESSION = 0x1,
STATE_IN_CONNECT = 0x2,
STATE_IN_SEND = 0x4,
STATE_IN_RECV = 0x8,
STATE_IN_IDLE = 0x10,
};
/**
* @brief hash, keyhash
* @return hash
*/
virtual uint32_t HashValue();
/**
* @brief cmp, ID, key
* @return hash
*/
virtual int HashCmp(HashKey* rhs);
// 同步收发接口
int32_t SendRecv(void* data, uint32_t len, uint32_t timeout);
// 获取返回buff信息, 有效期直到helper析构
void* GetRspBuff() {
if (_rsp_buff != NULL) {
return _rsp_buff->data;
} else {
return NULL;
}
};
// 获取返回buff信息, 有效期直到helper析构
uint32_t GetRspLen() {
if (_rsp_buff != NULL) {
return _rsp_buff->data_len;
} else {
return 0;
}
};
// 设置rsp信息
void SetRespBuff(TSkBuffer* buff) {
if (_rsp_buff != NULL) {
delete_sk_buffer(_rsp_buff);
_rsp_buff = NULL;
}
_rsp_buff = buff;
};
// 设置协议的类型, 默认UDP
void SetProtoType(MT_PROTO_TYPE type) {
_proto_type = type;
};
// 设置连接类型, 默认长连接
void SetConnType(MT_CONN_TYPE type) {
_conn_type = type;
};
// 设置目的IP地址
void SetDestAddress(struct sockaddr_in* dst) {
if (dst != NULL) {
memcpy(&_dest_ipv4, dst, sizeof(*dst));
}
};
// 设置session本次session id信息, 必须非0
void SetSessionId(uint64_t sid) {
_session_id = sid;
};
// 设置session解析回调函数
void SetSessionCallback(CHECK_SESSION_CALLBACK function) {
_callback = function;
};
// 获取回调函数信息
CHECK_SESSION_CALLBACK GetSessionCallback() {
return _callback;
};
public:
// 关联连接对象
void Link(CSockLink* conn);
// 解耦连接对象
void Unlink();
// 检查必要的参数信息
int32_t CheckParams();
// 获取链接, 同时关联到等待连接的队列中
int32_t GetConnLink();
// 检查必要的参数信息
int32_t WaitConnect(uint64_t timeout);
// 检查必要的参数信息
int32_t WaitSend(uint64_t timeout);
// 检查必要的参数信息
int32_t WaitRecv(uint64_t timeout);
// 关联在等待连接队列
void SwitchToConn();
// 切换到发送队列
void SwitchToSend();
// 切换到接收队列
void SwitchToRecv();
// 切换到空闲状态
void SwitchToIdle();
// 解耦连接对象
void DetachConn();
// 注册session管理
bool RegistSession();
// 取消注册session
void UnRegistSession();
// 跳过发送的请求长度
uint32_t SkipSendPos(uint32_t len);
// 设置返回码
void SetErrNo(int32_t err) {
_err_no = err;
};
// 获取关联的线程信息
MicroThread* GetThread() {
return _thread;
};
// 获取待发送的指针与数据长度
void GetSendData(void*& data, uint32_t& len) {
data = _req_data;
len = _req_len;
};
// 复用接口
void Reset();
// 构造与析构
CNetHandler();
~CNetHandler();
// 队列快捷访问的宏定义
TAILQ_ENTRY(CNetHandler) _link_entry;
uint64_t _release_time;
protected:
MicroThread* _thread; ///< 关联线程指针对象
MT_PROTO_TYPE _proto_type; ///< 协议类型
MT_CONN_TYPE _conn_type; ///< 连接类型
struct sockaddr_in _dest_ipv4; ///< ipv4目的地址
uint64_t _session_id; ///< 会话ID
CHECK_SESSION_CALLBACK _callback; ///< 会话提取回调函数
uint32_t _state_flags; ///< 内部状态字段
int32_t _err_no; ///< 返回码信息
void* _conn_ptr; ///< socket 链路指针
uint32_t _send_pos; ///< 已发送的pos位置
uint32_t _req_len; ///< 请求包长度
void* _req_data; ///< 请求包指针
TSkBuffer* _rsp_buff; ///< 应答buff信息
};
typedef TAILQ_HEAD(__NetHandlerList, CNetHandler) TNetItemList; ///< 高效的双链管理
typedef CRecyclePool<TNetItemList, CNetHandler> TNetItemPool; ///< 定时回收的对象池
/**
* @brief
*/
class CSockLink : public KqueuerObj
{
public:
// 句柄状态描述
enum {
LINK_CONNECTING = 0x1,
LINK_CONNECTED = 0x2,
};
// 状态队列定义
enum {
LINK_IDLE_LIST = 1,
LINK_CONN_LIST = 2,
LINK_SEND_LIST = 3,
LINK_RECV_LIST = 4,
};
// 检查或创建socket句柄
int32_t CreateSock();
// 关闭链路的句柄
void Close();
// 发起连接过程
bool Connect();
bool Connected() {
return (_state & LINK_CONNECTED);
}
// 异常终止的处理函数
void Destroy();
// 获取管理链表
TNetItemList* GetItemList(int32_t type);
// 管理句柄信息
void AppendToList(int32_t type, CNetHandler* item);
// 管理句柄信息
void RemoveFromList(int32_t type, CNetHandler* item);
// 获取目标ip信息
struct sockaddr_in* GetDestAddr(struct sockaddr_in* addr);
// 发起连接过程
int32_t SendData(void* data, uint32_t len);
// udp发送数据
int32_t SendCacheUdp(void* data, uint32_t len);
// tcp发送数据
int32_t SendCacheTcp(void* data, uint32_t len);
// 尝试接收更多的数据到临时buff
void ExtendRecvRsp();
// 数据分发处理过程
int32_t RecvDispath();
// 或者回调函数, 优先从排队等待中获取, 备份从父节点获取
CHECK_SESSION_CALLBACK GetSessionCallback();
// TCP接收数据流处理与分发
int32_t DispathTcp();
// UDP接收数据流处理与分发
int32_t DispathUdp();
// 查询本地sessionid关联的session信息
CNetHandler* FindSession(uint64_t sid);
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int InputNotify();
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int OutputNotify();
/**
* @brief
* @return ,
*/
virtual int HangupNotify();
// 构造与析构函数
CSockLink();
~CSockLink();
// 清理置初始化逻辑
void Reset();
// 通知唤醒线程
void NotifyThread(CNetHandler* item, int32_t result);
// 通知唤醒线程
void NotifyAll(int32_t result);
// 设置协议类型, 决定buff池的指针
void SetProtoType(MT_PROTO_TYPE type);
// 设置上级指针信息
void SetParentsPtr(void* ptr) {
_parents = ptr;
};
// 获取上级节点指针
void* GetParentsPtr() {
return _parents;
};
// 获取上次的访问时间
uint64_t GetLastAccess() {
return _last_access;
};
public:
// 队列快捷访问的宏定义
TAILQ_ENTRY(CSockLink) _link_entry;
uint64_t _release_time;
private:
TNetItemList _wait_connect;
TNetItemList _wait_send;
TNetItemList _wait_recv;
TNetItemList _idle_list;
MT_PROTO_TYPE _proto_type;
int32_t _errno;
uint32_t _state;
uint64_t _last_access;
TRWCache _recv_cache;
TSkBuffer* _rsp_buff;
void* _parents;
};
typedef TAILQ_HEAD(__SocklinkList, CSockLink) TLinkList; ///< 高效的双链管理
typedef CRecyclePool<TLinkList, CSockLink> TLinkPool; ///< 定时回收的对象池
class CDestLinks : public CTimerNotify, public HashKey
{
public:
// 构造函数
CDestLinks();
// 析构函数
~CDestLinks();
// 重置复用的接口函数
void Reset();
// 启动定时器
void StartTimer();
// 获取一个连接link, 暂时按轮询
CSockLink* GetSockLink();
// 释放一个连接link
void FreeSockLink(CSockLink* sock);
// 获取协议类型
MT_PROTO_TYPE GetProtoType() {
return _proto_type;
};
// 获取连接类型
MT_CONN_TYPE GetConnType() {
return _conn_type;
};
// 设置关键信息
void SetKeyInfo(uint32_t ipv4, uint16_t port, MT_PROTO_TYPE proto, MT_CONN_TYPE conn) {
_addr_ipv4 = ipv4;
_net_port = port;
_proto_type = proto;
_conn_type = conn;
};
// 拷贝KEY信息
void CopyKeyInfo(CDestLinks* key) {
_addr_ipv4 = key->_addr_ipv4;
_net_port = key->_net_port;
_proto_type = key->_proto_type;
_conn_type = key->_conn_type;
};
// 获取IP port信息
void GetDestIP(uint32_t& ip, uint16_t& port) {
ip = _addr_ipv4;
port = _net_port;
};
/**
* @brief , ,
*/
virtual void timer_notify();
/**
* @brief hash, keyhash
* @return hash
*/
virtual uint32_t HashValue() {
return _addr_ipv4 ^ (((uint32_t)_net_port << 16) | (_proto_type << 8) | _conn_type);
};
/**
* @brief cmp, ID, key
* @return hash
*/
virtual int HashCmp(HashKey* rhs) {
CDestLinks* data = (CDestLinks*)(rhs);
if (!data) {
return -1;
}
if (this->_addr_ipv4 != data->_addr_ipv4) {
return (this->_addr_ipv4 > data->_addr_ipv4) ? 1 : -1;
}
if (this->_net_port != data->_net_port) {
return (this->_net_port > data->_net_port) ? 1 : -1;
}
if (this->_proto_type != data->_proto_type) {
return (this->_proto_type > data->_proto_type) ? 1 : -1;
}
if (this->_conn_type != data->_conn_type) {
return (this->_conn_type > data->_conn_type) ? 1 : -1;
}
return 0;
};
// 设置session解析回调函数
void SetDefaultCallback(CHECK_SESSION_CALLBACK function) {
_dflt_callback = function;
};
// 获取回调函数信息
CHECK_SESSION_CALLBACK GetDefaultCallback() {
return _dflt_callback;
};
// 队列快捷访问的宏定义
TAILQ_ENTRY(CDestLinks) _link_entry;
uint64_t _release_time;
private:
uint32_t _timeout; ///< idle的超时时间
uint32_t _addr_ipv4; ///< ip地址
uint16_t _net_port; ///< port 网络序列
MT_PROTO_TYPE _proto_type; ///< 协议类型
MT_CONN_TYPE _conn_type; ///< 连接类型
uint32_t _max_links; ///< 最大连接数
uint32_t _curr_link; ///< 当前连接数
TLinkList _sock_list; ///< 连接链表
CHECK_SESSION_CALLBACK _dflt_callback; ///< 默认的check函数
};
typedef TAILQ_HEAD(__DestlinkList, CDestLinks) TDestList; ///< 高效的双链管理
typedef CRecyclePool<TDestList, CDestLinks> TDestPool; ///< 定时回收的对象池
/**
* @brief
*/
class CNetMgr
{
public:
/**
* @brief buff
* @return
*/
static CNetMgr* Instance (void);
/**
* @brief
*/
static void Destroy(void);
// 查询是否已经存在同一个sid的对象
CNetHandler* FindNetItem(CNetHandler* key);
// 注册一个item, 先查询后插入, 保证无冲突
void InsertNetItem(CNetHandler* item);
// 移除一个item对象
void RemoveNetItem(CNetHandler* item);
// 查询或创建一个目标ip的links节点
CDestLinks* FindCreateDest(CDestLinks* key);
// 删除掉已有的目标链路信息
void DeleteDestLink(CDestLinks* dst);
// 查询是否已经存在同一个sid的对象
CDestLinks* FindDestLink(CDestLinks* key);
// 注册一个item, 先查询后插入, 保证无冲突
void InsertDestLink(CDestLinks* item);
// 移除一个item对象
void RemoveDestLink(CDestLinks* item);
/**
* @brief buff
*/
~CNetMgr();
/**
* @brief
*/
void RecycleObjs(uint64_t now);
// 分配一个网络管理句柄
CNetHandler* AllocNetItem() {
return _net_item_pool.AllocItem();
};
// 释放一个网络管理句柄
void FreeNetItem(CNetHandler* item) {
return _net_item_pool.FreeItem(item);
};
// 分配一个SOCK连接链路
CSockLink* AllocSockLink() {
return _sock_link_pool.AllocItem();
};
// 释放一个SOCK连接链路
void FreeSockLink(CSockLink* item) {
return _sock_link_pool.FreeItem(item);
};
// 分配一个SOCK连接链路
CDestLinks* AllocDestLink() {
return _dest_ip_pool.AllocItem();
};
// 释放一个SOCK连接链路
void FreeDestLink(CDestLinks* item) {
return _dest_ip_pool.FreeItem(item);
};
// 获取udp的buff池信息
TSkBuffMng* GetSkBuffMng(MT_PROTO_TYPE type) {
if (type == NET_PROTO_TCP) {
return &_tcp_pool;
} else {
return &_udp_pool;
}
};
private:
/**
* @brief buff
*/
CNetMgr();
static CNetMgr * _instance; ///< 单例类句柄
HashList* _ip_hash; ///< 目的地址hash
HashList* _session_hash; ///< session id的hash
TSkBuffMng _udp_pool; ///< udp pool, 64K
TSkBuffMng _tcp_pool; ///< tcp pool, 4K
TDestPool _dest_ip_pool; ///< 目的ip对象池
TLinkPool _sock_link_pool; ///< socket pool
TNetItemPool _net_item_pool; ///< net handle pool
};
}
#endif

View File

@ -0,0 +1,123 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_net_api.h
* @info 线
**/
#ifndef __MT_NET_API_H__
#define __MT_NET_API_H__
#include <netinet/in.h>
namespace NS_MICRO_THREAD {
/**
* @brief
*/
enum MT_PROTO_TYPE
{
NET_PROTO_UNDEF = 0,
NET_PROTO_UDP = 0x1, ///< 连接类型 UDP
NET_PROTO_TCP = 0x2 ///< 连接类型 TCP
};
/**
* @brief
*/
enum MT_RC_TYPE
{
RC_SUCCESS = 0,
RC_ERR_SOCKET = -1, ///< 创建socket失败
RC_SEND_FAIL = -2, ///< 发送失败
RC_RECV_FAIL = -3, ///< 接收失败
RC_CONNECT_FAIL = -4, ///< 连接失败
RC_CHECK_PKG_FAIL = -5, ///< 报文检测失败
RC_NO_MORE_BUFF = -6, ///< 空间超过限制
RC_REMOTE_CLOSED = -7, ///< 后端关闭连接
RC_INVALID_PARAM = -10, ///< 无效参数
RC_INVALID_HANDLER = -11, ///< 无效的句柄
RC_MEM_ERROR = -12, ///< 内存异常
RC_CONFLICT_SID = -13, ///< SESSION ID冲突
RC_KQUEUE_ERROR = -14, ///< rst信号等
};
/**
* @brief , session
* @info need_len, ,
* ,
* @param data -
* @param len -
* @param session_id -sessionid
* @param need_len -buff, 100M
* @return >0 ; =0 , ; <0
*/
typedef int32_t (*CHECK_SESSION_CALLBACK)(const void* data, uint32_t len,
uint64_t* session_id, uint32_t* need_len);
/**
* @brief
*/
class CNetHelper
{
public:
// 转发返回码信息, 按需获取
static char* GetErrMsg(int32_t result);
// 同步收发接口
int32_t SendRecv(void* data, uint32_t len, uint32_t timeout);
// 获取返回buff信息, 有效期直到helper析构
void* GetRspBuff();
// 获取返回包的长度
uint32_t GetRspLen();
// 设置协议的类型, 默认UDP
void SetProtoType(MT_PROTO_TYPE type);
// 设置目的IP地址
void SetDestAddress(struct sockaddr_in* dst);
// 设置session本次session id信息, 必须非0
void SetSessionId(uint64_t sid);
// 设置session解析回调函数
void SetSessionCallback(CHECK_SESSION_CALLBACK function);
// 构造与虚构
CNetHelper();
~CNetHelper();
private:
void* handler; // 私有句柄, 利于扩展
};
}
#endif

View File

@ -0,0 +1,571 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_notify.cpp
* @info 线
* @time 20130924
**/
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "micro_thread.h"
#include "mt_session.h"
#include "mt_msg.h"
#include "mt_notify.h"
#include "mt_connection.h"
#include "mt_sys_hook.h"
#include "ff_hook.h"
using namespace std;
using namespace NS_MICRO_THREAD;
/**
* @brief ,
* @param proxy session
*/
void ISessionNtfy::InsertWriteWait(SessionProxy* proxy)
{
if (!proxy->_flag) {
TAILQ_INSERT_TAIL(&_write_list, proxy, _write_entry);
proxy->_flag = 1;
}
}
/**
* @brief
* @param proxy session
*/
void ISessionNtfy::RemoveWriteWait(SessionProxy* proxy)
{
if (proxy->_flag) {
TAILQ_REMOVE(&_write_list, proxy, _write_entry);
proxy->_flag = 0;
}
}
/**
* @brief , 线
* @info UDP线, TCP
*/
void UdpSessionNtfy::NotifyWriteWait()
{
MtFrame* frame = MtFrame::Instance();
SessionProxy* proxy = NULL;
MicroThread* thread = NULL;
TAILQ_FOREACH(proxy, &_write_list, _write_entry)
{
proxy->SetRcvEvents(KQ_EVENT_WRITE);
thread = proxy->GetOwnerThread();
if (thread && thread->HasFlag(MicroThread::IO_LIST))
{
frame->RemoveIoWait(thread);
frame->InsertRunable(thread);
}
}
}
/**
* @brief socket,
* @return fd, <0
*/
int UdpSessionNtfy::CreateSocket()
{
// 1. UDP短连接, 每次新创SOCKET
int osfd = socket(AF_INET, SOCK_DGRAM, 0);
if (osfd < 0)
{
MTLOG_ERROR("socket create failed, errno %d(%s)", errno, strerror(errno));
return -1;
}
// 2. 非阻塞设置
int flags = 1;
if (ioctl(osfd, FIONBIO, &flags) < 0)
{
MTLOG_ERROR("socket unblock failed, errno %d(%s)", errno, strerror(errno));
close(osfd);
osfd = -1;
return -2;
}
// 可选bind执行, 设置本地port后执行
if (_local_addr.sin_port != 0)
{
int ret = bind(osfd, (struct sockaddr *)&_local_addr, sizeof(_local_addr));
if (ret < 0)
{
MTLOG_ERROR("socket bind(%s:%d) failed, errno %d(%s)", inet_ntoa(_local_addr.sin_addr),
ntohs(_local_addr.sin_port), errno, strerror(errno));
close(osfd);
osfd = -1;
return -3;
}
}
// 3. 更新管理信息, 默认udp session 侦听 epollin
this->SetOsfd(osfd);
this->EnableInput();
MtFrame* frame = MtFrame::Instance();
frame->KqueueNtfyReg(osfd, this);
frame->KqueueCtrlAdd(osfd, KQ_EVENT_READ);
return osfd;
}
/**
* @brief socket,
*/
void UdpSessionNtfy::CloseSocket()
{
int osfd = this->GetOsfd();
if (osfd > 0)
{
MtFrame* frame = MtFrame::Instance();
frame->KqueueCtrlDel(osfd, KQ_EVENT_READ);
frame->KqueueNtfyReg(osfd, NULL);
this->DisableInput();
this->SetOsfd(-1);
close(osfd);
}
}
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
int UdpSessionNtfy::InputNotify()
{
while (1)
{
int ret = 0;
int have_rcv_len = 0;
// 1. 获取收包缓冲区, 优先选择未处理完的链接buff
if (!_msg_buff) {
_msg_buff = MsgBuffPool::Instance()->GetMsgBuf(this->GetMsgBuffSize());
if (NULL == _msg_buff) {
MTLOG_ERROR("Get memory failed, size %d, wait next time", this->GetMsgBuffSize());
return 0;
}
_msg_buff->SetBuffType(BUFF_RECV);
}
char* buff = (char*)_msg_buff->GetMsgBuff();
// 2. 获取socket, 收包处理
int osfd = this->GetOsfd();
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
mt_hook_syscall(recvfrom);
ret = ff_hook_recvfrom(osfd, buff, _msg_buff->GetMaxLen(),
0, (struct sockaddr*)&from, &fromlen);
if (ret < 0)
{
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
{
return 0;
}
else
{
MTLOG_ERROR("recv error, fd %d", osfd);
return 0; // 系统错误, UDP 暂不关闭
}
}
else if (ret == 0)
{
MTLOG_DEBUG("remote close connection, fd %d", osfd);
return 0; // 对端关闭, UDP 暂不关闭
}
else
{
have_rcv_len = ret;
_msg_buff->SetHaveRcvLen(have_rcv_len);
_msg_buff->SetMsgLen(have_rcv_len);
}
// 3. 检查消息的完整性, 提取sessionid
int sessionid = 0;
ret = this->GetSessionId(buff, have_rcv_len, sessionid);
if (ret <= 0)
{
MTLOG_ERROR("recv get session failed, len %d, fd %d, drop it",
have_rcv_len, osfd);
MsgBuffPool::Instance()->FreeMsgBuf(_msg_buff);
_msg_buff = NULL;
return 0;
}
// 4. 映射查询thread句柄, 连接handle句柄, 设置读事件来临, 挂接msgbuff
ISession* session = SessionMgr::Instance()->FindSession(sessionid);
if (NULL == session)
{
MT_ATTR_API(350403, 1); // session 到达已超时
MTLOG_DEBUG("session %d, not find, maybe timeout, drop pkg", sessionid);
MsgBuffPool::Instance()->FreeMsgBuf(_msg_buff);
_msg_buff = NULL;
return 0;
}
// 5. 挂接recvbuff, 唤醒线程
IMtConnection* conn = session->GetSessionConn();
MicroThread* thread = session->GetOwnerThread();
if (!thread || !conn || !conn->GetNtfyObj())
{
MTLOG_ERROR("sesson obj %p, no thread ptr %p, no conn %p wrong",
session, thread, conn);
MsgBuffPool::Instance()->FreeMsgBuf(_msg_buff);
_msg_buff = NULL;
return 0;
}
MtMsgBuf* msg = conn->GetMtMsgBuff();
if (msg) {
MsgBuffPool::Instance()->FreeMsgBuf(msg);
}
conn->SetMtMsgBuff(_msg_buff);
_msg_buff = NULL;
conn->GetNtfyObj()->SetRcvEvents(KQ_EVENT_READ);
if (thread->HasFlag(MicroThread::IO_LIST))
{
MtFrame* frame = MtFrame::Instance();
frame->RemoveIoWait(thread);
frame->InsertRunable(thread);
}
}
return 0;
}
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
int UdpSessionNtfy::OutputNotify()
{
NotifyWriteWait();
return 0;
}
/**
* @brief , fd, thread
* @return ,
*/
int UdpSessionNtfy::HangupNotify()
{
// 1. 清理epoll ctl监听事件
MtFrame* frame = MtFrame::Instance();
frame->KqueueCtrlDel(this->GetOsfd(), this->GetEvents());
MTLOG_ERROR("sesson obj %p, recv error event. fd %d", this, this->GetOsfd());
// 2. 重新打开socket
CloseSocket();
// 3. 重加入epoll listen
CreateSocket();
return 0;
}
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
* @info ,
*/
int UdpSessionNtfy::KqueueCtlAdd(void* args)
{
MtFrame* frame = MtFrame::Instance();
KqFdRef* fd_ref = (KqFdRef*)args;
//ASSERT(fd_ref != NULL);
int osfd = this->GetOsfd();
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
KqueuerObj* old_obj = fd_ref->GetNotifyObj();
if ((old_obj != NULL) && (old_obj != this))
{
MTLOG_ERROR("epfd ref conflict, fd: %d, old: %p, now: %p", osfd, old_obj, this);
return -1;
}
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
if (!frame->KqueueCtrlAdd(osfd, KQ_EVENT_WRITE))
{
MTLOG_ERROR("epfd ref add failed, log");
return -2;
}
this->EnableOutput();
return 0;
}
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
int UdpSessionNtfy::KqueueCtlDel(void* args)
{
MtFrame* frame = MtFrame::Instance();
KqFdRef* fd_ref = (KqFdRef*)args;
//ASSERT(fd_ref != NULL);
int osfd = this->GetOsfd();
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
KqueuerObj* old_obj = fd_ref->GetNotifyObj();
if (old_obj != this)
{
MTLOG_ERROR("epfd ref conflict, fd: %d, old: %p, now: %p", osfd, old_obj, this);
return -1;
}
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
if (!frame->KqueueCtrlDel(osfd, KQ_EVENT_WRITE))
{
MTLOG_ERROR("epfd ref del failed, log");
return -2;
}
this->DisableOutput();
return 0;
}
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
int TcpKeepNtfy::InputNotify()
{
KeepaliveClose();
return -1;
}
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
int TcpKeepNtfy::OutputNotify()
{
KeepaliveClose();
return -1;
}
/**
* @brief
* @return ,
*/
int TcpKeepNtfy::HangupNotify()
{
KeepaliveClose();
return -1;
}
/**
* @brief
*/
void TcpKeepNtfy::KeepaliveClose()
{
if (_keep_conn) {
MTLOG_DEBUG("remote close, fd %d, close connection", _fd);
ConnectionMgr::Instance()->CloseIdleTcpKeep(_keep_conn);
} else {
MTLOG_ERROR("_keep_conn ptr null, error");
}
}
/**
* @brief session
* @return
*/
NtfyObjMgr* NtfyObjMgr::_instance = NULL;
NtfyObjMgr* NtfyObjMgr::Instance (void)
{
if (NULL == _instance)
{
_instance = new NtfyObjMgr;
}
return _instance;
}
/**
* @brief session
*/
void NtfyObjMgr::Destroy()
{
if( _instance != NULL )
{
delete _instance;
_instance = NULL;
}
}
/**
* @brief buff
*/
NtfyObjMgr::NtfyObjMgr()
{
}
/**
* @brief , ,
*/
NtfyObjMgr::~NtfyObjMgr()
{
}
/**
* @brief session
* @param session_name , session
* @param session ,
* @return 0 , < 0
*/
int NtfyObjMgr::RegisterSession(int session_name, ISessionNtfy* session)
{
if (session_name <= 0 || NULL == session) {
MTLOG_ERROR("session %d, register %p failed", session_name, session);
return -1;
}
SessionMap::iterator it = _session_map.find(session_name);
if (it != _session_map.end())
{
MTLOG_ERROR("session %d, register %p already", session_name, session);
return -2;
}
_session_map.insert(SessionMap::value_type(session_name, session));
return 0;
}
/**
* @brief session
* @param session_name , session
* @return , NULL
*/
ISessionNtfy* NtfyObjMgr::GetNameSession(int session_name)
{
SessionMap::iterator it = _session_map.find(session_name);
if (it != _session_map.end())
{
return it->second;
}
else
{
return NULL;
}
}
/**
* @brief , 线session
* @param type , 线UDP/TCP SESSION
* @param session_name proxy,session
* @return , NULL
*/
KqueuerObj* NtfyObjMgr::GetNtfyObj(int type, int session_name)
{
KqueuerObj* obj = NULL;
SessionProxy* proxy = NULL;
switch (type)
{
case NTFY_OBJ_THREAD:
obj = _fd_ntfy_pool.AllocPtr();
break;
case NTFY_OBJ_SESSION:
proxy = _udp_proxy_pool.AllocPtr();
obj = proxy;
break;
case NTFY_OBJ_KEEPALIVE: // no need get this now
break;
default:
break;
}
// 获取底层的长连接对象, 关联代理与实际的通知对象
if (proxy) {
ISessionNtfy* ntfy = this->GetNameSession(session_name);
if (!ntfy) {
MTLOG_ERROR("ntfy get session name(%d) failed", session_name);
this->FreeNtfyObj(proxy);
obj = NULL;
} else {
proxy->SetRealNtfyObj(ntfy);
}
}
return obj;
}
/**
* @brief
* @param obj
*/
void NtfyObjMgr::FreeNtfyObj(KqueuerObj* obj)
{
SessionProxy* proxy = NULL;
if (!obj) {
return;
}
int type = obj->GetNtfyType();
obj->Reset();
switch (type)
{
case NTFY_OBJ_THREAD:
return _fd_ntfy_pool.FreePtr(obj);
break;
case NTFY_OBJ_SESSION:
proxy = dynamic_cast<SessionProxy*>(obj);
return _udp_proxy_pool.FreePtr(proxy);
break;
case NTFY_OBJ_KEEPALIVE:
break;
default:
break;
}
delete obj;
return;
}

View File

@ -0,0 +1,568 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_notify.h
* @info 线
* @time 20130926
**/
#ifndef __MT_NOTIFY_H__
#define __MT_NOTIFY_H__
#include <netinet/in.h>
#include <queue>
#include <map>
#include "mt_mbuf_pool.h"
namespace NS_MICRO_THREAD {
using std::queue;
using std::map;
class SessionProxy;
class TcpKeepConn;
/**
* @brief
*/
enum NTFY_OBJ_TYPE
{
NTFY_OBJ_UNDEF = 0, ///< 未定义的连接对象
NTFY_OBJ_THREAD = 1, ///< 短连接对象, 一个fd对应一个thread
NTFY_OBJ_KEEPALIVE = 2, ///< TCP心跳保持的notify对象, 不关联 thread
NTFY_OBJ_SESSION = 3, ///< UDP的session模型, 代理的长连接对象
};
/**
* @brief
*/
enum MULTI_PROTO
{
MT_UNKNOWN = 0,
MT_UDP = 0x1, ///< 连接类型 UDP
MT_TCP = 0x2 ///< 连接类型 TCP
};
/**
* @brief session,
*/
typedef TAILQ_ENTRY(SessionProxy) NtfyEntry;
typedef TAILQ_HEAD(__NtfyList, SessionProxy) NtfyList;
class ISessionNtfy : public KqueuerObj
{
public:
/**
* @brief , sessionid
* @param pkg
* @param len
* @param session sessionid,
* @return <=0 , >0
*/
virtual int GetSessionId(void* pkg, int len, int& session) { return 0;};
/**
* @brief socket,
* @return fd, <0
*/
virtual int CreateSocket(){return -1;};
/**
* @brief socket,
*/
virtual void CloseSocket(){};
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int InputNotify(){return 0;};
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int OutputNotify(){return 0;};
/**
* @brief
* @return ,
*/
virtual int HangupNotify(){return 0;};
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
virtual int KqueueCtlAdd(void* args){return 0;};
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
virtual int KqueueCtlDel(void* args){return 0;};
/**
* @brief
*/
ISessionNtfy(): KqueuerObj(0) {
_proto = MT_UDP;
_buff_size = 0;
_msg_buff = NULL;
TAILQ_INIT(&_write_list);
}
virtual ~ISessionNtfy() { };
/**
* @brief proto
*/
void SetProtoType(MULTI_PROTO proto) {
_proto = proto;
};
/**
* @brief proto
* @return proto type
*/
MULTI_PROTO GetProtoType() {
return _proto;
};
/**
* @brief buff, 使msgbuff
* @return 0
*/
void SetMsgBuffSize(int buff_size) {
_buff_size = buff_size;
};
/**
* @brief buff, , 65535
* @return buff
*/
int GetMsgBuffSize() {
return (_buff_size > 0) ? _buff_size : 65535;
}
/**
* @brief
*/
void InsertWriteWait(SessionProxy* proxy);
/**
* @brief
*/
void RemoveWriteWait(SessionProxy* proxy);
/**
* @brief , 线
* @info UDP线, TCP
*/
virtual void NotifyWriteWait(){};
protected:
MULTI_PROTO _proto; // 协议类型 UDP/TCP
int _buff_size; // 最大消息长度
NtfyList _write_list; // 可写等待队列
MtMsgBuf* _msg_buff; // 临时收包存放缓冲区
};
/**
* @brief UDPsession
* @info session, , GetSessionId
* @info ,
*/
class UdpSessionNtfy : public ISessionNtfy
{
public:
/**
* @brief , sessionid,
* @param pkg
* @param len
* @param session sessionid,
* @return <=0 , >0
*/
virtual int GetSessionId(void* pkg, int len, int& session) { return 0;};
public:
/**
* @brief
*/
UdpSessionNtfy() : ISessionNtfy(){
ISessionNtfy::SetProtoType(MT_UDP);
_local_addr.sin_family = AF_INET;
_local_addr.sin_addr.s_addr = 0;
_local_addr.sin_port = 0;
}
virtual ~UdpSessionNtfy() { };
/**
* @brief , 线
* @info UDP线, TCP
*/
virtual void NotifyWriteWait();
/**
* @brief socket,
* @return fd, <0
*/
virtual int CreateSocket();
/**
* @brief socket,
*/
virtual void CloseSocket();
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int InputNotify();
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int OutputNotify();
/**
* @brief
* @return ,
*/
virtual int HangupNotify();
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
virtual int KqueueCtlAdd(void* args);
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
virtual int KqueueCtlDel(void* args);
public:
/**
* @brief udpbind, bind,
* , port使
*/
void SetLocalAddr(struct sockaddr_in* local_addr) {
memcpy(&_local_addr, local_addr, sizeof(_local_addr));
};
protected:
struct sockaddr_in _local_addr;
};
/**
* @brief UDPsession, session notify
* @info session proxy epoll, ,
*/
class SessionProxy : public KqueuerObj
{
public:
int _flag; ///< 0-不在队列中, 1-在等待队列
NtfyEntry _write_entry; ///< 关联可写等待队列的管理入口
/**
* @brief , fd
*/
void SetRealNtfyObj(ISessionNtfy* obj) {
_real_ntfy = obj;
this->SetOsfd(obj->GetOsfd());
};
/**
* @brief
*/
ISessionNtfy* GetRealNtfyObj() {
return _real_ntfy;
};
public:
/**
* @brief ,
*/
virtual void Reset() {
_real_ntfy = NULL;
this->KqueuerObj::Reset();
};
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
virtual int KqueueCtlAdd(void* args) {
if (!_real_ntfy) {
return -1;
}
int events = this->GetEvents();
if (!(events & KQ_EVENT_WRITE)) {
return 0;
}
if (_real_ntfy->KqueueCtlAdd(args) < 0) {
return -2;
}
_real_ntfy->InsertWriteWait(this);
return 0;
};
/**
* @brief epoll, EPOLLIN, EPOLLOUT
* @param args fd
* @return 0 , < 0 ,
*/
virtual int KqueueCtlDel(void* args) {
if (!_real_ntfy) {
return -1;
}
int events = this->GetEvents();
if (!(events & KQ_EVENT_WRITE)) {
return 0;
}
_real_ntfy->RemoveWriteWait(this);
return _real_ntfy->KqueueCtlDel(args);
};
private:
ISessionNtfy* _real_ntfy; // 实际的执行者
};
/**
* @brief TCPkeepalive, ,
*/
class TcpKeepNtfy: public KqueuerObj
{
public:
/**
* @brief
*/
TcpKeepNtfy() : _keep_conn(NULL){};
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int InputNotify();
/**
* @brief , ,
* @return 0 fd; !=0 fd
*/
virtual int OutputNotify();
/**
* @brief
* @return ,
*/
virtual int HangupNotify();
/**
* @brief
*/
void SetKeepNtfyObj(TcpKeepConn* obj) {
_keep_conn = obj;
};
/**
* @brief
*/
TcpKeepConn* GetKeepNtfyObj() {
return _keep_conn;
};
/**
* @brief
*/
void KeepaliveClose();
private:
TcpKeepConn* _keep_conn; // 实际的连接器对象
};
/**
* @brief , new/delete,
*/
template<typename ValueType>
class CPtrPool
{
public:
typedef typename std::queue<ValueType*> PtrQueue; ///< 内存指针队列
public:
/**
* @brief
* @param max , 500
*/
explicit CPtrPool(int max = 500) : _max_free(max), _total(0){};
/**
* @brief , freelist
*/
~CPtrPool() {
ValueType* ptr = NULL;
while (!_ptr_list.empty()) {
ptr = _ptr_list.front();
_ptr_list.pop();
delete ptr;
}
};
/**
* @brief , , new
* @return ,
*/
ValueType* AllocPtr() {
ValueType* ptr = NULL;
if (!_ptr_list.empty()) {
ptr = _ptr_list.front();
_ptr_list.pop();
} else {
ptr = new ValueType;
_total++;
}
return ptr;
};
/**
* @brief , , ,
*/
void FreePtr(ValueType* ptr) {
if ((int)_ptr_list.size() >= _max_free) {
delete ptr;
_total--;
} else {
_ptr_list.push(ptr);
}
};
protected:
PtrQueue _ptr_list; ///< 空闲队列
int _max_free; ///< 最大空闲元素
int _total; ///< 所有new的对象个数统计
};
/**
* @brief
*/
class NtfyObjMgr
{
public:
typedef std::map<int, ISessionNtfy*> SessionMap;
typedef CPtrPool<KqueuerObj> NtfyThreadQueue;
typedef CPtrPool<SessionProxy> NtfySessionQueue;
/**
* @brief
* @return
*/
static NtfyObjMgr* Instance (void);
/**
* @brief
*/
static void Destroy(void);
/**
* @brief session
* @param session_name , session
* @param session ,
* @return 0 , < 0
*/
int RegisterSession(int session_name, ISessionNtfy* session);
/**
* @brief session
* @param session_name , session
* @return , NULL
*/
ISessionNtfy* GetNameSession(int session_name);
/**
* @brief , 线session
* @param type , 线UDP/TCP SESSION
* @param session_name proxy,session
* @return , NULL
*/
KqueuerObj* GetNtfyObj(int type, int session_name = 0);
/**
* @brief
* @param obj
*/
void FreeNtfyObj(KqueuerObj* obj);
/**
* @brief
*/
~NtfyObjMgr();
private:
/**
* @brief buff
*/
NtfyObjMgr();
static NtfyObjMgr * _instance; ///< 单例类句柄
SessionMap _session_map; ///< 全局的注册session管理
NtfyThreadQueue _fd_ntfy_pool; ///< fd通知对象
NtfySessionQueue _udp_proxy_pool; ///< fd通知对象
};
}
#endif

View File

@ -0,0 +1,251 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mt_incl.h"
#include "micro_thread.h"
using namespace NS_MICRO_THREAD;
static bool run = true;
static struct sockaddr_in addr;
int mt_tcp_create_sock(void)
{
int fd;
//int flag;
// ´´½¨socket
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
printf("create tcp socket failed, error: %m\n");
return -1;
}
// ÉèÖÃsocket·Ç×èÈû
/*
flag = fcntl(fd, F_GETFL, 0);
if (flag == -1)
{
::close(fd);
printf("get fd flags failed, error: %m\n");
return -2;
}
if (flag & O_NONBLOCK)
return fd;
if (fcntl(fd, F_SETFL, flag | O_NONBLOCK | O_NDELAY) == -1)
{
::close(fd);
printf("set fd flags failed, error: %m\n");
return -3;
}
*/
int nb = 1;
ioctl(fd, FIONBIO, &nb);
return fd;
}
void echo(void* arg)
{
char buf[1024];
int ret = 0;
int *p = (int *)arg;
int clt_fd = *p;
printf("start to echo with client: %d\n", clt_fd);
while (1) {
ret = mt_recv(clt_fd, (void*)buf,1024,0,-1);
if(ret<0)
{
printf("recv client data failed[%m]\n");
mt_sleep(1);
break;
}
ret = mt_send(clt_fd, (void*)buf, ret, 0, 1000);
if (ret < 0) {
printf("send client data failed[%m]\n");
mt_sleep(1);
break;
}
}
if(clt_fd>0) close(clt_fd);
delete p;
}
void server(void* arg)
{
int fd = mt_tcp_create_sock();
if(fd<0)
{
run = false;
printf("create listen socket failed\n");
return;
}
int optval = 1;
unsigned optlen = sizeof(optval);
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
close(fd);
printf("bind failed [%m]\n");
return ;
}
if (listen(fd, 1024) < 0)
{
close(fd);
printf("listen failed[%m]\n");
return ;
}
int clt_fd = 0;
int *p;
while(run)
{
struct sockaddr_in client_addr;
int addr_len = sizeof(client_addr);;
clt_fd = mt_accept(fd, (struct sockaddr*)&client_addr, (socklen_t*)&addr_len, -1);
if(clt_fd<0)
{
mt_sleep(1);
continue;
}
int nb = 1;
ioctl(clt_fd, FIONBIO, &nb);
p = new int(clt_fd);
printf("start a new micro thread to echo with client: %d\n", clt_fd);
mt_start_thread((void*)echo, (void *)p);
mt_sleep(1);
}
printf("server exit\n");
}
struct MsgCtx
{
int check_count;
int msg_id;
};
int TcpMsgChecker(void* buf, int len, bool closed, void* msg_ctx, bool& msg_len_detected)
{
struct MsgCtx* ctx = (struct MsgCtx*)msg_ctx;
ctx->check_count++;
printf("#%d msg check msg times #%d, buf=%p, len=%d, closed=%d\n", ctx->msg_id, ctx->check_count, buf,len,closed);
if(len<4)
{
return 0;
}
int r_len=ntohl(*(uint32_t*)buf);
//if(r_len!=len)
// {
// return 0;
//}
msg_len_detected = true;
return r_len;
}
/*
void client(void* arg)
{
//char buf[1024];
struct MsgCtx ctx;
void* rcv_buf = NULL;
int rcv_len = 0;
bool keep_rcv_buf = true;
int ret = 0;
char snd_ch = 1;
int count=0;
while(true)
{
rcv_buf = NULL;
rcv_len = 1;
keep_rcv_buf = (((++count)%2) == 0);
ctx.check_count = 0;
ctx.msg_id = count;
ret = mt_tcpsendrcv_ex((struct sockaddr_in*)&addr, (void*)&snd_ch, 1, rcv_buf, rcv_len,20000, &TcpMsgChecker, (void*)&ctx, MT_TCP_SHORT,keep_rcv_buf);
if(ret<0)
{
printf("client send rcv failed[%m]\n");
continue;
}
printf("#%d client tcp finished: rcv_len=%d, rcv_buf=%p, keep_rcv_buf=%d\n",count, rcv_len, rcv_buf,keep_rcv_buf);
if(keep_rcv_buf)
{
if(rcv_buf==NULL)
{
printf("client should hold rcvbuf, something wrong\n");
continue;
}
free(rcv_buf);
}
}
printf("client exit!");
}
*/
int main(int argc, char* argv[])
{
memset((void*)&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr = inet_addr("112.90.143.29");
addr.sin_port = htons(19999);
mt_init_frame("./config.ini", argc, argv);
mt_start_thread((void*)server,NULL);
while (run) {
mt_sleep(10);
}
printf("main exit");
}

View File

@ -0,0 +1,142 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_session.cpp
* @info 线
* @time 20130924
**/
#include "micro_thread.h"
#include "mt_session.h"
using namespace std;
using namespace NS_MICRO_THREAD;
/**
* @brief session
*/
ISession::~ISession()
{
if (_session_flg) {
SessionMgr* sessionmgr = SessionMgr::Instance();
sessionmgr->RemoveSession(_session_id);
_session_flg = (int)SESSION_IDLE; // 额外处理, 在remove函数内处理会加大开销
}
}
/**
* @brief session
* @return
*/
SessionMgr* SessionMgr::_instance = NULL;
SessionMgr* SessionMgr::Instance (void)
{
if (NULL == _instance)
{
_instance = new SessionMgr;
}
return _instance;
}
/**
* @brief session
*/
void SessionMgr::Destroy()
{
if( _instance != NULL )
{
delete _instance;
_instance = NULL;
}
}
/**
* @brief buff
*/
SessionMgr::SessionMgr()
{
_curr_session = 0;
_hash_map = new HashList(100000);
}
/**
* @brief , ,
*/
SessionMgr::~SessionMgr()
{
if (_hash_map) {
delete _hash_map;
_hash_map = NULL;
}
}
/**
* @brief Session
*/
int SessionMgr::InsertSession(ISession* session)
{
if (!_hash_map || !session) {
MTLOG_ERROR("Mngr not init(%p), or session null(%p)", _hash_map, session);
return -100;
}
int flag = session->GetSessionFlag();
if (flag & SESSION_INUSE) {
MTLOG_ERROR("Session already in hash, bugs, %p, %d", session, flag);
return -200;
}
session->SetSessionFlag((int)SESSION_INUSE);
return _hash_map->HashInsert(session);
}
/**
* @brief session
*/
ISession* SessionMgr::FindSession(int session_id)
{
if (!_hash_map) {
MTLOG_ERROR("Mngr not init(%p)", _hash_map);
return NULL;
}
ISession key;
key.SetSessionId(session_id);
return dynamic_cast<ISession*>(_hash_map->HashFind(&key));
}
/**
* @brief session
*/
void SessionMgr::RemoveSession(int session_id)
{
if (!_hash_map) {
MTLOG_ERROR("Mngr not init(%p)", _hash_map);
return;
}
ISession key;
key.SetSessionId(session_id);
return _hash_map->HashRemove(&key);
}

View File

@ -0,0 +1,187 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_session.h
* @info 线, session
* @time 20130924
**/
#ifndef __MT_SESSION_H__
#define __MT_SESSION_H__
#include "hash_list.h"
namespace NS_MICRO_THREAD {
class MicroThread;
class IMtConnection;
enum SESSION_FLAG
{
SESSION_IDLE = 0, ///< SESSION 未加入hash管理
SESSION_INUSE = 1, ///< SESSION 进入管理状态
};
/**
* @brief session, sessionthread,action
*/
class ISession : public HashKey
{
public:
/**
* @brief
*/
ISession() : _session_id(0), _session_flg(0), _thread(NULL), _connection(NULL) {};
virtual ~ISession();
public:
/**
* @brief ID
*/
void SetSessionId(int id) {
_session_id = id;
};
int GetSessionId() {
return _session_id;
};
/**
* @brief 线
*/
MicroThread* GetOwnerThread(){
return _thread;
};
void SetOwnerThread(MicroThread* thread) {
_thread = thread;
};
/**
* @brief
*/
IMtConnection* GetSessionConn(){
return _connection;
};
void SetSessionConn(IMtConnection* conn) {
_connection = conn;
};
/**
* @brief flag
*/
void SetSessionFlag(int flag) {
_session_flg = flag;
};
int GetSessionFlag() {
return _session_flg;
};
/**
* @brief hash, keyhash
* @return hash
*/
virtual uint32_t HashValue(){
return _session_id;
};
/**
* @brief cmp, ID, key
* @return hash
*/
virtual int HashCmp(HashKey* rhs){
return this->_session_id - (int)rhs->HashValue();
};
protected:
int _session_id; // 会话id信息
int _session_flg; // 记录session状态 0 -不在hash中, 1 -hash管理中
MicroThread* _thread; // 会话所属的session
IMtConnection* _connection; // 会话关联的连接
};
/**
* @brief session
*/
class SessionMgr
{
public:
/**
* @brief
* @return
*/
static SessionMgr* Instance (void);
/**
* @brief
*/
static void Destroy();
/**
* @brief sessionid
* @return
*/
int GetSessionId(void) {
_curr_session++;
if (!_curr_session) {
_curr_session++;
}
return _curr_session;
};
/**
* @brief Session
*/
int InsertSession(ISession* session);
/**
* @brief session
*/
ISession* FindSession(int session_id);
/**
* @brief session
*/
void RemoveSession(int session_id);
/**
* @brief
*/
~SessionMgr();
private:
/**
* @brief buff
*/
SessionMgr();
static SessionMgr * _instance; ///< 单例类句柄
int _curr_session; ///< session种子
HashList* _hash_map; ///< 按sessionid hash存储
};
}
#endif

View File

@ -0,0 +1,413 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename mt_sys_hook.cpp
* @info 线hookapi, ,
* hook socketAPI, HOOK , pthlibco
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include "micro_thread.h"
#include "mt_sys_hook.h"
#include "ff_hook.h"
using namespace NS_MICRO_THREAD;
#define MT_HOOK_MAX_FD 65535*2
#define MT_FD_FLG_INUSE 0x1
#define MT_FD_FLG_UNBLOCK 0x2
/**
* @brief sockt, HOOK,
*/
typedef struct socket_hook_info
{
int sock_flag; // 是否使用HOOK, 是否用户设置UNBLOCK
int read_timeout; // socket读取超时时间, ms单位
int write_timeout; // socket写入超时时间, ms单位
}MtHookFd;
MtSyscallFuncTab g_mt_syscall_tab; // 全局符号表
int g_mt_hook_flag; // 全局控制标记
int g_ff_hook_flag; // 全局控制标记
static MtHookFd g_mt_hook_fd_tab[MT_HOOK_MAX_FD]; // 全局fd管理
/**
* @brief , hook fd, socket hook, open no hook
*/
MtHookFd* mt_hook_find_fd(int fd)
{
if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
return NULL;
}
MtHookFd* fd_info = &g_mt_hook_fd_tab[fd];
if (!(fd_info->sock_flag & MT_FD_FLG_INUSE)) {
return NULL;
} else {
return fd_info;
}
}
/**
* @brief , sockethook, socket, IO
*/
void mt_hook_new_fd(int fd)
{
if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
return;
}
MtHookFd* fd_info = &g_mt_hook_fd_tab[fd];
fd_info->sock_flag = MT_FD_FLG_INUSE;
fd_info->read_timeout = 500;
fd_info->write_timeout = 500;
}
/**
* @brief , hook socket
*/
void mt_hook_free_fd(int fd)
{
if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
return;
}
MtHookFd* fd_info = &g_mt_hook_fd_tab[fd];
fd_info->sock_flag = 0;
fd_info->read_timeout = 0;
fd_info->write_timeout = 0;
}
/**
* @brief HOOK, mt, api,
*/
#ifdef __cplusplus
extern "C" {
#endif
int ioctl(int fd, unsigned long cmd, ...)
{
va_list ap;
va_start(ap, cmd);
void* arg = va_arg(ap, void *);
va_end(ap);
mt_hook_syscall(ioctl);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_ioctl(fd, cmd, arg);
}
if (cmd == FIONBIO)
{
int flags = (arg != NULL) ? *((int*)arg) : 0;
if (flags != 0) {
hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK;
}
}
return ff_hook_ioctl(fd, cmd, arg);
}
/**
* @brief HOOK, mt, api, unblock
*/
int socket(int domain, int type, int protocol)
{
mt_hook_syscall(socket);
if (!mt_hook_active())
{
return ff_hook_socket(domain, type, protocol);
}
int fd = ff_hook_socket(domain, type, protocol);
if (fd < 0)
{
return fd;
}
mt_hook_new_fd(fd);
mt_hook_syscall(ioctl);
int nb = 1;
ff_hook_ioctl(fd, FIONBIO, &nb);
return fd;
}
/**
* @brief HOOK, mt, api
*/
int close(int fd)
{
mt_hook_syscall(close);
if (!mt_hook_active())
{
return ff_hook_close(fd);
}
mt_hook_free_fd(fd);
return ff_hook_close(fd);
}
/**
* @brief HOOK, mt, api
*/
int connect(int fd, const struct sockaddr *address, socklen_t address_len)
{
mt_hook_syscall(connect);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_connect(fd, address, address_len);
}
if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
{
return ff_hook_connect(fd, address, address_len);
}
return MtFrame::connect(fd, address, (int)address_len, hook_fd->write_timeout);
}
/**
* @brief HOOK, mt, api, unblock,
*/
ssize_t read(int fd, void *buf, size_t nbyte)
{
mt_hook_syscall(read);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_read(fd, buf, nbyte);
}
if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
{
return ff_hook_read(fd, buf, nbyte);
}
return MtFrame::read(fd, buf, nbyte, hook_fd->read_timeout);
}
/**
* @brief HOOK, mt, api, unblock,
*/
ssize_t write(int fd, const void *buf, size_t nbyte)
{
mt_hook_syscall(write);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_write(fd, buf, nbyte);
}
if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
{
return ff_hook_write(fd, buf, nbyte);
}
return MtFrame::write(fd, buf, nbyte, hook_fd->write_timeout);
}
/**
* @brief HOOK, mt, api, unblock,
*/
ssize_t sendto(int fd, const void *message, size_t length, int flags,
const struct sockaddr *dest_addr, socklen_t dest_len)
{
mt_hook_syscall(sendto);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_sendto(fd, message, length, flags, dest_addr, dest_len);
}
if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
{
return ff_hook_sendto(fd, message, length, flags, dest_addr, dest_len);
}
return MtFrame::sendto(fd, message, (int)length, flags,
dest_addr, dest_len, hook_fd->write_timeout);
}
/**
* @brief HOOK, mt, api, unblock,
*/
ssize_t recvfrom(int fd, void *buffer, size_t length, int flags,
struct sockaddr *address, socklen_t *address_len)
{
mt_hook_syscall(recvfrom);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_recvfrom(fd, buffer, length, flags, address, address_len);
}
if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
{
return ff_hook_recvfrom(fd, buffer, length, flags, address, address_len);
}
return MtFrame::recvfrom(fd, buffer, length, flags, address, address_len, hook_fd->read_timeout);
}
/**
* @brief HOOK, mt, api, unblock,
*/
ssize_t recv(int fd, void *buffer, size_t length, int flags)
{
mt_hook_syscall(recv);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_recv(fd, buffer, length, flags);
}
if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
{
return ff_hook_recv(fd, buffer, length, flags);
}
return MtFrame::recv(fd, buffer, length, flags, hook_fd->read_timeout);
}
/**
* @brief HOOK, mt, api, unblock,
*/
ssize_t send(int fd, const void *buf, size_t nbyte, int flags)
{
mt_hook_syscall(send);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_send(fd, buf, nbyte, flags);
}
if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
{
return ff_hook_send(fd, buf, nbyte, flags);
}
return MtFrame::send(fd, buf, nbyte, flags, hook_fd->write_timeout);
}
/**
* @brief HOOK, mt, api,
*/
int setsockopt(int fd, int level, int option_name, const void *option_value, socklen_t option_len)
{
mt_hook_syscall(setsockopt);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_setsockopt(fd, level, option_name, option_value, option_len);
}
if (SOL_SOCKET == level)
{
struct timeval *val = (struct timeval*)option_value;
if (SO_RCVTIMEO == option_name)
{
hook_fd->read_timeout = val->tv_sec * 1000 + val->tv_usec / 1000;
}
else if (SO_SNDTIMEO == option_name)
{
hook_fd->write_timeout = val->tv_sec * 1000 + val->tv_usec / 1000;
}
}
return ff_hook_setsockopt(fd, level, option_name, option_value, option_len);
}
/**
* @brief HOOK, mt, api,
*/
int fcntl(int fd, int cmd, ...)
{
va_list ap;
va_start(ap, cmd);
void* arg = va_arg(ap, void *);
va_end(ap);
mt_hook_syscall(fcntl);
MtHookFd* hook_fd = mt_hook_find_fd(fd);
if (!mt_hook_active() || !hook_fd)
{
return ff_hook_fcntl(fd, cmd, arg);
}
if (cmd == F_SETFL)
{
va_start(ap, cmd);
int flags = va_arg(ap, int);
va_end(ap);
if (flags & O_NONBLOCK)
{
hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK;
}
}
return ff_hook_fcntl(fd, cmd, arg);
}
int listen(int sockfd, int backlog)
{
mt_hook_syscall(listen);
return ff_hook_listen(sockfd, backlog);
}
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
mt_hook_syscall(bind);
return ff_hook_bind(sockfd, addr, addrlen);
}
int accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
{
mt_hook_syscall(accept);
return ff_hook_accept(fd, addr, addrlen);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,130 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @filename mt_sys_hook.h
* @info 线hookapi, ,
* HOOK , pthlibco
*/
#ifndef _MT_SYS_HOOK___
#define _MT_SYS_HOOK___
#include <poll.h>
#include <dlfcn.h>
#include "ff_api.h"
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************/
/* 1. HOOK 的函数定义部分 */
/******************************************************************************/
typedef int (*func_socket)(int domain, int type, int protocol);
typedef int (*func_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
typedef int (*func_listen)(int sockfd, int backlog);
typedef int (*func_close)(int fd);
typedef int (*func_connect)(int socket, const struct sockaddr *address, socklen_t address_len);
typedef int (*func_accept)(int socket, struct sockaddr *address, socklen_t *addrlen);
typedef ssize_t (*func_read)(int fildes, void *buf, size_t nbyte);
typedef ssize_t (*func_write)(int fildes, const void *buf, size_t nbyte);
typedef ssize_t (*func_sendto)(int socket, const void *message, size_t length,
int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
typedef ssize_t (*func_recvfrom)(int socket, void *buffer, size_t length,
int flags, struct sockaddr *address, socklen_t *address_len);
typedef size_t (*func_send)(int socket, const void *buffer, size_t length, int flags);
typedef ssize_t (*func_recv)(int socket, void *buffer, size_t length, int flags);
typedef int (*func_select)(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
typedef int (*func_poll)(struct pollfd fds[], nfds_t nfds, int timeout);
typedef int (*func_setsockopt)(int socket, int level, int option_name,
const void *option_value, socklen_t option_len);
typedef int (*func_ioctl)(int fd, unsigned long cmd, ...);
typedef int (*func_fcntl)(int fd, int cmd, ...);
typedef unsigned int (*func_sleep)(unsigned int seconds);
/******************************************************************************/
/* 2. 全局的hook函数结构 */
/******************************************************************************/
/**
* @brief Hook,
*/
typedef struct mt_syscall_func_tab
{
func_socket real_socket;
func_bind real_bind;
func_listen real_listen;
func_close real_close;
func_connect real_connect;
func_read real_read;
func_write real_write;
func_sendto real_sendto;
func_recvfrom real_recvfrom;
func_send real_send;
func_recv real_recv;
func_setsockopt real_setsockopt;
func_fcntl real_fcntl;
func_ioctl real_ioctl;
func_sleep real_sleep; // 暂不支持因为没有与fd关联, 防止滥用
func_select real_select; // 暂不支持, 1024限制问题
func_poll real_poll; // 暂不支持, 确认需求后实施
func_accept real_accept;
}MtSyscallFuncTab;
/******************************************************************************/
/* 3. 直接调用原始系统api的接口 */
/******************************************************************************/
extern MtSyscallFuncTab g_mt_syscall_tab; // 全局符号表
extern int g_mt_hook_flag; // 全局控制标记
extern int g_ff_hook_flag; // 全局控制标记
#define mt_hook_syscall(name) \
do { \
if (!g_mt_syscall_tab.real_##name) { \
g_mt_syscall_tab.real_##name = (func_##name)dlsym(RTLD_NEXT, #name);\
} \
} while (0)
#define mt_real_func(name) g_mt_syscall_tab.real_##name
#define mt_set_hook_flag() (g_mt_hook_flag = 1)
#define mt_unset_hook_flag() (g_mt_hook_flag = 0)
#define mt_hook_active() (g_mt_hook_flag == 1)
#define ff_set_hook_flag() (g_ff_hook_flag = 1)
#define ff_unset_hook_flag() (g_ff_hook_flag = 0)
#define ff_hook_active() (g_ff_hook_flag == 1)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,41 @@
/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
/**
* @file mt_version.h
* @info 线
* @time 20131018
* ------------------------------------------------------------------------
* @brief v0.2.0 - UDPsession
* v0.2.1 - TCPsendrcv
* v0.2.3 -
* v0.2.4 - TCPsendrcvbuf
*/
#ifndef _MT_VERSION_EX__
#define _MT_VERSION_EX__
namespace NS_MICRO_THREAD {
__attribute__((weak)) char IMT_VERSION[64] = "mt version: 0.2.4";
} // NAMESPACE NS_MICRO_THREAD
#endif

File diff suppressed because it is too large Load Diff

7739
app/nginx-1.11.10/CHANGES Normal file

File diff suppressed because it is too large Load Diff

7872
app/nginx-1.11.10/CHANGES.ru Normal file

File diff suppressed because it is too large Load Diff

26
app/nginx-1.11.10/LICENSE Normal file
View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2002-2017 Igor Sysoev
* Copyright (C) 2011-2017 Nginx, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

3
app/nginx-1.11.10/README Normal file
View File

@ -0,0 +1,3 @@
Documentation is available at http://nginx.org

View File

@ -0,0 +1,14 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
# aCC: HP ANSI C++ B3910B A.03.55.02
# C89 mode
CFLAGS="$CFLAGS -Ae"
CC_TEST_FLAGS="-Ae"
PCRE_OPT="$PCRE_OPT -Ae"
ZLIB_OPT="$ZLIB_OPT -Ae"

View File

@ -0,0 +1,72 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
# Borland C++ 5.5
# optimizations
# maximize speed
CFLAGS="$CFLAGS -O2"
case $CPU in
pentium)
# optimize for Pentium and Athlon
CPU_OPT="-5"
;;
pentiumpro)
# optimize for Pentium Pro, Pentium II and Pentium III
CPU_OPT="-6"
;;
esac
# __stdcall
#CPU_OPT="$CPU_OPT -ps"
# __fastcall
#CPU_OPT="$CPU_OPT -pr"
CFLAGS="$CFLAGS $CPU_OPT"
# multithreaded
CFLAGS="$CFLAGS -tWM"
# stop on warning
CFLAGS="$CFLAGS -w!"
# disable logo
CFLAGS="$CFLAGS -q"
# precompiled headers
CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.csm"
NGX_PCH="$NGX_OBJS/ngx_config.csm"
NGX_BUILD_PCH="-H=$NGX_OBJS/ngx_config.csm"
NGX_USE_PCH="-Hu -H=$NGX_OBJS/ngx_config.csm"
# Win32 GUI mode application
#LINK="\$(CC) -laa"
# the resource file
NGX_RES="$NGX_OBJS/nginx.res"
NGX_RCC="brcc32 -fo$NGX_OBJS/nginx.res \$(CORE_INCS) $NGX_WIN32_RC"
# the pragma allows to link the resource file using bcc32 and
# to avoid the direct ilink32 calling and the c0w32.obj's WinMain/main problem
NGX_PRAGMA="#pragma resource \"$NGX_OBJS/nginx.res\""
ngx_include_opt="-I"
ngx_objout="-o"
ngx_binout="-e"
ngx_objext="obj"
ngx_binext=".exe"
ngx_long_start='@&&|
'
ngx_long_end='|'
ngx_regex_dirsep='\\'
ngx_dirsep="\\"

View File

@ -0,0 +1,46 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
# Compaq C V6.5-207
ngx_include_opt="-I"
# warnings
CFLAGS="$CFLAGS -msg_enable level6 -msg_fatal level6"
CFLAGS="$CFLAGS -msg_disable unknownmacro"
CFLAGS="$CFLAGS -msg_disable unusedincl"
CFLAGS="$CFLAGS -msg_disable unnecincl"
CFLAGS="$CFLAGS -msg_disable nestincl"
CFLAGS="$CFLAGS -msg_disable strctpadding"
CFLAGS="$CFLAGS -msg_disable ansialiascast"
CFLAGS="$CFLAGS -msg_disable inlinestoclsmod"
CFLAGS="$CFLAGS -msg_disable cxxkeyword"
CFLAGS="$CFLAGS -msg_disable longlongsufx"
CFLAGS="$CFLAGS -msg_disable valuepres"
# STUB
CFLAGS="$CFLAGS -msg_disable truncintcast"
CFLAGS="$CFLAGS -msg_disable trunclongcast"
CFLAGS="$CFLAGS -msg_disable truncintasn"
CFLAGS="$CFLAGS -msg_disable trunclongint"
CFLAGS="$CFLAGS -msg_disable intconcastsgn"
CFLAGS="$CFLAGS -msg_disable intconstsign"
CFLAGS="$CFLAGS -msg_disable switchlong"
CFLAGS="$CFLAGS -msg_disable subscrbounds2"
CFLAGS="$CFLAGS -msg_disable hexoctunsign"
CFLAGS="$CFLAGS -msg_disable ignorecallval"
CFLAGS="$CFLAGS -msg_disable nonstandcast"
CFLAGS="$CFLAGS -msg_disable embedcomment"
CFLAGS="$CFLAGS -msg_disable unreachcode"
CFLAGS="$CFLAGS -msg_disable questcompare2"
CFLAGS="$CFLAGS -msg_disable unusedtop"
CFLAGS="$CFLAGS -msg_disable unrefdecl"
CFLAGS="$CFLAGS -msg_disable bitnotint"

View File

@ -0,0 +1,98 @@
# Copyright (C) Nginx, Inc.
# clang
NGX_CLANG_VER=`$CC -v 2>&1 | grep '\(clang\|LLVM\) version' 2>&1 \
| sed -e 's/^.* version \(.*\)/\1/'`
echo " + clang version: $NGX_CLANG_VER"
have=NGX_COMPILER value="\"clang $NGX_CLANG_VER\"" . auto/define
CC_TEST_FLAGS="-pipe"
# optimizations
#NGX_CLANG_OPT="-O2"
#NGX_CLANG_OPT="-Oz"
NGX_CLANG_OPT="-O"
case $CPU in
pentium)
# optimize for Pentium
CPU_OPT="-march=pentium"
NGX_CPU_CACHE_LINE=32
;;
pentiumpro | pentium3)
# optimize for Pentium Pro, Pentium II and Pentium III
CPU_OPT="-march=pentiumpro"
NGX_CPU_CACHE_LINE=32
;;
pentium4)
# optimize for Pentium 4
CPU_OPT="-march=pentium4"
NGX_CPU_CACHE_LINE=128
;;
athlon)
# optimize for Athlon
CPU_OPT="-march=athlon"
NGX_CPU_CACHE_LINE=64
;;
opteron)
# optimize for Opteron
CPU_OPT="-march=opteron"
NGX_CPU_CACHE_LINE=64
;;
esac
CC_AUX_FLAGS="$CC_AUX_FLAGS $CPU_OPT"
CFLAGS="$CFLAGS -pipe $CPU_OPT"
if [ ".$PCRE_OPT" = "." ]; then
PCRE_OPT="-O2 -pipe $CPU_OPT"
else
PCRE_OPT="$PCRE_OPT -pipe"
fi
if [ ".$ZLIB_OPT" = "." ]; then
ZLIB_OPT="-O2 -pipe $CPU_OPT"
else
ZLIB_OPT="$ZLIB_OPT -pipe"
fi
# warnings
CFLAGS="$CFLAGS $NGX_CLANG_OPT -Wall -Wextra -Wpointer-arith"
CFLAGS="$CFLAGS -Wconditional-uninitialized"
#CFLAGS="$CFLAGS -Wmissing-prototypes"
# we have a lot of unused function arguments
CFLAGS="$CFLAGS -Wno-unused-parameter"
# deprecated system OpenSSL library on OS X
if [ "$NGX_SYSTEM" = "Darwin" ]; then
CFLAGS="$CFLAGS -Wno-deprecated-declarations"
fi
# stop on warning
CFLAGS="$CFLAGS -Werror"
# debug
CFLAGS="$CFLAGS -g"
if [ ".$CPP" = "." ]; then
CPP="$CC -E"
fi

View File

@ -0,0 +1,250 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
LINK="\$(CC)"
MAIN_LINK=
MODULE_LINK="-shared"
ngx_include_opt="-I "
ngx_compile_opt="-c"
ngx_pic_opt="-fPIC"
ngx_objout="-o "
ngx_binout="-o "
ngx_objext="o"
ngx_binext=
ngx_modext=".so"
ngx_long_start=
ngx_long_end=
ngx_regex_dirsep="\/"
ngx_dirsep='/'
ngx_regex_cont=' \\\
'
ngx_cont=' \
'
ngx_tab=' \
'
ngx_spacer=
ngx_long_regex_cont=$ngx_regex_cont
ngx_long_cont=$ngx_cont
. auto/cc/name
if test -n "$CFLAGS"; then
CC_TEST_FLAGS="$CFLAGS $NGX_CC_OPT"
case $NGX_CC_NAME in
ccc)
# Compaq C V6.5-207
ngx_include_opt="-I"
;;
sunc)
MAIN_LINK=
MODULE_LINK="-G"
case "$NGX_MACHINE" in
i86pc)
NGX_AUX=" src/os/unix/ngx_sunpro_x86.il"
;;
sun4u | sun4v)
NGX_AUX=" src/os/unix/ngx_sunpro_sparc64.il"
;;
esac
case $CPU in
amd64)
NGX_AUX=" src/os/unix/ngx_sunpro_amd64.il"
;;
esac
;;
esac
else
case $NGX_CC_NAME in
gcc)
# gcc 2.7.2.3, 2.8.1, 2.95.4, egcs-1.1.2
# 3.0.4, 3.1.1, 3.2.3, 3.3.2, 3.3.3, 3.3.4, 3.4.0, 3.4.2
# 4.0.0, 4.0.1, 4.1.0
. auto/cc/gcc
;;
clang)
# Clang C compiler
. auto/cc/clang
;;
icc)
# Intel C++ compiler 7.1, 8.0, 8.1
. auto/cc/icc
;;
sunc)
# Sun C 5.7 Patch 117837-04 2005/05/11
. auto/cc/sunc
;;
ccc)
# Compaq C V6.5-207
. auto/cc/ccc
;;
acc)
# aCC: HP ANSI C++ B3910B A.03.55.02
. auto/cc/acc
;;
msvc*)
# MSVC++ 6.0 SP2, MSVC++ Toolkit 2003
. auto/cc/msvc
;;
owc)
# Open Watcom C 1.0, 1.2
. auto/cc/owc
;;
bcc)
# Borland C++ 5.5
. auto/cc/bcc
;;
esac
CC_TEST_FLAGS="$CC_TEST_FLAGS $NGX_CC_OPT"
fi
CFLAGS="$CFLAGS $NGX_CC_OPT"
NGX_TEST_LD_OPT="$NGX_LD_OPT"
if [ "$NGX_PLATFORM" != win32 ]; then
if test -n "$NGX_LD_OPT"; then
ngx_feature=--with-ld-opt=\"$NGX_LD_OPT\"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test=
. auto/feature
if [ $ngx_found = no ]; then
echo $0: error: the invalid value in --with-ld-opt=\"$NGX_LD_OPT\"
echo
exit 1
fi
fi
ngx_feature="-Wl,-E switch"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=-Wl,-E
ngx_feature_test=
. auto/feature
if [ $ngx_found = yes ]; then
MAIN_LINK="-Wl,-E"
fi
ngx_feature="gcc builtin atomic operations"
ngx_feature_name=NGX_HAVE_GCC_ATOMIC
ngx_feature_run=yes
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="long n = 0;
if (!__sync_bool_compare_and_swap(&n, 0, 1))
return 1;
if (__sync_fetch_and_add(&n, 1) != 1)
return 1;
if (n != 2)
return 1;
__sync_synchronize();"
. auto/feature
if [ "$NGX_CC_NAME" = "ccc" ]; then
echo "checking for C99 variadic macros ... disabled"
else
ngx_feature="C99 variadic macros"
ngx_feature_name="NGX_HAVE_C99_VARIADIC_MACROS"
ngx_feature_run=yes
ngx_feature_incs="#include <stdio.h>
#define var(dummy, ...) sprintf(__VA_ARGS__)"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[30]; buf[0] = '0';
var(0, buf, \"%d\", 1);
if (buf[0] != '1') return 1"
. auto/feature
fi
ngx_feature="gcc variadic macros"
ngx_feature_name="NGX_HAVE_GCC_VARIADIC_MACROS"
ngx_feature_run=yes
ngx_feature_incs="#include <stdio.h>
#define var(dummy, args...) sprintf(args)"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[30]; buf[0] = '0';
var(0, buf, \"%d\", 1);
if (buf[0] != '1') return 1"
. auto/feature
ngx_feature="gcc builtin 64 bit byteswap"
ngx_feature_name="NGX_HAVE_GCC_BSWAP64"
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="if (__builtin_bswap64(0)) return 1"
. auto/feature
# ngx_feature="inline"
# ngx_feature_name=
# ngx_feature_run=no
# ngx_feature_incs="int inline f(void) { return 1 }"
# ngx_feature_path=
# ngx_feature_libs=
# ngx_feature_test=
# . auto/feature
#
# if [ $ngx_found = yes ]; then
# fi
fi

View File

@ -0,0 +1,178 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
# gcc 2.7.2.3, 2.8.1, 2.95.4, egcs-1.1.2
# 3.0.4, 3.1.1, 3.2.3, 3.3.2, 3.3.3, 3.3.4, 3.4.0, 3.4.2
# 4.0.0, 4.0.1, 4.1.0
NGX_GCC_VER=`$CC -v 2>&1 | grep 'gcc version' 2>&1 \
| sed -e 's/^.* version \(.*\)/\1/'`
echo " + gcc version: $NGX_GCC_VER"
have=NGX_COMPILER value="\"gcc $NGX_GCC_VER\"" . auto/define
# Solaris 7's /usr/ccs/bin/as does not support "-pipe"
CC_TEST_FLAGS="-pipe"
ngx_feature="gcc -pipe switch"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test=
. auto/feature
CC_TEST_FLAGS=
if [ $ngx_found = yes ]; then
PIPE="-pipe"
fi
case "$NGX_MACHINE" in
sun4u | sun4v | sparc | sparc64 )
# "-mcpu=v9" enables the "casa" assembler instruction
CFLAGS="$CFLAGS -mcpu=v9"
;;
esac
# optimizations
#NGX_GCC_OPT="-O2"
NGX_GCC_OPT="-Os"
#CFLAGS="$CFLAGS -fomit-frame-pointer"
case $CPU in
pentium)
# optimize for Pentium and Athlon
CPU_OPT="-march=pentium"
NGX_CPU_CACHE_LINE=32
;;
pentiumpro | pentium3)
# optimize for Pentium Pro, Pentium II and Pentium III
CPU_OPT="-march=pentiumpro"
NGX_CPU_CACHE_LINE=32
;;
pentium4)
# optimize for Pentium 4, gcc 3.x
CPU_OPT="-march=pentium4"
NGX_CPU_CACHE_LINE=128
;;
athlon)
# optimize for Athlon, gcc 3.x
CPU_OPT="-march=athlon"
NGX_CPU_CACHE_LINE=64
;;
opteron)
# optimize for Opteron, gcc 3.x
CPU_OPT="-march=opteron"
NGX_CPU_CACHE_LINE=64
;;
sparc32)
# build 32-bit UltraSparc binary
CPU_OPT="-m32"
CORE_LINK="$CORE_LINK -m32"
NGX_CPU_CACHE_LINE=64
;;
sparc64)
# build 64-bit UltraSparc binary
CPU_OPT="-m64"
CORE_LINK="$CORE_LINK -m64"
NGX_CPU_CACHE_LINE=64
;;
ppc64)
# build 64-bit PowerPC binary
CPU_OPT="-m64"
CPU_OPT="$CPU_OPT -falign-functions=32 -falign-labels=32"
CPU_OPT="$CPU_OPT -falign-loops=32 -falign-jumps=32"
CORE_LINK="$CORE_LINK -m64"
NGX_CPU_CACHE_LINE=128
;;
esac
CC_AUX_FLAGS="$CC_AUX_FLAGS $CPU_OPT"
case "$NGX_GCC_VER" in
2.7*)
# batch build
CPU_OPT=
;;
esac
CFLAGS="$CFLAGS $PIPE $CPU_OPT"
if [ ".$PCRE_OPT" = "." ]; then
PCRE_OPT="-O2 -fomit-frame-pointer $PIPE $CPU_OPT"
else
PCRE_OPT="$PCRE_OPT $PIPE"
fi
if [ ".$ZLIB_OPT" = "." ]; then
ZLIB_OPT="-O2 -fomit-frame-pointer $PIPE $CPU_OPT"
else
ZLIB_OPT="$ZLIB_OPT $PIPE"
fi
# warnings
# -W requires at least -O
CFLAGS="$CFLAGS ${NGX_GCC_OPT:--O} -W"
CFLAGS="$CFLAGS -Wall -Wpointer-arith"
#CFLAGS="$CFLAGS -Wconversion"
#CFLAGS="$CFLAGS -Winline"
#CFLAGS="$CFLAGS -Wmissing-prototypes"
case "$NGX_GCC_VER" in
2.*)
# we have a lot of the unused function arguments
CFLAGS="$CFLAGS -Wno-unused"
;;
*)
# we have a lot of the unused function arguments
CFLAGS="$CFLAGS -Wno-unused-parameter"
# 4.2.1 shows the warning in wrong places
#CFLAGS="$CFLAGS -Wunreachable-code"
# deprecated system OpenSSL library on OS X
if [ "$NGX_SYSTEM" = "Darwin" ]; then
CFLAGS="$CFLAGS -Wno-deprecated-declarations"
fi
;;
esac
# stop on warning
CFLAGS="$CFLAGS -Werror"
# debug
CFLAGS="$CFLAGS -g"
# DragonFly's gcc3 generates DWARF
#CFLAGS="$CFLAGS -g -gstabs"
if [ ".$CPP" = "." ]; then
CPP="$CC -E"
fi

View File

@ -0,0 +1,117 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
# Intel C++ compiler 7.1, 8.0, 8.1, 9.0, 11.1
NGX_ICC_VER=`$CC -V 2>&1 | grep 'Version' 2>&1 \
| sed -e 's/^.* Version \([^ ]*\) *Build.*$/\1/'`
echo " + icc version: $NGX_ICC_VER"
have=NGX_COMPILER value="\"Intel C Compiler $NGX_ICC_VER\"" . auto/define
# optimizations
CFLAGS="$CFLAGS -O"
CORE_LINK="$CORE_LINK -opt_report_file=$NGX_OBJS/opt_report_file"
case $CPU in
pentium)
# optimize for Pentium and Athlon
CPU_OPT="-march=pentium"
;;
pentiumpro)
# optimize for Pentium Pro, Pentium II and Pentium III
CPU_OPT="-mcpu=pentiumpro -march=pentiumpro"
;;
pentium4)
# optimize for Pentium 4, default
CPU_OPT="-march=pentium4"
;;
esac
CFLAGS="$CFLAGS $CPU_OPT"
if [ ".$PCRE_OPT" = "." ]; then
PCRE_OPT="-O $CPU_OPT"
fi
if [ ".$ZLIB_OPT" = "." ]; then
ZLIB_OPT="-O $CPU_OPT"
fi
# warnings
CFLAGS="$CFLAGS -w2"
# disable some warnings
# invalid type conversion: "int" to "char *"
CFLAGS="$CFLAGS -wd171"
# argument is incompatible with corresponding format string conversion
CFLAGS="$CFLAGS -wd181"
# zero used for undefined preprocessing identifier
CFLAGS="$CFLAGS -wd193"
# the format string ends before this argument
CFLAGS="$CFLAGS -wd268"
# invalid format string conversion
CFLAGS="$CFLAGS -wd269"
# conversion from "long long" to "size_t" may lose significant bits
CFLAGS="$CFLAGS -wd810"
# parameter was never referenced
CFLAGS="$CFLAGS -wd869"
# attribute "unused" is only allowed in a function definition, warning on pTHX_
CFLAGS="$CFLAGS -wd1301"
# STUB
# enumerated type mixed with another type
CFLAGS="$CFLAGS -wd188"
# controlling expression is constant
CFLAGS="$CFLAGS -wd279"
# operands are evaluated in unspecified order
CFLAGS="$CFLAGS -wd981"
# external definition with no prior declaration
CFLAGS="$CFLAGS -wd1418"
# external declaration in primary source file
CFLAGS="$CFLAGS -wd1419"
case "$NGX_ICC_VER" in
9.*)
# "cc" clobber ignored, warnings for Linux's htonl()/htons()
CFLAGS="$CFLAGS -wd1469"
# explicit conversion of a 64-bit integral type to a smaller
# integral type
CFLAGS="$CFLAGS -wd1683"
# conversion from pointer to same-sized integral type,
# warning on offsetof()
CFLAGS="$CFLAGS -wd1684"
# floating-point equality and inequality comparisons are unreliable,
# warning on SvTRUE()
CFLAGS="$CFLAGS -wd1572"
;;
8.*)
# "cc" clobber ignored, warnings for Linux's htonl()/htons()
CFLAGS="$CFLAGS -wd1469"
# floating-point equality and inequality comparisons are unreliable,
# warning on SvTRUE()
CFLAGS="$CFLAGS -wd1572"
;;
*)
;;
esac
# stop on warning
CFLAGS="$CFLAGS -Werror"
# debug
CFLAGS="$CFLAGS -g"

View File

@ -0,0 +1,157 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
# MSVC 6.0 SP2 cl 12.00
# MSVC Toolkit 2003 (7.1) cl 13.10
# MSVC 2005 Express Edition SP1 (8.0) cl 14.00
# MSVC 2008 Express Edition (9.0) cl 15.00
# MSVC 2010 (10.0) cl 16.00
# MSVC 2015 (14.0) cl 19.00
NGX_MSVC_VER=`$NGX_WINE $CC 2>&1 | grep 'Compiler Version' 2>&1 \
| sed -e 's/^.* Version \(.*\)/\1/'`
echo " + cl version: $NGX_MSVC_VER"
have=NGX_COMPILER value="\"cl $NGX_MSVC_VER\"" . auto/define
ngx_msvc_ver=`echo $NGX_MSVC_VER | sed -e 's/^\([0-9]*\).*/\1/'`
# optimizations
# maximize speed, equivalent to -Og -Oi -Ot -Oy -Ob2 -Gs -GF -Gy
CFLAGS="$CFLAGS -O2"
# enable global optimization
#CFLAGS="$CFLAGS -Og"
# enable intrinsic functions
#CFLAGS="$CFLAGS -Oi"
# disable inline expansion
#CFLAGS="$CFLAGS -Ob0"
# explicit inline expansion
#CFLAGS="$CFLAGS -Ob1"
# explicit and implicit inline expansion
#CFLAGS="$CFLAGS -Ob2"
# enable frame pointer omission
#CFLAGS="$CFLAGS -Oy"
# disable stack checking calls
#CFLAGS="$CFLAGS -Gs"
# pools strings as read/write
#CFLAGS="$CFLAGS -Gf"
# pools strings as read-only
#CFLAGS="$CFLAGS -GF"
case $CPU in
pentium)
# optimize for Pentium and Athlon
CPU_OPT="-G5"
;;
pentiumpro)
# optimize for Pentium Pro, Pentium II and Pentium III
CPU_OPT="-G6"
;;
pentium4)
# optimize for Pentium 4, MSVC 7
CPU_OPT="-G7"
;;
esac
# __cdecl, default, must be used with OpenSSL, md5 asm, and sha1 asm
#CPU_OPT="$CPU_OPT -Gd"
# __stdcall
#CPU_OPT="$CPU_OPT -Gz"
# __fastcall
#CPU_OPT="$CPU_OPT -Gr"
CFLAGS="$CFLAGS $CPU_OPT"
# warnings
CFLAGS="$CFLAGS -W4"
# stop on warning
CFLAGS="$CFLAGS -WX"
# disable logo
CFLAGS="$CFLAGS -nologo"
# the link flags
CORE_LINK="$CORE_LINK -link -verbose:lib"
# link with libcmt.lib, multithreaded
LIBC="-MT"
# link with msvcrt.dll
# however, MSVC Toolkit 2003 has no MSVCRT.LIB
#LIBC="-MD"
CFLAGS="$CFLAGS $LIBC"
CORE_LIBS="$CORE_LIBS kernel32.lib user32.lib"
# Win32 GUI mode application
#CORE_LINK="$CORE_LINK -subsystem:windows -entry:mainCRTStartup"
# debug
# msvc under Wine issues
# C1902: Program database manager mismatch; please check your installation
if [ -z "$NGX_WINE" ]; then
CFLAGS="$CFLAGS -Zi"
CORE_LINK="$CORE_LINK -debug"
fi
# MSVC 2005 supports C99 variadic macros
if [ "$ngx_msvc_ver" -ge 14 ]; then
have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have
fi
# precompiled headers
CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
CORE_LINK="$CORE_LINK $NGX_OBJS/ngx_pch.obj"
NGX_PCH="$NGX_OBJS/ngx_config.pch"
NGX_BUILD_PCH="-Ycngx_config.h -Fp$NGX_OBJS/ngx_config.pch"
NGX_USE_PCH="-Yungx_config.h -Fp$NGX_OBJS/ngx_config.pch"
# the resource file
NGX_RES="$NGX_OBJS/nginx.res"
NGX_RCC="rc -fo$NGX_RES \$(CORE_INCS) $NGX_WIN32_RC"
CORE_LINK="$NGX_RES $CORE_LINK"
# dynamic modules
#MAIN_LINK="-link -def:$NGX_OBJS/nginx.def"
#MODULE_LINK="-LD $NGX_OBJS/nginx.lib"
ngx_pic_opt=
ngx_objout="-Fo"
ngx_binout="-Fe"
ngx_objext="obj"
ngx_binext=".exe"
ngx_long_start='@<<
'
ngx_long_end='<<'
ngx_long_regex_cont=' \
'
ngx_long_cont='
'
# MSVC understand / in path
#ngx_regex_dirsep='\\'
#ngx_dirsep="\\"

View File

@ -0,0 +1,66 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
if [ "$NGX_PLATFORM" != win32 ]; then
ngx_feature="C compiler"
ngx_feature_name=
ngx_feature_run=yes
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test=
. auto/feature
if [ $ngx_found = no ]; then
echo
echo $0: error: C compiler $CC is not found
echo
exit 1
fi
fi
if [ "$CC" = cl ]; then
NGX_CC_NAME=msvc
echo " + using Microsoft Visual C++ compiler"
elif [ "$CC" = wcl386 ]; then
NGX_CC_NAME=owc
echo " + using Open Watcom C compiler"
elif [ "$CC" = bcc32 ]; then
NGX_CC_NAME=bcc
echo " + using Borland C++ compiler"
elif `$CC -V 2>&1 | grep '^Intel(R) C' >/dev/null 2>&1`; then
NGX_CC_NAME=icc
echo " + using Intel C++ compiler"
elif `$CC -v 2>&1 | grep 'gcc version' >/dev/null 2>&1`; then
NGX_CC_NAME=gcc
echo " + using GNU C compiler"
elif `$CC -v 2>&1 | grep '\(clang\|LLVM\) version' >/dev/null 2>&1`; then
NGX_CC_NAME=clang
echo " + using Clang C compiler"
elif `$CC -V 2>&1 | grep 'Sun C' >/dev/null 2>&1`; then
NGX_CC_NAME=sunc
echo " + using Sun C compiler"
elif `$CC -V 2>&1 | grep '^Compaq C' >/dev/null 2>&1`; then
NGX_CC_NAME=ccc
echo " + using Compaq C compiler"
elif `$CC -V 2>&1 | grep '^aCC: ' >/dev/null 2>&1`; then
NGX_CC_NAME=acc
echo " + using HP aC++ compiler"
else
NGX_CC_NAME=unknown
fi

View File

@ -0,0 +1,104 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
# Open Watcom C 1.0, 1.2, 1.3
# optimizations
# maximize speed
CFLAGS="$CFLAGS -ot"
# reorder instructions for best pipeline usage
CFLAGS="$CFLAGS -op"
# inline intrinsic functions
CFLAGS="$CFLAGS -oi"
# inline expansion
CFLAGS="$CFLAGS -oe"
# disable stack checking calls
CFLAGS="$CFLAGS -s"
case $CPU in
pentium)
# optimize for Pentium and Athlon
# register-based arguments passing conventions
CPU_OPT="-5r"
# stack-based arguments passing conventions
#CPU_OPT="-5s"
;;
pentiumpro)
# optimize for Pentium Pro, Pentium II and Pentium III
# register-based arguments passing conventions
CPU_OPT="-6r"
# stack-based arguments passing conventions
#CPU_OPT="-6s"
;;
esac
CFLAGS="$CFLAGS $CPU_OPT"
# warnings
# maximum level
CFLAGS="$CFLAGS -wx"
#CFLAGS="$CFLAGS -w3"
# stop on warning
CFLAGS="$CFLAGS -we"
# built target is NT
CFLAGS="$CFLAGS -bt=nt"
# multithreaded
CFLAGS="$CFLAGS -bm"
# debug
CFLAGS="$CFLAGS -d2"
# quiet
CFLAGS="$CFLAGS -zq"
# Open Watcom C 1.2
have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have
# the precompiled headers
#CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
#NGX_PCH="$NGX_OBJS/ngx_config.pch"
#NGX_BUILD_PCH="-fhq=$NGX_OBJS/ngx_config.pch"
#NGX_USE_PCH="-fh=$NGX_OBJS/ngx_config.pch"
# the link flags, built target is NT GUI mode application
#CORE_LINK="$CORE_LINK -l=nt_win"
# the resource file
NGX_RCC="wrc \$(CORE_INCS) -fo=$NGX_OBJS/nginx.res "
NGX_RCC="$NGX_RCC $NGX_WIN32_RC $NGX_OBJS/nginx.exe"
ngx_include_opt="-i="
ngx_objout="-fo"
ngx_binout="-fe="
ngx_objext="obj"
ngx_binext=".exe"
ngx_regex_dirsep='\\'
ngx_dirsep="\\"
ngx_long_start=' '
ngx_long_end=' '
ngx_long_regex_cont=' \&\
'
ngx_long_cont=' &
'
ngx_regex_cont=' \&\
'
ngx_cont=' &
'
ngx_tab=' &
'

View File

@ -0,0 +1,160 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
# Sun C 5.7 Patch 117837-04 2005/05/11 Sun Studio 10
# Sun C 5.8 2005/10/13 Sun Studio 11
# Sun C 5.9 SunOS_i386 2007/05/03 Sun Studio 12
# Sun C 5.9 SunOS_sparc 2007/05/03
# Sun C 5.10 SunOS_i386 2009/06/03 Sun Studio 12.1
# Sun C 5.11 SunOS_i386 2010/08/13 Sun Studio 12.2
NGX_SUNC_VER=`$CC -V 2>&1 | grep 'Sun C' 2>&1 \
| sed -e 's/^.* Sun C \(.*\)/\1/'`
echo " + Sun C version: $NGX_SUNC_VER"
have=NGX_COMPILER value="\"Sun C $NGX_SUNC_VER\"" . auto/define
cat << END > $NGX_AUTOTEST.c
int main(void) {
printf("%d", __SUNPRO_C);
return 0;
}
END
eval "$CC -o $NGX_AUTOTEST $NGX_AUTOTEST.c >> $NGX_ERR 2>&1"
if [ -x $NGX_AUTOTEST ]; then
ngx_sunc_ver=`$NGX_AUTOTEST`
fi
rm -rf $NGX_AUTOTEST*
# 1424 == 0x590, Sun Studio 12
if [ "$ngx_sunc_ver" -ge 1424 ]; then
ngx_sparc32="-m32"
ngx_sparc64="-m64"
ngx_amd64="-m64"
else
ngx_sparc32="-xarch=v8plus"
ngx_sparc64="-xarch=v9"
ngx_amd64="-xarch=amd64"
fi
case "$NGX_MACHINE" in
i86pc)
NGX_AUX=" src/os/unix/ngx_sunpro_x86.il"
;;
sun4u | sun4v)
NGX_AUX=" src/os/unix/ngx_sunpro_sparc64.il"
;;
esac
MAIN_LINK=
MODULE_LINK="-G"
# optimizations
# 20736 == 0x5100, Sun Studio 12.1
if [ "$ngx_sunc_ver" -ge 20736 ]; then
ngx_fast="-fast"
else
# older versions had problems with bit-fields
ngx_fast="-fast -xalias_level=any"
fi
IPO=-xipo
CFLAGS="$CFLAGS $ngx_fast $IPO"
CORE_LINK="$CORE_LINK $ngx_fast $IPO"
case $CPU in
pentium)
# optimize for Pentium and Athlon
CPU_OPT="-xchip=pentium"
;;
pentiumpro)
# optimize for Pentium Pro, Pentium II
CPU_OPT="-xchip=pentium_pro"
;;
pentium3)
# optimize for Pentium III
CPU_OPT="-xchip=pentium3"
#CPU_OPT="$CPU_OPT -xarch=sse"
CPU_OPT="$CPU_OPT -xcache=16/32/4:256/32/4"
;;
pentium4)
# optimize for Pentium 4
CPU_OPT="-xchip=pentium4"
#CPU_OPT="$CPU_OPT -xarch=sse2"
CPU_OPT="$CPU_OPT -xcache=8/64/4:256/128/8"
;;
opteron)
# optimize for Opteron
CPU_OPT="-xchip=opteron"
#CPU_OPT="$CPU_OPT -xarch=sse2"
CPU_OPT="$CPU_OPT -xcache=64/64/2:1024/64/16"
;;
sparc32)
# build 32-bit UltraSparc binary
CPU_OPT="$ngx_sparc32"
CORE_LINK="$CORE_LINK $ngx_sparc32"
CC_AUX_FLAGS="$CC_AUX_FLAGS $ngx_sparc32"
NGX_CPU_CACHE_LINE=64
;;
sparc64)
# build 64-bit UltraSparc binary
CPU_OPT="$ngx_sparc64"
CORE_LINK="$CORE_LINK $ngx_sparc64"
CC_AUX_FLAGS="$CC_AUX_FLAGS $ngx_sparc64"
NGX_CPU_CACHE_LINE=64
;;
amd64)
# build 64-bit amd64 binary
CPU_OPT="$ngx_amd64"
CORE_LINK="$CORE_LINK $ngx_amd64"
CC_AUX_FLAGS="$CC_AUX_FLAGS $ngx_amd64"
NGX_AUX=" src/os/unix/ngx_sunpro_amd64.il"
NGX_CPU_CACHE_LINE=64
;;
esac
CFLAGS="$CFLAGS $CPU_OPT"
if [ ".$PCRE_OPT" = "." ]; then
PCRE_OPT="$ngx_fast $IPO $CPU_OPT"
fi
if [ ".$ZLIB_OPT" = "." ]; then
ZLIB_OPT="$ngx_fast $IPO $CPU_OPT"
fi
# stop on warning
CFLAGS="$CFLAGS -errwarn=%all"
# debug
CFLAGS="$CFLAGS -g"

View File

@ -0,0 +1,12 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
cat << END >> $NGX_AUTO_CONFIG_H
#ifndef $have
#define $have $value
#endif
END

View File

@ -0,0 +1,50 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
echo $ngx_n "checking for system byte ordering ...$ngx_c"
cat << END >> $NGX_AUTOCONF_ERR
----------------------------------------
checking for system byte ordering
END
cat << END > $NGX_AUTOTEST.c
int main(void) {
int i = 0x11223344;
char *p;
p = (char *) &i;
if (*p == 0x44) return 0;
return 1;
}
END
ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
-o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
if [ -x $NGX_AUTOTEST ]; then
if $NGX_AUTOTEST >/dev/null 2>&1; then
echo " little endian"
have=NGX_HAVE_LITTLE_ENDIAN . auto/have
else
echo " big endian"
fi
rm -rf $NGX_AUTOTEST*
else
rm -rf $NGX_AUTOTEST*
echo
echo "$0: error: cannot detect system byte ordering"
exit 1
fi

View File

@ -0,0 +1,123 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
echo $ngx_n "checking for $ngx_feature ...$ngx_c"
cat << END >> $NGX_AUTOCONF_ERR
----------------------------------------
checking for $ngx_feature
END
ngx_found=no
if test -n "$ngx_feature_name"; then
ngx_have_feature=`echo $ngx_feature_name \
| tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
fi
if test -n "$ngx_feature_path"; then
for ngx_temp in $ngx_feature_path; do
ngx_feature_inc_path="$ngx_feature_inc_path -I $ngx_temp"
done
fi
cat << END > $NGX_AUTOTEST.c
#include <sys/types.h>
$NGX_INCLUDE_UNISTD_H
$ngx_feature_incs
int main(void) {
$ngx_feature_test;
return 0;
}
END
ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \
-o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_TEST_LD_OPT $ngx_feature_libs"
ngx_feature_inc_path=
eval "/bin/sh -c \"$ngx_test\" >> $NGX_AUTOCONF_ERR 2>&1"
if [ -x $NGX_AUTOTEST ]; then
case "$ngx_feature_run" in
yes)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " found"
ngx_found=yes
if test -n "$ngx_feature_name"; then
have=$ngx_have_feature . auto/have
fi
else
echo " found but is not working"
fi
;;
value)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " found"
ngx_found=yes
cat << END >> $NGX_AUTO_CONFIG_H
#ifndef $ngx_feature_name
#define $ngx_feature_name `$NGX_AUTOTEST`
#endif
END
else
echo " found but is not working"
fi
;;
bug)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " not found"
else
echo " found"
ngx_found=yes
if test -n "$ngx_feature_name"; then
have=$ngx_have_feature . auto/have
fi
fi
;;
*)
echo " found"
ngx_found=yes
if test -n "$ngx_feature_name"; then
have=$ngx_have_feature . auto/have
fi
;;
esac
else
echo " not found"
echo "----------" >> $NGX_AUTOCONF_ERR
cat $NGX_AUTOTEST.c >> $NGX_AUTOCONF_ERR
echo "----------" >> $NGX_AUTOCONF_ERR
echo $ngx_test >> $NGX_AUTOCONF_ERR
echo "----------" >> $NGX_AUTOCONF_ERR
fi
rm -rf $NGX_AUTOTEST*

View File

@ -0,0 +1,12 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
cat << END >> $NGX_AUTO_CONFIG_H
#ifndef $have
#define $have 1
#endif
END

View File

@ -0,0 +1,12 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
cat << END >> $NGX_AUTO_HEADERS_H
#ifndef $have
#define $have 1
#endif
END

View File

@ -0,0 +1,13 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
ngx_include="unistd.h"; . auto/include
ngx_include="inttypes.h"; . auto/include
ngx_include="limits.h"; . auto/include
ngx_include="sys/filio.h"; . auto/include
ngx_include="sys/param.h"; . auto/include
ngx_include="sys/mount.h"; . auto/include
ngx_include="sys/statvfs.h"; . auto/include
ngx_include="crypt.h"; . auto/include

View File

@ -0,0 +1,58 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
echo $ngx_n "checking for $ngx_include ...$ngx_c"
cat << END >> $NGX_AUTOCONF_ERR
----------------------------------------
checking for $ngx_include
END
ngx_found=no
cat << END > $NGX_AUTOTEST.c
$NGX_INCLUDE_SYS_PARAM_H
#include <$ngx_include>
int main(void) {
return 0;
}
END
ngx_test="$CC -o $NGX_AUTOTEST $NGX_AUTOTEST.c"
eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
if [ -x $NGX_AUTOTEST ]; then
ngx_found=yes
echo " found"
ngx_name=`echo $ngx_include \
| tr abcdefghijklmnopqrstuvwxyz/. ABCDEFGHIJKLMNOPQRSTUVWXYZ__`
have=NGX_HAVE_$ngx_name . auto/have_headers
eval "NGX_INCLUDE_$ngx_name='#include <$ngx_include>'"
else
echo " not found"
echo "----------" >> $NGX_AUTOCONF_ERR
cat $NGX_AUTOTEST.c >> $NGX_AUTOCONF_ERR
echo "----------" >> $NGX_AUTOCONF_ERR
echo $ngx_test >> $NGX_AUTOCONF_ERR
echo "----------" >> $NGX_AUTOCONF_ERR
fi
rm -rf $NGX_AUTOTEST*

View File

@ -0,0 +1,51 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
NGX_MAKEFILE=$NGX_OBJS/Makefile
NGX_MODULES_C=$NGX_OBJS/ngx_modules.c
NGX_AUTO_HEADERS_H=$NGX_OBJS/ngx_auto_headers.h
NGX_AUTO_CONFIG_H=$NGX_OBJS/ngx_auto_config.h
NGX_AUTOTEST=$NGX_OBJS/autotest
NGX_AUTOCONF_ERR=$NGX_OBJS/autoconf.err
# STUBs
NGX_ERR=$NGX_OBJS/autoconf.err
MAKEFILE=$NGX_OBJS/Makefile
NGX_PCH=
NGX_USE_PCH=
# check the echo's "-n" option and "\c" capability
if echo "test\c" | grep c >/dev/null; then
if echo -n test | grep n >/dev/null; then
ngx_n=
ngx_c=
else
ngx_n=-n
ngx_c=
fi
else
ngx_n=
ngx_c='\c'
fi
# create Makefile
cat << END > Makefile
default: build
clean:
rm -rf Makefile $NGX_OBJS
END

View File

@ -0,0 +1,218 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
if [ $USE_PERL != NO ]; then
cat << END >> $NGX_MAKEFILE
install_perl_modules:
cd $NGX_OBJS/src/http/modules/perl && \$(MAKE) install
END
NGX_INSTALL_PERL_MODULES=install_perl_modules
fi
case ".$NGX_SBIN_PATH" in
./*)
;;
*)
NGX_SBIN_PATH=$NGX_PREFIX/$NGX_SBIN_PATH
;;
esac
case ".$NGX_MODULES_PATH" in
./*)
;;
*)
NGX_MODULES_PATH=$NGX_PREFIX/$NGX_MODULES_PATH
;;
esac
NGX_MODULES_PATH=`dirname $NGX_MODULES_PATH/.`
case ".$NGX_CONF_PATH" in
./*)
;;
*)
NGX_CONF_PATH=$NGX_PREFIX/$NGX_CONF_PATH
;;
esac
NGX_CONF_PREFIX=`dirname $NGX_CONF_PATH`
case ".$NGX_PID_PATH" in
./*)
;;
*)
NGX_PID_PATH=$NGX_PREFIX/$NGX_PID_PATH
;;
esac
case ".$NGX_ERROR_LOG_PATH" in
./* | .)
;;
*)
NGX_ERROR_LOG_PATH=$NGX_PREFIX/$NGX_ERROR_LOG_PATH
;;
esac
case ".$NGX_HTTP_LOG_PATH" in
./*)
;;
*)
NGX_HTTP_LOG_PATH=$NGX_PREFIX/$NGX_HTTP_LOG_PATH
;;
esac
if test -f man/nginx.8 ; then
NGX_MAN=man/nginx.8
else
NGX_MAN=docs/man/nginx.8
fi
if test -d html ; then
NGX_HTML=html
else
NGX_HTML=docs/html
fi
cat << END >> $NGX_MAKEFILE
manpage: $NGX_OBJS/nginx.8
$NGX_OBJS/nginx.8: $NGX_MAN $NGX_AUTO_CONFIG_H
sed -e "s|%%PREFIX%%|$NGX_PREFIX|" \\
-e "s|%%PID_PATH%%|$NGX_PID_PATH|" \\
-e "s|%%CONF_PATH%%|$NGX_CONF_PATH|" \\
-e "s|%%ERROR_LOG_PATH%%|${NGX_ERROR_LOG_PATH:-stderr}|" \\
< $NGX_MAN > \$@
install: build $NGX_INSTALL_PERL_MODULES
test -d '\$(DESTDIR)$NGX_PREFIX' || mkdir -p '\$(DESTDIR)$NGX_PREFIX'
test -d '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`' \\
|| mkdir -p '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`'
test ! -f '\$(DESTDIR)$NGX_SBIN_PATH' \\
|| mv '\$(DESTDIR)$NGX_SBIN_PATH' \\
'\$(DESTDIR)$NGX_SBIN_PATH.old'
cp $NGX_OBJS/nginx '\$(DESTDIR)$NGX_SBIN_PATH'
test -d '\$(DESTDIR)$NGX_CONF_PREFIX' \\
|| mkdir -p '\$(DESTDIR)$NGX_CONF_PREFIX'
cp conf/koi-win '\$(DESTDIR)$NGX_CONF_PREFIX'
cp conf/koi-utf '\$(DESTDIR)$NGX_CONF_PREFIX'
cp conf/win-utf '\$(DESTDIR)$NGX_CONF_PREFIX'
test -f '\$(DESTDIR)$NGX_CONF_PREFIX/mime.types' \\
|| cp conf/mime.types '\$(DESTDIR)$NGX_CONF_PREFIX'
cp conf/mime.types '\$(DESTDIR)$NGX_CONF_PREFIX/mime.types.default'
test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params' \\
|| cp conf/fastcgi_params '\$(DESTDIR)$NGX_CONF_PREFIX'
cp conf/fastcgi_params \\
'\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params.default'
test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf' \\
|| cp conf/fastcgi.conf '\$(DESTDIR)$NGX_CONF_PREFIX'
cp conf/fastcgi.conf '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf.default'
test -f '\$(DESTDIR)$NGX_CONF_PREFIX/uwsgi_params' \\
|| cp conf/uwsgi_params '\$(DESTDIR)$NGX_CONF_PREFIX'
cp conf/uwsgi_params \\
'\$(DESTDIR)$NGX_CONF_PREFIX/uwsgi_params.default'
test -f '\$(DESTDIR)$NGX_CONF_PREFIX/scgi_params' \\
|| cp conf/scgi_params '\$(DESTDIR)$NGX_CONF_PREFIX'
cp conf/scgi_params \\
'\$(DESTDIR)$NGX_CONF_PREFIX/scgi_params.default'
test -f '\$(DESTDIR)$NGX_CONF_PATH' \\
|| cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PATH'
cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PREFIX/nginx.conf.default'
test -d '\$(DESTDIR)`dirname "$NGX_PID_PATH"`' \\
|| mkdir -p '\$(DESTDIR)`dirname "$NGX_PID_PATH"`'
test -d '\$(DESTDIR)`dirname "$NGX_HTTP_LOG_PATH"`' \\
|| mkdir -p '\$(DESTDIR)`dirname "$NGX_HTTP_LOG_PATH"`'
test -d '\$(DESTDIR)$NGX_PREFIX/html' \\
|| cp -R $NGX_HTML '\$(DESTDIR)$NGX_PREFIX'
END
if test -n "$NGX_ERROR_LOG_PATH"; then
cat << END >> $NGX_MAKEFILE
test -d '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`' \\
|| mkdir -p '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`'
END
fi
if test -n "$DYNAMIC_MODULES"; then
cat << END >> $NGX_MAKEFILE
test -d '\$(DESTDIR)$NGX_MODULES_PATH' \\
|| mkdir -p '\$(DESTDIR)$NGX_MODULES_PATH'
END
fi
for ngx_module in $DYNAMIC_MODULES
do
ngx_module=$ngx_module$ngx_modext
cat << END >> $NGX_MAKEFILE
test ! -f '\$(DESTDIR)$NGX_MODULES_PATH/$ngx_module' \\
|| mv '\$(DESTDIR)$NGX_MODULES_PATH/$ngx_module' \\
'\$(DESTDIR)$NGX_MODULES_PATH/$ngx_module.old'
cp $NGX_OBJS/$ngx_module '\$(DESTDIR)$NGX_MODULES_PATH/$ngx_module'
END
done
# create Makefile
cat << END >> Makefile
build:
\$(MAKE) -f $NGX_MAKEFILE
install:
\$(MAKE) -f $NGX_MAKEFILE install
modules:
\$(MAKE) -f $NGX_MAKEFILE modules
upgrade:
$NGX_SBIN_PATH -t
kill -USR2 \`cat $NGX_PID_PATH\`
sleep 1
test -f $NGX_PID_PATH.oldbin
kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
END

View File

@ -0,0 +1,54 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
if [ $USE_PCRE = YES -o $PCRE != NONE ]; then
. auto/lib/pcre/conf
else
if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then
cat << END
$0: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option or you have to enable the PCRE support.
END
exit 1
fi
fi
if [ $USE_OPENSSL = YES ]; then
. auto/lib/openssl/conf
fi
if [ $USE_ZLIB = YES ]; then
. auto/lib/zlib/conf
fi
if [ $USE_LIBXSLT != NO ]; then
. auto/lib/libxslt/conf
fi
if [ $USE_LIBGD != NO ]; then
. auto/lib/libgd/conf
fi
if [ $USE_PERL != NO ]; then
. auto/lib/perl/conf
fi
if [ $USE_GEOIP != NO ]; then
. auto/lib/geoip/conf
fi
if [ $NGX_GOOGLE_PERFTOOLS = YES ]; then
. auto/lib/google-perftools/conf
fi
if [ $NGX_LIBATOMIC != NO ]; then
. auto/lib/libatomic/conf
fi

View File

@ -0,0 +1,97 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
ngx_feature="GeoIP library"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <GeoIP.h>"
ngx_feature_path=
ngx_feature_libs="-lGeoIP"
ngx_feature_test="GeoIP_open(NULL, 0)"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="GeoIP library in /usr/local/"
ngx_feature_path="/usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lGeoIP"
else
ngx_feature_libs="-L/usr/local/lib -lGeoIP"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="GeoIP library in /usr/pkg/"
ngx_feature_path="/usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lGeoIP"
else
ngx_feature_libs="-L/usr/pkg/lib -lGeoIP"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="GeoIP library in /opt/local/"
ngx_feature_path="/opt/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lGeoIP"
else
ngx_feature_libs="-L/opt/local/lib -lGeoIP"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
CORE_INCS="$CORE_INCS $ngx_feature_path"
if [ $USE_GEOIP = YES ]; then
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
fi
NGX_LIB_GEOIP=$ngx_feature_libs
ngx_feature="GeoIP IPv6 support"
ngx_feature_name="NGX_HAVE_GEOIP_V6"
ngx_feature_run=no
ngx_feature_incs="#include <stdio.h>
#include <GeoIP.h>"
#ngx_feature_path=
#ngx_feature_libs=
ngx_feature_test="printf(\"%d\", GEOIP_CITY_EDITION_REV0_V6);"
. auto/feature
else
cat << END
$0: error: the GeoIP module requires the GeoIP library.
You can either do not enable the module or install the library.
END
exit 1
fi

View File

@ -0,0 +1,61 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
ngx_feature="Google perftools"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs="-lprofiler"
ngx_feature_test="ProfilerStop()"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="Google perftools in /usr/local/"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lprofiler"
else
ngx_feature_libs="-L/usr/local/lib -lprofiler"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="Google perftools in /opt/local/"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lprofiler"
else
ngx_feature_libs="-L/opt/local/lib -lprofiler"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
else
cat << END
$0: error: the Google perftools module requires the Google perftools
library. You can either do not enable the module or install the library.
END
exit 1
fi

View File

@ -0,0 +1,43 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
if [ $NGX_LIBATOMIC != YES ]; then
have=NGX_HAVE_LIBATOMIC . auto/have
CORE_INCS="$CORE_INCS $NGX_LIBATOMIC/src"
LINK_DEPS="$LINK_DEPS $NGX_LIBATOMIC/src/libatomic_ops.a"
CORE_LIBS="$CORE_LIBS $NGX_LIBATOMIC/src/libatomic_ops.a"
else
ngx_feature="atomic_ops library"
ngx_feature_name=NGX_HAVE_LIBATOMIC
ngx_feature_run=yes
ngx_feature_incs="#define AO_REQUIRE_CAS
#include <atomic_ops.h>"
ngx_feature_path=
ngx_feature_libs="-latomic_ops"
ngx_feature_test="long n = 0;
if (!AO_compare_and_swap(&n, 0, 1))
return 1;
if (AO_fetch_and_add(&n, 1) != 1)
return 1;
if (n != 2)
return 1;
AO_nop();"
. auto/feature
if [ $ngx_found = yes ]; then
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
else
cat << END
$0: error: libatomic_ops library was not found.
END
exit 1
fi
fi

View File

@ -0,0 +1,16 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
cat << END >> $NGX_MAKEFILE
$NGX_LIBATOMIC/src/libatomic_ops.a: $NGX_LIBATOMIC/Makefile
cd $NGX_LIBATOMIC && \$(MAKE)
$NGX_LIBATOMIC/Makefile: $NGX_MAKEFILE
cd $NGX_LIBATOMIC \\
&& if [ -f Makefile ]; then \$(MAKE) distclean; fi \\
&& ./configure
END

View File

@ -0,0 +1,93 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
ngx_feature="GD library"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <gd.h>"
ngx_feature_path=
ngx_feature_libs="-lgd"
ngx_feature_test="gdImagePtr img = gdImageCreateFromGifPtr(1, NULL);"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="GD library in /usr/local/"
ngx_feature_path="/usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lgd"
else
ngx_feature_libs="-L/usr/local/lib -lgd"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="GD library in /usr/pkg/"
ngx_feature_path="/usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lgd"
else
ngx_feature_libs="-L/usr/pkg/lib -lgd"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="GD library in /opt/local/"
ngx_feature_path="/opt/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lgd"
else
ngx_feature_libs="-L/opt/local/lib -lgd"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
CORE_INCS="$CORE_INCS $ngx_feature_path"
if [ $USE_LIBGD = YES ]; then
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
fi
NGX_LIB_LIBGD=$ngx_feature_libs
ngx_feature="GD WebP support"
ngx_feature_name="NGX_HAVE_GD_WEBP"
ngx_feature_test="gdImagePtr img = gdImageCreateFromWebpPtr(1, NULL);"
. auto/feature
else
cat << END
$0: error: the HTTP image filter module requires the GD library.
You can either do not enable the module or install the libraries.
END
exit 1
fi

View File

@ -0,0 +1,165 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
ngx_feature="libxslt"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>"
ngx_feature_path="/usr/include/libxml2"
ngx_feature_libs="-lxml2 -lxslt"
ngx_feature_test="xmlParserCtxtPtr ctxt = NULL;
xsltStylesheetPtr sheet = NULL;
xmlDocPtr doc;
doc = xmlParseChunk(ctxt, NULL, 0, 0);
xsltApplyStylesheet(sheet, doc, NULL);"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="libxslt in /usr/local/"
ngx_feature_path="/usr/local/include/libxml2 /usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lxml2 -lxslt"
else
ngx_feature_libs="-L/usr/local/lib -lxml2 -lxslt"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="libxslt in /usr/pkg/"
ngx_feature_path="/usr/pkg/include/libxml2 /usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lxml2 -lxslt"
else
ngx_feature_libs="-L/usr/pkg/lib -lxml2 -lxslt"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="libxslt in /opt/local/"
ngx_feature_path="/opt/local/include/libxml2 /opt/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lxml2 -lxslt"
else
ngx_feature_libs="-L/opt/local/lib -lxml2 -lxslt"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
CORE_INCS="$CORE_INCS $ngx_feature_path"
if [ $USE_LIBXSLT = YES ]; then
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
fi
NGX_LIB_LIBXSLT=$ngx_feature_libs
else
cat << END
$0: error: the HTTP XSLT module requires the libxml2/libxslt
libraries. You can either do not enable the module or install the libraries.
END
exit 1
fi
ngx_feature="libexslt"
ngx_feature_name=NGX_HAVE_EXSLT
ngx_feature_run=no
ngx_feature_incs="#include <libexslt/exslt.h>"
ngx_feature_path="/usr/include/libxml2"
ngx_feature_libs="-lexslt"
ngx_feature_test="exsltRegisterAll();"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="libexslt in /usr/local/"
ngx_feature_path="/usr/local/include/libxml2 /usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lexslt"
else
ngx_feature_libs="-L/usr/local/lib -lexslt"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="libexslt in /usr/pkg/"
ngx_feature_path="/usr/pkg/include/libxml2 /usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lexslt"
else
ngx_feature_libs="-L/usr/pkg/lib -lexslt"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="libexslt in /opt/local/"
ngx_feature_path="/opt/local/include/libxml2 /opt/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lexslt"
else
ngx_feature_libs="-L/opt/local/lib -lexslt"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
if [ $USE_LIBXSLT = YES ]; then
CORE_LIBS="$CORE_LIBS -lexslt"
fi
NGX_LIB_LIBXSLT="$NGX_LIB_LIBXSLT -lexslt"
fi

View File

@ -0,0 +1,24 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
if [ $PCRE != NONE -a $PCRE != NO -a $PCRE != YES ]; then
. auto/lib/pcre/make
fi
if [ $OPENSSL != NONE -a $OPENSSL != NO -a $OPENSSL != YES ]; then
. auto/lib/openssl/make
fi
if [ $ZLIB != NONE -a $ZLIB != NO -a $ZLIB != YES ]; then
. auto/lib/zlib/make
fi
if [ $NGX_LIBATOMIC != NO -a $NGX_LIBATOMIC != YES ]; then
. auto/lib/libatomic/make
fi
if [ $USE_PERL != NO ]; then
. auto/lib/perl/make
fi

View File

@ -0,0 +1,135 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
if [ $OPENSSL != NONE ]; then
case "$CC" in
cl | bcc32)
have=NGX_OPENSSL . auto/have
have=NGX_SSL . auto/have
CFLAGS="$CFLAGS -DNO_SYS_TYPES_H"
CORE_INCS="$CORE_INCS $OPENSSL/openssl/include"
CORE_DEPS="$CORE_DEPS $OPENSSL/openssl/include/openssl/ssl.h"
if [ -f $OPENSSL/ms/do_ms.bat ]; then
# before OpenSSL 1.1.0
CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/ssleay32.lib"
CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libeay32.lib"
else
# OpenSSL 1.1.0+
CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libssl.lib"
CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libcrypto.lib"
fi
# libeay32.lib requires gdi32.lib
CORE_LIBS="$CORE_LIBS gdi32.lib"
# OpenSSL 1.0.0 requires crypt32.lib
CORE_LIBS="$CORE_LIBS crypt32.lib"
;;
*)
have=NGX_OPENSSL . auto/have
have=NGX_SSL . auto/have
CORE_INCS="$CORE_INCS $OPENSSL/.openssl/include"
CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h"
CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a"
CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a"
CORE_LIBS="$CORE_LIBS $NGX_LIBDL"
if [ "$NGX_PLATFORM" = win32 ]; then
CORE_LIBS="$CORE_LIBS -lgdi32 -lcrypt32 -lws2_32"
fi
;;
esac
else
if [ "$NGX_PLATFORM" != win32 ]; then
OPENSSL=NO
ngx_feature="OpenSSL library"
ngx_feature_name="NGX_OPENSSL"
ngx_feature_run=no
ngx_feature_incs="#include <openssl/ssl.h>"
ngx_feature_path=
ngx_feature_libs="-lssl -lcrypto $NGX_LIBDL"
ngx_feature_test="SSL_CTX_set_options(NULL, 0)"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="OpenSSL library in /usr/local/"
ngx_feature_path="/usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto $NGX_LIBDL"
else
ngx_feature_libs="-L/usr/local/lib -lssl -lcrypto $NGX_LIBDL"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="OpenSSL library in /usr/pkg/"
ngx_feature_path="/usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lssl -lcrypto $NGX_LIBDL"
else
ngx_feature_libs="-L/usr/pkg/lib -lssl -lcrypto $NGX_LIBDL"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="OpenSSL library in /opt/local/"
ngx_feature_path="/opt/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lssl -lcrypto $NGX_LIBDL"
else
ngx_feature_libs="-L/opt/local/lib -lssl -lcrypto $NGX_LIBDL"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
have=NGX_SSL . auto/have
CORE_INCS="$CORE_INCS $ngx_feature_path"
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
OPENSSL=YES
fi
fi
if [ $OPENSSL != YES ]; then
cat << END
$0: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl=<path> option.
END
exit 1
fi
fi

View File

@ -0,0 +1,62 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
case "$CC" in
cl)
cat << END >> $NGX_MAKEFILE
$OPENSSL/openssl/include/openssl/ssl.h: $NGX_MAKEFILE
\$(MAKE) -f auto/lib/openssl/makefile.msvc \
OPENSSL="$OPENSSL" OPENSSL_OPT="$OPENSSL_OPT"
END
;;
bcc32)
ngx_opt=`echo "-DOPENSSL=\"$OPENSSL\" -DOPENSSL_OPT=\"$OPENSSL_OPT\"" \
| sed -e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
`echo "$OPENSSL\\openssl\\lib\\libeay32.lib: \
$OPENSSL\\openssl\\include\\openssl\\ssl.h" \
| sed -e "s/\//$ngx_regex_dirsep/g"`
`echo "$OPENSSL\\openssl\\lib\\ssleay32.lib: \
$OPENSSL\\openssl\\include\\openssl\\ssl.h" \
| sed -e "s/\//$ngx_regex_dirsep/g"`
`echo "$OPENSSL\\openssl\\include\\openssl\\ssl.h: $NGX_MAKEFILE" \
| sed -e "s/\//$ngx_regex_dirsep/g"`
\$(MAKE) -f auto/lib/openssl/makefile.bcc $ngx_opt
END
;;
*)
case $OPENSSL in
/*) ngx_prefix="$OPENSSL/.openssl" ;;
*) ngx_prefix="$PWD/$OPENSSL/.openssl" ;;
esac
cat << END >> $NGX_MAKEFILE
$OPENSSL/.openssl/include/openssl/ssl.h: $NGX_MAKEFILE
cd $OPENSSL \\
&& if [ -f Makefile ]; then \$(MAKE) clean; fi \\
&& ./config --prefix=$ngx_prefix no-shared $OPENSSL_OPT \\
&& \$(MAKE) \\
&& \$(MAKE) install_sw LIBDIR=lib
END
;;
esac

View File

@ -0,0 +1,18 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
all:
cd $(OPENSSL)
perl Configure BC-32 no-shared --prefix=openssl $(OPENSSL_OPT)
ms\do_nasm
$(MAKE) -f ms\bcb.mak
$(MAKE) -f ms\bcb.mak install
# Borland's make does not expand "[ch]" in
# copy "inc32\openssl\*.[ch]" "openssl\include\openssl"
copy inc32\openssl\*.h openssl\include\openssl

View File

@ -0,0 +1,21 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
all:
cd $(OPENSSL)
perl Configure VC-WIN32 no-shared \
--prefix="%cd%/openssl" \
--openssldir="%cd%/openssl/ssl" \
$(OPENSSL_OPT)
if exist ms\do_ms.bat ( \
ms\do_ms \
&& $(MAKE) -f ms\nt.mak \
&& $(MAKE) -f ms\nt.mak install \
) else ( \
$(MAKE) \
&& $(MAKE) install_sw \
)

View File

@ -0,0 +1,203 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
if [ $PCRE != NONE ]; then
CORE_INCS="$CORE_INCS $PCRE"
case "$NGX_CC_NAME" in
msvc | owc | bcc)
have=NGX_PCRE . auto/have
have=PCRE_STATIC . auto/have
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
LINK_DEPS="$LINK_DEPS $PCRE/pcre.lib"
CORE_LIBS="$CORE_LIBS $PCRE/pcre.lib"
;;
icc)
have=NGX_PCRE . auto/have
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
echo $ngx_n "checking for PCRE library ...$ngx_c"
if [ -f $PCRE/pcre.h ]; then
ngx_pcre_ver=`grep PCRE_MAJOR $PCRE/pcre.h \
| sed -e 's/^.*PCRE_MAJOR.* \(.*\)$/\1/'`
else if [ -f $PCRE/configure.in ]; then
ngx_pcre_ver=`grep PCRE_MAJOR= $PCRE/configure.in \
| sed -e 's/^.*=\(.*\)$/\1/'`
else
ngx_pcre_ver=`grep pcre_major, $PCRE/configure.ac \
| sed -e 's/^.*pcre_major,.*\[\(.*\)\].*$/\1/'`
fi
fi
echo " $ngx_pcre_ver major version found"
# to allow -ipo optimization we link with the *.o but not library
case "$ngx_pcre_ver" in
4|5)
CORE_LIBS="$CORE_LIBS $PCRE/pcre.o"
;;
6)
CORE_LIBS="$CORE_LIBS $PCRE/pcre_chartables.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_compile.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_exec.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_fullinfo.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_globals.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_tables.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_try_flipped.o"
;;
*)
CORE_LIBS="$CORE_LIBS $PCRE/pcre_chartables.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_compile.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_exec.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_fullinfo.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_globals.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_tables.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_try_flipped.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_newline.o"
;;
esac
;;
*)
have=NGX_PCRE . auto/have
if [ "$NGX_PLATFORM" = win32 ]; then
have=PCRE_STATIC . auto/have
fi
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre.a"
;;
esac
if [ $PCRE_JIT = YES ]; then
have=NGX_HAVE_PCRE_JIT . auto/have
PCRE_CONF_OPT="$PCRE_CONF_OPT --enable-jit"
fi
else
if [ "$NGX_PLATFORM" != win32 ]; then
PCRE=NO
ngx_feature="PCRE library"
ngx_feature_name="NGX_PCRE"
ngx_feature_run=no
ngx_feature_incs="#include <pcre.h>"
ngx_feature_path=
ngx_feature_libs="-lpcre"
ngx_feature_test="pcre *re;
re = pcre_compile(NULL, 0, NULL, 0, NULL);
if (re == NULL) return 1"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="PCRE library in /usr/local/"
ngx_feature_path="/usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lpcre"
else
ngx_feature_libs="-L/usr/local/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# RedHat RPM, Solaris package
ngx_feature="PCRE library in /usr/include/pcre/"
ngx_feature_path="/usr/include/pcre"
ngx_feature_libs="-lpcre"
. auto/feature
fi
if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="PCRE library in /usr/pkg/"
ngx_feature_path="/usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lpcre"
else
ngx_feature_libs="-L/usr/pkg/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="PCRE library in /opt/local/"
ngx_feature_path="/opt/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lpcre"
else
ngx_feature_libs="-L/opt/local/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
CORE_INCS="$CORE_INCS $ngx_feature_path"
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
PCRE=YES
fi
if [ $PCRE = YES ]; then
ngx_feature="PCRE JIT support"
ngx_feature_name="NGX_HAVE_PCRE_JIT"
ngx_feature_test="int jit = 0;
pcre_free_study(NULL);
pcre_config(PCRE_CONFIG_JIT, &jit);
if (jit != 1) return 1;"
. auto/feature
if [ $ngx_found = yes ]; then
PCRE_JIT=YES
fi
fi
fi
if [ $PCRE != YES ]; then
cat << END
$0: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
END
exit 1
fi
fi

View File

@ -0,0 +1,64 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
case "$NGX_CC_NAME" in
msvc)
ngx_makefile=makefile.msvc
ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC"
ngx_pcre="PCRE=\"$PCRE\""
;;
owc)
ngx_makefile=makefile.owc
ngx_opt="CPU_OPT=\"$CPU_OPT\""
ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
;;
bcc)
ngx_makefile=makefile.bcc
ngx_opt="-DCPU_OPT=\"$CPU_OPT\""
ngx_pcre=`echo \-DPCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
;;
*)
ngx_makefile=
;;
esac
if [ -n "$ngx_makefile" ]; then
cat << END >> $NGX_MAKEFILE
`echo "$PCRE/pcre.lib: $PCRE/pcre.h $NGX_MAKEFILE" \
| sed -e "s/\//$ngx_regex_dirsep/g"`
\$(MAKE) -f auto/lib/pcre/$ngx_makefile $ngx_pcre $ngx_opt
`echo "$PCRE/pcre.h:" | sed -e "s/\//$ngx_regex_dirsep/g"`
\$(MAKE) -f auto/lib/pcre/$ngx_makefile $ngx_pcre pcre.h
END
else
cat << END >> $NGX_MAKEFILE
$PCRE/pcre.h: $PCRE/Makefile
$PCRE/Makefile: $NGX_MAKEFILE
cd $PCRE \\
&& if [ -f Makefile ]; then \$(MAKE) distclean; fi \\
&& CC="\$(CC)" CFLAGS="$PCRE_OPT" \\
./configure --disable-shared $PCRE_CONF_OPT
$PCRE/.libs/libpcre.a: $PCRE/Makefile
cd $PCRE \\
&& \$(MAKE) libpcre.la
END
fi

View File

@ -0,0 +1,27 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
CFLAGS = -q -O2 -tWM -w-8004 $(CPU_OPT)
PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 \
-DSUPPORT_PCRE8 -DHAVE_MEMMOVE
pcre.lib:
cd $(PCRE)
bcc32 -c $(CFLAGS) -I. $(PCREFLAGS) pcre_*.c
copy /y nul pcre.lst
for %n in (*.obj) do @echo +%n ^^& >> pcre.lst
echo + >> pcre.lst
tlib pcre.lib @pcre.lst
pcre.h:
cd $(PCRE)
copy /y pcre.h.generic pcre.h
copy /y config.h.generic config.h
copy /y pcre_chartables.c.dist pcre_chartables.c

View File

@ -0,0 +1,23 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
CFLAGS = -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT)
PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 \
-DSUPPORT_PCRE8 -DHAVE_MEMMOVE
pcre.lib:
cd $(PCRE)
cl -nologo -c $(CFLAGS) -I . $(PCREFLAGS) pcre_*.c
link -lib -out:pcre.lib -verbose:lib pcre_*.obj
pcre.h:
cd $(PCRE)
copy /y pcre.h.generic pcre.h
copy /y config.h.generic config.h
copy /y pcre_chartables.c.dist pcre_chartables.c

View File

@ -0,0 +1,25 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
CFLAGS = -c -zq -bt=nt -ot -op -oi -oe -s -bm $(CPU_OPT)
PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 &
-DSUPPORT_PCRE8 -DHAVE_MEMMOVE
pcre.lib:
cd $(PCRE)
wcl386 $(CFLAGS) -i=. $(PCREFLAGS) pcre_*.c
dir /b *.obj > pcre.lst
wlib -n pcre.lib @pcre.lst
pcre.h:
cd $(PCRE)
copy /y pcre.h.generic pcre.h
copy /y config.h.generic config.h
copy /y pcre_chartables.c.dist pcre_chartables.c

View File

@ -0,0 +1,83 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
echo "checking for perl"
NGX_PERL_VER=`$NGX_PERL -v 2>&1 | grep '^This is perl' 2>&1 \
| sed -e 's/^This is perl, \(.*\)/\1/'`
if test -n "$NGX_PERL_VER"; then
echo " + perl version: $NGX_PERL_VER"
if [ "`$NGX_PERL -e 'use 5.008006; print "OK"'`" != "OK" ]; then
echo
echo "$0: error: perl 5.8.6 or higher is required"
echo
exit 1;
fi
if [ "`$NGX_PERL -MExtUtils::Embed -e 'print "OK"'`" != "OK" ]; then
echo
echo "$0: error: perl module ExtUtils::Embed is required"
echo
exit 1;
fi
NGX_PM_CFLAGS=`$NGX_PERL -MExtUtils::Embed -e ccopts`
NGX_PM_LDFLAGS=`$NGX_PERL -MConfig -e 'print $Config{lddlflags}'`
NGX_PERL_CFLAGS="$CFLAGS `$NGX_PERL -MExtUtils::Embed -e ccopts`"
# gcc 4.1/4.2 warn about unused values in pTHX_
NGX_PERL_CFLAGS=`echo $NGX_PERL_CFLAGS \
| sed -e 's/-Wunused-value/-Wno-unused-value/'`
# icc8 warns 'declaration hides parameter "my_perl"' in ENTER and LEAVE
NGX_PERL_CFLAGS=`echo $NGX_PERL_CFLAGS \
| sed -e 's/-wd171/-wd171 -wd1599/'`
ngx_perl_ldopts=`$NGX_PERL -MExtUtils::Embed -e ldopts`
ngx_perl_dlext=`$NGX_PERL -MConfig -e 'print $Config{dlext}'`
ngx_perl_libdir="src/http/modules/perl/blib/arch/auto"
ngx_perl_module="$ngx_perl_libdir/nginx/nginx.$ngx_perl_dlext"
if $NGX_PERL -V:usemultiplicity | grep define > /dev/null; then
have=NGX_HAVE_PERL_MULTIPLICITY . auto/have
echo " + perl interpreter multiplicity found"
fi
if $NGX_PERL -V:useithreads | grep undef > /dev/null; then
# FreeBSD port wants to link with -pthread non-threaded perl
ngx_perl_ldopts=`echo $ngx_perl_ldopts | sed 's/ -pthread//'`
fi
if [ "$NGX_SYSTEM" = "Darwin" ]; then
# OS X system perl wants to link universal binaries
ngx_perl_ldopts=`echo $ngx_perl_ldopts \
| sed -e 's/-arch i386//' -e 's/-arch x86_64//'`
fi
if [ $USE_PERL = YES ]; then
CORE_LINK="$CORE_LINK $ngx_perl_ldopts"
fi
NGX_LIB_PERL="$ngx_perl_ldopts"
if test -n "$NGX_PERL_MODULES"; then
have=NGX_PERL_MODULES value="(u_char *) \"$NGX_PERL_MODULES\""
. auto/define
NGX_PERL_MODULES_MAN=$NGX_PERL_MODULES/man3
fi
else
echo
echo "$0: error: perl 5.8.6 or higher is required"
echo
exit 1;
fi

View File

@ -0,0 +1,46 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
cat << END >> $NGX_MAKEFILE
$NGX_OBJS/src/http/modules/perl/ngx_http_perl_module.o: \\
$NGX_OBJS/$ngx_perl_module
$NGX_OBJS/$ngx_perl_module: \\
\$(CORE_DEPS) \$(HTTP_DEPS) \\
src/http/modules/perl/ngx_http_perl_module.h \\
$NGX_OBJS/src/http/modules/perl/Makefile
cd $NGX_OBJS/src/http/modules/perl && \$(MAKE)
rm -rf $NGX_OBJS/install_perl
$NGX_OBJS/src/http/modules/perl/Makefile: \\
$NGX_AUTO_CONFIG_H \\
src/core/nginx.h \\
src/http/modules/perl/Makefile.PL \\
src/http/modules/perl/nginx.pm \\
src/http/modules/perl/nginx.xs \\
src/http/modules/perl/typemap
grep 'define NGINX_VERSION' src/core/nginx.h \\
| sed -e 's/^.*"\(.*\)".*/\1/' > \\
$NGX_OBJS/src/http/modules/perl/version
sed "s/%%VERSION%%/\`cat $NGX_OBJS/src/http/modules/perl/version\`/" \\
src/http/modules/perl/nginx.pm > \\
$NGX_OBJS/src/http/modules/perl/nginx.pm
cp -p src/http/modules/perl/nginx.xs $NGX_OBJS/src/http/modules/perl/
cp -p src/http/modules/perl/typemap $NGX_OBJS/src/http/modules/perl/
cp -p src/http/modules/perl/Makefile.PL $NGX_OBJS/src/http/modules/perl/
cd $NGX_OBJS/src/http/modules/perl \\
&& NGX_PM_CFLAGS="\$(NGX_PM_CFLAGS) -g $NGX_CC_OPT" \\
NGX_PM_LDFLAGS="$NGX_LD_OPT \$(NGX_PM_LDFLAGS)" \\
NGX_INCS="$CORE_INCS $NGX_OBJS $HTTP_INCS" \\
NGX_DEPS="\$(CORE_DEPS) \$(HTTP_DEPS)" \\
$NGX_PERL Makefile.PL \\
LIB=$NGX_PERL_MODULES \\
INSTALLSITEMAN3DIR=$NGX_PERL_MODULES_MAN
END

View File

@ -0,0 +1,79 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
if [ $ZLIB != NONE ]; then
CORE_INCS="$CORE_INCS $ZLIB"
case "$NGX_CC_NAME" in
msvc | owc | bcc)
have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/zlib.lib"
CORE_LIBS="$CORE_LIBS $ZLIB/zlib.lib"
;;
icc)
have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/libz.a"
# to allow -ipo optimization we link with the *.o but not library
CORE_LIBS="$CORE_LIBS $ZLIB/adler32.o"
CORE_LIBS="$CORE_LIBS $ZLIB/crc32.o"
CORE_LIBS="$CORE_LIBS $ZLIB/deflate.o"
CORE_LIBS="$CORE_LIBS $ZLIB/trees.o"
CORE_LIBS="$CORE_LIBS $ZLIB/zutil.o"
CORE_LIBS="$CORE_LIBS $ZLIB/compress.o"
if [ $ZLIB_ASM != NO ]; then
CORE_LIBS="$CORE_LIBS $ZLIB/match.o"
fi
;;
*)
have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/libz.a"
CORE_LIBS="$CORE_LIBS $ZLIB/libz.a"
#CORE_LIBS="$CORE_LIBS -L $ZLIB -lz"
;;
esac
else
if [ "$NGX_PLATFORM" != win32 ]; then
ZLIB=NO
# FreeBSD, Solaris, Linux
ngx_feature="zlib library"
ngx_feature_name="NGX_ZLIB"
ngx_feature_run=no
ngx_feature_incs="#include <zlib.h>"
ngx_feature_path=
ngx_feature_libs="-lz"
ngx_feature_test="z_stream z; deflate(&z, Z_NO_FLUSH)"
. auto/feature
if [ $ngx_found = yes ]; then
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
ZLIB=YES
ngx_found=no
fi
fi
if [ $ZLIB != YES ]; then
cat << END
$0: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using --without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using --with-zlib=<path> option.
END
exit 1
fi
fi

View File

@ -0,0 +1,135 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
case "$NGX_CC_NAME" in
msvc)
ngx_makefile=makefile.msvc
ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC"
ngx_zlib="ZLIB=\"$ZLIB\""
;;
owc)
ngx_makefile=makefile.owc
ngx_opt="CPU_OPT=\"$CPU_OPT\""
ngx_zlib=`echo ZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"`
;;
bcc)
ngx_makefile=makefile.bcc
ngx_opt="-DCPU_OPT=\"$CPU_OPT\""
ngx_zlib=`echo \-DZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"`
;;
*)
ngx_makefile=
;;
esac
done=NO
case "$NGX_PLATFORM" in
win32)
if [ -n "$ngx_makefile" ]; then
cat << END >> $NGX_MAKEFILE
`echo "$ZLIB/zlib.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"`
\$(MAKE) -f auto/lib/zlib/$ngx_makefile $ngx_opt $ngx_zlib
END
else
cat << END >> $NGX_MAKEFILE
$ZLIB/libz.a: $NGX_MAKEFILE
cd $ZLIB \\
&& \$(MAKE) distclean \\
&& \$(MAKE) -f win32/Makefile.gcc \\
CFLAGS="$ZLIB_OPT" CC="\$(CC)" \\
libz.a
END
fi
done=YES
;;
# FreeBSD: i386
# Linux: i686
*:i386 | *:i686)
case $ZLIB_ASM in
pentium)
cat << END >> $NGX_MAKEFILE
$ZLIB/libz.a: $NGX_MAKEFILE
cd $ZLIB \\
&& \$(MAKE) distclean \\
&& cp contrib/asm586/match.S . \\
&& CFLAGS="$ZLIB_OPT -DASMV" CC="\$(CC)" \\
./configure \\
&& \$(MAKE) OBJA=match.o libz.a
END
done=YES
;;
pentiumpro)
cat << END >> $NGX_MAKEFILE
$ZLIB/libz.a: $NGX_MAKEFILE
cd $ZLIB \\
&& \$(MAKE) distclean \\
&& cp contrib/asm686/match.S . \\
&& CFLAGS="$ZLIB_OPT -DASMV" CC="\$(CC)" \\
./configure \\
&& \$(MAKE) OBJA=match.o libz.a
END
done=YES
;;
NO)
;;
*)
echo "$0: error: invalid --with-zlib-asm=$ZLIB_ASM option."
echo "The valid values are \"pentium\" and \"pentiumpro\" only".
echo
exit 1;
;;
esac
;;
esac
if [ $done = NO ]; then
cat << END >> $NGX_MAKEFILE
$ZLIB/libz.a: $NGX_MAKEFILE
cd $ZLIB \\
&& \$(MAKE) distclean \\
&& CFLAGS="$ZLIB_OPT" CC="\$(CC)" \\
./configure \\
&& \$(MAKE) libz.a
END
fi

View File

@ -0,0 +1,17 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
CFLAGS = -q -O2 -tWM -w-8004 -w-8012 $(CPU_OPT)
zlib.lib:
cd $(ZLIB)
bcc32 -c $(CFLAGS) adler32.c crc32.c deflate.c \
trees.c zutil.c compress.c \
inflate.c inffast.c inftrees.c
tlib zlib.lib +adler32.obj +crc32.obj +deflate.obj \
+trees.obj +zutil.obj +compress.obj \
+inflate.obj +inffast.obj +inftrees.obj

View File

@ -0,0 +1,17 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT)
zlib.lib:
cd $(ZLIB)
cl -c $(CFLAGS) adler32.c crc32.c deflate.c \
trees.c zutil.c compress.c \
inflate.c inffast.c inftrees.c
link -lib -out:zlib.lib adler32.obj crc32.obj deflate.obj \
trees.obj zutil.obj compress.obj \
inflate.obj inffast.obj inftrees.obj

View File

@ -0,0 +1,14 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
CFLAGS = -zq -bt=nt -ot -op -oi -oe -s -bm $(CPU_OPT)
zlib.lib:
cd $(ZLIB)
wcl386 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c &
compress.c inflate.c inffast.c inftrees.c
wlib -n zlib.lib adler32.obj crc32.obj deflate.obj trees.obj &
zutil.obj compress.obj inflate.obj inffast.obj inftrees.obj

691
app/nginx-1.11.10/auto/make Normal file
View File

@ -0,0 +1,691 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
echo "creating $NGX_MAKEFILE"
mkdir -p $NGX_OBJS/src/core $NGX_OBJS/src/event $NGX_OBJS/src/event/modules \
$NGX_OBJS/src/os/unix $NGX_OBJS/src/os/win32 \
$NGX_OBJS/src/http $NGX_OBJS/src/http/v2 $NGX_OBJS/src/http/modules \
$NGX_OBJS/src/http/modules/perl \
$NGX_OBJS/src/mail \
$NGX_OBJS/src/stream \
$NGX_OBJS/src/misc
ngx_objs_dir=$NGX_OBJS$ngx_regex_dirsep
ngx_use_pch=`echo $NGX_USE_PCH | sed -e "s/\//$ngx_regex_dirsep/g"`
if [ ! $FF_PATH ]; then
echo "Please define FF_PATH environment variable"
exit 1
fi
if [ ! $FF_DPDK ]; then
FF_DPDK=$FF_PATH/dpdk/x86_64-native-linuxapp-gcc
echo "FF_DPDK environment variable not defined, default:$FF_DPDK"
fi
CORE_LIBS+=" -L$FF_PATH/lib -L$FF_DPDK/lib -Wl,--whole-archive,-lfstack,--no-whole-archive"
CORE_LIBS+=" -g -Wl,--no-as-needed -fvisibility=default -pthread -lm -lrt"
CORE_LIBS+=" -Wl,--whole-archive -lrte_pmd_vmxnet3_uio -lrte_pmd_i40e -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ring"
CORE_LIBS+=" -Wl,--whole-archive -lrte_hash -lrte_kvargs -Wl,-lrte_mbuf -lethdev -lrte_eal -Wl,-lrte_mempool"
CORE_LIBS+=" -lrte_ring -lrte_cmdline -lrte_cfgfile -lrte_kni -lrte_timer -Wl,-lrte_pmd_virtio"
CORE_LIBS+=" -Wl,--no-whole-archive -lrt -lm -ldl -lm -lcrypto"
cat << END > $NGX_MAKEFILE
CC = $CC
CFLAGS = $CFLAGS
CPP = $CPP
LINK = $LINK
CFLAGS += -I$FF_PATH/lib
END
if test -n "$NGX_PERL_CFLAGS"; then
echo NGX_PERL_CFLAGS = $NGX_PERL_CFLAGS >> $NGX_MAKEFILE
echo NGX_PM_CFLAGS = $NGX_PM_CFLAGS >> $NGX_MAKEFILE
echo NGX_PM_LDFLAGS = $NGX_PM_LDFLAGS >> $NGX_MAKEFILE
fi
# ALL_INCS, required by the addons and by OpenWatcom C precompiled headers
ngx_incs=`echo $CORE_INCS $NGX_OBJS $HTTP_INCS $MAIL_INCS $STREAM_INCS\
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont$ngx_include_opt\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
ALL_INCS = $ngx_include_opt$ngx_incs
END
ngx_all_srcs="$CORE_SRCS"
# the core dependencies and include paths
ngx_deps=`echo $CORE_DEPS $NGX_AUTO_CONFIG_H $NGX_PCH \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
ngx_incs=`echo $CORE_INCS $NGX_OBJS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont$ngx_include_opt\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
CORE_DEPS = $ngx_deps
CORE_INCS = $ngx_include_opt$ngx_incs
END
# the http dependencies and include paths
if [ $HTTP = YES ]; then
ngx_all_srcs="$ngx_all_srcs $HTTP_SRCS"
ngx_deps=`echo $HTTP_DEPS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
ngx_incs=`echo $HTTP_INCS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont$ngx_include_opt\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
HTTP_DEPS = $ngx_deps
HTTP_INCS = $ngx_include_opt$ngx_incs
END
fi
# the mail dependencies and include paths
if [ $MAIL != NO ]; then
if [ $MAIL = YES ]; then
ngx_all_srcs="$ngx_all_srcs $MAIL_SRCS"
fi
ngx_deps=`echo $MAIL_DEPS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
ngx_incs=`echo $MAIL_INCS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont$ngx_include_opt\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
MAIL_DEPS = $ngx_deps
MAIL_INCS = $ngx_include_opt$ngx_incs
END
fi
# the stream dependencies and include paths
if [ $STREAM != NO ]; then
if [ $STREAM = YES ]; then
ngx_all_srcs="$ngx_all_srcs $STREAM_SRCS"
fi
ngx_deps=`echo $STREAM_DEPS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
ngx_incs=`echo $STREAM_INCS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont$ngx_include_opt\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
STREAM_DEPS = $ngx_deps
STREAM_INCS = $ngx_include_opt$ngx_incs
END
fi
ngx_all_srcs="$ngx_all_srcs $MISC_SRCS"
if test -n "$NGX_ADDON_SRCS$DYNAMIC_MODULES"; then
cat << END >> $NGX_MAKEFILE
ADDON_DEPS = \$(CORE_DEPS) $NGX_ADDON_DEPS
END
fi
# nginx
ngx_all_srcs=`echo $ngx_all_srcs | sed -e "s/\//$ngx_regex_dirsep/g"`
for ngx_src in $NGX_ADDON_SRCS
do
ngx_obj="addon/`basename \`dirname $ngx_src\``"
test -d $NGX_OBJS/$ngx_obj || mkdir -p $NGX_OBJS/$ngx_obj
ngx_obj=`echo $ngx_obj/\`basename $ngx_src\` \
| sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_all_srcs="$ngx_all_srcs $ngx_obj"
done
ngx_all_objs=`echo $ngx_all_srcs \
| sed -e "s#\([^ ]*\.\)cpp#$NGX_OBJS\/\1$ngx_objext#g" \
-e "s#\([^ ]*\.\)cc#$NGX_OBJS\/\1$ngx_objext#g" \
-e "s#\([^ ]*\.\)c#$NGX_OBJS\/\1$ngx_objext#g" \
-e "s#\([^ ]*\.\)S#$NGX_OBJS\/\1$ngx_objext#g"`
ngx_modules_c=`echo $NGX_MODULES_C | sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_modules_obj=`echo $ngx_modules_c | sed -e "s/\(.*\.\)c/\1$ngx_objext/"`
if test -n "$NGX_RES"; then
ngx_res=$NGX_RES
else
ngx_res="$NGX_RC $NGX_ICONS"
ngx_rcc=`echo $NGX_RCC | sed -e "s/\//$ngx_regex_dirsep/g"`
fi
ngx_deps=`echo $ngx_all_objs $ngx_modules_obj $ngx_res $LINK_DEPS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
ngx_objs=`echo $ngx_all_objs $ngx_modules_obj \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_long_regex_cont\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
ngx_libs=
if test -n "$NGX_LD_OPT$CORE_LIBS"; then
ngx_libs=`echo $NGX_LD_OPT $CORE_LIBS \
| sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`
fi
ngx_link=${CORE_LINK:+`echo $CORE_LINK \
| sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`}
ngx_main_link=${MAIN_LINK:+`echo $MAIN_LINK \
| sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`}
cat << END >> $NGX_MAKEFILE
build: binary modules manpage
binary: $NGX_OBJS${ngx_dirsep}nginx$ngx_binext
$NGX_OBJS${ngx_dirsep}nginx$ngx_binext: $ngx_deps$ngx_spacer
\$(LINK) $ngx_long_start$ngx_binout$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_main_link
$ngx_rcc
$ngx_long_end
modules:
END
# ngx_modules.c
if test -n "$NGX_PCH"; then
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)"
else
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) \$(CORE_INCS)"
fi
cat << END >> $NGX_MAKEFILE
$ngx_modules_obj: \$(CORE_DEPS)$ngx_cont$ngx_modules_c
$ngx_cc$ngx_tab$ngx_objout$ngx_modules_obj$ngx_tab$ngx_modules_c$NGX_AUX
END
# the core sources
for ngx_src in $CORE_SRCS
do
ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_obj=`echo $ngx_src \
| sed -e "s#^\(.*\.\)cpp\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)cc\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"`
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(CORE_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
# the http sources
if [ $HTTP = YES ]; then
if test -n "$NGX_PCH"; then
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)"
else
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) \$(CORE_INCS) \$(HTTP_INCS)"
ngx_perl_cc="\$(CC) $ngx_compile_opt \$(NGX_PERL_CFLAGS)"
ngx_perl_cc="$ngx_perl_cc \$(CORE_INCS) \$(HTTP_INCS)"
fi
for ngx_source in $HTTP_SRCS
do
ngx_src=`echo $ngx_source | sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_obj=`echo $ngx_src \
| sed -e "s#^\(.*\.\)cpp\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)cc\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"`
if [ $ngx_source = src/http/modules/perl/ngx_http_perl_module.c ]; then
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(CORE_DEPS) \$(HTTP_DEPS)$ngx_cont$ngx_src
$ngx_perl_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
else
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(CORE_DEPS) \$(HTTP_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
fi
done
fi
# the mail sources
if [ $MAIL = YES ]; then
if test -n "$NGX_PCH"; then
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)"
else
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) \$(CORE_INCS) \$(MAIL_INCS)"
fi
for ngx_src in $MAIL_SRCS
do
ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_obj=`echo $ngx_src \
| sed -e "s#^\(.*\.\)cpp\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)cc\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"`
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(CORE_DEPS) \$(MAIL_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
fi
# the stream sources
if [ $STREAM = YES ]; then
if test -n "$NGX_PCH"; then
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)"
else
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) \$(CORE_INCS) \$(STREAM_INCS)"
fi
for ngx_src in $STREAM_SRCS
do
ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_obj=`echo $ngx_src \
| sed -e "s#^\(.*\.\)cpp\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)cc\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"`
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(CORE_DEPS) \$(STREAM_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
fi
# the misc sources
if test -n "$MISC_SRCS"; then
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)"
for ngx_src in $MISC_SRCS
do
ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_obj=`echo $ngx_src \
| sed -e "s#^\(.*\.\)cpp\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)cc\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"`
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(CORE_DEPS) $ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
fi
# the addons sources
if test -n "$NGX_ADDON_SRCS"; then
ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)"
for ngx_src in $NGX_ADDON_SRCS
do
ngx_obj="addon/`basename \`dirname $ngx_src\``"
ngx_obj=`echo $ngx_obj/\`basename $ngx_src\` \
| sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_obj=`echo $ngx_obj \
| sed -e "s#^\(.*\.\)cpp\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)cc\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"`
ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
done
fi
# the addons config.make
if test -n "$NGX_ADDONS$DYNAMIC_ADDONS"; then
for ngx_addon_dir in $NGX_ADDONS $DYNAMIC_ADDONS
do
if test -f $ngx_addon_dir/config.make; then
. $ngx_addon_dir/config.make
fi
done
fi
# Win32 resource file
if test -n "$NGX_RES"; then
ngx_res=`echo "$NGX_RES: $NGX_RC $NGX_ICONS" \
| sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_rcc=`echo $NGX_RCC | sed -e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
$ngx_res
$ngx_rcc
END
fi
# the precompiled headers
if test -n "$NGX_PCH"; then
echo "#include <ngx_config.h>" > $NGX_OBJS/ngx_pch.c
ngx_pch="src/core/ngx_config.h $OS_CONFIG $NGX_OBJS/ngx_auto_config.h"
ngx_pch=`echo "$NGX_PCH: $ngx_pch" | sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_src="\$(CC) \$(CFLAGS) $NGX_BUILD_PCH $ngx_compile_opt \$(ALL_INCS)"
ngx_src="$ngx_src $ngx_objout$NGX_OBJS/ngx_pch.obj $NGX_OBJS/ngx_pch.c"
ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"`
cat << END >> $NGX_MAKEFILE
$ngx_pch
$ngx_src
END
fi
# dynamic modules
if test -n "$NGX_PCH"; then
ngx_cc="\$(CC) $ngx_compile_opt $ngx_pic_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)"
else
ngx_cc="\$(CC) $ngx_compile_opt $ngx_pic_opt \$(CFLAGS) \$(ALL_INCS)"
ngx_perl_cc="\$(CC) $ngx_compile_opt $ngx_pic_opt \$(NGX_PERL_CFLAGS)"
ngx_perl_cc="$ngx_perl_cc \$(ALL_INCS)"
fi
for ngx_module in $DYNAMIC_MODULES
do
eval ngx_module_srcs="\$${ngx_module}_SRCS"
eval eval ngx_module_libs="\\\"\$${ngx_module}_LIBS\\\""
eval ngx_module_modules="\$${ngx_module}_MODULES"
eval ngx_module_order="\$${ngx_module}_ORDER"
ngx_modules_c=$NGX_OBJS/${ngx_module}_modules.c
cat << END > $ngx_modules_c
#include <ngx_config.h>
#include <ngx_core.h>
END
for mod in $ngx_module_modules
do
echo "extern ngx_module_t $mod;" >> $ngx_modules_c
done
echo >> $ngx_modules_c
echo 'ngx_module_t *ngx_modules[] = {' >> $ngx_modules_c
for mod in $ngx_module_modules
do
echo " &$mod," >> $ngx_modules_c
done
cat << END >> $ngx_modules_c
NULL
};
END
echo 'char *ngx_module_names[] = {' >> $ngx_modules_c
for mod in $ngx_module_modules
do
echo " \"$mod\"," >> $ngx_modules_c
done
cat << END >> $ngx_modules_c
NULL
};
END
echo 'char *ngx_module_order[] = {' >> $ngx_modules_c
for mod in $ngx_module_order
do
echo " \"$mod\"," >> $ngx_modules_c
done
cat << END >> $ngx_modules_c
NULL
};
END
ngx_modules_c=`echo $ngx_modules_c | sed -e "s/\//$ngx_regex_dirsep/g"`
ngx_modules_obj=`echo $ngx_modules_c \
| sed -e "s/\(.*\.\)c/\1$ngx_objext/"`
ngx_module_objs=
for ngx_src in $ngx_module_srcs
do
case "$ngx_src" in
src/*)
ngx_obj=$ngx_src
;;
*)
ngx_obj="addon/`basename \`dirname $ngx_src\``"
mkdir -p $NGX_OBJS/$ngx_obj
ngx_obj="$ngx_obj/`basename $ngx_src`"
;;
esac
ngx_module_objs="$ngx_module_objs $ngx_obj"
done
ngx_module_objs=`echo $ngx_module_objs \
| sed -e "s#\([^ ]*\.\)cpp#$NGX_OBJS\/\1$ngx_objext#g" \
-e "s#\([^ ]*\.\)cc#$NGX_OBJS\/\1$ngx_objext#g" \
-e "s#\([^ ]*\.\)c#$NGX_OBJS\/\1$ngx_objext#g" \
-e "s#\([^ ]*\.\)S#$NGX_OBJS\/\1$ngx_objext#g"`
ngx_deps=`echo $ngx_module_objs $ngx_modules_obj $LINK_DEPS \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
ngx_objs=`echo $ngx_module_objs $ngx_modules_obj \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_long_regex_cont\1/g" \
-e "s/\//$ngx_regex_dirsep/g"`
ngx_obj=$NGX_OBJS$ngx_dirsep$ngx_module$ngx_modext
if [ "$NGX_PLATFORM" = win32 ]; then
ngx_module_libs="$CORE_LIBS $ngx_module_libs"
fi
ngx_libs=
if test -n "$NGX_LD_OPT$ngx_module_libs"; then
ngx_libs=`echo $NGX_LD_OPT $ngx_module_libs \
| sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`
fi
ngx_link=${CORE_LINK:+`echo $CORE_LINK \
| sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`}
ngx_module_link=${MODULE_LINK:+`echo $MODULE_LINK \
| sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`}
cat << END >> $NGX_MAKEFILE
modules: $ngx_obj
$ngx_obj: $ngx_deps$ngx_spacer
\$(LINK) $ngx_long_start$ngx_binout$ngx_obj$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_module_link
$ngx_long_end
$ngx_modules_obj: \$(CORE_DEPS)$ngx_cont$ngx_modules_c
$ngx_cc$ngx_tab$ngx_objout$ngx_modules_obj$ngx_tab$ngx_modules_c$NGX_AUX
END
for ngx_source in $ngx_module_srcs
do
case "$ngx_source" in
src/*)
ngx_obj=`echo $ngx_source | sed -e "s/\//$ngx_regex_dirsep/g"`
;;
*)
ngx_obj="addon/`basename \`dirname $ngx_source\``"
ngx_obj=`echo $ngx_obj/\`basename $ngx_source\` \
| sed -e "s/\//$ngx_regex_dirsep/g"`
;;
esac
ngx_obj=`echo $ngx_obj \
| sed -e "s#^\(.*\.\)cpp\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)cc\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \
-e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"`
ngx_src=`echo $ngx_source | sed -e "s/\//$ngx_regex_dirsep/g"`
if [ $ngx_source = src/http/modules/perl/ngx_http_perl_module.c ]; then
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src
$ngx_perl_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
else
cat << END >> $NGX_MAKEFILE
$ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
END
fi
done
done

View File

@ -0,0 +1,138 @@
# Copyright (C) Ruslan Ermilov
# Copyright (C) Nginx, Inc.
case $ngx_module_type in
HTTP_*) ngx_var=HTTP ;;
*) ngx_var=$ngx_module_type ;;
esac
if [ "$ngx_module_link" = DYNAMIC ]; then
for ngx_module in $ngx_module_name; do
# extract the first name
break
done
DYNAMIC_MODULES="$DYNAMIC_MODULES $ngx_module"
eval ${ngx_module}_SRCS=\"$ngx_module_srcs\"
eval ${ngx_module}_MODULES=\"$ngx_module_name\"
if [ -z "$ngx_module_order" -a \
\( "$ngx_module_type" = "HTTP_FILTER" \
-o "$ngx_module_type" = "HTTP_AUX_FILTER" \) ]
then
eval ${ngx_module}_ORDER=\"$ngx_module_name \
ngx_http_copy_filter_module\"
else
eval ${ngx_module}_ORDER=\"$ngx_module_order\"
fi
if test -n "$ngx_module_incs"; then
CORE_INCS="$CORE_INCS $ngx_module_incs"
fi
if test -n "$ngx_module_deps"; then
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_module_deps"
fi
libs=
for lib in $ngx_module_libs
do
case $lib in
LIBXSLT | LIBGD | GEOIP | PERL)
libs="$libs \$NGX_LIB_$lib"
if eval [ "\$USE_${lib}" = NO ] ; then
eval USE_${lib}=DYNAMIC
fi
;;
PCRE | OPENSSL | ZLIB)
eval USE_${lib}=YES
;;
MD5 | SHA1)
# obsolete
;;
*)
libs="$libs $lib"
;;
esac
done
eval ${ngx_module}_LIBS=\'$libs\'
elif [ "$ngx_module_link" = YES ]; then
eval ${ngx_module_type}_MODULES=\"\$${ngx_module_type}_MODULES \
$ngx_module_name\"
eval ${ngx_var}_SRCS=\"\$${ngx_var}_SRCS $ngx_module_srcs\"
if test -n "$ngx_module_incs"; then
eval ${ngx_var}_INCS=\"\$${ngx_var}_INCS $ngx_module_incs\"
fi
if test -n "$ngx_module_deps"; then
eval ${ngx_var}_DEPS=\"\$${ngx_var}_DEPS $ngx_module_deps\"
fi
for lib in $ngx_module_libs
do
case $lib in
PCRE | OPENSSL | ZLIB | LIBXSLT | LIBGD | PERL | GEOIP)
eval USE_${lib}=YES
;;
MD5 | SHA1)
# obsolete
;;
*)
CORE_LIBS="$CORE_LIBS $lib"
;;
esac
done
elif [ "$ngx_module_link" = ADDON ]; then
eval ${ngx_module_type}_MODULES=\"\$${ngx_module_type}_MODULES \
$ngx_module_name\"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_module_srcs"
if test -n "$ngx_module_incs"; then
eval ${ngx_var}_INCS=\"\$${ngx_var}_INCS $ngx_module_incs\"
fi
if test -n "$ngx_module_deps"; then
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_module_deps"
fi
for lib in $ngx_module_libs
do
case $lib in
PCRE | OPENSSL | ZLIB | LIBXSLT | LIBGD | PERL | GEOIP)
eval USE_${lib}=YES
;;
MD5 | SHA1)
# obsolete
;;
*)
CORE_LIBS="$CORE_LIBS $lib"
;;
esac
done
fi

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
cat << END >> $NGX_AUTO_CONFIG_H
#ifndef $have
#define $have 0
#endif
END

View File

@ -0,0 +1,631 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
help=no
NGX_PREFIX=
NGX_SBIN_PATH=
NGX_MODULES_PATH=
NGX_CONF_PREFIX=
NGX_CONF_PATH=
NGX_ERROR_LOG_PATH=
NGX_PID_PATH=
NGX_LOCK_PATH=
NGX_USER=
NGX_GROUP=
NGX_BUILD=
CC=${CC:-cc}
CPP=
NGX_OBJS=objs
NGX_DEBUG=NO
NGX_CC_OPT=
NGX_LD_OPT=
CPU=NO
NGX_RPATH=NO
NGX_TEST_BUILD_DEVPOLL=NO
NGX_TEST_BUILD_EVENTPORT=NO
NGX_TEST_BUILD_EPOLL=NO
NGX_TEST_BUILD_SOLARIS_SENDFILEV=NO
NGX_PLATFORM=
NGX_WINE=
EVENT_FOUND=NO
EVENT_SELECT=NO
EVENT_POLL=NO
USE_THREADS=NO
NGX_FILE_AIO=NO
HTTP=YES
NGX_HTTP_LOG_PATH=
NGX_HTTP_CLIENT_TEMP_PATH=
NGX_HTTP_PROXY_TEMP_PATH=
NGX_HTTP_FASTCGI_TEMP_PATH=
NGX_HTTP_UWSGI_TEMP_PATH=
NGX_HTTP_SCGI_TEMP_PATH=
HTTP_CACHE=YES
HTTP_CHARSET=YES
HTTP_GZIP=YES
HTTP_SSL=NO
HTTP_V2=NO
HTTP_SSI=YES
HTTP_POSTPONE=NO
HTTP_REALIP=NO
HTTP_XSLT=NO
HTTP_IMAGE_FILTER=NO
HTTP_SUB=NO
HTTP_ADDITION=NO
HTTP_DAV=NO
HTTP_ACCESS=YES
HTTP_AUTH_BASIC=YES
HTTP_AUTH_REQUEST=NO
HTTP_USERID=YES
HTTP_SLICE=NO
HTTP_AUTOINDEX=YES
HTTP_RANDOM_INDEX=NO
HTTP_STATUS=NO
HTTP_GEO=YES
HTTP_GEOIP=NO
HTTP_MAP=YES
HTTP_SPLIT_CLIENTS=YES
HTTP_REFERER=YES
HTTP_REWRITE=YES
HTTP_PROXY=YES
HTTP_FASTCGI=YES
HTTP_UWSGI=YES
HTTP_SCGI=YES
HTTP_PERL=NO
HTTP_MEMCACHED=YES
HTTP_LIMIT_CONN=YES
HTTP_LIMIT_REQ=YES
HTTP_EMPTY_GIF=YES
HTTP_BROWSER=YES
HTTP_SECURE_LINK=NO
HTTP_DEGRADATION=NO
HTTP_FLV=NO
HTTP_MP4=NO
HTTP_GUNZIP=NO
HTTP_GZIP_STATIC=NO
HTTP_UPSTREAM_HASH=YES
HTTP_UPSTREAM_IP_HASH=YES
HTTP_UPSTREAM_LEAST_CONN=YES
HTTP_UPSTREAM_KEEPALIVE=YES
HTTP_UPSTREAM_ZONE=YES
# STUB
HTTP_STUB_STATUS=NO
MAIL=NO
MAIL_SSL=NO
MAIL_POP3=YES
MAIL_IMAP=YES
MAIL_SMTP=YES
STREAM=NO
STREAM_SSL=NO
STREAM_REALIP=NO
STREAM_LIMIT_CONN=YES
STREAM_ACCESS=YES
STREAM_GEO=YES
STREAM_GEOIP=NO
STREAM_MAP=YES
STREAM_SPLIT_CLIENTS=YES
STREAM_RETURN=YES
STREAM_UPSTREAM_HASH=YES
STREAM_UPSTREAM_LEAST_CONN=YES
STREAM_UPSTREAM_ZONE=YES
STREAM_SSL_PREREAD=NO
DYNAMIC_MODULES=
NGX_ADDONS=
NGX_ADDON_DEPS=
DYNAMIC_ADDONS=
NGX_COMPAT=NO
USE_PCRE=NO
PCRE=NONE
PCRE_OPT=
PCRE_CONF_OPT=
PCRE_JIT=NO
USE_OPENSSL=NO
OPENSSL=NONE
USE_ZLIB=NO
ZLIB=NONE
ZLIB_OPT=
ZLIB_ASM=NO
USE_PERL=NO
NGX_PERL=perl
USE_LIBXSLT=NO
USE_LIBGD=NO
USE_GEOIP=NO
NGX_GOOGLE_PERFTOOLS=NO
NGX_CPP_TEST=NO
NGX_LIBATOMIC=NO
NGX_CPU_CACHE_LINE=
NGX_POST_CONF_MSG=
USE_FSTACK=NO
opt=
for option
do
opt="$opt `echo $option | sed -e \"s/\(--[^=]*=\)\(.* .*\)/\1'\2'/\"`"
case "$option" in
-*=*) value=`echo "$option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
*) value="" ;;
esac
case "$option" in
--help) help=yes ;;
--prefix=) NGX_PREFIX="!" ;;
--prefix=*) NGX_PREFIX="$value" ;;
--sbin-path=*) NGX_SBIN_PATH="$value" ;;
--modules-path=*) NGX_MODULES_PATH="$value" ;;
--conf-path=*) NGX_CONF_PATH="$value" ;;
--error-log-path=*) NGX_ERROR_LOG_PATH="$value";;
--pid-path=*) NGX_PID_PATH="$value" ;;
--lock-path=*) NGX_LOCK_PATH="$value" ;;
--user=*) NGX_USER="$value" ;;
--group=*) NGX_GROUP="$value" ;;
--crossbuild=*) NGX_PLATFORM="$value" ;;
--build=*) NGX_BUILD="$value" ;;
--builddir=*) NGX_OBJS="$value" ;;
--with-select_module) EVENT_SELECT=YES ;;
--without-select_module) EVENT_SELECT=NONE ;;
--with-poll_module) EVENT_POLL=YES ;;
--without-poll_module) EVENT_POLL=NONE ;;
--with-ff_module) USE_FSTACK=YES ;;
--with-threads) USE_THREADS=YES ;;
--with-file-aio) NGX_FILE_AIO=YES ;;
--with-ipv6)
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-ipv6\" option is deprecated"
;;
--without-http) HTTP=NO ;;
--without-http-cache) HTTP_CACHE=NO ;;
--http-log-path=*) NGX_HTTP_LOG_PATH="$value" ;;
--http-client-body-temp-path=*) NGX_HTTP_CLIENT_TEMP_PATH="$value" ;;
--http-proxy-temp-path=*) NGX_HTTP_PROXY_TEMP_PATH="$value" ;;
--http-fastcgi-temp-path=*) NGX_HTTP_FASTCGI_TEMP_PATH="$value" ;;
--http-uwsgi-temp-path=*) NGX_HTTP_UWSGI_TEMP_PATH="$value" ;;
--http-scgi-temp-path=*) NGX_HTTP_SCGI_TEMP_PATH="$value" ;;
--with-http_ssl_module) HTTP_SSL=YES ;;
--with-http_v2_module) HTTP_V2=YES ;;
--with-http_realip_module) HTTP_REALIP=YES ;;
--with-http_addition_module) HTTP_ADDITION=YES ;;
--with-http_xslt_module) HTTP_XSLT=YES ;;
--with-http_xslt_module=dynamic) HTTP_XSLT=DYNAMIC ;;
--with-http_image_filter_module) HTTP_IMAGE_FILTER=YES ;;
--with-http_image_filter_module=dynamic)
HTTP_IMAGE_FILTER=DYNAMIC ;;
--with-http_geoip_module) HTTP_GEOIP=YES ;;
--with-http_geoip_module=dynamic)
HTTP_GEOIP=DYNAMIC ;;
--with-http_sub_module) HTTP_SUB=YES ;;
--with-http_dav_module) HTTP_DAV=YES ;;
--with-http_flv_module) HTTP_FLV=YES ;;
--with-http_mp4_module) HTTP_MP4=YES ;;
--with-http_gunzip_module) HTTP_GUNZIP=YES ;;
--with-http_gzip_static_module) HTTP_GZIP_STATIC=YES ;;
--with-http_auth_request_module) HTTP_AUTH_REQUEST=YES ;;
--with-http_random_index_module) HTTP_RANDOM_INDEX=YES ;;
--with-http_secure_link_module) HTTP_SECURE_LINK=YES ;;
--with-http_degradation_module) HTTP_DEGRADATION=YES ;;
--with-http_slice_module) HTTP_SLICE=YES ;;
--without-http_charset_module) HTTP_CHARSET=NO ;;
--without-http_gzip_module) HTTP_GZIP=NO ;;
--without-http_ssi_module) HTTP_SSI=NO ;;
--without-http_userid_module) HTTP_USERID=NO ;;
--without-http_access_module) HTTP_ACCESS=NO ;;
--without-http_auth_basic_module) HTTP_AUTH_BASIC=NO ;;
--without-http_autoindex_module) HTTP_AUTOINDEX=NO ;;
--without-http_status_module) HTTP_STATUS=NO ;;
--without-http_geo_module) HTTP_GEO=NO ;;
--without-http_map_module) HTTP_MAP=NO ;;
--without-http_split_clients_module) HTTP_SPLIT_CLIENTS=NO ;;
--without-http_referer_module) HTTP_REFERER=NO ;;
--without-http_rewrite_module) HTTP_REWRITE=NO ;;
--without-http_proxy_module) HTTP_PROXY=NO ;;
--without-http_fastcgi_module) HTTP_FASTCGI=NO ;;
--without-http_uwsgi_module) HTTP_UWSGI=NO ;;
--without-http_scgi_module) HTTP_SCGI=NO ;;
--without-http_memcached_module) HTTP_MEMCACHED=NO ;;
--without-http_limit_conn_module) HTTP_LIMIT_CONN=NO ;;
--without-http_limit_req_module) HTTP_LIMIT_REQ=NO ;;
--without-http_empty_gif_module) HTTP_EMPTY_GIF=NO ;;
--without-http_browser_module) HTTP_BROWSER=NO ;;
--without-http_upstream_hash_module) HTTP_UPSTREAM_HASH=NO ;;
--without-http_upstream_ip_hash_module) HTTP_UPSTREAM_IP_HASH=NO ;;
--without-http_upstream_least_conn_module)
HTTP_UPSTREAM_LEAST_CONN=NO ;;
--without-http_upstream_keepalive_module) HTTP_UPSTREAM_KEEPALIVE=NO ;;
--without-http_upstream_zone_module) HTTP_UPSTREAM_ZONE=NO ;;
--with-http_perl_module) HTTP_PERL=YES ;;
--with-http_perl_module=dynamic) HTTP_PERL=DYNAMIC ;;
--with-perl_modules_path=*) NGX_PERL_MODULES="$value" ;;
--with-perl=*) NGX_PERL="$value" ;;
# STUB
--with-http_stub_status_module) HTTP_STUB_STATUS=YES ;;
--with-mail) MAIL=YES ;;
--with-mail=dynamic) MAIL=DYNAMIC ;;
--with-mail_ssl_module) MAIL_SSL=YES ;;
# STUB
--with-imap)
MAIL=YES
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-imap\" option is deprecated, \
use the \"--with-mail\" option instead"
;;
--with-imap_ssl_module)
MAIL_SSL=YES
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-imap_ssl_module\" option is deprecated, \
use the \"--with-mail_ssl_module\" option instead"
;;
--without-mail_pop3_module) MAIL_POP3=NO ;;
--without-mail_imap_module) MAIL_IMAP=NO ;;
--without-mail_smtp_module) MAIL_SMTP=NO ;;
--with-stream) STREAM=YES ;;
--with-stream=dynamic) STREAM=DYNAMIC ;;
--with-stream_ssl_module) STREAM_SSL=YES ;;
--with-stream_realip_module) STREAM_REALIP=YES ;;
--with-stream_geoip_module) STREAM_GEOIP=YES ;;
--with-stream_geoip_module=dynamic)
STREAM_GEOIP=DYNAMIC ;;
--with-stream_ssl_preread_module)
STREAM_SSL_PREREAD=YES ;;
--without-stream_limit_conn_module)
STREAM_LIMIT_CONN=NO ;;
--without-stream_access_module) STREAM_ACCESS=NO ;;
--without-stream_geo_module) STREAM_GEO=NO ;;
--without-stream_map_module) STREAM_MAP=NO ;;
--without-stream_split_clients_module)
STREAM_SPLIT_CLIENTS=NO ;;
--without-stream_return_module) STREAM_RETURN=NO ;;
--without-stream_upstream_hash_module)
STREAM_UPSTREAM_HASH=NO ;;
--without-stream_upstream_least_conn_module)
STREAM_UPSTREAM_LEAST_CONN=NO ;;
--without-stream_upstream_zone_module)
STREAM_UPSTREAM_ZONE=NO ;;
--with-google_perftools_module) NGX_GOOGLE_PERFTOOLS=YES ;;
--with-cpp_test_module) NGX_CPP_TEST=YES ;;
--add-module=*) NGX_ADDONS="$NGX_ADDONS $value" ;;
--add-dynamic-module=*) DYNAMIC_ADDONS="$DYNAMIC_ADDONS $value" ;;
--with-compat) NGX_COMPAT=YES ;;
--with-cc=*) CC="$value" ;;
--with-cpp=*) CPP="$value" ;;
--with-cc-opt=*) NGX_CC_OPT="$value" ;;
--with-ld-opt=*) NGX_LD_OPT="$value" ;;
--with-cpu-opt=*) CPU="$value" ;;
--with-debug) NGX_DEBUG=YES ;;
--without-pcre) USE_PCRE=DISABLED ;;
--with-pcre) USE_PCRE=YES ;;
--with-pcre=*) PCRE="$value" ;;
--with-pcre-opt=*) PCRE_OPT="$value" ;;
--with-pcre-jit) PCRE_JIT=YES ;;
--with-openssl=*) OPENSSL="$value" ;;
--with-openssl-opt=*) OPENSSL_OPT="$value" ;;
--with-md5=*)
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-md5\" option is deprecated"
;;
--with-md5-opt=*)
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-md5-opt\" option is deprecated"
;;
--with-md5-asm)
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-md5-asm\" option is deprecated"
;;
--with-sha1=*)
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-sha1\" option is deprecated"
;;
--with-sha1-opt=*)
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-sha1-opt\" option is deprecated"
;;
--with-sha1-asm)
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-sha1-asm\" option is deprecated"
;;
--with-zlib=*) ZLIB="$value" ;;
--with-zlib-opt=*) ZLIB_OPT="$value" ;;
--with-zlib-asm=*) ZLIB_ASM="$value" ;;
--with-libatomic) NGX_LIBATOMIC=YES ;;
--with-libatomic=*) NGX_LIBATOMIC="$value" ;;
--test-build-devpoll) NGX_TEST_BUILD_DEVPOLL=YES ;;
--test-build-eventport) NGX_TEST_BUILD_EVENTPORT=YES ;;
--test-build-epoll) NGX_TEST_BUILD_EPOLL=YES ;;
--test-build-solaris-sendfilev) NGX_TEST_BUILD_SOLARIS_SENDFILEV=YES ;;
*)
echo "$0: error: invalid option \"$option\""
exit 1
;;
esac
done
NGX_CONFIGURE="$opt"
if [ $help = yes ]; then
cat << END
--help print this message
--prefix=PATH set installation prefix
--sbin-path=PATH set nginx binary pathname
--modules-path=PATH set modules path
--conf-path=PATH set nginx.conf pathname
--error-log-path=PATH set error log pathname
--pid-path=PATH set nginx.pid pathname
--lock-path=PATH set nginx.lock pathname
--user=USER set non-privileged user for
worker processes
--group=GROUP set non-privileged group for
worker processes
--build=NAME set build name
--builddir=DIR set build directory
--with-select_module enable select module
--without-select_module disable select module
--with-poll_module enable poll module
--without-poll_module disable poll module
--with-ff_module enable F-Stack module
--with-threads enable thread pool support
--with-file-aio enable file AIO support
--with-http_ssl_module enable ngx_http_ssl_module
--with-http_v2_module enable ngx_http_v2_module
--with-http_realip_module enable ngx_http_realip_module
--with-http_addition_module enable ngx_http_addition_module
--with-http_xslt_module enable ngx_http_xslt_module
--with-http_xslt_module=dynamic enable dynamic ngx_http_xslt_module
--with-http_image_filter_module enable ngx_http_image_filter_module
--with-http_image_filter_module=dynamic
enable dynamic ngx_http_image_filter_module
--with-http_geoip_module enable ngx_http_geoip_module
--with-http_geoip_module=dynamic enable dynamic ngx_http_geoip_module
--with-http_sub_module enable ngx_http_sub_module
--with-http_dav_module enable ngx_http_dav_module
--with-http_flv_module enable ngx_http_flv_module
--with-http_mp4_module enable ngx_http_mp4_module
--with-http_gunzip_module enable ngx_http_gunzip_module
--with-http_gzip_static_module enable ngx_http_gzip_static_module
--with-http_auth_request_module enable ngx_http_auth_request_module
--with-http_random_index_module enable ngx_http_random_index_module
--with-http_secure_link_module enable ngx_http_secure_link_module
--with-http_degradation_module enable ngx_http_degradation_module
--with-http_slice_module enable ngx_http_slice_module
--with-http_stub_status_module enable ngx_http_stub_status_module
--without-http_charset_module disable ngx_http_charset_module
--without-http_gzip_module disable ngx_http_gzip_module
--without-http_ssi_module disable ngx_http_ssi_module
--without-http_userid_module disable ngx_http_userid_module
--without-http_access_module disable ngx_http_access_module
--without-http_auth_basic_module disable ngx_http_auth_basic_module
--without-http_autoindex_module disable ngx_http_autoindex_module
--without-http_geo_module disable ngx_http_geo_module
--without-http_map_module disable ngx_http_map_module
--without-http_split_clients_module disable ngx_http_split_clients_module
--without-http_referer_module disable ngx_http_referer_module
--without-http_rewrite_module disable ngx_http_rewrite_module
--without-http_proxy_module disable ngx_http_proxy_module
--without-http_fastcgi_module disable ngx_http_fastcgi_module
--without-http_uwsgi_module disable ngx_http_uwsgi_module
--without-http_scgi_module disable ngx_http_scgi_module
--without-http_memcached_module disable ngx_http_memcached_module
--without-http_limit_conn_module disable ngx_http_limit_conn_module
--without-http_limit_req_module disable ngx_http_limit_req_module
--without-http_empty_gif_module disable ngx_http_empty_gif_module
--without-http_browser_module disable ngx_http_browser_module
--without-http_upstream_hash_module
disable ngx_http_upstream_hash_module
--without-http_upstream_ip_hash_module
disable ngx_http_upstream_ip_hash_module
--without-http_upstream_least_conn_module
disable ngx_http_upstream_least_conn_module
--without-http_upstream_keepalive_module
disable ngx_http_upstream_keepalive_module
--without-http_upstream_zone_module
disable ngx_http_upstream_zone_module
--with-http_perl_module enable ngx_http_perl_module
--with-http_perl_module=dynamic enable dynamic ngx_http_perl_module
--with-perl_modules_path=PATH set Perl modules path
--with-perl=PATH set perl binary pathname
--http-log-path=PATH set http access log pathname
--http-client-body-temp-path=PATH set path to store
http client request body temporary files
--http-proxy-temp-path=PATH set path to store
http proxy temporary files
--http-fastcgi-temp-path=PATH set path to store
http fastcgi temporary files
--http-uwsgi-temp-path=PATH set path to store
http uwsgi temporary files
--http-scgi-temp-path=PATH set path to store
http scgi temporary files
--without-http disable HTTP server
--without-http-cache disable HTTP cache
--with-mail enable POP3/IMAP4/SMTP proxy module
--with-mail=dynamic enable dynamic POP3/IMAP4/SMTP proxy module
--with-mail_ssl_module enable ngx_mail_ssl_module
--without-mail_pop3_module disable ngx_mail_pop3_module
--without-mail_imap_module disable ngx_mail_imap_module
--without-mail_smtp_module disable ngx_mail_smtp_module
--with-stream enable TCP/UDP proxy module
--with-stream=dynamic enable dynamic TCP/UDP proxy module
--with-stream_ssl_module enable ngx_stream_ssl_module
--with-stream_realip_module enable ngx_stream_realip_module
--with-stream_geoip_module enable ngx_stream_geoip_module
--with-stream_geoip_module=dynamic enable dynamic ngx_stream_geoip_module
--with-stream_ssl_preread_module enable ngx_stream_ssl_preread_module
--without-stream_limit_conn_module disable ngx_stream_limit_conn_module
--without-stream_access_module disable ngx_stream_access_module
--without-stream_geo_module disable ngx_stream_geo_module
--without-stream_map_module disable ngx_stream_map_module
--without-stream_split_clients_module
disable ngx_stream_split_clients_module
--without-stream_return_module disable ngx_stream_return_module
--without-stream_upstream_hash_module
disable ngx_stream_upstream_hash_module
--without-stream_upstream_least_conn_module
disable ngx_stream_upstream_least_conn_module
--without-stream_upstream_zone_module
disable ngx_stream_upstream_zone_module
--with-google_perftools_module enable ngx_google_perftools_module
--with-cpp_test_module enable ngx_cpp_test_module
--add-module=PATH enable external module
--add-dynamic-module=PATH enable dynamic external module
--with-compat dynamic modules compatibility
--with-cc=PATH set C compiler pathname
--with-cpp=PATH set C preprocessor pathname
--with-cc-opt=OPTIONS set additional C compiler options
--with-ld-opt=OPTIONS set additional linker options
--with-cpu-opt=CPU build for the specified CPU, valid values:
pentium, pentiumpro, pentium3, pentium4,
athlon, opteron, sparc32, sparc64, ppc64
--without-pcre disable PCRE library usage
--with-pcre force PCRE library usage
--with-pcre=DIR set path to PCRE library sources
--with-pcre-opt=OPTIONS set additional build options for PCRE
--with-pcre-jit build PCRE with JIT compilation support
--with-zlib=DIR set path to zlib library sources
--with-zlib-opt=OPTIONS set additional build options for zlib
--with-zlib-asm=CPU use zlib assembler sources optimized
for the specified CPU, valid values:
pentium, pentiumpro
--with-libatomic force libatomic_ops library usage
--with-libatomic=DIR set path to libatomic_ops library sources
--with-openssl=DIR set path to OpenSSL library sources
--with-openssl-opt=OPTIONS set additional build options for OpenSSL
--with-debug enable debug logging
END
exit 1
fi
if [ $HTTP = NO ]; then
HTTP_CHARSET=NO
HTTP_GZIP=NO
HTTP_SSI=NO
HTTP_USERID=NO
HTTP_ACCESS=NO
HTTP_STATUS=NO
HTTP_REWRITE=NO
HTTP_PROXY=NO
HTTP_FASTCGI=NO
fi
if [ ".$NGX_PLATFORM" = ".win32" ]; then
NGX_WINE=$WINE
fi
NGX_SBIN_PATH=${NGX_SBIN_PATH:-sbin/nginx}
NGX_MODULES_PATH=${NGX_MODULES_PATH:-modules}
NGX_CONF_PATH=${NGX_CONF_PATH:-conf/nginx.conf}
NGX_CONF_PREFIX=`dirname $NGX_CONF_PATH`
NGX_PID_PATH=${NGX_PID_PATH:-logs/nginx.pid}
NGX_LOCK_PATH=${NGX_LOCK_PATH:-logs/nginx.lock}
if [ ".$NGX_ERROR_LOG_PATH" = ".stderr" ]; then
NGX_ERROR_LOG_PATH=
else
NGX_ERROR_LOG_PATH=${NGX_ERROR_LOG_PATH:-logs/error.log}
fi
NGX_HTTP_LOG_PATH=${NGX_HTTP_LOG_PATH:-logs/access.log}
NGX_HTTP_CLIENT_TEMP_PATH=${NGX_HTTP_CLIENT_TEMP_PATH:-client_body_temp}
NGX_HTTP_PROXY_TEMP_PATH=${NGX_HTTP_PROXY_TEMP_PATH:-proxy_temp}
NGX_HTTP_FASTCGI_TEMP_PATH=${NGX_HTTP_FASTCGI_TEMP_PATH:-fastcgi_temp}
NGX_HTTP_UWSGI_TEMP_PATH=${NGX_HTTP_UWSGI_TEMP_PATH:-uwsgi_temp}
NGX_HTTP_SCGI_TEMP_PATH=${NGX_HTTP_SCGI_TEMP_PATH:-scgi_temp}
case ".$NGX_PERL_MODULES" in
./*)
;;
.)
;;
*)
NGX_PERL_MODULES=$NGX_PREFIX/$NGX_PERL_MODULES
;;
esac

View File

@ -0,0 +1,116 @@
# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.
echo "checking for $NGX_SYSTEM specific features"
case "$NGX_PLATFORM" in
FreeBSD:*)
. auto/os/freebsd
;;
Linux:*)
. auto/os/linux
;;
SunOS:*)
. auto/os/solaris
;;
Darwin:*)
. auto/os/darwin
;;
win32)
. auto/os/win32
;;
DragonFly:*)
have=NGX_FREEBSD . auto/have_headers
CORE_INCS="$UNIX_INCS"
CORE_DEPS="$UNIX_DEPS $FREEBSD_DEPS"
CORE_SRCS="$UNIX_SRCS $FREEBSD_SRCS"
echo " + sendfile() found"
have=NGX_HAVE_SENDFILE . auto/have
CORE_SRCS="$CORE_SRCS $FREEBSD_SENDFILE_SRCS"
ngx_spacer='
'
;;
HP-UX:*)
# HP/UX
have=NGX_HPUX . auto/have_headers
CORE_INCS="$UNIX_INCS"
CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
CORE_SRCS="$UNIX_SRCS"
CC_AUX_FLAGS="$CC_AUX_FLAGS -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
CC_AUX_FLAGS="$CC_AUX_FLAGS -D_HPUX_ALT_XOPEN_SOCKET_API"
;;
OSF1:*)
# Tru64 UNIX
have=NGX_TRU64 . auto/have_headers
have=NGX_HAVE_STRERROR_R . auto/nohave
CORE_INCS="$UNIX_INCS"
CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
CORE_SRCS="$UNIX_SRCS"
;;
GNU:*)
# GNU Hurd
have=NGX_GNU_HURD . auto/have_headers
CORE_INCS="$UNIX_INCS"
CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
CORE_SRCS="$UNIX_SRCS"
CC_AUX_FLAGS="$CC_AUX_FLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
;;
*)
CORE_INCS="$UNIX_INCS"
CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
CORE_SRCS="$UNIX_SRCS"
;;
esac
case "$NGX_MACHINE" in
i386 | i686 | i86pc)
have=NGX_HAVE_NONALIGNED . auto/have
NGX_MACH_CACHE_LINE=32
;;
amd64 | x86_64)
have=NGX_HAVE_NONALIGNED . auto/have
NGX_MACH_CACHE_LINE=64
;;
sun4u | sun4v | sparc | sparc64)
have=NGX_ALIGNMENT value=16 . auto/define
# TODO
NGX_MACH_CACHE_LINE=64
;;
ia64 )
have=NGX_ALIGNMENT value=16 . auto/define
# TODO
NGX_MACH_CACHE_LINE=64
;;
*)
have=NGX_ALIGNMENT value=16 . auto/define
NGX_MACH_CACHE_LINE=32
;;
esac
if test -z "$NGX_CPU_CACHE_LINE"; then
NGX_CPU_CACHE_LINE=$NGX_MACH_CACHE_LINE
fi
have=NGX_CPU_CACHE_LINE value=$NGX_CPU_CACHE_LINE . auto/define

Some files were not shown because too many files have changed in this diff Show More