📄 readme.dev
字号:
interested by the main (non-error) code path not about the error code path. Also the traditional way replicates codes (those replicated free()) which is error prone (more badly, its prone to memory leaks, and believe me, I did fixed a lot of this forgotten free() in error exit paths).NOTE: however, with the xalloc wrappers that never fail the above examples are obsolete, still there are many other similar situations where you need a complex error exit path and goto comes in handy.When developing code you should compile always with "all warnings" enabled and try to fix them (some warnings uncover real bugs), like for gcc use "-Wall". When running/testing the codes you should use a memory debugger like valgrind and/or bounds checking compiler patches like bounds-checking-gcc. For more details about how to run pvpgn check Appendix B.b. Code OrganizingPvPGN (inhireted from bnetd) trys to group functions based on their data onwhich they work on. Thus it somewhat resembles the principle of dataencapsulation used in OOP. For example connection.h defines structs necesarryto work with connections (the main one beeing t_connection) and functionswhich work with this structs and which do actions related to this connections.Also notice that all this functions are named like conn_<name>(). In generalif you have a set of functions working on a set of structs, you define thestructs and the functions in a <module>.h file (thus defining the API) thenwrite the function implementations in <module>.c file. And the function namesshould be something like <module>_<name>(). Separating and grouping functionsin their own modules, working on their own data structures helps isolatingfunctionality in the server and thus hunting bugs a lot easier.c. Code FlowNote: this chapter is more or less correct. Is intended to give a generalideea about the code flow, it may contain flows and things which are notin sync with the actual code, for a better understanding I recommend readingthe actual codeThe server starts in main() found in bnetd/main.c file. There it parsescommand line arguments then tries to initilize the modules by calling theirinitilizing function (many of them called like <module>_init()). Some of thismodules depend on the initilizing of others so the order there may be important.Also some of the modules if fail on initilizing may represent a general failthus PvPGN bails out. But should print out a explaining message (or write itto the log configured file).From there the server calls the main server loop function found in server.c.Here the loop may be simplified to something like:1. fdwatch() on the set of opened sockets2. call fdwatch_handle() which reads (if any) network data and "handle" them (by calling the handle function coresponding to the class of the connection receiving the data)3. write (if any) to the network from the output queue4. do any periodic or time based events5. go to 1As seen on step 2. above we call the handling functions coresponding to theclass of the connection. The handle functions usualy are a big switch/case ora for/if (which is equivalent) and they check for the packet type received, thenthey act acordingly to the data received (many of them responing with packetsby adding them to the output packet queue of the connection).Appendix A. Glossary of terms===============================* autoupdate: the feature of Battle.Net servers to send a (MPQ, see MPQ) fileto the client which after downloading it, it is used to update the client* connection class: when a connection is established to a bnet listeningaddress the client sends an initial byte which tells the server of what classof connection the following packets will be; classes of connections determinewhat packets can go through that connection.* MPQ: a format archive which is used by Blizzard clients and Battle.Net servers. This files are used for containing verious files (sound/graphics inclients, AI scripts, update patches etc...)* versioncheck: also know as vcheck and sometimes just vc ; a client verification system used by Battle.Net servers to identify client version and "purity". Based on this the server may accept/refuse connection or ask for upgrade (see autoupdate).Appendix B. How to run PvPGN for debugging===========================================It is very helpfull in finding out memory coruption bugs as soon as possible so while developing codes or just when running a server it is good that you use some memory coruption run-time debuggers. I dont know about Win32 users but on Unix/Linux there are some good options.1. valgrind (http://valgrind.kde.org)Valgrind is not very portable (only x86, Linux and very recently FreeBSD), also it slows down the debugged codes (it acts like a CPU emulator so it has to do that) but I have yet to find out a better debugging tool for what he does. Valgrind is so cool that recently many OSS projects use it for finding out bugs in their codes. For more information you can check out their web page. I will focus on valgrind with PvPGN.After you have compiled and installed valgrind (it's easy, ./configure, make, make install) you will use it by running PvPGN like this:$ valgrind --tool=memcheck --num-callers=10 /path/to/bnetd -f 2> valg.out"num-callers" makes valgrind record backtraces with 10 entries and is usually needed with PvPGN which has not very small backtrace path :)Another option you might want to use is "--leak-check=yes" and probably "--leak-resolution=high". This options make valgrind even slower but they will give memory leak information when PvPGN exits.I encourage EVERYONE to use it if available (that is if you run PvPGN on a supported platform). Only very big servers won't be able to do it because there is no hardware powerfull enough to run a big server with valgrind (but big means over 500 users online). You should test it with your server and if it does not make your bnetd go over 90% CPU then you should be fine. If you cannot run valgrind for any reason or if you are hunting for some bugs valgrind cannot find (yes, valgrind is superb but there is a class of bugs, especially overflows which valgrind can't help you with) you should then try the next debugging tool.2. bounds-checking GCC (http://sourceforge.net/projects/boundschecking/)This has the drawback of beeing just for GCC (as far as I know of) but has the advantage over valgrind that is : more portable (virtually it should be possible to use it anywhere you can use a recent GCC), a lot faster and can detect bugs that valgrind cannot find. However it has the disadvantage that it's error reports do not contain backtraces so they might be lesser usefull.To use it basically it cuts down to:- download a recent compiler (ex GCC 3.4.1)- download the coresponding patch from the project's sf.net page- apply the patch while beeing in the gcc source dir you unpacked with a command like bunzip2 -c /path/to/patch.bz2 | patch -p1- compile gcc and install gcc- to make pvpgn compile with your new gcc do something like:$ CC=/path/to/new/gcc CFLAGS="-O0 -Wall -fbounds-checking -g" ./configure- then the usual make, make install- to run PvPGN you will probably need to redirect stderr like:$ /path/to/bnetd -f 2> debug.outYou will probably encounter some problems when configuring, building gcc, so you should read the text in the beginning of the bounds-checking patch file. Also the gcc install docs are usefull.When starting up your new bounds checking enabled binary you will see some usefull messages. By default the patch makes the debugged program exit on the first error it encounters. For a production server this is not very nice so you will want to set GCC_BOUNDS_OPTS shell variable to "-never-fatal" like:$ GCC_BOUNDS_OPTS="-never-fatal" /path/to/bnetd -f 2> debug.outAppendix C. How to generate and use "core" files=================================================This appendix is for Unix users. I dont know if other platforms have similar features, that when the program crashes unexpectedly the OS would dump the contents of the memory of the crashing process into a disk file for later inspection.First make sure that PvPGN has been compiled with debugging ("-g" parameter to gcc) and with no optimizations ("-O0" parameter to gcc). PvPGN default build process puts "-g -O2" so you need to edit Makefile file before compile and change it to "-g -O0". Then something like "make clean; make".On Unix/Linux to be able to get core dumps you first need to make sure your core file size limit is set acordingly. Use "ulimit -c" for querying and setting this limit (I recommend setting it to "unlimited"). After that when you start PvPGN make sure you are in a directory where you have write access (so the OS when it wants to do the core dump it will be allowed to do so). The last thing to do is when starting PvPGN make sure it starts in FOREGROUND, example : /path/to/bnetd -f . If you did all this then when PvPGN will crash you will get a core dump. On linux this is a file called "core", on *BSD it's called <processname>.core (for bnetd that means it's called bnetd.core). Now that you got a core file it is time to use it to identify what happened wrong in the crashing process. We use gdb (the GNU debugger, should be available on all Unices) to do this. Run gdb like this:$ gdb /path/to/bnetd /path/to/corefileThen gdb should startup, print out a lot of messages and stop after printing a file and line number and quoting some C code where the crash has happened. You can find out a lot more information than this. Run gdb's command "bt full" and it will display a full backtrace of the moment of the crash. The backtrace will contain how the functions were called along the way (their parameters), and also any local variables. If you do not know what to do next from here contact a PvPGN developer and give him exactly that backtrace dump, he should know more.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -