pax_global_header00006660000000000000000000000064131703560270014516gustar00rootroot0000000000000052 comment=5b9f64c2438517e1c95b28678097419542d1d084 ccnet-6.1.5/000077500000000000000000000000001317035602700126235ustar00rootroot00000000000000ccnet-6.1.5/.gitignore000066400000000000000000000024061317035602700146150ustar00rootroot00000000000000*~ *.bak *.o *.exe cscope* *# Makefile.in net/Makefile net/.deps ltmain.sh libtool *.lo *.la lib/libccnet.a lib/libcommon.a lib/ccnetevent.c lib/ccnetobj.c lib/event-object.h lib/ccnet-object.h net/ccnet-test install-sh depcomp config.guess config.h config.log config.status config.sub config.cache configure */.deps cli/Makefile cli/ccnet-cli cli/ccnet-create-group autom4te* po/POTFILES missing mkinstalldirs stamp-h1 *.libs/ Makefile aclocal.m4 gtk/ccnet-gtk *core tools/ccnet-init gtk/ccnet-board gtk/ccnet-msgview data/new-conf* m4/intltool.m4 m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 ccnet-*.tar.gz config.h.in py-compile python/ccnet/ccnet.c *.stamp include/ccnet/buildin-types.h lib/buildin-types.c *.pyc *.tmp.ui *.defs *.log .deps *.db cli/ccnet-servtool cli/ccnet-tool tests/peer-add/conf1/c882e263e9d02c63ca6b61c68508761cbc74c358.peer tests/peer-add/conf1/c882e263e9d02c63ca6b61c68508761cbc74c358.user *.dll *.aps *.so build-stamp debian/files debian/seafile debian/*.substvars net/daemon/ccnet net/server/ccnet-server lib/searpc-marshal.h lib/searpc-signature.h lib/rpc_table.stamp lib/rpc_table.tmp net/cluster/ccnet-cserver tests/common-conf.sh libccnet.pc demo/ccnet-demo-client demo/ccnet-demo-server net/daemon/ccnet-test /compile ccnet-6.1.5/.travis.yml000066400000000000000000000003551317035602700147370ustar00rootroot00000000000000sudo: false language: c compiler: - gcc - clang addons: apt: packages: - valac - uuid-dev - libevent-dev - re2c - libjansson-dev cache: directories: - $HOME/downloads script: - ./ci/travis.sh ccnet-6.1.5/HACKING000066400000000000000000000076701317035602700136240ustar00rootroot00000000000000 Terminology =========== * Peer * Ccnet daemon * Client * Service daemon: for example seafile daemon. Peer Transfer Layer =================== Communication between peer is packet oriented. The packet structure is defined in `lib/packet.h` as struct ccnet_header { uint8_t version; uint8_t type; uint16_t length; /* length of payload */ uint32_t id; /* for identify a service session id */ }; struct ccnet_packet { struct ccnet_header header; char data[0]; }; So the max length of payload is 65535. Service Invocation ================== Ccnet provide a service invocation layer upon transfer layer. Local Service Invoking ---------------------- A local service is provided either by ccnet daemon or a service daemon. To invoke a local service, client first sends a REQUEST packet containing the service name and arguments to ccnet daemon. Ccnet daemon will find the daemon who provide the service and start the service. This starts a `service session`. A service session is identified by a unique id. Later communication for this session using REQUEST and UPDATE packets. These packets constains the unique id in their header for the partners to identify the session. Client --------------> Ccnet Daemon --------------> Service Daemon UPDATE UPDATE Client --------------> Ccnet Daemon ------------> Service Daemon <------------- <------------ RESPONSE RESPONSE Remote Service Invoking ----------------------- remote Client -----------------------> Ccnet Daemon --------------> Remote Ccnet UPDATE UPDATE Client -----------------------> Ccnet Daemon --------------> Remote Ccnet <----------------------- <-------------- RESPONSE RESPONSE Note: if is self, remote service invoking will be automatically turned to local service invoking. Service Registration -------------------- The daemons implements a service by a subclass of `CcnetProcessor` and registers it to ccnet daemon by calling `ccnet_register_service()`: CcnetClient *client; ccnet_register_service (client, "seafile-rpcserver", CCNET_TYPE_RPCSERVER_PROC); This is used by the seafile daemon to register service "seafile-rpcserver" to ccnet daemon. Inside the ccnet daemon, a service is registered simply by calling void ccnet_proc_factory_register_processor (CcnetProcFactory *factory, const char *proc_name, GType type); Processor Management ==================== Local Service Invoking ---------------------- To support local service invoking, a service proxy processor and a service stub processor will be started when necessary. The runtime configuration is as following: Local Client Ccnet Daemon Service Daemon ---------------------------------- Client Processor ---> | Service Proxy --> Service Stub | --> Daemon Processor ---------------------------------- Remote Service Invoking ----------------------- The runtime configuration is as following: Local Client Ccnet Daemon Remote Ccnet Daemon ---------------------------------- Client Processor ---> | Service Proxy --> Service Stub | --> Daemon Processor ---------------------------------- Notes when using processor -------------------------- * A class of processor may provide different services, we use 'processor->name' to remember which service an instance of a processor class provided. ccnet-6.1.5/LICENSE.txt000066400000000000000000000450241317035602700144530ustar00rootroot00000000000000COPYRIGHT 2012 - Seafile Ltd. This program is released under GPLv2, with the following addition permission to link with OpenSSL library. If you modify this program, or any covered work, by linking or combining it with the OpenSSL project's OpenSSL library (or a modified version of that library), containing parts covered by the terms of the OpenSSL or SSLeay licenses, Seafile Ltd. grants you additional permission to convey the resulting work. Corresponding Source for a non-source form of such a combination shall include the source code for the parts of OpenSSL used as well as that of the covered work. Some individual files have their speicific license: * lib/buffer.c is from libevent, so it has a BSD-3-clause license. Copyright (c) 2002-2007 Niels Provos Copyright (c) 2007-2010 Niels Provos and Nick Mathewson 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 Lesser 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. GNU GENERAL PUBLIC LICENSE 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. Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. , 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 Lesser General Public License instead of this License. ccnet-6.1.5/Makefile.am000066400000000000000000000007251317035602700146630ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in pcfiles = libccnet.pc pkgconfig_DATA = $(pcfiles) pkgconfigdir = $(libdir)/pkgconfig SUBDIRS = include lib net python tools EXTRA_DIST = install-sh libccnet.pc.in LICENSE.txt ACLOCAL_AMFLAGS = -I m4 install-data-local: if MACOS sed -i '' -e "s|(DESTDIR)|${DESTDIR}|g" $(pcfiles) else ${SED} -i "s|(DESTDIR)|${DESTDIR}|g" $(pcfiles) endif dist-hook: git log --format='%H' -1 > $(distdir)/latest_commit ccnet-6.1.5/README.markdown000066400000000000000000000012771317035602700153330ustar00rootroot00000000000000[![Build Status](https://secure.travis-ci.org/haiwen/ccnet.png?branch=master)](http://travis-ci.org/haiwen/ccnet) Ccnet is a framework for writing networked applications in C. It provides the following basic services: 1. Peer identification 2. Connection Management 3. Service invocation 4. Message sending In ccnet network, there are two types of nodes, i.e., client and server. Server has the following functions: 1. User management 2. Group management 3. Cluster management Dependency ========== The following packages are required to build ccnet: valac >= 0.8 libsearpc Compile ======= To compile the client components, just ./autogen.sh && ./configure && make && make install ccnet-6.1.5/autogen.sh000077500000000000000000000040661317035602700146320ustar00rootroot00000000000000#!/bin/bash # Run this to generate all the initial makefiles, etc. : ${AUTOCONF=autoconf} : ${AUTOHEADER=autoheader} : ${AUTOMAKE=automake} : ${ACLOCAL=aclocal} if test "$(uname)" != "Darwin"; then : ${LIBTOOLIZE=libtoolize} else : ${LIBTOOLIZE=glibtoolize} fi : ${LIBTOOL=libtool} srcdir=`dirname $0` test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` cd $srcdir PROJECT=ccnet TEST_TYPE=-f CONFIGURE=configure.ac DIE=0 ($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || { echo echo "You must have autoconf installed to compile $PROJECT." echo "Download the appropriate package for your distribution," echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" DIE=1 } ($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { echo echo "You must have automake installed to compile $PROJECT." echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.7.tar.gz" echo "(or a newer version if it is available)" DIE=1 } if test "$(uname)" != "Darwin"; then (grep "^AC_PROG_LIBTOOL" $CONFIGURE >/dev/null) && { ($LIBTOOL --version) < /dev/null > /dev/null 2>&1 || { echo echo "**Error**: You must have \`libtool' installed to compile $PROJECT." echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.4.tar.gz" echo "(or a newer version if it is available)" DIE=1 } } fi if test "$DIE" -eq 1; then exit 1 fi dr=`dirname .` echo processing $dr aclocalinclude="$aclocalinclude -I m4" if test x"$MSYSTEM" = x"MINGW32"; then aclocalinclude="$aclocalinclude -I /mingw32/share/aclocal" elif test "$(uname)" = "Darwin"; then aclocalinclude="$aclocalinclude -I /opt/local/share/aclocal" fi echo "Creating $dr/aclocal.m4 ..." test -r $dr/aclocal.m4 || touch $dr/aclocal.m4 echo "Making $dr/aclocal.m4 writable ..." test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4 echo "Running $LIBTOOLIZE..." $LIBTOOLIZE --force --copy echo "Running $ACLOCAL $aclocalinclude ..." $ACLOCAL $aclocalinclude echo "Running $AUTOHEADER..." $AUTOHEADER echo "Running $AUTOMAKE --gnu $am_opt ..." $AUTOMAKE --add-missing --gnu $am_opt echo "Running $AUTOCONF ..." $AUTOCONF ccnet-6.1.5/ci/000077500000000000000000000000001317035602700132165ustar00rootroot00000000000000ccnet-6.1.5/ci/travis.sh000077500000000000000000000016411317035602700150670ustar00rootroot00000000000000#!/bin/bash set -e -x PREFIX=$HOME/opt/local export CPPFLAGS="$CPPFLAGS -I$PREFIX/include" export LDFLAGS="$LDFLAGS -L$PREFIX/lib -L$PREFIX/lib64" export PATH="$PREFIX/bin:$PATH" export PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig:$PREFIX/lib64/pkgconfig:$PKG_CONFIG_PATH" install_deps() { pushd $HOME # download precompiled libzdb zdb_bin=libzdb-bin_2.11.1.tar.gz wget https://dl.bintray.com/lins05/generic/libzdb-bin/$zdb_bin tar xf $zdb_bin sed -i -e "s|prefix=/opt/local|prefix=$HOME/opt/local|g" $HOME/opt/local/lib/pkgconfig/zdb.pc find $HOME/opt # build libsearpc git clone --depth=1 --branch=master git://github.com/haiwen/libsearpc.git /tmp/libsearpc pushd /tmp/libsearpc ./autogen.sh ./configure --prefix=$PREFIX make -j2 && make install popd popd } install_deps ./autogen.sh ./configure --prefix=$PREFIX --enable-server --enable-client make -j2 make check ccnet-6.1.5/configure.ac000066400000000000000000000122701317035602700151130ustar00rootroot00000000000000dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) AC_INIT([ccnet], [6.0.4], [info@seafile.com]) AC_CONFIG_SRCDIR([net/daemon/ccnet-daemon.c]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.9 foreign]) #AC_MINGW32 AC_CANONICAL_BUILD dnl enable the build of share library by default AC_ENABLE_SHARED AC_SUBST(LIBTOOL_DEPS) # Checks for programs. AC_PROG_CC #AM_C_PROTOTYPES AC_C_CONST AC_PROG_MAKE_SET # AC_PROG_RANLIB LT_INIT # Checks for headers. AC_CHECK_HEADERS([sys/ioctl.h sys/time.h stdarg.h]) # Checks for typedefs, structures, and compiler characteristics. AC_SYS_LARGEFILE # Checks for library functions. #AC_CHECK_FUNCS([alarm dup2 ftruncate getcwd gethostbyname gettimeofday memmove memset mkdir rmdir select setlocale socket strcasecmp strchr strdup strrchr strstr strtol uname utime strtok_r sendfile]) # check platform AC_MSG_CHECKING(for WIN32) if test "$build_os" = "mingw32" -o "$build_os" = "mingw64"; then bwin32=true AC_MSG_RESULT(compile in mingw) else AC_MSG_RESULT(no) fi AC_MSG_CHECKING(for Mac) if test "$(uname)" = "Darwin"; then bmac=true AC_MSG_RESULT(compile in mac) else AC_MSG_RESULT(no) fi AC_MSG_CHECKING(for Linux) if test "$bmac" != "true" -a "$bwin32" != "true"; then blinux=true AC_MSG_RESULT(compile in linux) else AC_MSG_RESULT(no) fi AM_CONDITIONAL([WIN32], [test "$bwin32" = "true"]) AM_CONDITIONAL([MACOS], [test "$bmac" = "true"]) AM_CONDITIONAL([LINUX], [test "$blinux" = "true"]) # check libraries if test "$bwin32" != true; then if test "$bmac" = true; then AC_CHECK_LIB(c, uuid_generate, [echo "found library uuid"], AC_MSG_ERROR([*** Unable to find uuid_generate in libc]), ) else AC_CHECK_LIB(uuid, uuid_generate, [echo "found library uuid"], AC_MSG_ERROR([*** Unable to find uuid library]), ) fi fi AC_CHECK_LIB(pthread, pthread_create, [echo "found library pthread"], AC_MSG_ERROR([*** Unable to find pthread library]), ) AC_CHECK_LIB(sqlite3, sqlite3_open,[echo "found library sqlite3"] , AC_MSG_ERROR([*** Unable to find sqlite3 library]), ) AC_CHECK_LIB(crypto, SHA1_Init, [echo "found library crypto"], AC_MSG_ERROR([*** Unable to find openssl crypto library]), ) PTHREAD_CFLAGS=-pthread PTHREAD_LIBS=-lpthread has_winpthread=false if test "$bwin32" = "true"; then has_winpthread=false dnl this will tell us if the implementation of pthread is winpthread AC_CHECK_LIB(winpthread, pthread_create, has_winpthread=true, [echo "found library winpthread"], ) PTHREAD_CFLAGS=-pthread PTHREAD_LIBS=-lwinpthread fi dnl Saddly, the old mingw gcc doesn't support -pthread flag if test "$bwin32" = "true" -a "$has_winpthread" != "true"; then PTHREAD_CFLAGS= PTHREAD_LIBS=-lpthread fi AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_LIBS) dnl Do we need to use AX_LIB_SQLITE3 to check sqlite? dnl AX_LIB_SQLITE3 CONSOLE= if test "$bwin32" = "true"; then AC_ARG_ENABLE(console, AC_HELP_STRING([--enable-console], [enable console]), [console=$enableval],[console="yes"]) if test x${console} != xyes ; then CONSOLE="-Wl,--subsystem,windows -Wl,--entry,_mainCRTStartup" fi fi AC_SUBST(CONSOLE) if test "$bwin32" = true; then LIB_WS32=-lws2_32 LIB_GDI32=-lgdi32 LIB_RT= LIB_INTL=-lintl LIBS= LIB_RESOLV= LIB_UUID=-lrpcrt4 LIB_IPHLPAPI=-liphlpapi LIB_SHELL32=-lshell32 LIB_PSAPI=-lpsapi MSVC_CFLAGS=-D__MSVCRT_VERSION__=0x0601 LIB_DIRWATCH= elif test "$bmac" = true ; then LIB_WS32= LIB_GDI32= LIB_RT= LIB_INTL= LIB_RESOLV=-lresolv LIB_UUID= LIB_IPHLPAPI= LIB_SHELL32= LIB_PSAPI= MSVC_CFLAGS= LIB_DIRWATCH="-framework CoreServices" else LIB_WS32= LIB_GDI32= LIB_RT= LIB_INTL= LIB_RESOLV=-lresolv LIB_UUID=-luuid LIB_IPHLPAPI= LIB_SHELL32= LIB_PSAPI= MSVC_CFLAGS= LIB_DIRWATCH= fi AC_SUBST(LIB_WS32) AC_SUBST(LIB_GDI32) AC_SUBST(LIB_RT) AC_SUBST(LIB_INTL) AC_SUBST(LIB_RESOLV) AC_SUBST(LIB_UUID) AC_SUBST(LIB_IPHLPAPI) AC_SUBST(LIB_SHELL32) AC_SUBST(LIB_PSAPI) AC_SUBST(MSVC_CFLAGS) AC_SUBST(LIB_DIRWATCH) LIBEVENT_REQUIRED=2.0 # gtk and glib APPINDICATOR_REQUIRED=0.0.7 GLIB_REQUIRED=2.16.0 GTK_REQUIRED=2.16.0 SEARPC_REQUIRED=1.0 SEARPC_REQUIRED=1.0 PKG_CHECK_MODULES(SSL, [openssl]) AC_SUBST(SSL_CFLAGS) AC_SUBST(SSL_LIBS) PKG_CHECK_MODULES(GLIB2, [glib-2.0 >= $GLIB_REQUIRED]) AC_SUBST(GLIB2_CFLAGS) AC_SUBST(GLIB2_LIBS) PKG_CHECK_MODULES(GOBJECT, [gobject-2.0 >= $GLIB_REQUIRED]) AC_SUBST(GOBJECT_CFLAGS) AC_SUBST(GOBJECT_LIBS) PKG_CHECK_MODULES(SEARPC, [libsearpc >= $SEARPC_REQUIRED]) AC_SUBST(SEARPC_CFLAGS) AC_SUBST(SEARPC_LIBS) PKG_CHECK_MODULES(LIBEVENT, [libevent >= $LIBEVENT_REQUIRED]) AC_SUBST(LIBEVENT_CFLAGS) AC_SUBST(LIBEVENT_LIBS) AM_PATH_PYTHON([2.6]) if test "$bwin32" = true; then # set pyexecdir to somewhere like /c/Python26/Lib/site-packages pyexecdir=${PYTHON_DIR}/Lib/site-packages pythondir=${pyexecdir} pkgpyexecdir=${pyexecdir}/${PACKAGE} pkgpythondir=${pythondir}/${PACKAGE} fi # end for bwin32 ac_configure_args="$ac_configure_args -q" AC_CONFIG_FILES( Makefile libccnet.pc net/Makefile net/daemon/Makefile lib/Makefile include/Makefile include/ccnet/Makefile python/Makefile python/ccnet/Makefile tools/Makefile ) AC_OUTPUT ccnet-6.1.5/debian/000077500000000000000000000000001317035602700140455ustar00rootroot00000000000000ccnet-6.1.5/debian/README.Debian000066400000000000000000000002271317035602700161070ustar00rootroot00000000000000Seafile ------- For more information about Seafile, please visit http://seafile.com -- plt Fri, 30 March 2012 16:43:10 +0800 ccnet-6.1.5/debian/ccnet.install000066400000000000000000000000411317035602700165240ustar00rootroot00000000000000usr/bin/ccnet usr/bin/ccnet-init ccnet-6.1.5/debian/changelog000066400000000000000000000027651317035602700157310ustar00rootroot00000000000000ccnet (6.0.4) unstable; urgency=low * new upstream release -- Jonathan Xu Tue, 21 Feb 2017 14:14:08 +0800 ccnet (6.0.3) unstable; urgency=low * new upstream release -- Jonathan Xu Sat, 11 Feb 2017 12:17:05 +0800 ccnet (6.0.2) unstable; urgency=low * new upstream release -- Jonathan Xu Thu, 5 Jan 2017 14:12:05 +0800 ccnet (6.0.1) unstable; urgency=low * new upstream release -- Jonathan Xu Mon, 12 Dec 2016 14:49:40 +0800 ccnet (6.0.0) unstable; urgency=low * new upstream release -- Jonathan Xu Fri, 14 Oct 2016 13:49:07 +0800 ccnet (5.1.4) unstable; urgency=low * new upstream release -- Jonathan Xu Fri, 29 Jul 2016 13:59:28 +0800 ccnet (5.1.3-1ubuntu1) UNRELEASED; urgency=medium * new upstream release -- m.eik michalke Thu, 30 Jun 2016 21:59:28 +0200 ccnet (5.1.2-5ubuntu1) unstable; urgency=medium * repackaging with cleaned up orig.tar.xz archives * added symbols file -- m.eik michalke Fri, 17 Jun 2016 19:21:05 +0200 ccnet (5.1.2-4) unstable; urgency=medium * split package ccnet, libccnet0 and libccnet-dev * updated the debian/copyright notice so people know who's responisble for the packaging * rewrote the rules file, much simpler now * prep for release on github -- m.eik michalke Wed, 15 Jun 2016 22:36:08 +0200 ccnet-6.1.5/debian/compat000066400000000000000000000000021317035602700152430ustar00rootroot000000000000007 ccnet-6.1.5/debian/control000066400000000000000000000034531317035602700154550ustar00rootroot00000000000000Source: ccnet Section: net Priority: extra Maintainer: m.eik michalke Build-Depends: debhelper (>= 7), autotools-dev, libssl1.0-dev | libssl-dev (<< 1.1), libsqlite3-dev, intltool, libglib2.0-dev, libevent-dev, uuid-dev, libtool, libcurl4-openssl-dev, valac, libjansson-dev, python, libsearpc-dev Standards-Version: 3.9.5 Homepage: http://seafile.com Package: ccnet Section: net Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends} Conflicts: seafile Description: Seafile client ccnet framework. A framework for writing networked applications in C. It provides basic services like peer identification, connection management, service invocation, and message sending. Package: libccnet0 Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends} Conflicts: seafile Description: Shared libraries for package ccnet. This package contains the shared libraries for the ccnet package. Package: libccnet-dev Section: libdevel Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libccnet0 (= ${binary:Version}) Conflicts: seafile Description: Development files for package libccnet0. This package contains the development files for the libccnet0 package. Package: ccnet-dbg Section: debug Architecture: any Depends: ccnet (= ${binary:Version}), ${misc:Depends}, Description: Debugging symbols for the ccnet package. This package contains the debugging symbols for the ccnet package. Package: libccnet-dbg Section: debug Architecture: any Depends: libccnet0 (= ${binary:Version}), ${misc:Depends}, Description: Debugging symbols for the libccnet package. This package contains the debugging symbols for the libccnet0 package. ccnet-6.1.5/debian/copyright000066400000000000000000000075221317035602700160060ustar00rootroot00000000000000Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: ccnet Upstream-Contact: GongGeng Source: https://github.com/haiwen/ccnet Files: * Copyright: 2012-2013 GongGeng License: GPL-3 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 3 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 license with your Debian system, in the file /usr/share/common-licenses/GPL-3, or with the source package as the file COPYING or LICENSE. . In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the OpenSSL library under certain conditions as described in each individual source file, and distribute linked combinations including the two. . You must obey the GNU General Public License in all respects for all of the code used other than OpenSSL. If you modify file(s) with this exception, you may extend this exception to your version of the file(s), but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. If you delete this exception statement from all source files in the program, then also delete it here. Files: lib/buffer.c Copyright: 2002-2007 Niels Provos 2007-2010 Niels Provos and Nick Mathewson License: BSD-3-clause 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. Files: debian/* Copyright: 2016 m.eik michalke License: GPL-2 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 software 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. . You should have received a copy of the license with your Debian system, in the file /usr/share/common-licenses/GPL-2, or with the source package as the file COPYING or LICENSE. ccnet-6.1.5/debian/libccnet-dev.install000066400000000000000000000001311317035602700177670ustar00rootroot00000000000000usr/include usr/lib/pkgconfig usr/lib/libccnet.a usr/lib/libccnet.la usr/lib/libccnet.so ccnet-6.1.5/debian/libccnet0.install000066400000000000000000000002261317035602700173000ustar00rootroot00000000000000usr/lib/*.so.* usr/lib/python2.7/dist-packages/ccnet/*.py usr/lib/python2.7/dist-packages/ccnet/async/*.py usr/lib/python2.7/dist-packages/ccnet/*.py ccnet-6.1.5/debian/libccnet0.symbols000066400000000000000000000216011317035602700173220ustar00rootroot00000000000000libccnet.so.0 libccnet0 #MINVER# buffer_add@Base 5.1.2 buffer_add_buffer@Base 5.1.2 buffer_drain@Base 5.1.2 buffer_expand@Base 5.1.2 buffer_find@Base 5.1.2 buffer_free@Base 5.1.2 buffer_new@Base 5.1.2 buffer_read@Base 5.1.2 buffer_readline@Base 5.1.2 buffer_remove@Base 5.1.2 buffer_setcb@Base 5.1.2 buffer_write@Base 5.1.2 ccnet_add_peer@Base 5.1.2 ccnet_async_rpc_client_free@Base 5.1.2 ccnet_async_rpc_proc_get_type@Base 5.1.2 ccnet_async_rpc_proc_set_rpc@Base 5.1.2 ccnet_client_add_processor@Base 5.1.2 ccnet_client_clean_rpc_request@Base 5.1.2 ccnet_client_connect_daemon@Base 5.1.2 ccnet_client_disconnect_daemon@Base 5.1.2 ccnet_client_get_processor@Base 5.1.2 ccnet_client_get_request_id@Base 5.1.2 ccnet_client_get_rpc_request_id@Base 5.1.2 ccnet_client_get_type@Base 5.1.2 ccnet_client_load_confdir@Base 5.1.2 ccnet_client_new@Base 5.1.2 ccnet_client_pool_get_client@Base 5.1.2 ccnet_client_pool_new@Base 5.1.2 ccnet_client_pool_return_client@Base 5.1.2 ccnet_client_prepare_recv_message@Base 5.1.2 ccnet_client_read_input@Base 5.1.2 ccnet_client_read_response@Base 5.1.2 ccnet_client_receive_message@Base 5.1.2 ccnet_client_remove_processor@Base 5.1.2 ccnet_client_run_synchronizer@Base 5.1.2 ccnet_client_send_cmd@Base 5.1.2 ccnet_client_send_message@Base 5.1.2 ccnet_client_send_request@Base 5.1.2 ccnet_client_send_response@Base 5.1.2 ccnet_client_send_update@Base 5.1.2 ccnet_connect_peer@Base 5.1.2 ccnet_create_async_rpc_client@Base 5.1.2 ccnet_create_pooled_rpc_client@Base 5.1.2 ccnet_create_rpc_client@Base 5.1.2 ccnet_disconnect_peer@Base 5.1.2 ccnet_email_user_construct@Base 5.1.2 ccnet_email_user_get_ctime@Base 5.1.2 ccnet_email_user_get_email@Base 5.1.2 ccnet_email_user_get_id@Base 5.1.2 ccnet_email_user_get_is_active@Base 5.1.2 ccnet_email_user_get_is_staff@Base 5.1.2 ccnet_email_user_get_password@Base 5.1.2 ccnet_email_user_get_role@Base 5.1.2 ccnet_email_user_get_source@Base 5.1.2 ccnet_email_user_get_type@Base 5.1.2 ccnet_email_user_new@Base 5.1.2 ccnet_email_user_set_ctime@Base 5.1.2 ccnet_email_user_set_email@Base 5.1.2 ccnet_email_user_set_id@Base 5.1.2 ccnet_email_user_set_is_active@Base 5.1.2 ccnet_email_user_set_is_staff@Base 5.1.2 ccnet_email_user_set_password@Base 5.1.2 ccnet_email_user_set_role@Base 5.1.2 ccnet_email_user_set_source@Base 5.1.2 ccnet_get_binding_email@Base 5.1.2 ccnet_get_binding_email_async@Base 5.1.2 ccnet_get_config@Base 5.1.2 ccnet_get_default_relay@Base 5.1.2 ccnet_get_group_members@Base 5.1.2 ccnet_get_groups_by_user@Base 5.1.2 ccnet_get_peer@Base 5.1.2 ccnet_get_peer_bind_status@Base 5.1.2 ccnet_get_peer_by_idname@Base 5.1.2 ccnet_get_peer_net_state@Base 5.1.2 ccnet_get_peers_by_role@Base 5.1.2 ccnet_group_construct@Base 5.1.2 ccnet_group_get_creator_name@Base 5.1.2 ccnet_group_get_group_name@Base 5.1.2 ccnet_group_get_id@Base 5.1.2 ccnet_group_get_source@Base 5.1.2 ccnet_group_get_timestamp@Base 5.1.2 ccnet_group_get_type@Base 5.1.2 ccnet_group_new@Base 5.1.2 ccnet_group_set_creator_name@Base 5.1.2 ccnet_group_set_group_name@Base 5.1.2 ccnet_group_set_id@Base 5.1.2 ccnet_group_set_source@Base 5.1.2 ccnet_group_set_timestamp@Base 5.1.2 ccnet_group_user_construct@Base 5.1.2 ccnet_group_user_get_group_id@Base 5.1.2 ccnet_group_user_get_is_staff@Base 5.1.2 ccnet_group_user_get_type@Base 5.1.2 ccnet_group_user_get_user_name@Base 5.1.2 ccnet_group_user_new@Base 5.1.2 ccnet_group_user_set_group_id@Base 5.1.2 ccnet_group_user_set_is_staff@Base 5.1.2 ccnet_group_user_set_user_name@Base 5.1.2 ccnet_init@Base 5.1.2 ccnet_job_free@Base 5.1.2 ccnet_job_manager_free@Base 5.1.2 ccnet_job_manager_new@Base 5.1.2 ccnet_job_manager_remove_job@Base 5.1.2 ccnet_job_manager_schedule_job@Base 5.1.2 ccnet_job_new@Base 5.1.2 ccnet_login_to_relay@Base 5.1.2 ccnet_main@Base 5.1.2 ccnet_message_body_dup@Base 5.1.2 ccnet_message_body_take@Base 5.1.2 ccnet_message_free@Base 5.1.2 ccnet_message_from_string@Base 5.1.2 ccnet_message_get_type@Base 5.1.2 ccnet_message_is_to_group@Base 5.1.2 ccnet_message_new@Base 5.1.2 ccnet_message_new_full@Base 5.1.2 ccnet_message_to_string_buf@Base 5.1.2 ccnet_mqclient_proc_get_type@Base 5.1.2 ccnet_mqclient_proc_put_message@Base 5.1.2 ccnet_mqclient_proc_set_message_got_cb@Base 5.1.2 ccnet_mqclient_proc_unsubscribe_apps@Base 5.1.2 ccnet_org_user_exists@Base 5.1.2 ccnet_organization_construct@Base 5.1.2 ccnet_organization_get_creator@Base 5.1.2 ccnet_organization_get_ctime@Base 5.1.2 ccnet_organization_get_email@Base 5.1.2 ccnet_organization_get_is_staff@Base 5.1.2 ccnet_organization_get_org_id@Base 5.1.2 ccnet_organization_get_org_name@Base 5.1.2 ccnet_organization_get_type@Base 5.1.2 ccnet_organization_get_url_prefix@Base 5.1.2 ccnet_organization_new@Base 5.1.2 ccnet_organization_set_creator@Base 5.1.2 ccnet_organization_set_ctime@Base 5.1.2 ccnet_organization_set_email@Base 5.1.2 ccnet_organization_set_is_staff@Base 5.1.2 ccnet_organization_set_org_id@Base 5.1.2 ccnet_organization_set_org_name@Base 5.1.2 ccnet_organization_set_url_prefix@Base 5.1.2 ccnet_packet_add@Base 5.1.2 ccnet_packet_finish@Base 5.1.2 ccnet_packet_finish_send@Base 5.1.2 ccnet_packet_io_free@Base 5.1.2 ccnet_packet_io_new@Base 5.1.2 ccnet_packet_io_read@Base 5.1.2 ccnet_packet_io_read_packet@Base 5.1.2 ccnet_packet_io_set_callback@Base 5.1.2 ccnet_packet_prepare@Base 5.1.2 ccnet_packet_send@Base 5.1.2 ccnet_packet_write_string@Base 5.1.2 ccnet_peer_get_net_state_string@Base 5.1.2 ccnet_peer_get_type@Base 5.1.2 ccnet_peer_is_ready@Base 5.1.2 ccnet_peer_new@Base 5.1.2 ccnet_peer_stat_construct@Base 5.1.2 ccnet_peer_stat_get_encrypt@Base 5.1.2 ccnet_peer_stat_get_id@Base 5.1.2 ccnet_peer_stat_get_ip@Base 5.1.2 ccnet_peer_stat_get_last_up@Base 5.1.2 ccnet_peer_stat_get_name@Base 5.1.2 ccnet_peer_stat_get_proc_num@Base 5.1.2 ccnet_peer_stat_get_type@Base 5.1.2 ccnet_peer_stat_new@Base 5.1.2 ccnet_peer_stat_set_encrypt@Base 5.1.2 ccnet_peer_stat_set_id@Base 5.1.2 ccnet_peer_stat_set_ip@Base 5.1.2 ccnet_peer_stat_set_last_up@Base 5.1.2 ccnet_peer_stat_set_name@Base 5.1.2 ccnet_peer_stat_set_proc_num@Base 5.1.2 ccnet_privkey_decrypt@Base 5.1.2 ccnet_proc_construct@Base 5.1.2 ccnet_proc_factory_create_master_processor@Base 5.1.2 ccnet_proc_factory_create_processor@Base 5.1.2 ccnet_proc_factory_create_remote_master_processor@Base 5.1.2 ccnet_proc_factory_create_slave_processor@Base 5.1.2 ccnet_proc_factory_get_type@Base 5.1.2 ccnet_proc_factory_new@Base 5.1.2 ccnet_proc_factory_recycle@Base 5.1.2 ccnet_proc_factory_register_processor@Base 5.1.2 ccnet_proc_get_ctime@Base 5.1.2 ccnet_proc_get_dtime@Base 5.1.2 ccnet_proc_get_name@Base 5.1.2 ccnet_proc_get_peer_name@Base 5.1.2 ccnet_proc_get_type@Base 5.1.2 ccnet_proc_new@Base 5.1.2 ccnet_proc_set_ctime@Base 5.1.2 ccnet_proc_set_dtime@Base 5.1.2 ccnet_proc_set_name@Base 5.1.2 ccnet_proc_set_peer_name@Base 5.1.2 ccnet_processor_done@Base 5.1.2 ccnet_processor_get_type@Base 5.1.2 ccnet_processor_handle_response@Base 5.1.2 ccnet_processor_handle_sigchld@Base 5.1.2 ccnet_processor_handle_update@Base 5.1.2 ccnet_processor_release_resource@Base 5.1.2 ccnet_processor_send_request@Base 5.1.2 ccnet_processor_send_request_l@Base 5.1.2 ccnet_processor_send_response@Base 5.1.2 ccnet_processor_send_update@Base 5.1.2 ccnet_processor_start@Base 5.1.2 ccnet_processor_startl@Base 5.1.2 ccnet_processor_thread_create@Base 5.1.2 ccnet_pubkey_encrypt@Base 5.1.2 ccnet_register_service@Base 5.1.2 ccnet_register_service_sync@Base 5.1.2 ccnet_rpc_client_free@Base 5.1.2 ccnet_rpcserver_proc_get_type@Base 5.1.2 ccnet_send_command@Base 5.1.2 ccnet_sendcmd_proc_get_type@Base 5.1.2 ccnet_sendcmd_proc_send_command@Base 5.1.2 ccnet_sendcmd_proc_set_rcvrsp_cb@Base 5.1.2 ccnet_service_proc_get_type@Base 5.1.2 ccnet_service_proc_set_response_cb@Base 5.1.2 ccnet_session_base_get_type@Base 5.1.2 ccnet_session_base_new@Base 5.1.2 ccnet_set_config@Base 5.1.2 ccnet_sign_message@Base 5.1.2 ccnet_threaded_rpcserver_proc_get_type@Base 5.1.2 ccnet_timer_free@Base 5.1.2 ccnet_timer_new@Base 5.1.2 ccnet_update_peer_address@Base 5.1.2 ccnet_util_checkdir@Base 5.1.2 ccnet_util_checkdir_with_mkdir@Base 5.1.2 ccnet_util_expand_path@Base 5.1.2 ccnet_util_gen_uuid@Base 5.1.2 ccnet_util_hex_to_rawdata@Base 5.1.2 ccnet_util_key_file_get_string@Base 5.1.2 ccnet_util_recvn@Base 5.1.2 ccnet_util_sendn@Base 5.1.2 ccnet_util_string_list_free@Base 5.1.2 ccnet_util_string_list_join@Base 5.1.2 ccnet_util_string_list_parse_sorted@Base 5.1.2 ccnet_util_strjoin_n@Base 5.1.2 ccnet_util_timeval_from_msec@Base 5.1.2 ccnet_verify_message@Base 5.1.2 ccnetrpc_async_transport_send@Base 5.1.2 ccnetrpc_transport_send@Base 5.1.2 cevent_manager_add_event@Base 5.1.2 cevent_manager_new@Base 5.1.2 cevent_manager_register@Base 5.1.2 cevent_manager_start@Base 5.1.2 cevent_manager_unregister@Base 5.1.2 g_cclosure_user_marshal_VOID__POINTER_STRING@Base 5.1.2 job_thread_create@Base 5.1.2 pipe_callback@Base 5.1.2 ccnet-6.1.5/debian/patches/000077500000000000000000000000001317035602700154745ustar00rootroot00000000000000ccnet-6.1.5/debian/patches/fix-pkgconfig-paths.patch000066400000000000000000000012671317035602700223730ustar00rootroot00000000000000Fixing pkgconfig paths. --- a/libccnet.pc.in +++ b/libccnet.pc.in @@ -1,4 +1,4 @@ -prefix=(DESTDIR)@prefix@ +prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,5 @@ ## Process this file with automake to produce Makefile.in - pcfiles = libccnet.pc pkgconfig_DATA = $(pcfiles) pkgconfigdir = $(libdir)/pkgconfig @@ -21,12 +20,5 @@ ACLOCAL_AMFLAGS = -I m4 -install-data-local: -if MACOS - sed -i '' -e "s|(DESTDIR)|${DESTDIR}|g" $(pcfiles) -else - ${SED} -i "s|(DESTDIR)|${DESTDIR}|g" $(pcfiles) -endif - dist-hook: git log --format='%H' -1 > $(distdir)/latest_commit \ Kein Zeilenumbruch am Dateiende. ccnet-6.1.5/debian/patches/series000066400000000000000000000000321317035602700167040ustar00rootroot00000000000000fix-pkgconfig-paths.patch ccnet-6.1.5/debian/rules000077500000000000000000000006221317035602700151250ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- %: dh $@ --with python2 --with autotools_dev override_dh_auto_configure: ./autogen.sh dh_auto_configure -- --disable-compile-demo override_dh_strip: # emptying the dependency_libs field in .la files sed -i "/dependency_libs/ s/'.*'/''/" `find debian/ -name '*.la'` dh_strip -pccnet --dbg-package=ccnet-dbg dh_strip -plibccnet0 --dbg-package=libccnet-dbg ccnet-6.1.5/debian/source/000077500000000000000000000000001317035602700153455ustar00rootroot00000000000000ccnet-6.1.5/debian/source/format000066400000000000000000000000141317035602700165530ustar00rootroot000000000000003.0 (quilt) ccnet-6.1.5/include/000077500000000000000000000000001317035602700142465ustar00rootroot00000000000000ccnet-6.1.5/include/Makefile.am000066400000000000000000000001141317035602700162760ustar00rootroot00000000000000 SUBDIRS = ccnet include_HEADERS = ccnet.h ccnetdir = $(includedir)/ccnet ccnet-6.1.5/include/ccnet.h000066400000000000000000000105331317035602700155150ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef _CCNET_H #define _CCNET_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* mainloop */ void ccnet_main (CcnetClient *client); typedef void (*RegisterServiceCB) (gboolean success); void ccnet_register_service (CcnetClient *client, const char *service, const char *group, GType proc_type, RegisterServiceCB cb); gboolean ccnet_register_service_sync (CcnetClient *client, const char *service, const char *group); CcnetClient *ccnet_init (const char *central_config_dir, const char *confdir); void ccnet_send_command (CcnetClient *client, const char *command, SendcmdProcRcvrspCallback cmd_cb, void *cbdata); void ccnet_add_peer (CcnetClient *client, const char *id, const char *addr); void ccnet_connect_peer (CcnetClient *client, const char *id); void ccnet_disconnect_peer (CcnetClient *client, const char *id); /* client pool */ struct CcnetClientPool; typedef struct CcnetClientPool CcnetClientPool; struct CcnetClientPool * ccnet_client_pool_new (const char *central_config_dir, const char *conf_dir); CcnetClient * ccnet_client_pool_get_client (struct CcnetClientPool *cpool); void ccnet_client_pool_return_client (struct CcnetClientPool *cpool, CcnetClient *client); /* rpc wrapper */ /* Create rpc client using a single client for transport. */ SearpcClient * ccnet_create_rpc_client (CcnetClient *cclient, const char *peer_id, const char *service_name); /* Create rpc client using client pool for transport. */ SearpcClient * ccnet_create_pooled_rpc_client (struct CcnetClientPool *cpool, const char *peer_id, const char *service); SearpcClient * ccnet_create_async_rpc_client (CcnetClient *cclient, const char *peer_id, const char *service_name); void ccnet_rpc_client_free (SearpcClient *client); void ccnet_async_rpc_client_free (SearpcClient *client); CcnetPeer *ccnet_get_peer (SearpcClient *client, const char *peer_id); CcnetPeer *ccnet_get_peer_by_idname (SearpcClient *client, const char *idname); int ccnet_get_peer_net_state (SearpcClient *client, const char *peer_id); int ccnet_get_peer_bind_status (SearpcClient *client, const char *peer_id); int ccnet_peer_is_ready (SearpcClient *client, const char *peer_id); CcnetPeer *ccnet_get_default_relay (SearpcClient *client); GList *ccnet_get_peers_by_role (SearpcClient *client, const char *role); char *ccnet_get_binding_email (SearpcClient *client, const char *peer_id); GList *ccnet_get_groups_by_user (SearpcClient *client, const char *user); GList * ccnet_get_group_members (SearpcClient *client, int group_id); int ccnet_org_user_exists (SearpcClient *client, int org_id, const char *user); int ccnet_get_binding_email_async (SearpcClient *client, const char *peer_id, AsyncCallback callback, void *user_data); char *ccnet_sign_message (SearpcClient *client, const char *message); int ccnet_verify_message (SearpcClient *client, const char *message, const char *sig_base64, const char *peer_id); char * ccnet_pubkey_encrypt (SearpcClient *client, const char *msg_base64, const char *peer_id); char * ccnet_privkey_decrypt (SearpcClient *client, const char *msg_base64); char *ccnet_get_config (SearpcClient *client, const char *key); int ccnet_set_config (SearpcClient *client, const char *key, const char *value); void ccnet_login_to_relay (SearpcClient *client, const char *relay_id, const char *username, const char *passwd); int ccnet_update_peer_address (SearpcClient *client, const char *peer_id, const char *addr, int port); #endif ccnet-6.1.5/include/ccnet/000077500000000000000000000000001317035602700153425ustar00rootroot00000000000000ccnet-6.1.5/include/ccnet/Makefile.am000066400000000000000000000005451317035602700174020ustar00rootroot00000000000000 ccnetdir = $(includedir)/ccnet ccnet_HEADERS = ccnet-client.h peer.h proc-factory.h \ message.h option.h \ processor.h sendcmd-proc.h \ mqclient-proc.h invoke-service-proc.h \ status-code.h cevent.h timer.h ccnet-session-base.h \ valid-check.h job-mgr.h packet.h \ async-rpc-proc.h ccnetrpc-transport.h \ rpcserver-proc.h threaded-rpcserver-proc.h ccnet-6.1.5/include/ccnet/async-rpc-proc.h000066400000000000000000000027051317035602700203570ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_ASYNC_RPC_PROC_H #define CCNET_ASYNC_RPC_PROC_H #include #define CCNET_TYPE_ASYNC_RPC_PROC (ccnet_async_rpc_proc_get_type ()) #define CCNET_ASYNC_RPC_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_ASYNC_RPC_PROC, CcnetAsyncRpcProc)) #define CCNET_IS_ASYNC_RPC_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_ASYNC_RPC_PROC)) #define CCNET_ASYNC_RPC_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_ASYNC_RPC_PROC, CcnetAsyncRpcProcClass)) #define IS_CCNET_ASYNC_RPC_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_ASYNC_RPC_PROC)) #define CCNET_ASYNC_RPC_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_ASYNC_RPC_PROC, CcnetAsyncRpcProcClass)) typedef struct _CcnetAsyncRpcProc CcnetAsyncRpcProc; typedef struct _CcnetAsyncRpcProcClass CcnetAsyncRpcProcClass; struct _CcnetAsyncRpcProc { CcnetProcessor parent_instance; }; struct _CcnetAsyncRpcProcClass { CcnetProcessorClass parent_class; }; GType ccnet_async_rpc_proc_get_type (); void ccnet_async_rpc_proc_set_rpc (CcnetAsyncRpcProc *proc, const char *service, char *fcall_str, size_t fcall_len, void *rpc_priv); #endif ccnet-6.1.5/include/ccnet/ccnet-client.h000066400000000000000000000132011317035602700200600ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_CLIENT_SESSION_H #define CCNET_CLIENT_SESSION_H #define SESSION_ID_LENGTH 40 #include #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #include "ccnet-session-base.h" #define CCNET_TYPE_CLIENT (ccnet_client_get_type ()) #define CCNET_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_CLIENT, CcnetClient)) #define CCNET_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_CLIENT)) #define CCNET_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_CLIENT, CcnetClientClass)) #define CCNET_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_CLIENT)) #define CCNET_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_CLIENT, CcnetClientClass)) typedef struct _CcnetClient CcnetClient; typedef struct _CcnetClientClass CcnetClientClass; struct _CcnetPeer; struct _CcnetUser; struct _CcnetProcessor; struct CcnetPacketIO; #include #include #define SESSION_CONFIG_FILENAME "ccnet.conf" #define CCNET_USER_ID_START 1000 /** * CcnetClientMode: * @CCNET_CLIENT_SYNC: Synchronous mode * @CCNET_CLIENT_ASYNC: Asynchronous mode * * #CcnetClient can run in synchronous or asynchronous mode. In * synchronous mode, every function call to #CcnetClient is blocked * until the ccnet daemon returns. In asynchronous mode, function * calls are not blocked, and the user should use the processor * mechanism to interact with the daemon. * **/ typedef enum { CCNET_CLIENT_SYNC, CCNET_CLIENT_ASYNC } CcnetClientMode; struct CcnetResponse { char *code; char *code_msg; char *content; int clen; /* content length */ }; typedef struct CcnetClientPriv CcnetClientPriv; /** * CcnetClient: * @id: The ccnet ID in plain text, including the ending '\0' * @id_sha1: The ccnet ID in binary. * @id_quark: The ccnet ID in GQuark. * @name: Ccnet name * @mode: See #CcnetClientMode */ struct _CcnetClient { CcnetSessionBase base; /*< public >*/ int mode; char *central_config_dir; char *config_dir; char *config_file; int daemon_port; char *un_path; int connected : 1; struct _CcnetProcFactory *proc_factory; struct _CcnetGroupManager *group_mgr; /* For processor threads. */ struct _CcnetJobManager *job_mgr; struct CcnetResponse response; /*< private >*/ evutil_socket_t connfd; uint32_t req_id; /* the current request id */ struct CcnetPacketIO *io; GHashTable *processors; GList *rpc_pool; CcnetClientPriv *priv; }; struct _CcnetClientClass { CcnetSessionBaseClass parent_class; }; GType ccnet_client_get_type (void); CcnetClient* ccnet_client_new (void); int ccnet_client_load_confdir (CcnetClient *client, const char *central_config_dir, const char *confdir); /* void ccnet_client_add_alias (CcnetClient *client, const char *alias_str); void ccnet_client_del_alias (CcnetClient *client, const char *alias_str); gboolean ccnet_client_has_alias (CcnetClient *client, const char *alias_id); */ int ccnet_client_connect_daemon (CcnetClient *client, CcnetClientMode mode); int ccnet_client_disconnect_daemon (CcnetClient *client); uint32_t ccnet_client_get_request_id (CcnetClient *client); /* async mode */ void ccnet_client_run_synchronizer (CcnetClient *client); void ccnet_client_add_processor (CcnetClient *client, CcnetProcessor *processor); void ccnet_client_remove_processor (CcnetClient *client, CcnetProcessor *processor); CcnetProcessor * ccnet_client_get_processor (CcnetClient *client, int id); int ccnet_client_read_input (CcnetClient *client); /* sync mode */ int ccnet_client_read_response (CcnetClient *client); void ccnet_client_send_request (CcnetClient *client, int req_id, const char *req); void ccnet_client_send_update (CcnetClient *client, int req_id, const char *code, const char *reason, const char *content, int clen); void ccnet_client_send_response (CcnetClient *client, int req_id, const char *code, const char *reason, const char *content, int clen); const char *ccnet_client_send_cmd (CcnetClient *client, const char *cmd, GError **error); int ccnet_client_send_message (CcnetClient *client, CcnetMessage *message); /* For a sync client to receive a given type of message, 1. call ccnet_client_prepare_recv_message() with the message type you want to receive 2. call ccnet_client_receive_message() repeatly */ int ccnet_client_prepare_recv_message (CcnetClient *client, const char *app); CcnetMessage * ccnet_client_receive_message (CcnetClient *client); uint32_t ccnet_client_get_rpc_request_id (CcnetClient *client, const char *peer_id, const char *service); void ccnet_client_clean_rpc_request (CcnetClient *client, uint32_t req_id); /* void ccnet_client_send_event (CcnetClient *client, GObject *event); */ #endif ccnet-6.1.5/include/ccnet/ccnet-session-base.h000066400000000000000000000027411317035602700212040ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SESSION_BASE_H #define CCNET_SESSION_BASE_H #include #define CCNET_TYPE_SESSION_BASE (ccnet_session_base_get_type ()) #define CCNET_SESSION_BASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SESSION_BASE, CcnetSessionBase)) #define CCNET_IS_SESSION_BASE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SESSION_BASE)) #define CCNET_SESSION_BASE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SESSION_BASE, CcnetSessionBaseClass)) #define CCNET_IS_SESSION_BASE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SESSION_BASE)) #define CCNET_SESSION_BASE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SESSION_BASE, CcnetSessionBaseClass)) #define CCNET_PIPE_NAME "ccnet.sock" typedef struct _CcnetSessionBase CcnetSessionBase; typedef struct _CcnetSessionBaseClass CcnetSessionBaseClass; struct _CcnetSessionBase { GObject parent_instance; char id[41]; unsigned char id_sha1[20]; char *user_name; char *name; int public_port; int net_status; char *service_url; char *relay_id; }; struct _CcnetSessionBaseClass { GObjectClass parent_class; }; GType ccnet_session_base_get_type (void); CcnetSessionBase *ccnet_session_base_new (void); #endif ccnet-6.1.5/include/ccnet/ccnetrpc-transport.h000066400000000000000000000017361317035602700213550ustar00rootroot00000000000000#ifndef CCNETRPC_TRANPORT_H #define CCNETRPC_TRANPORT_H #include typedef struct { /* either session or pool will be set. */ CcnetClient *session; CcnetClientPool *pool; char *peer_id; /* NULL if local */ char *service; } CcnetrpcTransportParam; /* this structure will be parsed to * ccnet_transport_send () */ typedef struct { CcnetClient *session; char *peer_id; /* NULL if local */ char *service; } CcnetrpcAsyncTransportParam; /* this structure will be parsed to * ccnet_async_transport_send () */ char *ccnetrpc_transport_send (void *arg, const gchar *fcall_str, size_t fcall_len, size_t *ret_len); int ccnetrpc_async_transport_send (void *arg, gchar *fcall_str, size_t fcall_len, void *rpc_priv); #endif /* SEARPC_TRANPORT_H */ ccnet-6.1.5/include/ccnet/cevent.h000066400000000000000000000024521317035602700170020ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * CEvent is used for send message from a work thread to main thread. */ #ifndef CEVENT_H #define CEVENT_H #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #else #include #endif #include #include #ifdef WIN32 #define ccnet_pipe_t intptr_t #else #define ccnet_pipe_t int #endif typedef struct CEvent CEvent; typedef void (*cevent_handler) (CEvent *event, void *handler_data); struct CEvent { uint32_t id; void *data; }; typedef struct CEventManager CEventManager; struct CEventManager { ccnet_pipe_t pipefd[2]; struct event event; GHashTable *handler_table; uint32_t next_id; pthread_mutex_t mutex; }; CEventManager* cevent_manager_new (); int cevent_manager_start (CEventManager *manager); uint32_t cevent_manager_register (CEventManager *manager, cevent_handler handler, void *handler_data); void cevent_manager_unregister (CEventManager *manager, uint32_t id); void cevent_manager_add_event (CEventManager *manager, uint32_t id, void *event_data); #endif ccnet-6.1.5/include/ccnet/invoke-service-proc.h000066400000000000000000000027621317035602700214140ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SERVICE_PROC_H #define CCNET_SERVICE_PROC_H #include #include "processor.h" #define CCNET_TYPE_SERVICE_PROC (ccnet_service_proc_get_type ()) #define CCNET_SERVICE_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SERVICE_PROC, CcnetServiceProc)) #define CCNET_IS_SERVICE_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SERVICE_PROC)) #define CCNET_SERVICE_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SERVICE_PROC, CcnetServiceProcClass)) #define CCNET_IS_SERVICE_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SERVICE_PROC)) #define CCNET_SERVICE_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SERVICE_PROC, CcnetServiceProcClass)) typedef struct _CcnetServiceProc CcnetServiceProc; typedef struct _CcnetServiceProcClass CcnetServiceProcClass; typedef void (*ResponseCB) (const char *code, const char *code_msg, char *content, int clen, void *cb_data); struct _CcnetServiceProc { CcnetProcessor parent_instance; ResponseCB resp_cb; void *cb_data; }; struct _CcnetServiceProcClass { CcnetProcessorClass parent_class; }; GType ccnet_service_proc_get_type (); void ccnet_service_proc_set_response_cb (CcnetServiceProc *proc, ResponseCB resp_cb, void *data); #endif ccnet-6.1.5/include/ccnet/job-mgr.h000066400000000000000000000022321317035602700170470ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /** * Job Manager manages long term jobs. These jobs are run in their * own threads. */ #ifndef JOB_MGR_H #define JOB_MGR_H #include struct _CcnetSession; typedef struct _CcnetJob CcnetJob; typedef struct _CcnetJobManager CcnetJobManager; /* The thread func should return the result back by return (void *)result; The result will be passed to JobDoneCallback. */ typedef void* (*JobThreadFunc)(void *data); typedef void (*JobDoneCallback)(void *result); struct _CcnetJobManager { GHashTable *jobs; GThreadPool *thread_pool; int next_job_id; }; void ccnet_job_cancel (CcnetJob *job); CcnetJobManager * ccnet_job_manager_new (int max_threads); void ccnet_job_manager_free (CcnetJobManager *mgr); int ccnet_job_manager_schedule_job (CcnetJobManager *mgr, JobThreadFunc func, JobDoneCallback done_func, void *data); /** * Wait a specific job to be done. */ void ccnet_job_manager_wait_job (CcnetJobManager *mgr, int job_id); #endif ccnet-6.1.5/include/ccnet/message.h000066400000000000000000000051141317035602700171400ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_MESSAGE_H #define CCNET_MESSAGE_H #include #include #define CCNET_TYPE_MESSAGE (ccnet_message_get_type ()) #define CCNET_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_MESSAGE, CcnetMessage)) #define CCNET_IS_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_MESSAGE)) #define CCNET_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_MESSAGE, CcnetMessageClass)) #define CCNET_IS_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_MESSAGE)) #define CCNET_MESSAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_MESSAGE, CcnetMessageClass)) typedef struct _CcnetMessage CcnetMessage; typedef struct _CcnetMessageClass CcnetMessageClass; #define FLAG_TO_GROUP 0x01 #define FLAG_IS_ERROR 0x02 #define FLAG_WITH_BLOOM 0x04 #define FLAG_IS_ACK 0x08 #define FLAG_IS_RENDEZVOUS 0x10 #define FLAG_TO_USER 0x20 struct _CcnetMessage { GObject parent_instance; char flags; char *id; /* UUID */ char from[41]; char to[41]; int ctime; /* creation time */ int rtime; /* receive time */ char *app; /* application */ char *body; }; struct _CcnetMessageClass { GObjectClass parent_class; }; GType ccnet_message_get_type (void); CcnetMessage* ccnet_message_new (const char *from_id, const char *to_id, const char *app, const char *body, int flags); CcnetMessage* ccnet_message_new_full (const char *from_id, const char *to_id, const char *app, const char *body, time_t ctime, time_t rcv_time, const char *msg_id, int flags); void ccnet_message_free (CcnetMessage *msg); void ccnet_message_to_string_buf (CcnetMessage *msg, GString *buf); CcnetMessage *ccnet_message_from_string (char *buf, int len); gboolean ccnet_message_is_to_group(CcnetMessage *msg); /* to avoid string allocation */ /* inline void ccnet_message_body_take (CcnetMessage *msg, char *body); */ /* inline void ccnet_message_body_dup (CcnetMessage *msg, char *body); */ #endif ccnet-6.1.5/include/ccnet/mqclient-proc.h000066400000000000000000000032401317035602700202670ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_MQCLIENT_PROC_H #define CCNET_MQCLIENT_PROC_H #include #include "processor.h" #include "message.h" #define CCNET_TYPE_MQCLIENT_PROC (ccnet_mqclient_proc_get_type ()) #define CCNET_MQCLIENT_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_MQCLIENT_PROC, CcnetMqclientProc)) #define CCNET_IS_MQCLIENT_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_MQCLIENT_PROC)) #define CCNET_MQCLIENT_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_MQCLIENT_PROC, CcnetMqclientProcClass)) #define CCNET_IS_MQCLIENT_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_MQCLIENT_PROC)) #define CCNET_MQCLIENT_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_MQCLIENT_PROC, CcnetMqclientProcClass)) typedef struct _CcnetMqclientProc CcnetMqclientProc; typedef struct _CcnetMqclientProcClass CcnetMqclientProcClass; typedef void (*MessageGotCB) (CcnetMessage *message, void *data); struct _CcnetMqclientProc { CcnetProcessor parent_instance; MessageGotCB message_got_cb; void *cb_data; }; struct _CcnetMqclientProcClass { CcnetProcessorClass parent_class; }; void ccnet_mqclient_proc_set_message_got_cb (CcnetMqclientProc *, MessageGotCB, void *); GType ccnet_mqclient_proc_get_type (); void ccnet_mqclient_proc_put_message (CcnetMqclientProc *proc, CcnetMessage *message); void ccnet_mqclient_proc_unsubscribe_apps (CcnetMqclientProc *proc); #endif ccnet-6.1.5/include/ccnet/option.h000066400000000000000000000017461317035602700170330ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_OPTION_H #define CCNET_OPTION_H #include #include #ifdef WIN32 static inline char *GetDeafaultDir() { static char buf[128]; static int inited = 0; if (!inited) { const char *home = g_get_home_dir(); inited = 1; snprintf(buf, 128, "%s/ccnet", home); } return buf; } #define DEFAULT_CONFIG_DIR GetDeafaultDir() #define CONFIG_FILE_NAME "ccnet.conf" #define PREFS_FILE_NAME "prefs.conf" #else #define DEFAULT_CONFIG_DIR "~/.ccnet" #define CONFIG_FILE_NAME "ccnet.conf" #define PREFS_FILE_NAME "prefs.conf" #endif #define PEER_KEYFILE "mykey.peer" #define MAX_USERNAME_LEN 20 #define MIN_USERNAME_LEN 2 #define DEFAULT_PORT 10001 #define CHAT_APP "Chat" #define PEERMGR_APP "PeerMgr" #define GROUPMGR_APP "GroupMgr" enum { NET_STATUS_DOWN, NET_STATUS_INNAT, NET_STATUS_FULL }; #endif ccnet-6.1.5/include/ccnet/packet.h000066400000000000000000000015711317035602700167660ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PEER_MSG #define CCNET_PEER_MSG #define CCNET_MSG_OK 0 #define CCNET_MSG_HANDSHAKE 1 #define CCNET_MSG_REQUEST 2 #define CCNET_MSG_RESPONSE 3 #define CCNET_MSG_UPDATE 4 #define CCNET_MSG_RELAY 5 /* NOT USED NOW */ #define CCNET_MSG_ENCPACKET 6 /* an encrypt packet */ typedef struct ccnet_header ccnet_header; struct ccnet_header { uint8_t version; uint8_t type; uint16_t length; /* length of payload */ uint32_t id; /* used as length in ecrypted packet */ }; typedef struct ccnet_packet ccnet_packet; struct ccnet_packet { struct ccnet_header header; char data[0]; }; #define CCNET_PACKET_MAX_PAYLOAD_LEN 65535 #define CCNET_PACKET_LENGTH_HEADER 8 #define CCNET_USER_ID_START 1000 #endif ccnet-6.1.5/include/ccnet/peer.h000066400000000000000000000037571317035602700164620ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PEER_H #define CCNET_PEER_H #include #include #include #define CCNET_TYPE_PEER (ccnet_peer_get_type ()) #define CCNET_PEER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_PEER, CcnetPeer)) #define CCNET_IS_PEER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_PEER)) #define CCNET_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_PEER, CcnetPeerClass)) #define CCNET_IS_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_PEER)) #define CCNET_PEER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_PEER, CcnetPeerClass)) enum { PEER_DOWN, PEER_CONNECTED }; enum { BIND_UNKNOWN, BIND_YES, BIND_NO }; typedef struct _CcnetPeer CcnetPeer; typedef struct _CcnetPeerClass CcnetPeerClass; #define CCNET_PEERID_LEN 40 struct _CcnetPeer { GObject parent_instance; char id[41]; char user_id[41]; gint64 timestamp; char *name; unsigned int is_self : 1; unsigned int can_connect : 1; unsigned int in_local_network : 1; unsigned int in_connection : 1; unsigned int is_ready : 1; unsigned int encrypt_channel : 1; gboolean login_started; char *login_error; gboolean logout_started; char *public_addr; uint16_t public_port; char *service_url; /* http server for relay in seaflie */ char *addr_str; uint16_t port; int net_state; GList *role_list; GList *myrole_list; /* my role on this user */ gint8 bind_status; char *bind_email; char *session_key; }; struct _CcnetPeerClass { GObjectClass parent_class; }; GType ccnet_peer_get_type (void); CcnetPeer* ccnet_peer_new (const char *id); #endif ccnet-6.1.5/include/ccnet/proc-factory.h000066400000000000000000000047261317035602700201340ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PROC_FACTORY_H #define CCNET_PROC_FACTORY_H #include #include "processor.h" #define CCNET_TYPE_PROC_FACTORY (ccnet_proc_factory_get_type ()) #define CCNET_PROC_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_PROC_FACTORY, CcnetProcFactory)) #define CCNET_IS_PROC_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_PROC_FACTORY)) #define CCNET_PROC_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_PROC_FACTORY, CcnetProcFactoryClass)) #define CCNET_IS_PROC_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_PROC_FACTORY)) #define CCNET_PROC_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_PROC_FACTORY, CcnetProcFactoryClass)) typedef struct _CcnetProcFactory CcnetProcFactory; typedef struct _CcnetProcFactoryClass CcnetProcFactoryClass; struct _CcnetProcFactory { GObject parent_instance; /* protected */ CcnetClient *session; }; struct _CcnetProcFactoryClass { GObjectClass parent_class; }; GType ccnet_proc_factory_get_type (void); CcnetProcFactory *ccnet_proc_factory_new (CcnetClient *session); void ccnet_proc_factory_register_processor (CcnetProcFactory *facotry, const char *serv_name, GType proc_type); enum { SLAVE = 0, MASTER = 1, }; CcnetProcessor* ccnet_proc_factory_create_processor (CcnetProcFactory *factory, const char *serv_name, int is_master, int req_id); CcnetProcessor* ccnet_proc_factory_create_master_processor (CcnetProcFactory *factory, const char *serv_name); CcnetProcessor * ccnet_proc_factory_create_remote_master_processor (CcnetProcFactory *factory, const char *serv_name, const char *peer_id); CcnetProcessor * ccnet_proc_factory_create_slave_processor (CcnetProcFactory *factory, const char *serv_name, const char *peer_id, int req_id); void ccnet_proc_factory_recycle(CcnetProcFactory *factory, CcnetProcessor *processor); #endif ccnet-6.1.5/include/ccnet/processor.h000066400000000000000000000134121317035602700175330ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PROCESSOR_H #define CCNET_PROCESSOR_H #include #include #include #include #include #ifdef WIN32 #define ccnet_pipe_t intptr_t #else #define ccnet_pipe_t int #endif struct _CcnetClient; #define CCNET_TYPE_PROCESSOR (ccnet_processor_get_type ()) #define CCNET_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_PROCESSOR, CcnetProcessor)) #define CCNET_IS_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_PROCESSOR)) #define CCNET_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_PROCESSOR, CcnetProcessorClass)) #define CCNET_IS_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_PROCESSOR)) #define CCNET_PROCESSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_PROCESSOR, CcnetProcessorClass)) typedef struct _CcnetProcessor CcnetProcessor; typedef struct _CcnetProcessorClass CcnetProcessorClass; struct _CcnetProcessor { GObject parent_instance; char *peer_id; struct _CcnetClient *session; char *name; /* highest bit = 0, master; highest bit = 1, slave */ uint32_t id; int state; int failure; struct CcnetTimer *timer; int num_retry; /* Set to 1 when handling update or response */ gboolean is_active; /* Internal flags for handling processor thread. */ gboolean thread_running; gboolean delay_shutdown; gboolean was_success; }; enum { STATE_IN_SHUTDOWN = 1 << 8, STATE_RECYCLED, }; enum { PROC_NOTSET, PROC_DONE, PROC_REMOTE_DEAD, PROC_NO_SERVICE, PROC_PERM_ERR, PROC_BAD_RESP, /* code[0] =='5' || '4' */ }; #define SLAVE_MASK 0x80000000 #define REQUEST_ID_MASK 0x7fffffff #define REQUEST_ID(processor_id) ((processor_id) & REQUEST_ID_MASK) #define UPDATE_ID(processor_id) ((processor_id) & REQUEST_ID_MASK) #define RESPONSE_ID(processor_id) ((processor_id) & REQUEST_ID_MASK) #define SLAVE_ID(request_id) ((request_id) | SLAVE_MASK) #define MASTER_ID(request_id) (request_id) #define PRINT_ID(processor_id) ((processor_id) & SLAVE_MASK) ? \ - REQUEST_ID(processor_id) : REQUEST_ID(processor_id) #define IS_SLAVE(processor) ((processor)->id & SLAVE_MASK) #define GET_PNAME(processor) CCNET_PROCESSOR_GET_CLASS(processor)->name struct _CcnetProcessorClass { GObjectClass parent_class; char *name; /* pure virtual function */ int (*start) (CcnetProcessor *processor, int argc, char **argv); void (*handle_update) (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); void (*handle_response) (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); void (*handle_sigchld) (CcnetProcessor *processor, int status); void (*shutdown) (CcnetProcessor *processor); void (*release_resource) (CcnetProcessor *processor); }; GType ccnet_processor_get_type (); int ccnet_processor_start (CcnetProcessor *processor, int argc, char **argv); int ccnet_processor_startl (CcnetProcessor *processor, ...) G_GNUC_NULL_TERMINATED; void ccnet_processor_done (CcnetProcessor *processor, gboolean success); void ccnet_processor_handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); void ccnet_processor_handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); void ccnet_processor_handle_sigchld (CcnetProcessor *processor, int status); void ccnet_processor_send_request (CcnetProcessor *processor, const char *request); void ccnet_processor_send_request_l (CcnetProcessor *processor, ...) G_GNUC_NULL_TERMINATED; void ccnet_processor_send_update(CcnetProcessor *processor, const char *code, const char *code_msg, const char *content, int clen); void ccnet_processor_send_response(CcnetProcessor *processor, const char *code, const char *code_msg, const char *content, int clen); /* The thread func should return the result back by return (void *)result; The result will be passed to ProcThreadDoneFunc. In the done func, the caller should check whether processor->delay_shutdown is TRUE. If it is, you should call processor_done(). */ typedef void* (*ProcThreadFunc)(void *data); typedef void (*ProcThreadDoneFunc)(void *result); struct _CcnetJobManager; /* * @job_mgr: the thread pool to create the worker thread. * If it's NULL, processor->session->job_mgr will be used. */ int ccnet_processor_thread_create (CcnetProcessor *processor, struct _CcnetJobManager *job_mgr, ProcThreadFunc func, ProcThreadDoneFunc done_func, void *data); #endif ccnet-6.1.5/include/ccnet/rpcserver-proc.h000066400000000000000000000022751317035602700204750ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_RPCSERVER_PROC_H #define CCNET_RPCSERVER_PROC_H #include #define CCNET_TYPE_RPCSERVER_PROC (ccnet_rpcserver_proc_get_type ()) #define CCNET_RPCSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_RPCSERVER_PROC, CcnetRpcserverProc)) #define CCNET_IS_RPCSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_RPCSERVER_PROC)) #define CCNET_RPCSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_RPCSERVER_PROC, CcnetRpcserverProcClass)) #define IS_CCNET_RPCSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_RPCSERVER_PROC)) #define CCNET_RPCSERVER_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_RPCSERVER_PROC, CcnetRpcserverProcClass)) typedef struct _CcnetRpcserverProc CcnetRpcserverProc; typedef struct _CcnetRpcserverProcClass CcnetRpcserverProcClass; struct _CcnetRpcserverProc { CcnetProcessor parent_instance; }; struct _CcnetRpcserverProcClass { CcnetProcessorClass parent_class; }; GType ccnet_rpcserver_proc_get_type (); #endif ccnet-6.1.5/include/ccnet/sendcmd-proc.h000066400000000000000000000031711317035602700200730ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_CMD_PROC_H #define CCNET_CMD_PROC_H #include #include "processor.h" #define CCNET_TYPE_SENDCMD_PROC (ccnet_sendcmd_proc_get_type ()) #define CCNET_SENDCMD_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SENDCMD_PROC, CcnetSendcmdProc)) #define CCNET_IS_SENDCMD_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SENDCMD_PROC)) #define CCNET_SENDCMD_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SENDCMD_PROC, CcnetSendcmdProcClass)) #define CCNET_IS_SENDCMD_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SENDCMD_PROC)) #define CCNET_SENDCMD_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SENDCMD_PROC, CcnetSendcmdProcClass)) typedef struct _CcnetSendcmdProc CcnetSendcmdProc; typedef struct _CcnetSendcmdProcClass CcnetSendcmdProcClass; typedef int (*SendcmdProcRcvrspCallback) (const char *code, char *content, int clen, void *data); struct _CcnetSendcmdProc { CcnetProcessor parent_instance; SendcmdProcRcvrspCallback rcvrsp_cb; void *cb_data; }; struct _CcnetSendcmdProcClass { CcnetProcessorClass parent_class; }; GType ccnet_sendcmd_proc_get_type (); int ccnet_sendcmd_proc_send_command (CcnetSendcmdProc *proc, const char *cmd); void ccnet_sendcmd_proc_set_rcvrsp_cb (CcnetSendcmdProc *proc, SendcmdProcRcvrspCallback rcvrsp_cb, void *data); #endif ccnet-6.1.5/include/ccnet/status-code.h000066400000000000000000000036371317035602700177570ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef STATUS_CODE_H #define STATUS_CODE_H /* SC: Status Code. SS: Status String */ /* Error Code for use in GError */ #define EC_NETWORK_ERR 1 #define ES_NETWORK_ERR "Network Error" #define SC_PROC_KEEPALIVE "100" #define SS_PROC_KEEPALIVE "processor keep alive" #define SC_PROC_ALIVE "101" #define SS_PROC_ALIVE "processor is alive" #define SC_PROC_DEAD "102" #define SS_PROC_DEAD "processor is dead" #define SC_PROC_DONE "103" #define SS_PROC_DONE "service is done" #define SC_OK "200" #define SS_OK "OK" #define SC_PERM_CHECKING "250" #define SS_PERM_CHECKING "Permission Checking" #define SC_SHUTDOWN "500" #define SS_SHUTDOWN "Shutdown" #define SC_CREATE_PROC_ERR "501" #define SS_CREATE_PROC_ERR "Create Processor Error" #define SC_BAD_PEER "502" #define SS_BAD_PEER "Bad peer id" #define SC_BAD_USER "502" #define SS_BAD_USER "Bad user id" #define SC_BAD_ARGS "503" #define SS_BAD_ARGS "Bad arguments" #define SC_PERM_ERR "504" #define SS_PERM_ERR "Permission Error" #define SC_BAD_UPDATE_CODE "506" #define SS_BAD_UPDATE_CODE "Bad update code" #define SC_BAD_RESPONSE_CODE "507" #define SS_BAD_RESPONSE_CODE "Bad response code" #define SC_VERSION_MISMATCH "508" #define SS_VERSION_MISMATCH "Version Mismatch" #define SC_UNKNOWN_PEER "510" #define SS_UNKNOWN_PEER "Unknown peer" #define SC_UNKNOWN_SERVICE "511" #define SS_UNKNOWN_SERVICE "Unknown service" #define SC_UNKNOWN_SERVICE_IN_PERM "511" #define SS_UNKNOWN_SERVICE_IN_PERM "Unknown service in permission check" #define SC_PEER_UNREACHABLE "512" #define SS_PEER_UNREACHABLE "Peer Unreachable" #define SC_CON_TIMEOUT "513" #define SS_CON_TIMEOUT "connection timeout" #define SC_KEEPALIVE_TIMEOUT "514" #define SS_KEEPALIVE_TIMEOUT "keepalive timeout" #define SC_NETDOWN "515" #define SS_NETDOWN "peer down" #define SC_SERV_EXISTED "516" #define SS_SERV_EXISTED "The service existed" #endif ccnet-6.1.5/include/ccnet/threaded-rpcserver-proc.h000066400000000000000000000026141317035602700222500ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_THREADED_RPCSERVER_PROC_H #define CCNET_THREADED_RPCSERVER_PROC_H #include #define CCNET_TYPE_THREADED_RPCSERVER_PROC (ccnet_threaded_rpcserver_proc_get_type ()) #define CCNET_THREADED_RPCSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_THREADED_RPCSERVER_PROC, CcnetThreadedRpcserverProc)) #define CCNET_IS_THREADED_RPCSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_THREADED_RPCSERVER_PROC)) #define CCNET_THREADED_RPCSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_THREADED_RPCSERVER_PROC, CcnetThreadedRpcserverProcClass)) #define IS_CCNET_THREADED_RPCSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_THREADED_RPCSERVER_PROC)) #define CCNET_THREADED_RPCSERVER_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_THREADED_RPCSERVER_PROC, CcnetThreadedRpcserverProcClass)) typedef struct _CcnetThreadedRpcserverProc CcnetThreadedRpcserverProc; typedef struct _CcnetThreadedRpcserverProcClass CcnetThreadedRpcserverProcClass; struct _CcnetThreadedRpcserverProc { CcnetProcessor parent_instance; }; struct _CcnetThreadedRpcserverProcClass { CcnetProcessorClass parent_class; }; GType ccnet_threaded_rpcserver_proc_get_type (); #endif ccnet-6.1.5/include/ccnet/timer.h000066400000000000000000000014011317035602700166270ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_TIMER_H #define CCNET_TIMER_H /* return TRUE to reschedule the timer, return FALSE to cancle the timer */ typedef int (*TimerCB) (void *data); struct CcnetTimer; typedef struct CcnetTimer CcnetTimer; /** * Calls timer_func(user_data) after the specified interval. * The timer is freed if timer_func returns zero. * Otherwise, it's called again after the same interval. */ CcnetTimer* ccnet_timer_new (TimerCB func, void *user_data, uint64_t timeout_milliseconds); /** * Frees a timer and sets the timer pointer to NULL. */ void ccnet_timer_free (CcnetTimer **timer); #endif ccnet-6.1.5/include/ccnet/valid-check.h000066400000000000000000000010451317035602700176650ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef VALID_CHECK_H #define VALID_CHECK_H #include inline static gboolean user_id_valid(const char *id) { if (!id || strlen(id) != 40) return FALSE; return TRUE; } inline static gboolean peer_id_valid(const char *id) { if (!id || strlen(id) != 40) return FALSE; return TRUE; } gboolean is_uuid_valid (const char *uuid_str); inline static gboolean group_id_valid(const char *id) { return is_uuid_valid(id); } #endif ccnet-6.1.5/lib/000077500000000000000000000000001317035602700133715ustar00rootroot00000000000000ccnet-6.1.5/lib/Makefile.am000066400000000000000000000047331317035602700154340ustar00rootroot00000000000000 AM_CPPFLAGS = @GLIB2_CFLAGS@ -I$(top_srcdir)/include \ -I$(top_srcdir)/include/ccnet \ -I$(top_srcdir)/lib \ -I$(top_builddir)/include \ -DG_LOG_DOMAIN=\"Ccnet\" \ @SEARPC_CFLAGS@ \ @MSVC_CFLAGS@ \ -Wall BUILT_SOURCES = gensource lib_LTLIBRARIES = libccnet.la noinst_HEADERS = buffer.h \ packet-io.h \ include.h \ marshal.h \ peer-common.h \ string-util.h \ libccnet_utils.h \ ccnet-object.h \ rpc-common.h \ net.h \ utils.h \ db.h \ rsa.h ccnetincludedir = $(includedir)/ccnet ccnetinclude_DATA = ccnet-object.h libccnet_la_CPPFLAGS = $(AM_CPPFLAGS) -DCCNET_LIB @PTHREAD_CFLAGS@ libccnet_la_SOURCES = ccnet-client.c packet-io.c libccnet_utils.c \ message.c proc-factory.c \ processor.c buffer.c \ peer.c sendcmd-proc.c \ mqclient-proc.c invoke-service-proc.c \ marshal.c \ mainloop.c cevent.c timer.c ccnet-session-base.c job-mgr.c \ rpcserver-proc.c ccnetrpc-transport.c threaded-rpcserver-proc.c \ ccnetobj.c \ async-rpc-proc.c ccnet-rpc-wrapper.c \ client-pool.c EXTRA_DIST = ccnetobj.vala rpc_table.py libccnet_la_LDFLAGS = -no-undefined -version-info 0:0:0 libccnet_la_LIBADD = @PTHREAD_LIBS@ @GLIB2_LIBS@ @GOBJECT_LIBS@ @LIB_GDI32@ \ @LIB_UUID@ @LIB_WS32@ @LIB_PSAPI@ -lsqlite3 \ @LIBEVENT_LIBS@ @SEARPC_LIBS@ @LIB_SHELL32@ noinst_LTLIBRARIES = libccnetd.la libccnetd_la_SOURCES = utils.c db.c job-mgr.c \ rsa.c marshal.c net.c timer.c ccnet-session-base.c \ ccnetobj.c libccnetd_la_LDFLAGS = -no-undefined libccnetd_la_LIBADD = @GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_GDI32@ \ -lsqlite3 @LIBEVENT_LIBS@ @LIB_WS32@ @LIB_UUID@ \ @LIB_SHELL32@ @LIB_PSAPI@ @SEARPC_LIBS@ ccnet_object_define = ccnetobj.vala valac_gen = ccnetobj.c ccnet-object.h ccnet-client.c: ccnet-object.h ccnet-object.h: ${ccnet_object_define} rm -f $@ valac --pkg posix ${ccnet_object_define} -C -H ccnet-object.h ccnetobj.c: ${ccnet_object_define} rm -f $@ valac -C --pkg posix ${ccnet_object_define} searpc_gen = searpc-signature.h searpc-marshal.h gensource: ${searpc_gen} ${valac_gen} rpc_table.stamp: ${top_srcdir}/lib/rpc_table.py @rm -f rpc_table.tmp @touch rpc_table.tmp @echo "[libsearpc]: generating rpc header files" @PYTHON@ `which searpc-codegen.py` ${top_srcdir}/lib/rpc_table.py @echo "[libsearpc]: done" @mv -f rpc_table.tmp $@ ${searpc_gen}: rpc_table.stamp clean-local: rm -f ${searpc_gen} rm -f rpc_table.pyc rm -f rpc_table.stamp rm -f rpc_table.tmp rm -f ${valac_gen} CLEANFILES = ${searpc_gen} ${valac_gen} ccnet-6.1.5/lib/async-rpc-proc.c000066400000000000000000000100551317035602700163760ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include #include #include "rpc-common.h" #include #define MAX_RET_LEN 5242880 /* 5M */ typedef struct { const char *service; char *fcall_str; size_t fcall_len; void *rpc_priv; GString *buf; } CcnetAsyncRpcProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_ASYNC_RPC_PROC, CcnetAsyncRpcProcPriv)) G_DEFINE_TYPE (CcnetAsyncRpcProc, ccnet_async_rpc_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { CcnetAsyncRpcProcPriv *priv = GET_PRIV (processor); g_free (priv->fcall_str); CCNET_PROCESSOR_CLASS (ccnet_async_rpc_proc_parent_class)->release_resource (processor); } static void ccnet_async_rpc_proc_class_init (CcnetAsyncRpcProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->start = start; proc_class->handle_response = handle_response; proc_class->release_resource = release_resource; proc_class->name = "async-rpc-proc"; g_type_class_add_private (klass, sizeof(CcnetAsyncRpcProcPriv)); } static void ccnet_async_rpc_proc_init (CcnetAsyncRpcProc *processor) { } void ccnet_async_rpc_proc_set_rpc (CcnetAsyncRpcProc *proc, const char *service, char *fcall_str, size_t fcall_len, void *rpc_priv) { CcnetAsyncRpcProcPriv *priv = GET_PRIV (proc); priv->service = service; priv->fcall_str = fcall_str; priv->fcall_len = fcall_len; priv->rpc_priv = rpc_priv; } static int start (CcnetProcessor *processor, int argc, char **argv) { CcnetAsyncRpcProcPriv *priv = GET_PRIV (processor); char buf[256]; if (argc != 0) { ccnet_processor_done (processor, FALSE); return -1; } if (processor->peer_id) { snprintf (buf, sizeof(buf), "remote %s %s", processor->peer_id, priv->service); } else snprintf (buf, sizeof(buf), "%s", priv->service); ccnet_processor_send_request (processor, buf); return 0; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetAsyncRpcProcPriv *priv = GET_PRIV (processor); if (memcmp (code, SC_OK, 3) == 0) { ccnet_processor_send_update (processor, SC_CLIENT_CALL, SS_CLIENT_CALL, priv->fcall_str, priv->fcall_len); return; } if (memcmp (code, SC_SERVER_RET, 3) == 0) { if (priv->buf == NULL) searpc_client_generic_callback (content, clen, priv->rpc_priv, NULL); else { g_string_append_len (priv->buf, content, clen); searpc_client_generic_callback (priv->buf->str, priv->buf->len, priv->rpc_priv, NULL); g_string_free (priv->buf, TRUE); priv->buf = NULL; } ccnet_processor_done (processor, TRUE); } else if (memcmp (code, SC_SERVER_MORE, 3) == 0) { if (priv->buf == NULL) priv->buf = g_string_new (NULL); g_string_append_len (priv->buf, content, clen); if (priv->buf->len > MAX_RET_LEN) { g_warning ("[async-rpc] ret is too long\n"); g_string_free (priv->buf, TRUE); priv->buf = NULL; ccnet_processor_send_update (processor, "400", "Too many data", NULL, 0); ccnet_processor_done (processor, FALSE); } else ccnet_processor_send_update ( processor, SC_CLIENT_MORE, SS_CLIENT_MORE, NULL, 0); } } ccnet-6.1.5/lib/buffer.c000066400000000000000000000210711317035602700150070ustar00rootroot00000000000000/* * Copyright (c) 2002, 2003 Niels Provos * 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. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #include #endif #ifdef HAVE_VASPRINTF /* If we have vasprintf, we need to define this before we include stdio.h. */ #define _GNU_SOURCE #endif #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #include #include #include #include #include #ifdef HAVE_STDARG_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include "buffer.h" struct buffer * buffer_new(void) { struct buffer *buffer; buffer = calloc(1, sizeof(struct buffer)); return (buffer); } void buffer_free(struct buffer *buffer) { if (buffer->orig_buffer != NULL) free(buffer->orig_buffer); free(buffer); } /* * This is a destructive add. The data from one buffer moves into * the other buffer. */ #define SWAP(x,y) do { \ (x)->buffer = (y)->buffer; \ (x)->orig_buffer = (y)->orig_buffer; \ (x)->misalign = (y)->misalign; \ (x)->totallen = (y)->totallen; \ (x)->off = (y)->off; \ } while (0) int buffer_add_buffer(struct buffer *outbuf, struct buffer *inbuf) { int res; /* Short cut for better performance */ if (outbuf->off == 0) { struct buffer tmp; size_t oldoff = inbuf->off; /* Swap them directly */ SWAP(&tmp, outbuf); SWAP(outbuf, inbuf); SWAP(inbuf, &tmp); /* * Optimization comes with a price; we need to notify the * buffer if necessary of the changes. oldoff is the amount * of data that we transfered from inbuf to outbuf */ if (inbuf->off != oldoff && inbuf->cb != NULL) (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg); if (oldoff && outbuf->cb != NULL) (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg); return (0); } res = buffer_add(outbuf, inbuf->buffer, inbuf->off); if (res == 0) { /* We drain the input buffer on success */ buffer_drain(inbuf, inbuf->off); } return (res); } /* Reads data from an event buffer and drains the bytes read */ int buffer_remove(struct buffer *buf, void *data, size_t datlen) { size_t nread = datlen; if (nread >= buf->off) nread = buf->off; memcpy(data, buf->buffer, nread); buffer_drain(buf, nread); return (nread); } /* * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'. * The returned buffer needs to be freed by the called. */ char * buffer_readline(struct buffer *buffer) { u_char *data = BUFFER_DATA(buffer); size_t len = BUFFER_LENGTH(buffer); char *line; unsigned int i; for (i = 0; i < len; i++) { if (data[i] == '\r' || data[i] == '\n') break; } if (i == len) return (NULL); if ((line = malloc(i + 1)) == NULL) { fprintf(stderr, "%s: out of memory\n", __func__); buffer_drain(buffer, i); return (NULL); } memcpy(line, data, i); line[i] = '\0'; /* * Some protocols terminate a line with '\r\n', so check for * that, too. */ if ( i < len - 1 ) { char fch = data[i], sch = data[i+1]; /* Drain one more character if needed */ if ( (sch == '\r' || sch == '\n') && sch != fch ) i += 1; } buffer_drain(buffer, i + 1); return (line); } /* Adds data to an event buffer */ static void buffer_align(struct buffer *buf) { memmove(buf->orig_buffer, buf->buffer, buf->off); buf->buffer = buf->orig_buffer; buf->misalign = 0; } /* Expands the available space in the event buffer to at least datlen */ int buffer_expand(struct buffer *buf, size_t datlen) { size_t need = buf->misalign + buf->off + datlen; /* If we can fit all the data, then we don't have to do anything */ if (buf->totallen >= need) return (0); /* * If the misalignment fulfills our data needs, we just force an * alignment to happen. Afterwards, we have enough space. */ if (buf->misalign >= datlen) { buffer_align(buf); } else { void *newbuf; size_t length = buf->totallen; if (length < 256) length = 256; while (length < need) length <<= 1; if (buf->orig_buffer != buf->buffer) buffer_align(buf); if ((newbuf = realloc(buf->buffer, length)) == NULL) return (-1); buf->orig_buffer = buf->buffer = newbuf; buf->totallen = length; } return (0); } int buffer_add(struct buffer *buf, const void *data, size_t datlen) { size_t need = buf->misalign + buf->off + datlen; size_t oldoff = buf->off; if (buf->totallen < need) { if (buffer_expand(buf, datlen) == -1) return (-1); } memcpy(buf->buffer + buf->off, data, datlen); buf->off += datlen; if (datlen && buf->cb != NULL) (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); return (0); } void buffer_drain(struct buffer *buf, size_t len) { size_t oldoff = buf->off; if (len >= buf->off) { buf->off = 0; buf->buffer = buf->orig_buffer; buf->misalign = 0; goto done; } buf->buffer += len; buf->misalign += len; buf->off -= len; done: /* Tell someone about changes in this buffer */ if (buf->off != oldoff && buf->cb != NULL) (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); } /* * Reads data from a file descriptor into a buffer. */ #define BUFFER_MAX_READ 4096 int buffer_read(struct buffer *buf, int fd, int howmuch) { u_char *p; size_t oldoff = buf->off; int n = BUFFER_MAX_READ; #if defined(FIONREAD) #ifdef WIN32 unsigned long lng = n; if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) == 0) { #else if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) { #endif n = BUFFER_MAX_READ; } else if (n > BUFFER_MAX_READ && n > howmuch) { /* * It's possible that a lot of data is available for * reading. We do not want to exhaust resources * before the reader has a chance to do something * about it. If the reader does not tell us how much * data we should read, we artifically limit it. */ if (n > buf->totallen << 2) n = buf->totallen << 2; if (n < BUFFER_MAX_READ) n = BUFFER_MAX_READ; } #endif if (howmuch < 0 || howmuch > n) howmuch = n; /* If we don't have FIONREAD, we might waste some space here */ if (buffer_expand(buf, howmuch) == -1) return (-1); /* We can append new data at this point */ p = buf->buffer + buf->off; #ifndef WIN32 n = read(fd, p, howmuch); #else n = recv(fd, (char *)p, howmuch, 0); #endif if (n == -1) return (-1); if (n == 0) return (0); buf->off += n; /* Tell someone about changes in this buffer */ if (buf->off != oldoff && buf->cb != NULL) (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); return (n); } int buffer_write(struct buffer *buffer, int fd) { int n; #ifndef WIN32 n = write(fd, buffer->buffer, buffer->off); #else n = send(fd, (char *)buffer->buffer, buffer->off, 0); #endif if (n == -1) return (-1); if (n == 0) return (0); buffer_drain(buffer, n); return (n); } u_char * buffer_find(struct buffer *buffer, const u_char *what, size_t len) { u_char *search = buffer->buffer, *end = search + buffer->off; u_char *p; while (search < end && (p = memchr(search, *what, end - search)) != NULL) { if (p + len > end) break; if (memcmp(p, what, len) == 0) return (p); search = p + 1; } return (NULL); } void buffer_setcb(struct buffer *buffer, void (*cb)(struct buffer *, size_t, size_t, void *), void *cbarg) { buffer->cb = cb; buffer->cbarg = cbarg; } ccnet-6.1.5/lib/buffer.h000066400000000000000000000117001317035602700150120ustar00rootroot00000000000000#ifndef BUFFER_H #define BUFFER_H #include #ifdef WIN32 typedef unsigned char u_char; typedef unsigned short u_short; #endif struct buffer { u_char *buffer; u_char *orig_buffer; size_t misalign; size_t totallen; size_t off; void (*cb)(struct buffer *, size_t, size_t, void *); void *cbarg; }; /* Just for error reporting - use other constants otherwise */ #define BUFFER_READ 0x01 #define BUFFER_WRITE 0x02 #define BUFFER_EOF 0x10 #define BUFFER_ERROR 0x20 #define BUFFER_TIMEOUT 0x40 #define BUFFER_LENGTH(x) (x)->off #define BUFFER_DATA(x) (x)->buffer #define BUFFER_INPUT(x) (x)->input #define BUFFER_OUTPUT(x) (x)->output /** Allocate storage for a new buffer. @return a pointer to a newly allocated buffer struct, or NULL if an error occurred */ struct buffer *buffer_new(void); /** Deallocate storage for an buffer. @param pointer to the buffer to be freed */ void buffer_free(struct buffer *); /** Expands the available space in an event buffer. Expands the available space in the event buffer to at least datlen @param buf the event buffer to be expanded @param datlen the new minimum length requirement @return 0 if successful, or -1 if an error occurred */ int buffer_expand(struct buffer *, size_t); /** Append data to the end of an buffer. @param buf the event buffer to be appended to @param data pointer to the beginning of the data buffer @param datlen the number of bytes to be copied from the data buffer */ int buffer_add(struct buffer *, const void *, size_t); /** Read data from an event buffer and drain the bytes read. @param buf the event buffer to be read from @param data the destination buffer to store the result @param datlen the maximum size of the destination buffer @return the number of bytes read */ int buffer_remove(struct buffer *, void *, size_t); /** * Read a single line from an event buffer. * * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'. * The returned buffer needs to be freed by the caller. * * @param buffer the buffer to read from * @return pointer to a single line, or NULL if an error occurred */ char *buffer_readline(struct buffer *); /** Move data from one buffer into another buffer. This is a destructive add. The data from one buffer moves into the other buffer. The destination buffer is expanded as needed. @param outbuf the output buffer @param inbuf the input buffer @return 0 if successful, or -1 if an error occurred */ int buffer_add_buffer(struct buffer *, struct buffer *); /** Append a formatted string to the end of an buffer. @param buf the buffer that will be appended to @param fmt a format string @param ... arguments that will be passed to printf(3) @return The number of bytes added if successful, or -1 if an error occurred. */ int buffer_add_printf(struct buffer *, const char *fmt, ...) #ifdef __GNUC__ __attribute__((format(printf, 2, 3))) #endif ; /** Append a va_list formatted string to the end of an buffer. @param buf the buffer that will be appended to @param fmt a format string @param ap a varargs va_list argument array that will be passed to vprintf(3) @return The number of bytes added if successful, or -1 if an error occurred. */ int buffer_add_vprintf(struct buffer *, const char *fmt, va_list ap); /** Remove a specified number of bytes data from the beginning of an buffer. @param buf the buffer to be drained @param len the number of bytes to drain from the beginning of the buffer @return 0 if successful, or -1 if an error occurred */ void buffer_drain(struct buffer *, size_t); /** Write the contents of an buffer to a file descriptor. The buffer will be drained after the bytes have been successfully written. @param buffer the buffer to be written and drained @param fd the file descriptor to be written to @return the number of bytes written, or -1 if an error occurred @see buffer_read() */ int buffer_write(struct buffer *, int); /** Read from a file descriptor and store the result in an buffer. @param buf the buffer to store the result @param fd the file descriptor to read from @param howmuch the number of bytes to be read @return the number of bytes read, or -1 if an error occurred @see buffer_write() */ int buffer_read(struct buffer *, int, int); /** Find a string within an buffer. @param buffer the buffer to be searched @param what the string to be searched for @param len the length of the search string @return a pointer to the beginning of the search string, or NULL if the search failed. */ u_char *buffer_find(struct buffer *, const u_char *, size_t); /** Set a callback to invoke when the buffer is modified. @param buffer the buffer to be monitored @param cb the callback function to invoke when the buffer is modified @param cbarg an argument to be provided to the callback function */ void buffer_setcb(struct buffer *, void (*)(struct buffer *, size_t, size_t, void *), void *); #endif ccnet-6.1.5/lib/buildin-types.c.template000066400000000000000000000014451317035602700201430ustar00rootroot00000000000000/*** BEGIN file-header ***/ #include #include #include /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) { static GType etype = 0; if (G_UNLIKELY(etype == 0)) { static const G@Type@Value values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); } return etype; } /*** END value-tail ***/ /*** BEGIN file-tail ***/ /*** END file-tail ***/ ccnet-6.1.5/lib/ccnet-client.c000066400000000000000000000614451317035602700161170ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "option.h" #include "include.h" #include #include #include #ifdef WIN32 #include #include #include #else #include #include #include #include #include #endif #include "message.h" #include "processor.h" #include "packet-io.h" #include "peer.h" #include "ccnet-client.h" #include "proc-factory.h" #include "job-mgr.h" #include "ccnet-object.h" /** * SECTION:ccnet-client * @short_description: The basic class to interact with the ccnet daemon * @title: CcnetClient * @include: ccnet.h * * CcnetClient is the basic class to interact with the ccnet daemon. * CcnetClient can work in two different mode, i.e., CCNET_CLIENT_SYNC * and CCNET_CLIENT_ASYNC (See #CcnetClientMode). The two modes have * different sets of APIs. * */ G_DEFINE_TYPE (CcnetClient, ccnet_client, CCNET_TYPE_SESSION_BASE); static void handle_packet (ccnet_packet *packet, void *vclient); static void ccnet_client_free (GObject *object); static void free_rpc_pool (CcnetClient *client); static void set_property (GObject *object, guint property_id, const GValue *v, GParamSpec *pspec) { /* CcnetClient *client = CCNET_CLIENT (object); */ switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); return; } } static void get_property (GObject *object, guint property_id, GValue *v, GParamSpec *pspec) { /* CcnetClient *client = CCNET_CLIENT (object); */ switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ccnet_client_class_init (CcnetClientClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = set_property; gobject_class->get_property = get_property; gobject_class->finalize = ccnet_client_free; /* ccnet_object_init (); */ } static void ccnet_client_init (CcnetClient *client) { client->connfd = -1; client->req_id = CCNET_USER_ID_START; client->processors = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); client->proc_factory = ccnet_proc_factory_new (client); /* job_mgr should be created by user, so that max_thread can * be chosen properly. */ } CcnetClient* ccnet_client_new (void) { return g_object_new (CCNET_TYPE_CLIENT, NULL); } static void ccnet_client_free (GObject *object) { CcnetClient *client = CCNET_CLIENT (object); if (client->io) ccnet_client_disconnect_daemon (client); if (client->config_dir) free (client->config_dir); g_free (client->config_file); if (client->proc_factory) g_object_unref (client->proc_factory); if (client->job_mgr) ccnet_job_manager_free (client->job_mgr); if (client->processors) g_hash_table_destroy (client->processors); free_rpc_pool (client); G_OBJECT_CLASS(ccnet_client_parent_class)->finalize (object); } int ccnet_client_load_confdir (CcnetClient *client, const char *central_config_dir_r, const char *config_dir_r) { char *config_file = NULL, *config_dir = NULL, *central_config_dir = NULL; char *id = NULL, *name = NULL, *port_str = NULL, *un_path = NULL, *user_name = NULL, *service_url = NULL; unsigned char sha1[20]; GKeyFile *key_file; CcnetSessionBase *base = CCNET_SESSION_BASE(client); config_dir = ccnet_util_expand_path (config_dir_r); if (ccnet_util_checkdir(config_dir) < 0) { g_warning ("Config dir %s does not exist or is not " "a directory.\n", config_dir); return -1; } if (central_config_dir_r) { central_config_dir = ccnet_util_expand_path (central_config_dir_r); if (ccnet_util_checkdir(config_dir) < 0) { g_warning ("Server config dir %s does not exist or is not " "a directory.\n", central_config_dir); return -1; } } config_file = g_strconcat(central_config_dir ? central_config_dir : config_dir, "/", SESSION_CONFIG_FILENAME, NULL); ccnet_debug ("using config file %s\n", config_file); key_file = g_key_file_new(); if (!g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) { g_warning ("Can't load config file %s.\n", config_file); goto onerror; } id = ccnet_util_key_file_get_string (key_file, "General", "ID"); user_name = ccnet_util_key_file_get_string (key_file, "General", "USER_NAME"); name = ccnet_util_key_file_get_string (key_file, "General", "NAME"); service_url = ccnet_util_key_file_get_string (key_file, "General", "SERVICE_URL"); port_str = ccnet_util_key_file_get_string (key_file, "Client", "PORT"); un_path = ccnet_util_key_file_get_string (key_file, "Client", "UNIX_SOCKET"); if ( (id == NULL) || (strlen (id) != SESSION_ID_LENGTH) || (ccnet_util_hex_to_sha1 (id, sha1) < 0) ) { ccnet_error ("Wrong ID\n"); g_key_file_free (key_file); goto onerror; } memcpy (base->id, id, 40); base->id[40] = '\0'; base->user_name = g_strdup(user_name); base->name = g_strdup(name); memcpy (base->id_sha1, sha1, 20); if (service_url) base->service_url = g_strdup(service_url); client->config_file = g_strdup(config_file); client->config_dir = config_dir; client->central_config_dir = central_config_dir; if (port_str) client->daemon_port = atoi (port_str); client->un_path = un_path; g_free (id); g_free (name); g_free (user_name); g_free (port_str); g_free (config_file); g_free (service_url); g_key_file_free (key_file); return 0; onerror: g_free (id); g_free (name); g_free (user_name); g_free (port_str); g_free (config_file); g_free (service_url); return -1; } int ccnet_client_connect_daemon (CcnetClient *client, CcnetClientMode mode) { evutil_socket_t sockfd; /* CcnetProcessor *processor; */ #ifdef WIN32 static int inited = 0; if (inited == 0) { inited = 1; WSADATA wsadata; WSAStartup(0x0101, &wsadata); } #endif g_return_val_if_fail (client->connected == 0, -1); client->mode = mode; #ifdef WIN32 sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in servaddr; memset (&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons (client->daemon_port); ccnet_util_inet_pton (AF_INET, "127.0.0.1", &servaddr.sin_addr); if (connect (sockfd, (struct sockaddr *) &servaddr, (socklen_t)sizeof(servaddr)) < 0) return -1; #else char *un_path = NULL; sockfd = socket(AF_UNIX, SOCK_STREAM, 0); struct sockaddr_un servaddr; servaddr.sun_family = AF_UNIX; if (!client->un_path) un_path = g_build_filename (client->config_dir, CCNET_PIPE_NAME, NULL); else un_path = g_strdup(client->un_path); g_strlcpy (servaddr.sun_path, un_path, sizeof(servaddr.sun_path)); g_free (un_path); if (connect(sockfd, (struct sockaddr *)&servaddr, (socklen_t)sizeof(servaddr)) < 0) { return -1; } #endif client->connfd = sockfd; client->io = ccnet_packet_io_new (client->connfd); if (mode == CCNET_CLIENT_ASYNC) ccnet_packet_io_set_callback (client->io, handle_packet, client); client->connected = 1; g_debug ("connected to daemon\n"); return client->connfd; } void ccnet_client_run_synchronizer (CcnetClient *client) { g_return_if_fail(client->mode == CCNET_CLIENT_ASYNC); } int ccnet_client_disconnect_daemon (CcnetClient *client) { ccnet_packet_io_free (client->io); client->io = NULL; client->connfd = -1; client->connected = 0; free_rpc_pool (client); return 0; } uint32_t ccnet_client_get_request_id (CcnetClient *client) { return (++client->req_id); } typedef struct RpcPoolItem { uint32_t req_id; char *peer_id; char *service; } RpcPoolItem; static void free_rpc_pool_item (RpcPoolItem *item) { g_free (item->peer_id); g_free (item->service); g_free (item); } static void free_rpc_pool (CcnetClient *client) { GList *ptr; for (ptr = client->rpc_pool; ptr; ptr = ptr->next) { RpcPoolItem *item = ptr->data; free_rpc_pool_item (item); } g_list_free (client->rpc_pool); client->rpc_pool = NULL; } static RpcPoolItem * get_pool_item (CcnetClient *client, const char *peer_id, const char *service) { GList *ptr; for (ptr = client->rpc_pool; ptr; ptr = ptr->next) { RpcPoolItem *item = ptr->data; if (g_strcmp0(peer_id, item->peer_id) == 0 && g_strcmp0(service, item->service) == 0) return item; } return NULL; } static uint32_t start_request (CcnetClient *client, const char *peer_id, const char *service) { uint32_t req_id = ccnet_client_get_request_id (client); char buf[512]; if (!peer_id) snprintf (buf, 512, "%s", service); else snprintf (buf, 512, "remote %s %s", peer_id, service); ccnet_client_send_request (client, req_id, buf); if (ccnet_client_read_response (client) < 0) { g_warning ("[RPC] failed to read response.\n"); return 0; } if (memcmp (client->response.code, "200", 3) != 0) { g_warning ("[RPC] failed to start rpc server: %s %s.\n", client->response.code, client->response.code_msg); return 0; } return req_id; } uint32_t ccnet_client_get_rpc_request_id (CcnetClient *client, const char *peer_id, const char *service) { RpcPoolItem *item = get_pool_item (client, peer_id, service); if (item) return item->req_id; uint32_t req_id = start_request (client, peer_id, service); if (req_id == 0) return 0; item = g_new0 (RpcPoolItem, 1); item->req_id = req_id; item->peer_id = g_strdup (peer_id); item->service = g_strdup (service); client->rpc_pool = g_list_prepend (client->rpc_pool, item); return req_id; } void ccnet_client_clean_rpc_request (CcnetClient *client, uint32_t req_id) { GList *ptr; RpcPoolItem *target = NULL; for (ptr = client->rpc_pool; ptr; ptr = ptr->next) { RpcPoolItem *item = ptr->data; if (req_id == item->req_id) target = item; } if (!target) return; client->rpc_pool = g_list_remove (client->rpc_pool, target); free_rpc_pool_item (target); } /* functions used in ASYNC mode */ void ccnet_client_add_processor (CcnetClient *client, CcnetProcessor *processor) { int *key = g_new0 (int, 1); *key = processor->id; g_hash_table_insert (client->processors, key, processor); } void ccnet_client_remove_processor (CcnetClient *client, CcnetProcessor *processor) { g_hash_table_remove (client->processors, &processor->id); } CcnetProcessor * ccnet_client_get_processor (CcnetClient *client, int id) { return g_hash_table_lookup (client->processors, &id); } int ccnet_client_read_input (CcnetClient *client) { if (!client->io) return -1; return ccnet_packet_io_read(client->io); } static void create_processor (CcnetClient *client, int req_id, int argc, char **argv) { CcnetProcessor *processor; CcnetProcFactory *factory = client->proc_factory; char *peer_id; if (strcmp(argv[0], "remote") == 0) { peer_id = argv[1]; argc -= 2; argv += 2; } else peer_id = client->base.id; processor = ccnet_proc_factory_create_slave_processor ( factory, argv[0], peer_id, req_id); if (processor) { ccnet_processor_start (processor, argc-1, argv+1); } else ccnet_client_send_response (client, req_id, SC_CREATE_PROC_ERR, SS_CREATE_PROC_ERR, NULL, 0); } #if 0 void ccnet_client_send_event (CcnetClient *client, GObject *event) { if (!event) return; CcnetProcessor *processor = NULL; processor = ccnet_proc_factory_create_master_processor (client->proc_factory, "send-event"); ccnet_sendevent_proc_set_event (CCNET_SENDEVENT_PROC(processor), (CcnetEvent *)event); ccnet_processor_start (processor, 0, NULL); } #endif static void handle_request (CcnetClient *client, int req_id, char *data, int len) { char *msg; gchar **commands; gchar **pcmd; int i; /* TODO: remove string copy */ g_return_if_fail (len >= 1); msg = g_malloc (len+1); memcpy (msg, data, len); msg[len] = '\0'; commands = g_strsplit_set (msg, " \t", 10); for (i=0, pcmd = commands; *pcmd; pcmd++) i++; g_free (msg); create_processor (client, req_id, i, commands); g_strfreev (commands); } static void handle_response (CcnetClient *client, int req_id, char *data, int len) { CcnetProcessor *processor; char *code, *code_msg = 0, *content = 0; int clen; char *ptr, *end; g_return_if_fail (len >= 4); code = data; ptr = data + 3; if (*ptr == '\n') { /* no code_msg */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); goto parsed; } if (*ptr != ' ') goto error; *ptr++ = '\0'; code_msg = ptr; end = data + len; for (ptr = data; *ptr != '\n' && ptr != end; ptr++) ; if (ptr == end) /* must end with '\n' */ goto error; /* if (*(ptr-1) == '\r') */ /* *(ptr-1) = '\0'; */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); parsed: /* ccnet_message ("Receive response %s from %s\n", msg, peer->id); */ /* ccnet_message ("code %s, code_msg %s, content %s\n", code, code_msg, */ /* content); */ processor = ccnet_client_get_processor (client, MASTER_ID (req_id)); if (processor == NULL) { if (strcmp (code, SC_PROC_DEAD) != 0) { ccnet_debug ("Delayed response from daemon, id is %d, %s %s\n", MASTER_ID(req_id), code, code_msg); ccnet_client_send_update (client, req_id, SC_PROC_DEAD, SS_PROC_DEAD, NULL, 0); } return; } /* ccnet_debug ("[client] handle_response %s id is %d, %s %s\n", */ /* GET_PNAME(processor), req_id, code, code_msg); */ ccnet_processor_handle_response (processor, code, code_msg, content, clen); return; error: g_warning ("Bad response format from daemon\n"); } static void handle_update (CcnetClient *client, int req_id, char *data, int len) { CcnetProcessor *processor; char *code, *code_msg = 0, *content = 0; int clen; char *ptr, *end; g_return_if_fail (len >= 4); code = data; ptr = data + 3; if (*ptr == '\n') { /* no code_msg */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); goto parsed; } if (*ptr != ' ') goto error; *ptr++ = '\0'; code_msg = ptr; end = data + len; for (ptr = data; *ptr != '\n' && ptr != end; ptr++) ; if (ptr == end) /* must end with '\n' */ goto error; /* if (*(ptr-1) == '\r') */ /* *(ptr-1) = '\0'; */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); parsed: processor = ccnet_client_get_processor (client, SLAVE_ID(req_id)); if (processor == NULL) { if (strcmp (code, SC_PROC_DEAD) != 0) { ccnet_debug ("Delayed update from daemon, id is %d, %s %s\n", req_id, code, code_msg); ccnet_client_send_response (client, req_id, SC_PROC_DEAD, SS_PROC_DEAD, NULL, 0); } return; } /* ccnet_debug ("[client] handle_update %s id is %d, %s %s\n", */ /* GET_PNAME(processor), req_id, code, code_msg); */ ccnet_processor_handle_update (processor, code, code_msg, content, clen); return; error: g_warning ("Bad update format\n"); } static void handle_packet (ccnet_packet *packet, void *vclient) { CcnetClient *client = vclient; if (packet == NULL) { /* disconnected from daemon */ g_warning ("Disconnected from daemon\n"); return; } switch (packet->header.type) { case CCNET_MSG_REQUEST: handle_request (client, packet->header.id, packet->data, packet->header.length); break; case CCNET_MSG_RESPONSE: handle_response (client, packet->header.id, packet->data, packet->header.length); break; case CCNET_MSG_UPDATE: handle_update (client, packet->header.id, packet->data, packet->header.length); break; default: g_return_if_reached (); } } void ccnet_client_send_request (CcnetClient *client, int req_id, const char *req) { ccnet_packet_prepare (client->io, CCNET_MSG_REQUEST, req_id); ccnet_packet_write_string (client->io, req); ccnet_packet_finish_send (client->io); g_debug ("Send a request: id %d, cmd %s\n", req_id, req); } /** * ccnet_client_send_update: * @client: * @req_id: request id * @code: A string of three numbers. Like "200" * @reason: long description for @code, can't contain '\n', can be %NULL * @content: A char array, can be %NULL. * @clen: length of %content, in bytes. */ void ccnet_client_send_update (CcnetClient *client, int req_id, const char *code, const char *reason, const char *content, int clen) { g_return_if_fail (req_id > 0); g_return_if_fail (clen < CCNET_PACKET_MAX_PAYLOAD_LEN); ccnet_packet_prepare (client->io, CCNET_MSG_UPDATE, req_id); /* code line */ ccnet_packet_add (client->io, code, 3); if (reason) { ccnet_packet_add (client->io, " ", 1); ccnet_packet_write_string (client->io, reason); } ccnet_packet_add (client->io, "\n", 1); if (content) ccnet_packet_add (client->io, content, clen); ccnet_packet_finish_send (client->io); /* g_debug ("[client] Send an update: id %d: %s %s len=%d\n", */ /* req_id, code, reason, clen); */ } void ccnet_client_send_response (CcnetClient *client, int req_id, const char *code, const char *reason, const char *content, int clen) { g_return_if_fail (clen < CCNET_PACKET_MAX_PAYLOAD_LEN); ccnet_packet_prepare (client->io, CCNET_MSG_RESPONSE, req_id); /* code line */ ccnet_packet_add (client->io, code, 3); if (reason) { ccnet_packet_add (client->io, " ", 1); ccnet_packet_write_string (client->io, reason); } ccnet_packet_add (client->io, "\n", 1); if (content) ccnet_packet_add (client->io, content, clen); ccnet_packet_finish_send (client->io); /* g_debug ("[client] Send an response: id %d: %s %s len=%d\n", */ /* req_id, code, reason, clen); */ } /* functions used in SYNC mode */ /** * ccnet_client_read_response: * @client: * * Read response from the daemon. The response can be accessed by * client->response. * * Returns: -1 if io error, -2 if response packet format error */ int ccnet_client_read_response (CcnetClient *client) { ccnet_packet *packet; char *data; int len, clen; char *code, *code_msg = 0, *content = 0; char *ptr, *end; restart: if ( (packet = ccnet_packet_io_read_packet (client->io)) == NULL) return -1; if (packet->header.type != CCNET_MSG_RESPONSE) goto error; data = packet->data; len = packet->header.length; g_return_val_if_fail (len >= 4, -1); code = data; ptr = data + 3; if (*ptr == '\n') { /* no code_msg */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); goto parsed; } if (*ptr != ' ') goto error; *ptr++ = '\0'; code_msg = ptr; end = data + len; for (ptr = data; *ptr != '\n' && ptr != end; ptr++) ; if (ptr == end) /* must end with '\n' */ goto error; /* if (*(ptr-1) == '\r') */ /* *(ptr-1) = '\0'; */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); /* In synchronized mode, we only have one processor at a time. The processor id is client->req_id, other processors are all treat as dead. */ /* if (packet->header.id != client->req_id) { if (strcmp (code, SC_PROC_DEAD) != 0) { g_debug ("Read response error: want %d, get %d %s %s\n", client->req_id, packet->header.id, code, code_msg); ccnet_client_send_update(client, packet->header.id, SC_PROC_DEAD, SS_PROC_DEAD, NULL, 0); } goto restart; } */ /* handle processor keep alive response */ if (strncmp(code, SC_PROC_KEEPALIVE, 3) == 0) { ccnet_client_send_update(client, packet->header.id, SC_PROC_ALIVE, SS_PROC_ALIVE, NULL, 0); goto restart; } parsed: client->response.code = code; client->response.code_msg = code_msg; client->response.content = content; client->response.clen = clen; return 0; error: g_warning ("Bad response format from daemon\n"); return -2; } static int read_response_common(CcnetClient *client) { if (ccnet_client_read_response(client) < 0) return -1; if (client->response.code[0] == '4' || client->response.code[0] == '5') { g_warning ("Error response from daemon: %s %s\n", client->response.code, client->response.code_msg); return -1; } return 0; } static gboolean check_response_error (CcnetClient *client, GError **error) { if (client->response.code[0] == '4' || client->response.code[0] == '5') { g_set_error (error, CCNET_DOMAIN, atoi(client->response.code), "%s", client->response.code_msg); return TRUE; } return FALSE; } const char * ccnet_client_send_cmd (CcnetClient *client, const char *cmd, GError **error) { int req_id = ccnet_client_get_request_id (client); ccnet_client_send_request (client, req_id, "receive-cmd"); if (ccnet_client_read_response(client) < 0) { g_set_error (error, CCNET_DOMAIN, EC_NETWORK_ERR, "%s", ES_NETWORK_ERR); goto on_error; } ccnet_client_send_update (client, req_id, "200", NULL, cmd, strlen(cmd) + 1); if (ccnet_client_read_response(client) < 0) { g_set_error (error, CCNET_DOMAIN, EC_NETWORK_ERR, "%s", ES_NETWORK_ERR); goto on_error; } if (check_response_error(client, error)) { goto on_error; } ccnet_client_send_update (client, req_id, SC_PROC_DONE, SS_PROC_DONE, NULL, 0); return client->response.content; on_error: ccnet_client_send_update (client, req_id, SC_PROC_DONE, SS_PROC_DONE, NULL, 0); return NULL; } #define SC_MSG "300" int ccnet_client_send_message (CcnetClient *client, CcnetMessage *message) { GString *buf; int req_id = ccnet_client_get_request_id (client); ccnet_client_send_request (client, req_id, "mq-server"); if (ccnet_client_read_response (client) < 0) return -1; /* TODO: handle response code */ buf = g_string_new (NULL); ccnet_message_to_string_buf (message, buf); ccnet_client_send_update (client, req_id, SC_MSG, NULL, buf->str, buf->len+1); if (ccnet_client_read_response (client) < 0) return -1; g_string_free (buf, TRUE); return 0; } int ccnet_client_prepare_recv_message (CcnetClient *client, const char *app) { int req_id = ccnet_client_get_request_id (client); char buf[256]; snprintf (buf, sizeof(buf), "mq-server %s", app); ccnet_client_send_request (client, req_id, buf); if (read_response_common (client) < 0) return -1; if (memcmp(client->response.code, "200", 3) != 0) return -1; return 0; } CcnetMessage * ccnet_client_receive_message (CcnetClient *client) { CcnetMessage *message; if (read_response_common (client) < 0) return NULL; message = ccnet_message_from_string (client->response.content, client->response.clen); return message; } ccnet-6.1.5/lib/ccnet-rpc-wrapper.c000066400000000000000000000174651317035602700171060ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include #include #include #include SearpcClient * ccnet_create_rpc_client (CcnetClient *cclient, const char *peer_id, const char *service_name) { SearpcClient *rpc_client; CcnetrpcTransportParam *priv; priv = g_new0(CcnetrpcTransportParam, 1); priv->session = cclient; priv->peer_id = g_strdup(peer_id); priv->service = g_strdup(service_name); rpc_client = searpc_client_new (); rpc_client->send = ccnetrpc_transport_send; rpc_client->arg = priv; return rpc_client; } SearpcClient * ccnet_create_pooled_rpc_client (struct CcnetClientPool *cpool, const char *peer_id, const char *service) { SearpcClient *rpc_client; CcnetrpcTransportParam *priv; priv = g_new0(CcnetrpcTransportParam, 1); priv->pool = cpool; priv->peer_id = g_strdup(peer_id); priv->service = g_strdup(service); rpc_client = searpc_client_new (); rpc_client->send = ccnetrpc_transport_send; rpc_client->arg = priv; return rpc_client; } SearpcClient * ccnet_create_async_rpc_client (CcnetClient *cclient, const char *peer_id, const char *service_name) { SearpcClient *rpc_client; CcnetrpcAsyncTransportParam *async_priv; async_priv = g_new0 (CcnetrpcAsyncTransportParam, 1); async_priv->session = cclient; async_priv->peer_id = g_strdup(peer_id); async_priv->service = g_strdup (service_name); rpc_client = searpc_client_new (); rpc_client->async_send = ccnetrpc_async_transport_send; rpc_client->async_arg = async_priv; return rpc_client; } void ccnet_rpc_client_free (SearpcClient *client) { CcnetrpcTransportParam *priv; if (!client) return; priv = client->arg; g_free (priv->peer_id); g_free (priv->service); g_free (priv); searpc_client_free (client); } void ccnet_async_rpc_client_free (SearpcClient *client) { CcnetrpcAsyncTransportParam *priv = client->arg; g_free (priv->peer_id); g_free (priv->service); g_free (priv); searpc_client_free (client); } CcnetPeer * ccnet_get_peer (SearpcClient *client, const char *peer_id) { if (!peer_id) return NULL; return (CcnetPeer *) searpc_client_call__object( client, "get_peer",CCNET_TYPE_PEER, NULL, 1, "string", peer_id); } CcnetPeer * ccnet_get_peer_by_idname (SearpcClient *client, const char *idname) { if (!idname) return NULL; return (CcnetPeer *) searpc_client_call__object( client, "get_peer_by_idname", CCNET_TYPE_PEER, NULL, 1, "string", idname); } int ccnet_get_peer_net_state (SearpcClient *client, const char *peer_id) { CcnetPeer *peer; int ret; peer = ccnet_get_peer (client, peer_id); if (!peer) return PEER_DOWN; ret = peer->net_state; g_object_unref (peer); return ret; } int ccnet_get_peer_bind_status (SearpcClient *client, const char *peer_id) { CcnetPeer *peer; int ret; peer = ccnet_get_peer (client, peer_id); if (!peer) return BIND_UNKNOWN; ret = peer->bind_status; g_object_unref (peer); return ret; } CcnetPeer * ccnet_get_default_relay (SearpcClient *client) { CcnetSessionBase *base = (CcnetSessionBase *) searpc_client_call__object( client, "get_session_info", CCNET_TYPE_SESSION_BASE, NULL, 0); if (!base) return NULL; CcnetPeer *relay = ccnet_get_peer (client, base->relay_id); g_object_unref (base); return relay; } GList * ccnet_get_peers_by_role (SearpcClient *client, const char *role) { if (!role) return NULL; return searpc_client_call__objlist ( client, "get_peers_by_role", CCNET_TYPE_PEER, NULL, 1, "string", role); } char * ccnet_get_binding_email (SearpcClient *client, const char *peer_id) { if (!peer_id) return NULL; return searpc_client_call__string ( client, "get_binding_email", NULL, 1, "string", peer_id); } GList * ccnet_get_groups_by_user (SearpcClient *client, const char *user) { if (!user) return NULL; return searpc_client_call__objlist ( client, "get_groups", CCNET_TYPE_GROUP, NULL, 1, "string", user); } GList * ccnet_get_group_members (SearpcClient *client, int group_id) { return searpc_client_call__objlist ( client, "get_group_members", CCNET_TYPE_GROUP_USER, NULL, 1, "int", group_id); } int ccnet_org_user_exists (SearpcClient *client, int org_id, const char *user) { return searpc_client_call__int (client, "org_user_exists", NULL, 2, "int", org_id, "string", user); } #if 0 int ccnet_get_peer_async (SearpcClient *client, const char *peer_id, AsyncCallback callback, void *user_data) { return get_peer_async (client, peer_id, callback, user_data); } #endif int ccnet_get_binding_email_async (SearpcClient *client, const char *peer_id, AsyncCallback callback, void *user_data) { return searpc_client_async_call__string ( client, "get_binding_email", callback, user_data, 1, "string", peer_id); } char * ccnet_sign_message (SearpcClient *client, const char *message) { if (!message) return NULL; return searpc_client_call__string ( client, "sign_message", NULL, 1, "string", message); } int ccnet_verify_message (SearpcClient *client, const char *message, const char *sig_base64, const char *peer_id) { if (!message || !sig_base64 || !peer_id) return -1; return searpc_client_call__int ( client, "verify_message", NULL, 3, "string", message, "string", sig_base64, "string", peer_id); } char * ccnet_pubkey_encrypt (SearpcClient *client, const char *msg_base64, const char *peer_id) { if (!msg_base64 || !peer_id) return NULL; return searpc_client_call__string (client, "pubkey_encrypt", NULL, 2, "string", msg_base64, "string", peer_id); } char * ccnet_privkey_decrypt (SearpcClient *client, const char *msg_base64) { if (!msg_base64) return NULL; return searpc_client_call__string (client, "privkey_decrypt", NULL, 1, "string", msg_base64); } char * ccnet_get_config (SearpcClient *client, const char *key) { if (!key) return NULL; return searpc_client_call__string ( client, "get_config", NULL, 1, "string", key); } int ccnet_set_config (SearpcClient *client, const char *key, const char *value) { if (!key || !value) return -1; return searpc_client_call__int ( client, "set_config", NULL, 2, "string", key, "string", value); } void ccnet_login_to_relay (SearpcClient *client, const char *relay_id, const char *username, const char *passwd) { searpc_client_call__int (client, "login_relay", NULL, 3, "string", relay_id, "string", username, "string", passwd); } gboolean ccnet_peer_is_ready (SearpcClient *client, const char *peer_id) { CcnetPeer *peer; gboolean ret; peer = ccnet_get_peer (client, peer_id); if (!peer) return FALSE; ret = peer->is_ready; g_object_unref (peer); return ret; } int ccnet_update_peer_address (SearpcClient *client, const char *peer_id, const char *addr, int port) { return searpc_client_call__int ( client, "update_peer_address", NULL, 3, "string", peer_id, "string", addr, "int", port); } ccnet-6.1.5/lib/ccnet-session-base.c000066400000000000000000000075721317035602700172350ustar00rootroot00000000000000 #include "option.h" #include "include.h" #include "ccnet-session-base.h" G_DEFINE_TYPE (CcnetSessionBase, ccnet_session_base, G_TYPE_OBJECT); enum { P_ID = 1, P_USER_NAME, P_NAME, P_PUBLIC_PORT, P_NET_STATUS, P_DEFAULT_RELAY, }; static void set_property (GObject *object, guint property_id, const GValue *v, GParamSpec *pspec) { CcnetSessionBase *session = CCNET_SESSION_BASE (object); const char *relay; switch (property_id) { case P_ID: strcpy(session->id, g_value_get_string(v)); break; case P_NAME: g_free (session->name); session->name = g_strdup (g_value_get_string(v)); break; case P_USER_NAME: g_free (session->user_name); session->user_name = g_strdup (g_value_get_string(v)); break; case P_PUBLIC_PORT: session->public_port = g_value_get_int (v); break; case P_NET_STATUS: session->net_status = g_value_get_int (v); break; case P_DEFAULT_RELAY: relay = g_value_get_string(v); session->relay_id = g_strdup(relay); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); return; } } static void get_property (GObject *object, guint property_id, GValue *v, GParamSpec *pspec) { CcnetSessionBase *session = CCNET_SESSION_BASE (object); switch (property_id) { /* commont properties to session and daemon */ case P_ID: g_value_set_string (v, session->id); break; case P_USER_NAME: g_value_set_string (v, session->user_name); break; case P_NAME: g_value_set_string (v, session->name); break; case P_PUBLIC_PORT: g_value_set_int (v, session->public_port); break; case P_NET_STATUS: g_value_set_int (v, session->net_status); break; case P_DEFAULT_RELAY: g_value_set_string (v, session->relay_id); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void finalize(GObject *gobject) { CcnetSessionBase *s = CCNET_SESSION_BASE(gobject); g_free (s->user_name); g_free (s->name); g_free (s->relay_id); G_OBJECT_CLASS(ccnet_session_base_parent_class)->finalize (gobject); } static void ccnet_session_base_class_init (CcnetSessionBaseClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = set_property; gobject_class->get_property = get_property; gobject_class->finalize = finalize; g_object_class_install_property (gobject_class, P_ID, g_param_spec_string ("id", NULL, "ID", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_USER_NAME, g_param_spec_string ("user-name", NULL, "User Name", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_NAME, g_param_spec_string ("name", NULL, "Name", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_PUBLIC_PORT, g_param_spec_int ("public-port", NULL, "Public Port", 0, 65525, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_NET_STATUS, g_param_spec_int ("net-status", NULL, "Network Status", 0, NET_STATUS_FULL, NET_STATUS_DOWN, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_DEFAULT_RELAY, g_param_spec_string ("default-relay", NULL, "Default Relay", NULL, G_PARAM_READWRITE)); } static void ccnet_session_base_init (CcnetSessionBase *sbase) { } CcnetSessionBase * ccnet_session_base_new (void) { return g_object_new (CCNET_TYPE_SESSION_BASE, NULL); } ccnet-6.1.5/lib/ccnetobj.vala000066400000000000000000000033551317035602700160330ustar00rootroot00000000000000 namespace Ccnet { public class Proc : Object { public string peer_name { get; set; } public string _name; public string name { get { return _name; } set { _name = value; } } public int _ctime; public int ctime { get { return _ctime; } set { _ctime = value; } } public int _dtime; //dead time public int dtime { get { return _dtime; } set { _dtime = value; } } } public class EmailUser : Object { public int id { get; set; } public string email { get; set; } public bool is_staff { get; set; } public bool is_active { get; set; } public int64 ctime { get; set; } public string source { get; set; } public string role { get; set; } public string password { get; set; } } public class Group : Object { public int id { get; set; } public string group_name { get; set; } public string creator_name { get; set; } public int64 timestamp { get; set; } public string source { get; set; } } public class GroupUser : Object { public int group_id { get; set; } public string user_name { get; set; } public int is_staff { get; set; } } public class Organization : Object { public int org_id { get; set; } public string email { get; set; } public int is_staff { get; set; } public string org_name { get; set; } public string url_prefix { get; set; } public string creator { get; set; } public int64 ctime { get; set; } } public class PeerStat : Object { public string id { get; set; } public string name { get; set; } public string ip { get; set; } public bool encrypt { get; set; } public int64 last_up { get; set; } public int proc_num { get; set; } } } // namespace ccnet-6.1.5/lib/ccnetrpc-transport.c000066400000000000000000000131641317035602700173750ustar00rootroot00000000000000 #include #include #include #include #include "rpc-common.h" #include static char * invoke_service (CcnetClient *session, const char *peer_id, const char *service, const char *fcall_str, size_t fcall_len, size_t *ret_len) { struct CcnetResponse *rsp; uint32_t req_id; GString *buf; req_id = ccnet_client_get_rpc_request_id (session, peer_id, service); if (req_id == 0) { *ret_len = 0; return NULL; } ccnet_client_send_update (session, req_id, SC_CLIENT_CALL, SS_CLIENT_CALL, fcall_str, fcall_len); if (ccnet_client_read_response (session) < 0) { *ret_len = 0; ccnet_client_clean_rpc_request (session, req_id); return NULL; } rsp = &session->response; if (memcmp (rsp->code, SC_SERVER_RET, 3) == 0) { *ret_len = (size_t) rsp->clen; return g_strndup (rsp->content, rsp->clen); } else if (memcmp (rsp->code, SC_SERVER_MORE, 3) != 0) { g_warning ("[Sea RPC] Bad response: %s %s.\n", rsp->code, rsp->code_msg); *ret_len = 0; return NULL; } buf = g_string_new_len (rsp->content, rsp->clen); while (1) { ccnet_client_send_update (session, req_id, SC_CLIENT_MORE, SS_CLIENT_MORE, fcall_str, fcall_len); if (ccnet_client_read_response (session) < 0) { *ret_len = 0; ccnet_client_clean_rpc_request (session, req_id); g_string_free (buf, TRUE); return NULL; } rsp = &session->response; if (memcmp (rsp->code, SC_SERVER_RET, 3) == 0) { g_string_append_len (buf, rsp->content, rsp->clen); *ret_len = buf->len; return g_string_free (buf, FALSE); } else if (memcmp (rsp->code, SC_SERVER_MORE, 3) == 0) { g_string_append_len (buf, rsp->content, rsp->clen); } else { g_warning ("[Sea RPC] Bad response: %s %s.\n", rsp->code, rsp->code_msg); *ret_len = 0; g_string_free (buf, TRUE); return NULL; } } /* Never reach here. */ return NULL; } static CcnetClient * create_new_client (const char *central_config_dir, const char *conf_dir) { CcnetClient *client; client = ccnet_client_new (); if (ccnet_client_load_confdir (client, central_config_dir, conf_dir) < 0) { g_warning ("[Sea RPC] Failed to load conf dir.\n"); g_object_unref (client); return NULL; } if (ccnet_client_connect_daemon (client, CCNET_CLIENT_SYNC) < 0) { g_warning ("[Sea RPC] Failed to connect ccnet.\n"); g_object_unref (client); return NULL; } return client; } char * ccnetrpc_transport_send (void *arg, const gchar *fcall_str, size_t fcall_len, size_t *ret_len) { CcnetrpcTransportParam *priv; CcnetClient *session, *new_session; g_warn_if_fail (arg != NULL && fcall_str != NULL); priv = (CcnetrpcTransportParam *)arg; if (priv->session != NULL) { /* Use single ccnet client as transport. */ return invoke_service (priv->session, priv->peer_id, priv->service, fcall_str, fcall_len, ret_len); } else { /* Use client pool as transport. */ session = ccnet_client_pool_get_client (priv->pool); if (!session) { g_warning ("[Sea RPC] Failed to get client from pool.\n"); *ret_len = 0; return NULL; } char *ret = invoke_service (session, priv->peer_id, priv->service, fcall_str, fcall_len, ret_len); if (ret != NULL) { ccnet_client_pool_return_client (priv->pool, session); return ret; } /* If we failed to send data through the ccnet client returned by * client pool, ccnet may have been restarted. * In this case, we create a new ccnet client and put it into * the client pool after use. */ g_message ("[Sea RPC] Ccnet disconnected. Connect again.\n"); new_session = create_new_client (session->central_config_dir, session->config_dir); if (!new_session) { *ret_len = 0; return NULL; } g_object_unref (session); ret = invoke_service (new_session, priv->peer_id, priv->service, fcall_str, fcall_len, ret_len); if (ret != NULL) ccnet_client_pool_return_client (priv->pool, new_session); else g_object_unref (new_session); return ret; } } int ccnetrpc_async_transport_send (void *arg, gchar *fcall_str, size_t fcall_len, void *rpc_priv) { CcnetrpcAsyncTransportParam *priv; CcnetClient *session; CcnetProcessor *proc; g_warn_if_fail (arg != NULL && fcall_str != NULL); priv = (CcnetrpcAsyncTransportParam *)arg; session = priv->session; if (!priv->peer_id) proc = ccnet_proc_factory_create_master_processor ( session->proc_factory, "async-rpc"); else proc = ccnet_proc_factory_create_remote_master_processor ( session->proc_factory, "async-rpc", priv->peer_id); ccnet_async_rpc_proc_set_rpc ((CcnetAsyncRpcProc *)proc, priv->service, fcall_str, fcall_len, rpc_priv); ccnet_processor_start (proc, 0, NULL); return 0; } ccnet-6.1.5/lib/cevent.c000066400000000000000000000052621317035602700150260ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include "cevent.h" #define CEVENT_SIZE (sizeof(CEvent)) typedef struct Handler { cevent_handler handler; void *handler_data; } Handler; CEventManager* cevent_manager_new () { CEventManager *manager; manager = g_new0 (CEventManager, 1); pthread_mutex_init (&manager->mutex, NULL); manager->handler_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); return manager; } void pipe_callback (evutil_socket_t fd, short event, void *vmgr) { CEventManager *manager = (CEventManager *) vmgr; CEvent *cevent; char buf[CEVENT_SIZE]; if (ccnet_util_pipereadn(fd, buf, CEVENT_SIZE) != CEVENT_SIZE) { return; } cevent = (CEvent *)buf; Handler *h = g_hash_table_lookup (manager->handler_table, (gconstpointer)(long)cevent->id); if (h == NULL) { g_warning ("no handler for event type %d\n", cevent->id); return; } h->handler(cevent, h->handler_data); } int cevent_manager_start (CEventManager *manager) { if (ccnet_util_pipe(manager->pipefd) < 0) { g_warning ("pipe error: %s\n", strerror(errno)); return -1; } event_set (&manager->event, manager->pipefd[0], EV_READ | EV_PERSIST, pipe_callback, manager); event_add (&manager->event, NULL); return 0; } uint32_t cevent_manager_register (CEventManager *manager, cevent_handler handler, void *handler_data) { uint32_t id; Handler *h; h = g_new0(Handler, 1); h->handler = handler; h->handler_data = handler_data; /* Since we're using 32-bit int for id, it may wrap around to 0. * If some caller persistently use one id, it's handler may be * overwritten by others. */ do { id = manager->next_id++; } while (g_hash_table_lookup (manager->handler_table, (gpointer)(long)id)); g_hash_table_insert (manager->handler_table, (gpointer)(long)id, h); return id; } void cevent_manager_unregister (CEventManager *manager, uint32_t id) { g_hash_table_remove (manager->handler_table, (gpointer)(long)id); } void cevent_manager_add_event (CEventManager *manager, uint32_t id, void *data) { pthread_mutex_lock (&manager->mutex); struct CEvent cevent; char *buf = (char *) &cevent; cevent.id = id; cevent.data = data; if (ccnet_util_pipewriten(manager->pipefd[1], buf, CEVENT_SIZE) != CEVENT_SIZE) { g_warning ("add event error\n"); } pthread_mutex_unlock (&manager->mutex); } ccnet-6.1.5/lib/client-pool.c000066400000000000000000000031541317035602700157650ustar00rootroot00000000000000#include "include.h" #include #include #include #include struct CcnetClientPool { GQueue *clients; pthread_mutex_t lock; const char *central_config_dir; const char *conf_dir; }; struct CcnetClientPool * ccnet_client_pool_new (const char *central_config_dir, const char *conf_dir) { CcnetClientPool *pool = g_new0 (CcnetClientPool, 1); pool->clients = g_queue_new (); pthread_mutex_init (&pool->lock, NULL); pool->conf_dir = g_strdup(conf_dir); pool->central_config_dir = g_strdup(central_config_dir); return pool; } CcnetClient * ccnet_client_pool_get_client (struct CcnetClientPool *cpool) { CcnetClient *client; pthread_mutex_lock (&cpool->lock); client = g_queue_pop_head (cpool->clients); pthread_mutex_unlock (&cpool->lock); if (!client) { client = ccnet_client_new (); if (ccnet_client_load_confdir (client, cpool->central_config_dir, cpool->conf_dir) < 0) { g_warning ("[client pool] Failed to load conf dir.\n"); g_object_unref (client); return NULL; } if (ccnet_client_connect_daemon (client, CCNET_CLIENT_SYNC) < 0) { g_warning ("[client pool] Failed to connect.\n"); g_object_unref (client); return NULL; } } return client; } void ccnet_client_pool_return_client (struct CcnetClientPool *cpool, CcnetClient *client) { pthread_mutex_lock (&cpool->lock); g_queue_push_tail (cpool->clients, client); pthread_mutex_unlock (&cpool->lock); } ccnet-6.1.5/lib/db.c000066400000000000000000000115031317035602700141220ustar00rootroot00000000000000 #include #include #include "db.h" int sqlite_open_db (const char *db_path, sqlite3 **db) { int result; const char *errmsg; result = sqlite3_open (db_path, db); if (result) { errmsg = sqlite3_errmsg (*db); g_warning ("Couldn't open database:'%s', %s\n", db_path, errmsg ? errmsg : "no error given"); sqlite3_close (*db); return -1; } return 0; } int sqlite_close_db (sqlite3 *db) { return sqlite3_close (db); } sqlite3_stmt * sqlite_query_prepare (sqlite3 *db, const char *sql) { sqlite3_stmt *stmt; int result; result = sqlite3_prepare_v2 (db, sql, -1, &stmt, NULL); if (result != SQLITE_OK) { const gchar *str = sqlite3_errmsg (db); g_warning ("Couldn't prepare query, error:%d->'%s'\n\t%s\n", result, str ? str : "no error given", sql); return NULL; } return stmt; } int sqlite_query_exec (sqlite3 *db, const char *sql) { char *errmsg = NULL; int result; result = sqlite3_exec (db, sql, NULL, NULL, &errmsg); if (result != SQLITE_OK) { if (errmsg != NULL) { g_warning ("SQL error: %d - %s\n:\t%s\n", result, errmsg, sql); sqlite3_free (errmsg); } return -1; } return 0; } int sqlite_begin_transaction (sqlite3 *db) { char *sql = "BEGIN TRANSACTION;"; return sqlite_query_exec (db, sql); } int sqlite_end_transaction (sqlite3 *db) { char *sql = "END TRANSACTION;"; return sqlite_query_exec (db, sql); } gboolean sqlite_check_for_existence (sqlite3 *db, const char *sql) { sqlite3_stmt *stmt; int result; stmt = sqlite_query_prepare (db, sql); if (!stmt) return FALSE; result = sqlite3_step (stmt); if (result == SQLITE_ERROR) { const gchar *str = sqlite3_errmsg (db); g_warning ("Couldn't execute query, error: %d->'%s'\n", result, str ? str : "no error given"); sqlite3_finalize (stmt); return FALSE; } sqlite3_finalize (stmt); if (result == SQLITE_ROW) return TRUE; return FALSE; } int sqlite_foreach_selected_row (sqlite3 *db, const char *sql, SqliteRowFunc callback, void *data) { sqlite3_stmt *stmt; int result; int n_rows = 0; stmt = sqlite_query_prepare (db, sql); if (!stmt) { return -1; } while (1) { result = sqlite3_step (stmt); if (result != SQLITE_ROW) break; n_rows++; if (!callback (stmt, data)) break; } if (result == SQLITE_ERROR) { const gchar *s = sqlite3_errmsg (db); g_warning ("Couldn't execute query, error: %d->'%s'\n", result, s ? s : "no error given"); sqlite3_finalize (stmt); return -1; } sqlite3_finalize (stmt); return n_rows; } int sqlite_get_int (sqlite3 *db, const char *sql) { int ret = -1; int result; sqlite3_stmt *stmt; if ( !(stmt = sqlite_query_prepare(db, sql)) ) return 0; result = sqlite3_step (stmt); if (result == SQLITE_ROW) { ret = sqlite3_column_int (stmt, 0); sqlite3_finalize (stmt); return ret; } if (result == SQLITE_ERROR) { const gchar *str = sqlite3_errmsg (db); g_warning ("Couldn't prepare query, error: %d->'%s'\n", result, str ? str : "no error given"); sqlite3_finalize (stmt); return 0; } return ret; } gint64 sqlite_get_int64 (sqlite3 *db, const char *sql) { gint64 ret = -1; int result; sqlite3_stmt *stmt; if ( !(stmt = sqlite_query_prepare(db, sql)) ) return 0; result = sqlite3_step (stmt); if (result == SQLITE_ROW) { ret = sqlite3_column_int64 (stmt, 0); sqlite3_finalize (stmt); return ret; } if (result == SQLITE_ERROR) { const gchar *str = sqlite3_errmsg (db); g_warning ("Couldn't prepare query, error: %d->'%s'\n", result, str ? str : "no error given"); sqlite3_finalize (stmt); return 0; } return ret; } char *sqlite_get_string (sqlite3 *db, const char *sql) { const char *res = NULL; int result; sqlite3_stmt *stmt; if ( !(stmt = sqlite_query_prepare(db, sql)) ) return NULL; result = sqlite3_step (stmt); if (result == SQLITE_ROW) { res = (const char *)sqlite3_column_text (stmt, 0); sqlite3_finalize (stmt); return g_strdup(res); } if (result == SQLITE_ERROR) { const gchar *str = sqlite3_errmsg (db); g_warning ("Couldn't prepare query, error: %d->'%s'\n", result, str ? str : "no error given"); sqlite3_finalize (stmt); return NULL; } return NULL; } ccnet-6.1.5/lib/db.h000066400000000000000000000015651317035602700141360ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef DB_UTILS_H #define DB_UTILS_H #include int sqlite_open_db (const char *db_path, sqlite3 **db); int sqlite_close_db (sqlite3 *db); sqlite3_stmt *sqlite_query_prepare (sqlite3 *db, const char *sql); int sqlite_query_exec (sqlite3 *db, const char *sql); int sqlite_begin_transaction (sqlite3 *db); int sqlite_end_transaction (sqlite3 *db); gboolean sqlite_check_for_existence (sqlite3 *db, const char *sql); typedef gboolean (*SqliteRowFunc) (sqlite3_stmt *stmt, void *data); int sqlite_foreach_selected_row (sqlite3 *db, const char *sql, SqliteRowFunc callback, void *data); int sqlite_get_int (sqlite3 *db, const char *sql); gint64 sqlite_get_int64 (sqlite3 *db, const char *sql); char *sqlite_get_string (sqlite3 *db, const char *sql); #endif ccnet-6.1.5/lib/htree.c000066400000000000000000000163111317035602700146460ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include #include #include #include "htree.h" #define MAX_HEIGHT 7 #define INDEX(hashid,depth) (depth%2 ? (hashid[depth/2] && 0x0f):(hashid[depth/2] >> 4)) #define IS_NODE(n) (n->is_node) static const int g_index[] = {0, 1, 17, 273, 4369, 69905, 1118481, 17895697, 286331153}; static inline void hashxor(char *hashid, char *id, int len) { int i = 0; for (i = 0; i < len; ++i) { hashid[i] = hashid[i] ^ id[i]; } } static inline int get_right_height (int size) { int height = 0; while (g_index[height+1] < size) ++height; if (height < 1)return 1; return height; } static inline unsigned int get_pos (HTree *tree, HTNode *node) { return (node - tree->nodes) - g_index[(int)node->depth]; } static inline void ht_set_data (HTree *tree, HTNode *node, HTData *data) { tree->datas[node - tree->nodes] = data; } static inline HTItem *create_item (unsigned char *hashid, void *data) { HTItem *it = malloc (sizeof (HTItem)); it->hashid = hashid; it->data = data; it->next = NULL; } static inline void delete_item (HTree *tree, HTItem *it) { if (tree->item_free) tree->item_free (it); free (it); } static void *load_node (HTree *tree, HTNode *node) { HTData *data = ht_get_data (tree, node); if (data) return data; data = malloc (sizeof(HTData)); data->size = 0; data->hashid = malloc (tree->hashid_len); memset (data->hashid, 0, tree->hashid_len); data->item_list = NULL; ht_set_data (tree, node, data); return data; } static void delete_data (HTree *tree, HTData *data) { HTItem *p = NULL;; if (data) { if (data->hashid) free (data->hashid); while (data->item_list) { p = data->item_list; data->item_list = p->next; delete_item (tree, p); } free(data); } } static int add_item (HTree *tree, HTNode *node, unsigned char *hashid, void *data) { if (node == NULL) return 0; int r = 0, i = 0; HTData *htdata = NULL; if (IS_NODE(node)) { r = add_item (tree, ht_get_child (tree, node, INDEX(hashid, node->depth)), hashid, data); if (r) { htdata = load_node(tree, node); hashxor (htdata->hashid, hashid, tree->hashid_len); } return r; } htdata = load_node(tree, node); HTItem *p = htdata->item_list; for (i = 0; i < htdata->size; i++){ if (memcmp (hashid, p->hashid, tree->hashid_len) == 0) { return 0; } p = p->next; } HTItem *it = create_item (hashid, data); it->next = htdata->item_list; htdata->item_list = it; ++htdata->size; hashxor (htdata->hashid, it->hashid, tree->hashid_len); return 1; } static int remove_item (HTree *tree, HTNode *node, unsigned char *hashid) { if (node == NULL) return 0; int r = 0, i = 0; HTData *data = NULL; if (IS_NODE(node)) { r = remove_item (tree, ht_get_child (tree, node, INDEX(hashid, node->depth)), hashid); if (r) { data = load_node(tree, node); hashxor (data->hashid, hashid, tree->hashid_len); } return r; } data = load_node(tree, node); HTItem *p = data->item_list; HTItem *pre = NULL; for (i = 0; i < data->size; i++){ if (memcmp (hashid, p->hashid, tree->hashid_len) == 0) { if (pre == NULL) { data->item_list = p->next; } else { pre->next = p->next; } --data->size; hashxor (data->hashid, hashid, tree->hashid_len); delete_item (tree, p); return 1; } pre = p; p = p->next; } return 0; } HTree* ht_new (int size, int hashlen) { HTree *ht = (HTree *)malloc (sizeof(HTree)); int height = get_right_height (size); int i = 0, j = 0; ht->height = height; ht->size = g_index[height]; ht->hashid_len = hashlen; ht->item_free = NULL; ht->nodes = malloc (ht->size *sizeof(HTNode)); ht->datas = malloc (ht->size *sizeof(HTData *)); memset (ht->nodes, 0, ht->size *sizeof(HTNode)); memset (ht->datas, 0, ht->size *sizeof(HTData *)); for (i = 0; i < height; ++i) { for (j = g_index[i]; j < g_index[i+1]; ++j) { (ht->nodes[j]).is_node = 1; (ht->nodes[j]).depth = i; } } for (j = g_index[height-1]; j < g_index[height]; ++j) { (ht->nodes[j]).is_node = 0; } } int ht_add (HTree *tree, unsigned char *hashid, void *data) { return add_item (tree, tree->nodes, hashid, data); } int ht_remove (HTree *tree, unsigned char *hashid) { return remove_item (tree, tree->nodes, hashid); } void ht_resize (HTree *ht, int size) { int height = get_right_height (size); if (height <= ht->height) { return; } /* TODO resize the hash tree */ } void ht_clear (HTree *tree) { assert (tree); int i; for(i = 0; i < tree->size; i++){ delete_data (tree, tree->datas[i]); } memset (tree->datas, 0, sizeof(HTData*) * tree->size); free (tree->nodes); free (tree->datas); free (tree); } HTData* ht_get_data (HTree *tree, HTNode *node) { return tree->datas[node - tree->nodes]; } unsigned char* ht_get_node_hash (HTree *tree, HTNode *node) { if (tree->datas[node - tree->nodes] == NULL) return NULL; return (tree->datas[node - tree->nodes])->hashid; } HTNode *ht_get_child (HTree *tree, HTNode *node, int b) { assert(0 <= b && b <= 0x0f); assert(node->depth < tree->height - 1); int i = g_index[node->depth + 1] + (get_pos(tree, node) << 4) + b; if (i >= tree->size){ fprintf(stderr, "get_child out of bound: %dth %d >= %d\n", b, i, tree->size); return NULL; } return tree->nodes + i; } HTNode *ht_get_parent (HTree *tree, HTNode *node) { if (node->depth == 0) return NULL; int i = g_index[node->depth - 1] + (get_pos(tree, node) >> 4) ; return tree->nodes + i; } HTNode *ht_get_brother (HTree *tree, HTNode *node) { if (get_pos(tree, node) & 0xff < 15) return node + 1; return NULL; } static void remove_node (HTree *tree, HTNode *node) { HTData* data = ht_get_data (tree, node); if (data == NULL) return; if (HTNODE_IS_LEAF(node)) { delete_data (tree, data); } else { int i = 0; HTNode *child = NULL; for (i = 0; i < 16; ++i) { child = ht_get_child (tree, node, i); remove_node (tree, child); } } } void ht_remove_node (HTree *tree, HTNode *node) { HTData *data = ht_get_data (tree, node); if (data == NULL) return; char *hash = data->hashid; HTNode *parent = ht_get_parent (tree, node); while (parent) { char *phash = ht_get_node_hash (tree, parent); hashxor (phash, hash, tree->hashid_len); parent = ht_get_parent (tree, parent); } remove_node (tree, node); ht_set_data (tree, node, NULL); } ccnet-6.1.5/lib/htree.h000066400000000000000000000035231317035602700146540ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef __HTREE_H__ #define __HTREE_H__ typedef struct hash_tree HTree; typedef void (*ItemFreeFunc)(void *); struct ht_item { unsigned char *hashid; void *data; struct ht_item *next; }; struct ht_data { int size; unsigned char *hashid; struct ht_item *item_list; }; struct ht_node { unsigned char is_node; unsigned char depth; /* from 0 */ }; struct hash_tree { int height; int hashid_len; int item_data_len; struct ht_node *nodes; /* an array of ht_node */ struct ht_data **datas; /* an array of the pointer of ht_data*/ int size; ItemFreeFunc item_free; }; typedef struct ht_item HTItem; typedef struct ht_data HTData; typedef struct ht_node HTNode; #define HTNODE_IS_LEAF(n) (!(((HTNode *)n)->is_node)) #define HTNODE_IS_NULL(tree, n) (ht_get_data(tree, n) == NULL) HTree* ht_new (int size, int hashlen); void ht_clear (HTree *tree); int ht_add (HTree *tree, unsigned char *hashid, void *data); int ht_remove (HTree *tree, unsigned char *hashid); void ht_resize (HTree *ht, int size); HTData* ht_get_data (HTree *tree, HTNode *node); unsigned char* ht_get_node_hash (HTree *tree, HTNode *node); HTNode *ht_get_parent (HTree *tree, HTNode *node); HTNode *ht_get_child (HTree *tree, HTNode *node, int b); HTNode *ht_get_brother (HTree *tree, HTNode *node); void ht_remove_node (HTree *tree, HTNode *node); static inline void ht_set_free_func (HTree *tree, ItemFreeFunc item_free) { tree->item_free = item_free; } static inline HTNode *ht_get_root (HTree *tree) { return tree->nodes; } static inline int ht_get_node_seq (HTree *tree, HTNode *node) { return node - tree->nodes; } static inline HTNode *ht_get_node_by_seq (HTree *tree, int seq) { return tree->nodes + seq; } #endif /* __HTREE_H__ */ ccnet-6.1.5/lib/include.h000066400000000000000000000013231317035602700151640ustar00rootroot00000000000000 #include #include #include #include #include #include #include #include "libccnet_utils.h" #include #ifndef ccnet_warning #define ccnet_warning(fmt, ...) g_warning( "%s: " fmt, __func__ , ##__VA_ARGS__) #endif #ifndef ccnet_error #define ccnet_error(fmt, ...) g_error( "%s: " fmt, __func__ , ##__VA_ARGS__) #endif #ifndef ccnet_message #define ccnet_message(fmt, ...) g_message(fmt, ##__VA_ARGS__) #endif #ifndef ccnet_debug #define ccnet_debug(fmt, ...) g_debug(fmt, ##__VA_ARGS__) #endif #define CCNET_DOMAIN g_quark_from_string("ccnet") #ifndef ENABLE_DEBUG #undef g_debug #define g_debug(...) #endif ccnet-6.1.5/lib/invoke-service-proc.c000066400000000000000000000041101317035602700174230ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include "ccnet-client.h" #include "peer.h" #include "processor.h" #include "invoke-service-proc.h" static int invoke_service_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SERVICE_PROC, CcnetServiceProcPriv)) G_DEFINE_TYPE (CcnetServiceProc, ccnet_service_proc, CCNET_TYPE_PROCESSOR) static void ccnet_service_proc_class_init (CcnetServiceProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->start = invoke_service_start; proc_class->handle_response = handle_response; } static void ccnet_service_proc_init (CcnetServiceProc *processor) { /* CCNET_PROCESSOR (processor)->state = INIT; */ } static int invoke_service_start (CcnetProcessor *processor, int argc, char **argv) { char *cmd; if (argc == 0) { g_warning ("Invalid argument for service-proc\n"); ccnet_processor_done (processor, FALSE); } cmd = ccnet_util_strjoin_n (" ", argc, argv); ccnet_client_send_request (processor->session, REQUEST_ID (processor->id), cmd); return 0; } void ccnet_service_proc_set_response_cb (CcnetServiceProc *proc, ResponseCB resp_cb, void *data) { proc->resp_cb = resp_cb; proc->cb_data = data; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetServiceProc *proc = (CcnetServiceProc *) processor; if (proc->resp_cb) proc->resp_cb (code, code_msg, content, clen, proc->cb_data); if (code[0] == '4' || code[0] == '5') ccnet_processor_done (processor, FALSE); } ccnet-6.1.5/lib/job-mgr.c000066400000000000000000000100211317035602700150640ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #else #include #endif #include #include #include #include #define MAX_THREADS 50 #define MAX_IDLE_THREADS 10 #ifdef CCNET_LIB #include "libccnet_utils.h" #define pipereadn ccnet_util_pipereadn #define pipewriten ccnet_util_pipewriten #define pipeclose ccnet_util_pipeclose #define ccnet_pipe ccnet_util_pipe #else #include "utils.h" #endif #include "job-mgr.h" struct _CcnetJob { CcnetJobManager *manager; int id; ccnet_pipe_t pipefd[2]; JobThreadFunc thread_func; JobDoneCallback done_func; /* called when the thread is done */ void *data; /* the done callback should only access this field */ void *result; }; void ccnet_job_manager_remove_job (CcnetJobManager *mgr, int job_id); static void job_thread_wrapper (void *vdata, void *unused) { CcnetJob *job = vdata; job->result = job->thread_func (job->data); if (pipewriten (job->pipefd[1], "a", 1) != 1) { /* g_warning ("[Job Manager] write to pipe error: %s\n", strerror(errno)); */ } } static void job_done_cb (evutil_socket_t fd, short event, void *vdata) { CcnetJob *job = vdata; char buf[1]; if (pipereadn (job->pipefd[0], buf, 1) != 1) { /* g_warning ("[Job Manager] read pipe error: %s\n", strerror(errno)); */ } pipeclose (job->pipefd[0]); pipeclose (job->pipefd[1]); if (job->done_func) { job->done_func (job->result); } ccnet_job_manager_remove_job (job->manager, job->id); } int job_thread_create (CcnetJob *job) { if (ccnet_pipe (job->pipefd) < 0) { /* g_warning ("pipe error: %s\n", strerror(errno)); */ return -1; } g_thread_pool_push (job->manager->thread_pool, job, NULL); #ifndef UNIT_TEST event_once (job->pipefd[0], EV_READ, job_done_cb, job, NULL); #endif return 0; } CcnetJob * ccnet_job_new () { CcnetJob *job; job = g_new0 (CcnetJob, 1); return job; } void ccnet_job_free (CcnetJob *job) { g_free (job); } CcnetJobManager * ccnet_job_manager_new (int max_threads) { CcnetJobManager *mgr; mgr = g_new0 (CcnetJobManager, 1); mgr->jobs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)ccnet_job_free); mgr->thread_pool = g_thread_pool_new (job_thread_wrapper, NULL, max_threads, FALSE, NULL); /* g_thread_pool_set_max_unused_threads (MAX_IDLE_THREADS); */ return mgr; } void ccnet_job_manager_free (CcnetJobManager *mgr) { g_hash_table_destroy (mgr->jobs); g_thread_pool_free (mgr->thread_pool, TRUE, FALSE); g_free (mgr); } int ccnet_job_manager_schedule_job (CcnetJobManager *mgr, JobThreadFunc func, JobDoneCallback done_func, void *data) { CcnetJob *job = ccnet_job_new (); job->id = mgr->next_job_id++; job->manager = mgr; job->thread_func = func; job->done_func = done_func; job->data = data; g_hash_table_insert (mgr->jobs, (gpointer)(long)job->id, job); if (job_thread_create (job) < 0) { g_hash_table_remove (mgr->jobs, (gpointer)(long)job->id); return -1; } return 0; } void ccnet_job_manager_remove_job (CcnetJobManager *mgr, int job_id) { g_hash_table_remove (mgr->jobs, (gpointer)(long)job_id); } #ifdef UNIT_TEST void ccnet_job_manager_wait_job (CcnetJobManager *mgr, int job_id) { CcnetJob *job; job = g_hash_table_lookup (mgr->jobs, (gpointer)(long)job_id); /* manually call job_done_cb */ job_done_cb (0, 0, (void *)job); } #endif ccnet-6.1.5/lib/libccnet_utils.c000066400000000000000000000516121317035602700165450ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include "libccnet_utils.h" #ifdef WIN32 #include #include #include #include #include #else #include #endif #ifndef WIN32 #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 int ccnet_util_pgpipe (ccnet_pipe_t handles[2]) { SOCKET s; struct sockaddr_in serv_addr; int len = sizeof( serv_addr ); handles[0] = handles[1] = INVALID_SOCKET; if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET ) { g_warning("pgpipe failed to create socket: %d\n", WSAGetLastError()); return -1; } memset( &serv_addr, 0, sizeof( serv_addr ) ); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(0); serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (bind(s, (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR) { g_warning("pgpipe failed to bind: %d\n", WSAGetLastError()); closesocket(s); return -1; } if (listen(s, 1) == SOCKET_ERROR) { g_warning("pgpipe failed to listen: %d\n", WSAGetLastError()); closesocket(s); return -1; } if (getsockname(s, (SOCKADDR *) & serv_addr, &len) == SOCKET_ERROR) { g_warning("pgpipe failed to getsockname: %d\n", WSAGetLastError()); closesocket(s); return -1; } if ((handles[1] = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { g_warning("pgpipe failed to create socket 2: %d\n", WSAGetLastError()); closesocket(s); return -1; } if (connect(handles[1], (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR) { g_warning("pgpipe failed to connect socket: %d\n", WSAGetLastError()); closesocket(s); return -1; } if ((handles[0] = accept(s, (SOCKADDR *) & serv_addr, &len)) == INVALID_SOCKET) { g_warning("pgpipe failed to accept socket: %d\n", WSAGetLastError()); closesocket(handles[1]); handles[1] = INVALID_SOCKET; closesocket(s); return -1; } closesocket(s); return 0; } #endif struct timeval ccnet_util_timeval_from_msec (uint64_t milliseconds) { struct timeval ret; const uint64_t microseconds = milliseconds * 1000; ret.tv_sec = microseconds / 1000000; ret.tv_usec = microseconds % 1000000; return ret; } int ccnet_util_checkdir (const char *dir) { struct stat st; #ifdef WIN32 /* remove trailing '\\' */ char *path = g_strdup(dir); char *p = (char *)path + strlen(path) - 1; while (*p == '\\' || *p == '/') *p-- = '\0'; if ((g_stat(dir, &st) < 0) || !S_ISDIR(st.st_mode)) { g_free (path); return -1; } g_free (path); return 0; #else if ((g_stat(dir, &st) < 0) || !S_ISDIR(st.st_mode)) return -1; return 0; #endif } int ccnet_util_checkdir_with_mkdir (const char *dir) { #ifdef WIN32 int ret; char *path = g_strdup(dir); char *p = (char *)path + strlen(path) - 1; while (*p == '\\' || *p == '/') *p-- = '\0'; ret = g_mkdir_with_parents(path, 0755); g_free (path); return ret; #else return g_mkdir_with_parents(dir, 0755); #endif } ssize_t /* Read "n" bytes from a descriptor. */ ccnet_util_recvn(evutil_socket_t fd, void *vptr, size_t n) { size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { #ifndef WIN32 if ( (nread = read(fd, ptr, nleft)) < 0) #else if ( (nread = recv(fd, ptr, nleft, 0)) < 0) #endif { if (errno == EINTR) nread = 0; /* and call read() again */ else return(-1); } else if (nread == 0) break; /* EOF */ nleft -= nread; ptr += nread; } return(n - nleft); /* return >= 0 */ } ssize_t /* Write "n" bytes to a descriptor. */ ccnet_util_sendn (evutil_socket_t fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { #ifndef WIN32 if ( (nwritten = write(fd, ptr, nleft)) <= 0) #else if ( (nwritten = send(fd, ptr, nleft, 0)) <= 0) #endif { if (nwritten < 0 && errno == EINTR) nwritten = 0; /* and call write() again */ else return(-1); /* error */ } nleft -= nwritten; ptr += nwritten; } return(n); } char* ccnet_util_expand_path (const char *src) { #ifdef WIN32 char new_path[PATH_MAX + 1]; char *p = new_path; const char *q = src; memset(new_path, 0, sizeof(new_path)); if (*src == '~') { const char *home = g_get_home_dir(); memcpy(new_path, home, strlen(home)); p += strlen(new_path); q++; } memcpy(p, q, strlen(q)); /* delete the charactor '\' or '/' at the end of the path * because the function stat faied to deal with directory names * with '\' or '/' in the end */ p = new_path + strlen(new_path) - 1; while(*p == '\\' || *p == '/') *p-- = '\0'; return strdup (new_path); #else const char *next_in, *ntoken; char new_path[PATH_MAX + 1]; char *next_out; int len; /* special cases */ if (!src || *src == '\0') return NULL; if (strlen(src) > PATH_MAX) return NULL; next_in = src; next_out = new_path; *next_out = '\0'; if (*src == '~') { /* handle src start with '~' or '~' like '~plt' */ struct passwd *pw = NULL; for ( ; *next_in != '/' && *next_in != '\0'; next_in++) ; len = next_in - src; if (len == 1) { pw = getpwuid (geteuid()); } else { /* copy '~' to new_path */ memcpy (new_path, src, len); new_path[len] = '\0'; pw = getpwnam (new_path + 1); } if (pw == NULL) return NULL; len = strlen (pw->pw_dir); memcpy (new_path, pw->pw_dir, len); next_out = new_path + len; *next_out = '\0'; if (*next_in == '\0') return strdup (new_path); } else if (*src != '/') { getcwd (new_path, PATH_MAX); for ( ; *next_out; next_out++) ; /* to '\0' */ } while (*next_in != '\0') { /* move ntoken to the next not '/' char */ for (ntoken = next_in; *ntoken == '/'; ntoken++) ; for (next_in = ntoken; *next_in != '/' && *next_in != '\0'; next_in++) ; len = next_in - ntoken; if (len == 0) { /* the path ends with '/', keep it */ *next_out++ = '/'; *next_out = '\0'; break; } if (len == 2 && ntoken[0] == '.' && ntoken[1] == '.') { /* '..' */ for (; next_out > new_path && *next_out != '/'; next_out--) ; *next_out = '\0'; } else if (ntoken[0] != '.' || len != 1) { /* not '.' */ *next_out++ = '/'; memcpy (next_out, ntoken, len); next_out += len; *next_out = '\0'; } } /* the final special case */ if (new_path[0] == '\0') { new_path[0] = '/'; new_path[1] = '\0'; } return strdup (new_path); #endif } #ifndef WIN32 char* ccnet_util_gen_uuid () { char *uuid_str = g_malloc (37); uuid_t uuid; uuid_generate (uuid); uuid_unparse_lower (uuid, uuid_str); return uuid_str; } #else char* ccnet_util_gen_uuid () { char *uuid_str = g_malloc (37); unsigned char *str = NULL; UUID uuid; UuidCreate(&uuid); UuidToString(&uuid, &str); memcpy(uuid_str, str, 37); RpcStringFree(&str); return uuid_str; } #endif char* ccnet_util_strjoin_n (const char *seperator, int argc, char **argv) { GString *buf; int i; char *str; if (argc == 0) return NULL; buf = g_string_new (argv[0]); for (i = 1; i < argc; ++i) { g_string_append (buf, seperator); g_string_append (buf, argv[i]); } str = buf->str; g_string_free (buf, FALSE); return str; } /** * handle the empty string problem. */ gchar* ccnet_util_key_file_get_string (GKeyFile *keyf, const char *category, const char *key) { gchar *v; if (!g_key_file_has_key (keyf, category, key, NULL)) return NULL; v = g_key_file_get_string (keyf, category, key, NULL); if (v != NULL && v[0] == '\0') { g_free(v); return NULL; } return v; } void ccnet_util_string_list_free (GList *str_list) { GList *ptr = str_list; while (ptr) { g_free (ptr->data); ptr = ptr->next; } g_list_free (str_list); } void ccnet_util_string_list_join (GList *str_list, GString *str, const char *seperator) { GList *ptr; if (!str_list) return; ptr = str_list; g_string_append (str, ptr->data); for (ptr = ptr->next; ptr; ptr = ptr->next) { g_string_append (str, seperator); g_string_append (str, (char *)ptr->data); } } static GList * string_list_parse (const char *list_in_str, const char *seperator) { if (!list_in_str) return NULL; GList *list = NULL; char **array = g_strsplit (list_in_str, seperator, 0); char **ptr; for (ptr = array; *ptr; ptr++) { list = g_list_prepend (list, g_strdup(*ptr)); } list = g_list_reverse (list); g_strfreev (array); return list; } GList * ccnet_util_string_list_parse_sorted (const char *list_in_str, const char *seperator) { GList *list = string_list_parse (list_in_str, seperator); return g_list_sort (list, (GCompareFunc)g_strcmp0); } static unsigned hexval(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return ~0; } int ccnet_util_hex_to_rawdata (const char *hex_str, unsigned char *rawdata, int n_bytes) { int i; for (i = 0; i < n_bytes; i++) { unsigned int val = (hexval(hex_str[0]) << 4) | hexval(hex_str[1]); if (val & ~0xff) return -1; *rawdata++ = val; hex_str += 2; } return 0; } #ifdef WIN32 #ifndef EAFNOSUPPORT #define EAFNOSUPPORT WSAEAFNOSUPPORT #endif #ifndef IN6ADDRSZ #define IN6ADDRSZ 16 #endif #ifndef INT16SZ #define INT16SZ 2 #endif #ifndef INADDRSZ #define INADDRSZ 4 #endif #ifndef inet_ntop static const char * inet_ntop4 (const u_char *src, char *dst, size_t size) { static const char fmt[] = "%u.%u.%u.%u"; char tmp[sizeof("255.255.255.255")]; int l; l = _snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]); if (l <= 0 || l >= size) { return (NULL); } strncpy(dst, tmp, size); return (dst); } static const char * inet_ntop6 (const u_char *src, char *dst, size_t size) { char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; char *tp, *ep; struct { int base, len; } best, cur; u_int words[IN6ADDRSZ / INT16SZ]; int i; int advance; memset(words, '\0', sizeof(words)); for (i = 0; i < IN6ADDRSZ; i++) words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); best.base = -1; cur.base = -1; best.len = -1; cur.len = -1; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else { if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } } if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; } if (best.base != -1 && best.len < 2) best.base = -1; tp = tmp; ep = tmp + sizeof(tmp); for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) { /** Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } continue; } /** Are we following an initial run of 0x00s or any real hex? */ if (i != 0) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } /** Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) return (NULL); tp += strlen(tp); break; } advance = snprintf(tp, ep - tp, "%x", words[i]); if (advance <= 0 || advance >= ep - tp) return (NULL); tp += advance; } /** Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { if (tp + 1 >= ep) return (NULL); *tp++ = ':'; } if (tp + 1 >= ep) return (NULL); *tp++ = '\0'; /** * Check for overflow, copy, and we're done. */ if ((size_t)(tp - tmp) > size) { errno = ENOSPC; return (NULL); } strncpy(dst, tmp, size); dst[size] = '\0'; return (dst); } const char * ccnet_util_inet_ntop(int af, const void *src, char *dst, size_t size) { switch (af) { case AF_INET: return (inet_ntop4(src, dst, size)); case AF_INET6: return (inet_ntop6(src, dst, size)); default: return (NULL); } /** NOTREACHED */ } #endif //inet_ntop #ifndef inet_aton int ccnet_util_inet_aton (const char *string, struct in_addr *addr) { addr->s_addr = inet_addr(string); if (addr->s_addr != -1 || strcmp("255.255.255.255", string) == 0) return 1; return 0; } #endif #ifndef inet_pton /* * Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ /* int * inet_pton4(src, dst, pton) * when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand. * when last arg is 1: inet_pton(). decimal dotted-quad only. * return: * 1 if `src' is a valid input, else 0. * notice: * does not touch `dst' unless it's returning 1. * author: * Paul Vixie, 1996. */ static int inet_pton4 (const char *src, u_char *dst, int pton) { u_int val; u_int digit; int base, n; unsigned char c; u_int parts[4]; register u_int *pp = parts; c = *src; for (;;) { /* * Collect number up to ``.''. * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ if (!isdigit(c)) return (0); val = 0; base = 10; if (c == '0') { c = *++src; if (c == 'x' || c == 'X') base = 16, c = *++src; else if (isdigit(c) && c != '9') base = 8; } /* inet_pton() takes decimal only */ if (pton && base != 10) return (0); for (;;) { if (isdigit(c)) { digit = c - '0'; if (digit >= base) break; val = (val * base) + digit; c = *++src; } else if (base == 16 && isxdigit(c)) { digit = c + 10 - (islower(c) ? 'a' : 'A'); if (digit >= 16) break; val = (val << 4) | digit; c = *++src; } else break; } if (c == '.') { /* * Internet format: * a.b.c.d * a.b.c (with c treated as 16 bits) * a.b (with b treated as 24 bits) * a (with a treated as 32 bits) */ if (pp >= parts + 3) return (0); *pp++ = val; c = *++src; } else break; } /* * Check for trailing characters. */ if (c != '\0' && !isspace(c)) return (0); /* * Concoct the address according to * the number of parts specified. */ n = pp - parts + 1; /* inet_pton() takes dotted-quad only. it does not take shorthand. */ if (pton && n != 4) return (0); switch (n) { case 0: return (0); /* initial nondigit */ case 1: /* a -- 32 bits */ break; case 2: /* a.b -- 8.24 bits */ if (parts[0] > 0xff || val > 0xffffff) return (0); val |= parts[0] << 24; break; case 3: /* a.b.c -- 8.8.16 bits */ if ((parts[0] | parts[1]) > 0xff || val > 0xffff) return (0); val |= (parts[0] << 24) | (parts[1] << 16); break; case 4: /* a.b.c.d -- 8.8.8.8 bits */ if ((parts[0] | parts[1] | parts[2] | val) > 0xff) return (0); val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); break; } if (dst) { val = htonl(val); memcpy(dst, &val, INADDRSZ); } return (1); } /* int * inet_pton6(src, dst) * convert presentation level address to network order binary form. * return: * 1 if `src' is a valid [RFC1884 2.2] address, else 0. * notice: * (1) does not touch `dst' unless it's returning 1. * (2) :: in a full address is silently ignored. * credit: * inspired by Mark Andrews. * author: * Paul Vixie, 1996. */ static int inet_pton6 (const char *src, u_char *dst) { static const char xdigits_l[] = "0123456789abcdef", xdigits_u[] = "0123456789ABCDEF"; u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp; const char *xdigits, *curtok; int ch, saw_xdigit; u_int val; memset((tp = tmp), '\0', IN6ADDRSZ); endp = tp + IN6ADDRSZ; colonp = NULL; /* Leading :: requires some special handling. */ if (*src == ':') if (*++src != ':') return (0); curtok = src; saw_xdigit = 0; val = 0; while ((ch = *src++) != '\0') { const char *pch; if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) pch = strchr((xdigits = xdigits_u), ch); if (pch != NULL) { val <<= 4; val |= (pch - xdigits); if (val > 0xffff) return (0); saw_xdigit = 1; continue; } if (ch == ':') { curtok = src; if (!saw_xdigit) { if (colonp) return (0); colonp = tp; continue; } else if (*src == '\0') return (0); if (tp + INT16SZ > endp) return (0); *tp++ = (u_char) (val >> 8) & 0xff; *tp++ = (u_char) val & 0xff; saw_xdigit = 0; val = 0; continue; } if (ch == '.' && ((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp, 1) > 0) { tp += INADDRSZ; saw_xdigit = 0; break; /* '\0' was seen by inet_pton4(). */ } return (0); } if (saw_xdigit) { if (tp + INT16SZ > endp) return (0); *tp++ = (u_char) (val >> 8) & 0xff; *tp++ = (u_char) val & 0xff; } if (colonp != NULL) { /* * Since some memmove()'s erroneously fail to handle * overlapping regions, we'll do the shift by hand. */ const int n = tp - colonp; int i; if (tp == endp) return (0); for (i = 1; i <= n; i++) { endp[- i] = colonp[n - i]; colonp[n - i] = 0; } tp = endp; } if (tp != endp) return (0); memcpy(dst, tmp, IN6ADDRSZ); return (1); } /* int * inet_pton(af, src, dst) * convert from presentation format (which usually means ASCII printable) * to network format (which is usually some kind of binary format). * return: * 1 if the address was valid for the specified address family * 0 if the address wasn't valid (`dst' is untouched in this case) * -1 if some other error occurred (`dst' is untouched in this case, too) * author: * Paul Vixie, 1996. */ int ccnet_util_inet_pton (int af, const char *src, void *dst) { switch (af) { case AF_INET: return (inet_pton4(src, dst, 1)); case AF_INET6: return (inet_pton6(src, dst)); default: errno = EAFNOSUPPORT; return (-1); } /* NOTREACHED */ } #endif #endif //WIN32 ccnet-6.1.5/lib/libccnet_utils.h000066400000000000000000000046701317035602700165540ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef LIBCCNET_UTILS_H #define LIBCCNET_UTILS_H /** * All the helper function names are prefixed with ccnet_util_XXX to avoid * name conflict. */ #include #include #include #include #include #include #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #ifdef WIN32 #include #include #ifndef WEXITSTATUS #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) #endif /* Borrowed from libevent */ #define ccnet_pipe_t intptr_t int ccnet_util_pgpipe (ccnet_pipe_t handles[2]); #define ccnet_util_pipe(a) ccnet_util_pgpipe((a)) #define ccnet_util_pipeclose(a) closesocket((a)) #else #define ccnet_pipe_t int #define ccnet_util_pipe(a) pipe((a)) #define ccnet_util_pipeclose(a) close((a)) #endif #define ccnet_util_pipereadn(a,b,c) ccnet_util_recvn((a),(b),(c)) #define ccnet_util_pipewriten(a,b,c) ccnet_util_sendn((a),(b),(c)) #ifndef O_BINARY #define O_BINARY 0 #endif struct timeval ccnet_util_timeval_from_msec (uint64_t milliseconds); char* ccnet_util_gen_uuid (); /* dir operations */ int ccnet_util_checkdir (const char *dir); char* ccnet_util_expand_path (const char *src); /* Read "n" bytes from a socket. */ ssize_t ccnet_util_recvn(evutil_socket_t fd, void *vptr, size_t n); ssize_t ccnet_util_sendn(evutil_socket_t fd, const void *vptr, size_t n); /* string utilities */ char * ccnet_util_strjoin_n (const char *seperator, int argc, char **argv); void ccnet_util_string_list_free (GList *str_list); void ccnet_util_string_list_join (GList *str_list, GString *strbuf, const char *seperator); GList *ccnet_util_string_list_parse_sorted (const char *list_in_str, const char *seperator); gchar* ccnet_util_key_file_get_string (GKeyFile *keyf, const char *category, const char *key); #define ccnet_util_hex_to_sha1(hex, sha1) \ ccnet_util_hex_to_rawdata((hex), (sha1), 20) int ccnet_util_hex_to_rawdata (const char *hex_str, unsigned char *rawdata, int n_bytes); #ifdef WIN32 int ccnet_util_inet_pton(int af, const char *src, void *dst); #else #define ccnet_util_inet_pton inet_pton #endif #endif ccnet-6.1.5/lib/mainloop.c000066400000000000000000000102411317035602700153510ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #else #include #endif static int cmdrsp_cb (const char *code, char *content, int clen, void *data) { RegisterServiceCB cb = data; if (clen != 0) ccnet_debug ("Receive cmd response {\n%s}\n", content); else ccnet_debug ("Receive cmd response null\n"); if (cb) { if (memcmp (SC_SERV_EXISTED, code, 3) == 0) cb (FALSE); else cb (TRUE); } return 0; } void ccnet_register_service (CcnetClient *client, const char *service, const char *group, GType proc_type, RegisterServiceCB cb) { char buf[512]; g_return_if_fail (group); ccnet_proc_factory_register_processor (client->proc_factory, service, proc_type); snprintf (buf, 512, "register-service %s %s", service, group); ccnet_send_command (client, buf, cmdrsp_cb, cb); } gboolean ccnet_register_service_sync (CcnetClient *client, const char *service, const char *group) { char buf[512]; GError *error = NULL; snprintf (buf, 512, "register-service %s %s", service, group); ccnet_client_send_cmd (client, buf, &error); if (error) { ccnet_warning ("Bad response for register service %s: %d %s", service, error->code, error->message); return FALSE; } return TRUE; } static void read_cb (evutil_socket_t fd, short event, void *vclient) { CcnetClient *client = vclient; if (ccnet_client_read_input (client) <= 0) { ccnet_client_disconnect_daemon (client); exit (1); } } /** * Inititialize ccnet client structure, connect daemon and initialize * event loop. */ CcnetClient * ccnet_init (const char *central_config_dir, const char *confdir) { CcnetClient *client; client = ccnet_client_new (); if ( (ccnet_client_load_confdir(client, central_config_dir, confdir)) < 0 ) { ccnet_warning ("Read config dir error\n"); return NULL; } if (ccnet_client_connect_daemon (client, CCNET_CLIENT_ASYNC) < 0) { ccnet_warning ("Connect to ccnet daemon error\n"); exit(1); } ccnet_client_run_synchronizer (client); event_init (); return client; } void ccnet_main (CcnetClient *client) { struct event ev; event_set (&ev, client->connfd, EV_READ | EV_PERSIST, read_cb, client); event_add (&ev, NULL); event_dispatch (); } void ccnet_send_command (CcnetClient *client, const char *command, SendcmdProcRcvrspCallback cmd_cb, void *cbdata) { CcnetSendcmdProc *sendcmd_proc = (CcnetSendcmdProc *) ccnet_proc_factory_create_master_processor (client->proc_factory, "send-cmd"); ccnet_sendcmd_proc_set_rcvrsp_cb (sendcmd_proc, cmd_cb, cbdata); ccnet_processor_start (CCNET_PROCESSOR(sendcmd_proc), 0, NULL); ccnet_sendcmd_proc_send_command (sendcmd_proc, command); } /* add-peer [--id ] [--addr ] */ void ccnet_add_peer (CcnetClient *client, const char *id, const char *addr) { char buf[256]; if (id == NULL || strlen(id) != 40 || addr == NULL) return; snprintf (buf, 256, "add-peer --id %s --addr %s", id, addr); ccnet_send_command (client, buf, NULL, NULL); } void ccnet_connect_peer (CcnetClient *client, const char *id) { char buf[256]; if (id == NULL || strlen(id) != 40) return; snprintf (buf, 256, "connect %s", id); ccnet_send_command (client, buf, NULL, NULL); } void ccnet_disconnect_peer (CcnetClient *client, const char *id) { char buf[256]; if (id == NULL || strlen(id) != 40) return; snprintf (buf, 256, "disconnect %s", id); ccnet_send_command (client, buf, NULL, NULL); } ccnet-6.1.5/lib/marshal.c000066400000000000000000000077271317035602700152010ustar00rootroot00000000000000 #include #ifdef G_ENABLE_DEBUG #define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) #define g_marshal_value_peek_char(v) g_value_get_char (v) #define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) #define g_marshal_value_peek_int(v) g_value_get_int (v) #define g_marshal_value_peek_uint(v) g_value_get_uint (v) #define g_marshal_value_peek_long(v) g_value_get_long (v) #define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) #define g_marshal_value_peek_int64(v) g_value_get_int64 (v) #define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) #define g_marshal_value_peek_enum(v) g_value_get_enum (v) #define g_marshal_value_peek_flags(v) g_value_get_flags (v) #define g_marshal_value_peek_float(v) g_value_get_float (v) #define g_marshal_value_peek_double(v) g_value_get_double (v) #define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) #define g_marshal_value_peek_param(v) g_value_get_param (v) #define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) #define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) #define g_marshal_value_peek_object(v) g_value_get_object (v) #else /* !G_ENABLE_DEBUG */ /* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. * Do not access GValues directly in your code. Instead, use the * g_value_get_*() functions */ #define g_marshal_value_peek_boolean(v) (v)->data[0].v_int #define g_marshal_value_peek_char(v) (v)->data[0].v_int #define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint #define g_marshal_value_peek_int(v) (v)->data[0].v_int #define g_marshal_value_peek_uint(v) (v)->data[0].v_uint #define g_marshal_value_peek_long(v) (v)->data[0].v_long #define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong #define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 #define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 #define g_marshal_value_peek_enum(v) (v)->data[0].v_long #define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong #define g_marshal_value_peek_float(v) (v)->data[0].v_float #define g_marshal_value_peek_double(v) (v)->data[0].v_double #define g_marshal_value_peek_string(v) (v)->data[0].v_pointer #define g_marshal_value_peek_param(v) (v)->data[0].v_pointer #define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer #define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer #define g_marshal_value_peek_object(v) (v)->data[0].v_pointer #endif /* !G_ENABLE_DEBUG */ /* VOID:POINTER,STRING (marshal.list:1) */ void g_cclosure_user_marshal_VOID__POINTER_STRING (GClosure *closure, GValue *return_value G_GNUC_UNUSED, guint n_param_values, const GValue *param_values, gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data) { typedef void (*GMarshalFunc_VOID__POINTER_STRING) (gpointer data1, gpointer arg_1, gpointer arg_2, gpointer data2); register GMarshalFunc_VOID__POINTER_STRING callback; register GCClosure *cc = (GCClosure*) closure; register gpointer data1, data2; g_return_if_fail (n_param_values == 3); if (G_CCLOSURE_SWAP_DATA (closure)) { data1 = closure->data; data2 = g_value_peek_pointer (param_values + 0); } else { data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } callback = (GMarshalFunc_VOID__POINTER_STRING) (marshal_data ? marshal_data : cc->callback); callback (data1, g_marshal_value_peek_pointer (param_values + 1), g_marshal_value_peek_string (param_values + 2), data2); } ccnet-6.1.5/lib/marshal.h000066400000000000000000000013711317035602700151730ustar00rootroot00000000000000 #ifndef __g_cclosure_user_marshal_MARSHAL_H__ #define __g_cclosure_user_marshal_MARSHAL_H__ #include G_BEGIN_DECLS /* VOID:POINTER,STRING (marshal.list:1) */ extern void g_cclosure_user_marshal_VOID__POINTER_STRING (GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data); G_END_DECLS #endif /* __g_cclosure_user_marshal_MARSHAL_H__ */ ccnet-6.1.5/lib/marshal.list000066400000000000000000000000241317035602700157110ustar00rootroot00000000000000VOID:POINTER,STRING ccnet-6.1.5/lib/message.c000066400000000000000000000152201317035602700151610ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include "message.h" enum { P_ID = 1, P_FLAGS, P_FROM, P_TO, P_CTIME, P_RTIME, P_APP, P_BODY, }; G_DEFINE_TYPE (CcnetMessage, ccnet_message, G_TYPE_OBJECT); static void set_property (GObject *object, guint property_id, const GValue *v, GParamSpec *pspec) { /* CcnetMessage *message = CCNET_MESSAGE (object); */ switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); return; } } static void get_property (GObject *object, guint property_id, GValue *v, GParamSpec *pspec) { CcnetMessage *message = CCNET_MESSAGE (object); switch (property_id) { case P_ID: g_value_set_string (v, message->id); break; case P_FLAGS: g_value_set_uint (v, message->flags); break; case P_FROM: g_value_set_string (v, message->from); break; case P_TO: g_value_set_string (v, message->to); break; case P_CTIME: g_value_set_uint (v, message->ctime); break; case P_RTIME: g_value_set_uint (v, message->rtime); break; case P_APP: g_value_set_string (v, message->app); break; case P_BODY: g_value_set_string (v, message->body); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void finalize (GObject *object) { CcnetMessage *message = (CcnetMessage *)object; g_free (message->app); g_free (message->id); g_free (message->body); } static void ccnet_message_class_init (CcnetMessageClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = set_property; gobject_class->get_property = get_property; gobject_class->finalize = finalize; g_object_class_install_property (gobject_class, P_ID, g_param_spec_string ("id", NULL, "ID", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_FLAGS, g_param_spec_uint ("flags", NULL, "Flags", 0, UINT_MAX, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_FROM, g_param_spec_string ("from_id", NULL, "From ID", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_TO, g_param_spec_string ("to_id", NULL, "To ID", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_CTIME, g_param_spec_uint ("ctime", NULL, "Creation Time", 0, UINT_MAX, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_RTIME, g_param_spec_uint ("rtime", NULL, "Receiving Time", 0, UINT_MAX, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_APP, g_param_spec_string ("app", NULL, "application", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_BODY, g_param_spec_string ("body", NULL, "message body", NULL, G_PARAM_READWRITE)); } static void ccnet_message_init (CcnetMessage *message) { } CcnetMessage * ccnet_message_new_full (const char *from, const char *to, const char *app, const char *body, time_t ctime, time_t rcv_time, const char *msg_id, int flags) { CcnetMessage *message; if (!from || !to || !app) return NULL; message = g_object_new (CCNET_TYPE_MESSAGE, NULL); message->flags = flags; memcpy (message->from, from, 40); message->from[40] = '\0'; memcpy (message->to, to, 40); message->to[40] = '\0'; message->app = g_strdup(app); message->body = g_strdup(body); message->ctime = (ctime ? ctime : time(NULL)); message->rtime = rcv_time; message->id = (msg_id ? g_strdup (msg_id) : ccnet_util_gen_uuid()); return message; } CcnetMessage * ccnet_message_new (const char *from, const char *to, const char *app, const char *body, int flags) { return ccnet_message_new_full (from, to, app, body, 0, 0, NULL, flags); } void ccnet_message_free (CcnetMessage *message) { g_object_unref (message); } void ccnet_message_to_string_buf (CcnetMessage *msg, GString *buf) { g_string_printf (buf, "%d %s %s %s %d %d %s %s", msg->flags, msg->from, msg->to, msg->id, (int)msg->ctime, (int)msg->rtime, msg->app, msg->body); } CcnetMessage * ccnet_message_from_string (char *buf, int len) { char flags; int is_group_msg; char *from_id, *to_id, *msg_id, *body, *p, *end, *app; int ctime, rcv_time = 0; CcnetMessage *message; g_return_val_if_fail (buf[len-1] == '\0', NULL); p = buf + 1; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; flags = atoi (buf); is_group_msg = flags & FLAG_TO_GROUP; from_id = ++p; p += 40; g_return_val_if_fail (*p == ' ', NULL); *p = '\0'; to_id = ++p; if (!is_group_msg) p += 40; /* SHA-1 */ else p += 36; /* UUID */ g_return_val_if_fail (*p == ' ', NULL); *p = '\0'; msg_id = ++p; p += 36; g_return_val_if_fail (*p == ' ', NULL); *p++ = '\0'; end = strchr (p, ' '); *end = '\0'; ctime = atoi (p); p = end + 1; end = strchr (p, ' '); *end = '\0'; rcv_time = atoi (p); p = app = end + 1; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; body = p + 1; message = ccnet_message_new_full (from_id, to_id, app, body, ctime, rcv_time, msg_id, flags); return message; error: return NULL; } gboolean ccnet_message_is_to_group(CcnetMessage *msg) { return msg->flags & FLAG_TO_GROUP; } void ccnet_message_body_take (CcnetMessage *msg, char *body) { msg->body = body; } void ccnet_message_body_dup (CcnetMessage *msg, char *body) { msg->body = g_strdup (body); } ccnet-6.1.5/lib/mqclient-proc.c000066400000000000000000000102461317035602700163150ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include #include "ccnet-client.h" #include "mqclient-proc.h" #define SC_MSG "300" #define SC_UNSUBSCRIBE "301" enum { INIT, REQUEST_SENT, READY }; enum { RECV_MSG_SIG, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static int mq_client_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetMqclientProc, ccnet_mqclient_proc, CCNET_TYPE_PROCESSOR) static void ccnet_mqclient_proc_class_init (CcnetMqclientProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->start = mq_client_start; proc_class->handle_response = handle_response; proc_class->name = "mqclient-proc"; signals[RECV_MSG_SIG] = g_signal_new ("recv-msg", CCNET_TYPE_MQCLIENT_PROC , G_SIGNAL_RUN_LAST, 0, NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, CCNET_TYPE_MESSAGE); } static void ccnet_mqclient_proc_init (CcnetMqclientProc *processor) { CCNET_PROCESSOR (processor)->state = INIT; } static int mq_client_start (CcnetProcessor *processor, int argc, char **argv) { GString *buf; int i; buf = g_string_new ("mq-server"); for (i = 0; i < argc; ++i) { g_string_append (buf, " "); g_string_append (buf, argv[i]); } ccnet_client_send_request (processor->session, REQUEST_ID (processor->id), buf->str); processor->state = REQUEST_SENT; g_string_free (buf, TRUE); return 0; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetMqclientProc *proc = (CcnetMqclientProc *) processor; CcnetMessage *msg; switch (processor->state) { case REQUEST_SENT: if (code[0] != '2') { g_warning ("receive bad response: %s %s\n", code, code_msg); ccnet_processor_done (processor, FALSE); return; } processor->state = READY; break; case READY: if (code[0] != '2' && code[0] != '3') { g_warning ("receive bad response: %s %s\n", code, code_msg); return; } /* message notification. */ if (code[0] == '3' && code[2] == '0') { msg = ccnet_message_from_string (content, clen); if (!msg) { g_warning ("Wrong message format.\n"); ccnet_processor_done (processor, FALSE); break; } if (proc->message_got_cb) proc->message_got_cb (msg, proc->cb_data); g_signal_emit (proc, signals[RECV_MSG_SIG], 0, msg); ccnet_message_free (msg); } break; default: break; } } void ccnet_mqclient_proc_set_message_got_cb (CcnetMqclientProc *processor, MessageGotCB callback, void *cb_data) { processor->message_got_cb = callback; processor->cb_data = cb_data; } void ccnet_mqclient_proc_put_message (CcnetMqclientProc *proc, CcnetMessage *message) { CcnetProcessor *processor = (CcnetProcessor *) proc; GString *msg_buf; msg_buf = g_string_new (NULL); ccnet_message_to_string_buf (message, msg_buf); ccnet_client_send_update (processor->session, UPDATE_ID(processor->id), SC_MSG, NULL, msg_buf->str, msg_buf->len+1); g_string_free (msg_buf, TRUE); } void ccnet_mqclient_proc_unsubscribe_apps (CcnetMqclientProc *proc) { CcnetProcessor *processor = (CcnetProcessor *) proc; ccnet_client_send_update (processor->session, UPDATE_ID(processor->id), SC_UNSUBSCRIBE, NULL, NULL, 0); ccnet_processor_done (processor, TRUE); } ccnet-6.1.5/lib/net.c000066400000000000000000000245751317035602700143400ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifdef WIN32 #define WINVER 0x0501 #endif #include "include.h" #include #include #include #include #include #ifdef WIN32 #include #include #include #include #define UNUSED #else #include #include #include #include #include #include #include #include #include #endif #include #include "net.h" #ifdef WIN32 #ifndef inet_aton int inet_aton(const char *string, struct in_addr *addr) { addr->s_addr = inet_addr(string); if (addr->s_addr != -1 || strcmp("255.255.255.255", string) == 0) return 1; return 0; } #endif #endif //WIN32 int ccnet_netSetTOS (evutil_socket_t s, int tos) { #ifdef IP_TOS return setsockopt( s, IPPROTO_IP, IP_TOS, (char*)&tos, sizeof( tos ) ); #else return 0; #endif } static evutil_socket_t makeSocketNonBlocking (evutil_socket_t fd) { if (fd >= 0) { if (evutil_make_socket_nonblocking(fd)) { ccnet_warning ("Couldn't make socket nonblock: %s", evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR())); evutil_closesocket(fd); fd = -1; } } return fd; } static evutil_socket_t createSocket (int family, int nonblock) { evutil_socket_t fd; int ret; fd = socket (family, SOCK_STREAM, 0); if (fd < 0) { ccnet_warning("create Socket failed %d\n", fd); } else if (nonblock) { int nodelay = 1; fd = makeSocketNonBlocking( fd ); ret = setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); if (ret < 0) { ccnet_warning("setsockopt failed\n"); evutil_closesocket(fd); return -1; } } return fd; } evutil_socket_t ccnet_net_open_tcp (const struct sockaddr *sa, int nonblock) { evutil_socket_t s; int sa_len; if( (s = createSocket(sa->sa_family, nonblock)) < 0 ) return -1; #ifndef WIN32 if (sa->sa_family == AF_INET) sa_len = sizeof (struct sockaddr_in); else sa_len = sizeof (struct sockaddr_in6); #else if (sa->sa_family == AF_INET) sa_len = sizeof (struct sockaddr_in); else return -1; #endif if( (connect(s, sa, sa_len) < 0) #ifdef WIN32 && (sockerrno != WSAEWOULDBLOCK) #endif && (sockerrno != EINPROGRESS) ) { evutil_closesocket(s); s = -1; } return s; } evutil_socket_t ccnet_net_bind_tcp (int port, int nonblock) { #ifndef WIN32 int sockfd, n; struct addrinfo hints, *res, *ressave; char buf[10]; memset (&hints, 0,sizeof (struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf (buf, sizeof(buf), "%d", port); if ( (n = getaddrinfo(NULL, buf, &hints, &res) ) != 0) { ccnet_warning ("getaddrinfo fails: %s\n", gai_strerror(n)); return -1; } ressave = res; do { int on = 1; sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) continue; /* error - try next one */ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { ccnet_warning ("setsockopt of SO_REUSEADDR error\n"); continue; } if (nonblock) sockfd = makeSocketNonBlocking (sockfd); if (sockfd < 0) continue; /* error - try next one */ if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0) break; /* success */ close(sockfd); /* bind error - close and try next one */ } while ( (res = res->ai_next) != NULL); freeaddrinfo (ressave); if (res == NULL) { ccnet_warning ("bind fails: %s\n", strerror(errno)); return -1; } return sockfd; #else evutil_socket_t s; struct sockaddr_in sock; const int type = AF_INET; #if defined( SO_REUSEADDR ) || defined( SO_REUSEPORT ) int optval; #endif if ((s = createSocket(type, nonblock)) < 0) return -1; optval = 1; setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(optval)); memset(&sock, 0, sizeof(sock)); sock.sin_family = AF_INET; sock.sin_addr.s_addr = INADDR_ANY; sock.sin_port = htons(port); if ( bind(s, (struct sockaddr *)&sock, sizeof(struct sockaddr_in)) < 0) { ccnet_warning ("bind fails: %s\n", strerror(errno)); evutil_closesocket (s); return -1; } if (nonblock) s = makeSocketNonBlocking (s); return s; #endif } evutil_socket_t ccnet_net_accept (evutil_socket_t b, struct sockaddr_storage *cliaddr, socklen_t *len, int nonblock) { evutil_socket_t s; /* int nodelay = 1; */ s = accept (b, (struct sockaddr *)cliaddr, len); /* setsockopt (s, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); */ if (nonblock) makeSocketNonBlocking(s); return s; } evutil_socket_t ccnet_net_bind_v4 (const char *ipaddr, int *port) { evutil_socket_t sockfd; struct sockaddr_in addr; int on = 1; sockfd = socket (AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { ccnet_warning("create socket failed: %s\n", strerror(errno)); exit(-1); } memset (&addr, 0, sizeof (struct sockaddr_in)); addr.sin_family = AF_INET; if (inet_aton(ipaddr, &addr.sin_addr) == 0) { ccnet_warning ("Bad ip address %s\n", ipaddr); return -1; } addr.sin_port = htons (*port); if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { ccnet_warning ("setsockopt of SO_REUSEADDR error: %s\n", strerror(errno)); return -1; } if ( bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { ccnet_warning ("Bind error: %s\n", strerror (errno)); return -1; } if (*port == 0) { struct sockaddr_storage ss; socklen_t len; len = sizeof(ss); if (getsockname(sockfd, (struct sockaddr *)&ss, &len) < 0) { ccnet_warning ("getsockname error: %s\n", strerror(errno)); return -1; } *port = sock_port ((struct sockaddr *)&ss); } return sockfd; } char * sock_ntop(const struct sockaddr *sa, socklen_t salen) { static char str[128]; /* Unix domain is largest */ switch (sa->sa_family) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *) sa; if (evutil_inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) return(NULL); return(str); } #ifdef IPv6 case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; if (evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str) - 1) == NULL) return(NULL); return (str); } #endif #ifndef WIN32 #ifdef AF_UNIX case AF_UNIX: { struct sockaddr_un *unp = (struct sockaddr_un *) sa; /* OK to have no pathname bound to the socket: happens on every connect() unless client calls bind() first. */ if (unp->sun_path[0] == 0) strcpy(str, "(no pathname bound)"); else snprintf(str, sizeof(str), "%s", unp->sun_path); return(str); } #endif #endif default: snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen); return(str); } return (NULL); } int sock_pton (const char *addr_str, uint16_t port, struct sockaddr_storage *sa) { struct sockaddr_in *saddr = (struct sockaddr_in *) sa; #ifndef WIN32 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) sa; #endif if (evutil_inet_pton (AF_INET, addr_str, &saddr->sin_addr) == 1 ) { saddr->sin_family = AF_INET; saddr->sin_port = htons (port); return 0; } #ifndef WIN32 else if (evutil_inet_pton (AF_INET6, addr_str, &saddr6->sin6_addr) == 1) { saddr6->sin6_family = AF_INET6; saddr6->sin6_port = htons (port); return 0; } #endif return -1; } /* return 1 if addr_str is a valid ipv4 or ipv6 address */ int is_valid_ipaddr (const char *addr_str) { struct sockaddr_storage addr; if (!addr_str) return 0; if (sock_pton(addr_str, 0, &addr) < 0) return 0; return 1; } uint16_t sock_port (const struct sockaddr *sa) { switch (sa->sa_family) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *) sa; return ntohs(sin->sin_port); } #ifdef IPv6 case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; return ntohs(sin6->sin6_port); } #endif default: return 0; } return 0; } evutil_socket_t udp_client (const char *host, const char *serv, struct sockaddr **saptr, socklen_t *lenp) { evutil_socket_t sockfd; int n; struct addrinfo hints, *res, *ressave; memset (&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) { ccnet_warning ("udp_client error for %s, %s: %s", host, serv, gai_strerror(n)); return -1; } ressave = res; do { sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd >= 0) break; /* success */ } while ( (res = res->ai_next) != NULL); if (res == NULL) { /* errno set from final socket() */ ccnet_warning ("udp_client error for %s, %s", host, serv); freeaddrinfo (ressave); return -1; } *saptr = malloc(res->ai_addrlen); memcpy(*saptr, res->ai_addr, res->ai_addrlen); *lenp = res->ai_addrlen; freeaddrinfo(ressave); return (sockfd); } int family_to_level(int family) { switch (family) { case AF_INET: return IPPROTO_IP; #ifdef IPV6 case AF_INET6: return IPPROTO_IPV6; #endif default: return -1; } } int sockfd_to_family(evutil_socket_t sockfd) { struct sockaddr_storage ss; socklen_t len; len = sizeof(ss); if (getsockname(sockfd, (struct sockaddr *) &ss, &len) < 0) return(-1); return(ss.ss_family); } ccnet-6.1.5/lib/net.h000066400000000000000000000041651317035602700143360ustar00rootroot00000000000000 #ifndef CCNET_NET_H #define CCNET_NET_H #ifdef WIN32 #include #include #include typedef int socklen_t; #define UNUSED #else #include #include #include #include #include #include #include #include #endif #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #ifdef WIN32 /* #define ECONNREFUSED WSAECONNREFUSED */ /* #define ECONNRESET WSAECONNRESET */ /* #define EHOSTUNREACH WSAEHOSTUNREACH */ /* #define EINPROGRESS WSAEINPROGRESS */ /* #define ENOTCONN WSAENOTCONN */ /* #define EWOULDBLOCK WSAEWOULDBLOCK */ #define sockerrno WSAGetLastError( ) #else #include #define sockerrno errno #endif #ifdef WIN32 extern int inet_aton(const char *string, struct in_addr *addr); extern const char *inet_ntop(int af, const void *src, char *dst, size_t size); extern int inet_pton(int af, const char *src, void *dst); #endif evutil_socket_t ccnet_net_open_tcp (const struct sockaddr *sa, int nonblock); evutil_socket_t ccnet_net_bind_tcp (int port, int nonblock); evutil_socket_t ccnet_net_accept (evutil_socket_t b, struct sockaddr_storage *cliaddr, socklen_t *len, int nonblock); /* bind to an IPv4 address, if (*port == 0) the port number will be returned */ evutil_socket_t ccnet_net_bind_v4 (const char *ipaddr, int *port); int ccnet_netSetTOS ( evutil_socket_t s, int tos ); char *sock_ntop(const struct sockaddr *sa, socklen_t salen); uint16_t sock_port (const struct sockaddr *sa); /* return 1 if addr_str is a valid ipv4 or ipv6 address */ int is_valid_ipaddr (const char *addr_str); /* return 0 if success, -1 if error */ int sock_pton (const char *addr_str, uint16_t port, struct sockaddr_storage *sa); evutil_socket_t udp_client (const char *host, const char *serv, struct sockaddr **saptr, socklen_t *lenp); #endif ccnet-6.1.5/lib/packet-io.c000066400000000000000000000116041317035602700154130ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include #ifdef WIN32 #include #else #include #endif #include #include #include #include #include #include #include #include "packet.h" #include "packet-io.h" #include "buffer.h" static ssize_t /* Write "n" bytes to a descriptor. */ writen(evutil_socket_t fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { #ifndef WIN32 if ( (nwritten = write(fd, ptr, nleft)) <= 0) { #else if ( (nwritten = send(fd, (char *)ptr, nleft, 0)) <= 0) { #endif if (nwritten < 0 && errno == EINTR) nwritten = 0; /* and call write() again */ else return(-1); /* error */ } nleft -= nwritten; ptr += nwritten; } return(n); } static ssize_t /* Read "n" bytes from a descriptor. */ readn(evutil_socket_t fd, struct buffer *buf, size_t n) { size_t nleft; ssize_t nread; nleft = n; while (nleft > 0) { if ( (nread = buffer_read(buf, fd, nleft)) < 0) { if (errno == EINTR) nread = 0; /* and call read() again */ else return(-1); } else if (nread == 0) break; /* EOF */ nleft -= nread; } return(n - nleft); /* return >= 0 */ } CcnetPacketIO* ccnet_packet_io_new (evutil_socket_t fd) { CcnetPacketIO *io; io = g_malloc (sizeof(CcnetPacketIO)); io->fd = fd; io->buffer = buffer_new (); io->in_buf = buffer_new (); return io; } void ccnet_packet_io_free (CcnetPacketIO *io) { evutil_closesocket(io->fd); buffer_free (io->buffer); buffer_free (io->in_buf); g_free (io); } void ccnet_packet_prepare (CcnetPacketIO *io, int type, int id) { ccnet_header header; header.version = 1; header.type = type; header.length = 0; header.id = htonl (id); buffer_add (io->buffer, &header, sizeof (header)); } void ccnet_packet_write_string (CcnetPacketIO *io, const char *str) { int len; len = strlen(str); buffer_add (io->buffer, str, len); } void ccnet_packet_add (CcnetPacketIO *io, const char *buf, int len) { buffer_add (io->buffer, buf, len); } void ccnet_packet_finish (CcnetPacketIO *io) { ccnet_header *header; header = (ccnet_header *) BUFFER_DATA(io->buffer); header->length = htons (BUFFER_LENGTH(io->buffer) - CCNET_PACKET_LENGTH_HEADER); } void ccnet_packet_send (CcnetPacketIO *io) { writen (io->fd, BUFFER_DATA (io->buffer), io->buffer->off); buffer_drain (io->buffer, io->buffer->off); } void ccnet_packet_finish_send (CcnetPacketIO *io) { ccnet_packet_finish (io); ccnet_packet_send (io); } ccnet_packet * ccnet_packet_io_read_packet (CcnetPacketIO* io) { ccnet_packet *packet; int len; buffer_drain (io->in_buf, io->in_buf->off); if (readn (io->fd, io->in_buf, CCNET_PACKET_LENGTH_HEADER) <= 0) return NULL; packet = (ccnet_packet *) BUFFER_DATA(io->in_buf); len = ntohs (packet->header.length); if (len > 0) { if (readn (io->fd, io->in_buf, len) <= 0) return NULL; } /* Note: must reset packet since readn() may cause realloc of buffer */ packet = (ccnet_packet *) BUFFER_DATA(io->in_buf); packet->header.length = len; packet->header.id = ntohl (packet->header.id); return packet; } void ccnet_packet_io_set_callback (CcnetPacketIO *io, got_packet_callback func, void *user_data) { io->func = func; io->user_data = user_data; } /* return 0 on EOF, -1 on error, 1 otherwise */ int ccnet_packet_io_read (CcnetPacketIO *io) { int n; ccnet_packet *packet; int len; again: if ( (n = buffer_read(io->in_buf, io->fd, 1024)) < 0) { if (errno == EINTR) goto again; g_warning ("read from connfd error: %s.\n", strerror(errno)); return -1; } if (n == 0) { if (io->func) io->func (NULL, io->user_data); return 0; } while (BUFFER_LENGTH(io->in_buf) >= CCNET_PACKET_LENGTH_HEADER) { packet = (ccnet_packet *) BUFFER_DATA(io->in_buf); len = ntohs (packet->header.length); if (BUFFER_LENGTH (io->in_buf) - CCNET_PACKET_LENGTH_HEADER < len) break; packet->header.length = len; packet->header.id = ntohl (packet->header.id); io->func (packet, io->user_data); buffer_drain (io->in_buf, len + CCNET_PACKET_LENGTH_HEADER); } return 1; } /* void */ /* ccnet_send_request (int req_id, const char *req) */ /* { */ /* ccnet_packet_prepear (CCNET_MSG_REQUEST, req_id); */ /* ccnet_packet_write_string (req); */ /* ccnet_packet_finish_send (); */ /* fprintf (stderr, "Send a request: id %d, cmd %s\n", req_id, req); */ /* } */ ccnet-6.1.5/lib/packet-io.h000066400000000000000000000024711317035602700154220ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_CLI_IO_H #define CCNET_CLI_IO_H #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif struct buffer; typedef struct CcnetPacketIO CcnetPacketIO; typedef void (*got_packet_callback) (ccnet_packet *packet, void *user_data); struct CcnetPacketIO { evutil_socket_t fd; struct buffer *buffer; struct buffer *in_buf; got_packet_callback func; void *user_data; }; CcnetPacketIO* ccnet_packet_io_new (evutil_socket_t fd); void ccnet_packet_io_free (CcnetPacketIO *io); void ccnet_packet_prepare (CcnetPacketIO *io, int type, int id); void ccnet_packet_write_string (CcnetPacketIO *io, const char *str); void ccnet_packet_add (CcnetPacketIO *io, const char *buf, int len); void ccnet_packet_finish (CcnetPacketIO *io); void ccnet_packet_send (CcnetPacketIO *io); void ccnet_packet_finish_send (CcnetPacketIO *io); void ccnet_packet_io_set_callback (CcnetPacketIO *io, got_packet_callback func, void *user_data); int ccnet_packet_io_read (CcnetPacketIO *io); ccnet_packet* ccnet_packet_io_read_packet (CcnetPacketIO* io); #endif ccnet-6.1.5/lib/peer-common.h000066400000000000000000000221161317035602700157650ustar00rootroot00000000000000#ifdef CCNET_LIB #define string_list_parse_sorted ccnet_util_string_list_parse_sorted #define string_list_free ccnet_util_string_list_free #define string_list_join ccnet_util_string_list_join #endif G_DEFINE_TYPE (CcnetPeer, ccnet_peer, G_TYPE_OBJECT); enum { P_ID = 1, P_IS_SELF, P_NAME, P_PUBLIC_ADDR, P_PUBLIC_PORT, P_SERVICE_URL, P_IP, P_PORT, P_AUTH_STATE, P_NET_STATE, P_PUBKEY, P_CAN_CONNECT, /* can be connected */ P_IN_LOCAL_NET, P_IN_CONNECTION, P_IS_READY, P_ROLE_LIST, P_MY_ROLE_LIST, P_SESSION_KEY, P_ENCRYPT_CHANNEL, }; static void get_property (GObject *object, guint property_id, GValue *v, GParamSpec *pspec) { CcnetPeer *peer = (CcnetPeer *)object; GString *buf; switch (property_id) { case P_ID: g_value_set_string (v, peer->id); break; case P_IS_SELF: g_value_set_boolean (v, peer->is_self); break; case P_NAME: g_value_set_string (v, peer->name); break; case P_PUBLIC_ADDR: g_value_set_string (v, peer->public_addr); break; case P_PUBLIC_PORT: g_value_set_int (v, peer->public_port); break; case P_IP: g_value_set_string (v, peer->addr_str); break; case P_PORT: g_value_set_int (v, peer->port); break; case P_SERVICE_URL: g_value_set_string (v, peer->service_url); break; case P_NET_STATE: g_value_set_int (v, peer->net_state); break; case P_PUBKEY: #ifndef CCNET_LIB if (peer->pubkey) { GString *str = public_key_to_gstring(peer->pubkey); g_value_set_string (v, str->str); g_string_free(str, TRUE); } else g_value_set_string (v, NULL); #else g_value_set_string (v, NULL); #endif break; case P_CAN_CONNECT: g_value_set_boolean (v, peer->can_connect); break; case P_IN_LOCAL_NET: g_value_set_boolean (v, peer->in_local_network); break; case P_IN_CONNECTION: g_value_set_boolean (v, peer->in_connection); break; case P_IS_READY: g_value_set_boolean (v, peer->is_ready); break; case P_ROLE_LIST: buf = g_string_new (NULL); string_list_join (peer->role_list, buf, ","); g_value_take_string (v, buf->str); g_string_free (buf, FALSE); break; case P_MY_ROLE_LIST: buf = g_string_new (NULL); string_list_join (peer->myrole_list, buf, ","); g_value_take_string (v, buf->str); g_string_free (buf, FALSE); break; case P_SESSION_KEY: g_value_set_string (v, peer->session_key); break; case P_ENCRYPT_CHANNEL: g_value_set_boolean (v, peer->encrypt_channel); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void set_roles (CcnetPeer *peer, const char *roles) { if (!roles) return; GList *role_list = string_list_parse_sorted (roles, ","); string_list_free (peer->role_list); peer->role_list = role_list; } static void set_my_roles (CcnetPeer *peer, const char *roles) { if (!roles) return; GList *role_list = string_list_parse_sorted (roles, ","); string_list_free (peer->myrole_list); peer->myrole_list = role_list; } static void set_property_common (GObject *object, guint property_id, const GValue *v, GParamSpec *pspec) { CcnetPeer *peer = (CcnetPeer *)object; switch (property_id) { case P_ID: memcpy(peer->id, g_value_get_string(v), 41); break; case P_NAME: g_free (peer->name); peer->name = g_value_dup_string(v); break; case P_IS_SELF: peer->is_self = g_value_get_boolean(v); break; case P_PUBLIC_ADDR: g_free (peer->public_addr); peer->public_addr = g_value_dup_string(v); break; case P_PUBLIC_PORT: peer->public_port = g_value_get_int (v); break; case P_SERVICE_URL: g_free (peer->service_url); peer->service_url = g_value_dup_string(v); break; case P_IP: g_free (peer->addr_str); peer->addr_str = g_value_dup_string(v); break; case P_PORT: peer->port = g_value_get_int (v); break; case P_NET_STATE: peer->net_state = g_value_get_int (v); break; case P_PUBKEY: #ifndef CCNET_LIB if (peer->pubkey) RSA_free(peer->pubkey); peer->pubkey = public_key_from_string ((char *)g_value_get_string(v)); #endif break; case P_CAN_CONNECT: peer->can_connect = g_value_get_boolean (v); break; case P_IN_LOCAL_NET: peer->in_local_network = g_value_get_boolean (v); break; case P_IN_CONNECTION: peer->in_connection = g_value_get_boolean (v); break; case P_IS_READY: peer->is_ready = g_value_get_boolean (v); break; case P_ROLE_LIST: set_roles (peer, g_value_get_string(v)); break; case P_MY_ROLE_LIST: set_my_roles (peer, g_value_get_string(v)); break; case P_SESSION_KEY: g_free (peer->session_key); peer->session_key = g_value_dup_string (v); break; case P_ENCRYPT_CHANNEL: peer->encrypt_channel = g_value_get_boolean (v); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); return; } } static void define_properties (GObjectClass *gobject_class) { g_object_class_install_property (gobject_class, P_ID, g_param_spec_string ("id", NULL, "Node ID", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_NAME, g_param_spec_string ("name", NULL, "Hostname", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_PUBLIC_ADDR, g_param_spec_string ("public-addr", NULL, "Public Addrress", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_PUBLIC_PORT, g_param_spec_int ("public-port", NULL, "Public Port", 0, 65535, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_SERVICE_URL, g_param_spec_string ("service-url", NULL, "Service Url", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_IP, g_param_spec_string ("ip", NULL, "Dynamic IP", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_PORT, g_param_spec_int ("port", NULL, "Dynamic Port", 0, 65535, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_NET_STATE, g_param_spec_int ("net-state", NULL, "Network State", -1, 3, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_IS_SELF, g_param_spec_boolean ("is-self", NULL, "Is self", 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_PUBKEY, g_param_spec_string ("pubkey", NULL, "Public Key", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_CAN_CONNECT, g_param_spec_boolean ("can-connect", NULL, "Can be connect via TCP", 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_IN_LOCAL_NET, g_param_spec_boolean ("in-local-network", NULL, "In local network", 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_IN_CONNECTION, g_param_spec_boolean ("in-connection", NULL, "in connection", 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_IS_READY, g_param_spec_boolean ("is_ready", NULL, "service ready", 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_ROLE_LIST, g_param_spec_string ("role-list", NULL, "Role list", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_MY_ROLE_LIST, g_param_spec_string ("myrole-list", NULL, "My role list", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_SESSION_KEY, g_param_spec_string ("session-key", NULL, "session key", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, P_ENCRYPT_CHANNEL, g_param_spec_boolean ("encrypt-channel", NULL, "encrypt channel", 0, G_PARAM_READWRITE)); } const char* ccnet_peer_get_net_state_string (int net_state) { switch (net_state) { case PEER_DOWN: return "down"; case PEER_CONNECTED: return "connected"; default: return "unknown"; } } ccnet-6.1.5/lib/peer.c000066400000000000000000000031551317035602700144740ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include "peer.h" #include "ccnet-client.h" #include "peer-common.h" static void ccnet_peer_free (GObject *object); static void set_property (GObject *object, guint property_id, const GValue *v, GParamSpec *pspec) { set_property_common (object, property_id, v, pspec); } static void ccnet_peer_class_init (CcnetPeerClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = set_property; gobject_class->get_property = get_property; gobject_class->finalize = ccnet_peer_free; define_properties (gobject_class); } static void ccnet_peer_init (CcnetPeer *peer) { } CcnetPeer* ccnet_peer_new (const char *id) { CcnetPeer *peer; peer = g_object_new (CCNET_TYPE_PEER, NULL); memcpy (peer->id, id, 40); peer->id[40] = '\0'; peer->net_state = PEER_DOWN; peer->public_port = 0; peer->port = 0; return peer; } void ccnet_peer_free (GObject *object) { CcnetPeer *peer = CCNET_PEER (object); GList *ptr; g_free (peer->name); g_free (peer->addr_str); g_free (peer->service_url); g_free (peer->public_addr); g_free (peer->login_error); g_free (peer->bind_email); g_free (peer->session_key); for (ptr = peer->role_list; ptr; ptr = ptr->next) g_free (ptr->data); g_list_free (peer->role_list); for (ptr = peer->myrole_list; ptr; ptr = ptr->next) g_free (ptr->data); g_list_free (peer->myrole_list); G_OBJECT_CLASS(ccnet_peer_parent_class)->finalize (object); } ccnet-6.1.5/lib/proc-factory.c000066400000000000000000000144671317035602700161610ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include "processor.h" #include "ccnet-client.h" #include "peer.h" #include "proc-factory.h" typedef struct { GHashTable *proc_type_table; } CcnetProcFactoryPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_PROC_FACTORY, CcnetProcFactoryPriv)) G_DEFINE_TYPE (CcnetProcFactory, ccnet_proc_factory, G_TYPE_OBJECT) static void ccnet_proc_factory_free (GObject *factory); static void ccnet_proc_factory_class_init (CcnetProcFactoryClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = ccnet_proc_factory_free; g_type_class_add_private (klass, sizeof (CcnetProcFactoryPriv)); } static void ccnet_proc_factory_init (CcnetProcFactory *factory) { CcnetProcFactoryPriv *priv = GET_PRIV (factory); priv->proc_type_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } static void ccnet_proc_factory_free (GObject *factory) { CcnetProcFactoryPriv *priv = GET_PRIV (factory); g_hash_table_destroy (priv->proc_type_table); } void ccnet_proc_factory_register_processor (CcnetProcFactory *factory, const char *serv_name, GType proc_type) { CcnetProcFactoryPriv *priv = GET_PRIV (factory); CcnetProcessorClass *proc_class = (CcnetProcessorClass *)g_type_class_ref(proc_type); g_type_class_unref (proc_class); /* check dumplication */ if (g_hash_table_lookup(priv->proc_type_table, serv_name)) return; g_hash_table_insert (priv->proc_type_table, g_strdup (serv_name), (gpointer) proc_type); } GType ccnet_sendcmd_proc_get_type (); GType ccnet_mqclient_proc_get_type (); GType ccnet_async_rpc_proc_get_type (); CcnetProcFactory *ccnet_proc_factory_new (CcnetClient *session) { CcnetProcFactory *factory; factory = g_object_new (CCNET_TYPE_PROC_FACTORY, NULL); factory->session = session; /* register fundamental processors */ ccnet_proc_factory_register_processor (factory, "send-cmd", ccnet_sendcmd_proc_get_type ()); /* ccnet_proc_factory_register_processor (factory, "send-event", */ /* ccnet_sendevent_proc_get_type ()); */ ccnet_proc_factory_register_processor (factory, "mq-client", ccnet_mqclient_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "async-rpc", ccnet_async_rpc_proc_get_type ()); return factory; } static GType ccnet_proc_factory_get_proc_type (CcnetProcFactory *factory, const char *serv_name) { CcnetProcFactoryPriv *priv = GET_PRIV (factory); return (GType) g_hash_table_lookup (priv->proc_type_table, serv_name); } CcnetProcessor * ccnet_proc_factory_create_processor (CcnetProcFactory *factory, const char *serv_name, int is_master, int req_id) { GType type; CcnetProcessor *processor; type = ccnet_proc_factory_get_proc_type (factory, serv_name); if (type == 0) { g_warning ("No processor for service: %s.\n", serv_name); return NULL; } processor = g_object_new (type, NULL); processor->session = factory->session; if (is_master) { if (req_id == 0) processor->id = MASTER_ID ( ccnet_client_get_request_id (factory->session)); else processor->id = MASTER_ID (req_id); } else processor->id = SLAVE_ID (req_id); /* Set the service this processor provide. * This may be different from the processor class name. */ processor->name = g_strdup(serv_name); ccnet_client_add_processor (factory->session, processor); return processor; } CcnetProcessor * ccnet_proc_factory_create_master_processor (CcnetProcFactory *factory, const char *serv_name) { return ccnet_proc_factory_create_processor (factory, serv_name, MASTER, 0); } CcnetProcessor * ccnet_proc_factory_create_remote_master_processor (CcnetProcFactory *factory, const char *serv_name, const char *peer_id) { GType type; CcnetProcessor *processor; type = ccnet_proc_factory_get_proc_type (factory, serv_name); if (type == 0) { ccnet_warning ("No such processor type: %s.\n", serv_name); return NULL; } processor = g_object_new (type, NULL); processor->peer_id = g_strdup(peer_id); processor->session = factory->session; processor->id = MASTER_ID (ccnet_client_get_request_id (factory->session)); /* Set the real processor name. * This may be different from the processor class name. */ processor->name = g_strdup(serv_name); ccnet_client_add_processor (factory->session, processor); return processor; } CcnetProcessor * ccnet_proc_factory_create_slave_processor (CcnetProcFactory *factory, const char *serv_name, const char *peer_id, int req_id) { GType type; CcnetProcessor *processor; type = ccnet_proc_factory_get_proc_type (factory, serv_name); if (type == 0) { g_warning ("No such processor type: %s.\n", serv_name); return NULL; } processor = g_object_new (type, NULL); processor->peer_id = g_strdup(peer_id); processor->session = factory->session; processor->id = SLAVE_ID (req_id); /* Set the real processor name. * This may be different from the processor class name. */ processor->name = g_strdup(serv_name); ccnet_client_add_processor (factory->session, processor); return processor; } void ccnet_proc_factory_recycle (CcnetProcFactory *factory, CcnetProcessor *processor) { ccnet_client_remove_processor (factory->session, processor); g_object_unref (processor); } ccnet-6.1.5/lib/processor.c000066400000000000000000000251041317035602700155560ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #include "ccnet-client.h" #include "processor.h" #include "proc-factory.h" #include "timer.h" #include "peer.h" #include "job-mgr.h" G_DEFINE_TYPE (CcnetProcessor, ccnet_processor, G_TYPE_OBJECT); static void default_shutdown (CcnetProcessor *processor); static void default_release_resource (CcnetProcessor *processor); enum { DONE_SIG, /* connection down */ LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void ccnet_processor_class_init (CcnetProcessorClass *klass) { /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ klass->start = NULL; klass->handle_update = NULL; klass->handle_response = NULL; klass->shutdown = default_shutdown; klass->release_resource = default_release_resource; signals[DONE_SIG] = g_signal_new ("done", CCNET_TYPE_PROCESSOR, G_SIGNAL_RUN_LAST, 0, /* no class singal handler */ NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); } static void ccnet_processor_init (CcnetProcessor *processor) { } int ccnet_processor_start (CcnetProcessor *processor, int argc, char **argv) { if (!processor->session->connected) { g_warning ("[proc] Not connected to daemon.\n"); return -1; } processor->failure = PROC_NOTSET; return CCNET_PROCESSOR_GET_CLASS (processor)->start (processor, argc, argv); } int ccnet_processor_startl (CcnetProcessor *processor, ...) { va_list ap; int argc = 0; char **argv = g_malloc (sizeof(char *) * 10); char *arg; int max = 10; int ret; va_start (ap, processor); arg = va_arg (ap, char *); while (arg) { if (argc >= max) { max *= 2; argv = realloc (argv, sizeof(char *) * max); } argv[argc++] = arg; arg = va_arg (ap, char *); } va_end (ap); ret = ccnet_processor_start (processor, argc, argv); g_free (argv); return ret; } static void default_shutdown (CcnetProcessor *processor) { } static void default_release_resource(CcnetProcessor *processor) { g_free (processor->name); g_free (processor->peer_id); if (processor->timer) ccnet_timer_free (&processor->timer); } /* should be called before recycle */ void ccnet_processor_release_resource(CcnetProcessor *processor) { CCNET_PROCESSOR_GET_CLASS (processor)->release_resource(processor); } void ccnet_processor_done (CcnetProcessor *processor, gboolean success) { if (processor->thread_running) { processor->delay_shutdown = TRUE; processor->was_success = success; return; } if (processor->state == STATE_IN_SHUTDOWN) { return; } processor->state = STATE_IN_SHUTDOWN; if (processor->failure == PROC_NOTSET && success) processor->failure = PROC_DONE; g_debug ("[proc] Processor %s(%d) done %d\n", GET_PNAME(processor), PRINT_ID(processor->id), success); /* Notify */ if (!IS_SLAVE (processor) && success) { ccnet_processor_send_update (processor, SC_PROC_DONE, SS_PROC_DONE, NULL, 0); } g_signal_emit (processor, signals[DONE_SIG], 0, success); ccnet_client_remove_processor (processor->session, processor); ccnet_processor_release_resource (processor); ccnet_proc_factory_recycle (processor->session->proc_factory, processor); } void ccnet_processor_handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { g_object_ref (processor); processor->is_active = TRUE; if (code[0] == '5') { ccnet_debug ("[Proc] Shutdown processor %s(%d) for bad update: %s %s\n", GET_PNAME(processor), PRINT_ID(processor->id), code, code_msg); if (memcmp(code, SC_UNKNOWN_SERVICE, 3) == 0) processor->failure = PROC_NO_SERVICE; else if (memcmp(code, SC_PERM_ERR, 3) == 0) processor->failure = PROC_PERM_ERR; else if (memcmp(code, SC_NETDOWN, 3) == 0) processor->failure = PROC_REMOTE_DEAD; else processor->failure = PROC_BAD_RESP; ccnet_processor_done (processor, FALSE); return; } if (strncmp (code, SC_PROC_KEEPALIVE, 3) == 0) { ccnet_processor_send_response (processor, SC_PROC_ALIVE, SS_PROC_ALIVE, NULL, 0); } else if (strncmp (code, SC_PROC_DEAD, 3) == 0) { ccnet_debug ("[proc] Shutdown processor %s(%d) when peer(%.8s) processor is dead\n", GET_PNAME(processor), PRINT_ID(processor->id), processor->peer_id); processor->failure = PROC_REMOTE_DEAD; ccnet_processor_done (processor, FALSE); } else if (strncmp (code, SC_PROC_DONE, 3) == 0) { ccnet_debug ("[proc] Shutdown processor when receive 103: service done\n"); ccnet_processor_done (processor, TRUE); } else { CCNET_PROCESSOR_GET_CLASS (processor)->handle_update (processor, code, code_msg, content, clen); } processor->is_active = FALSE; g_object_unref (processor); } void ccnet_processor_handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { g_return_if_fail (CCNET_PROCESSOR_GET_CLASS(processor)->handle_response != NULL); g_object_ref (processor); processor->is_active = TRUE; if (code[0] == '5') { ccnet_debug ("[Proc] Shutdown processor %s(%d) for bad response: %s %s from %s\n", GET_PNAME(processor), PRINT_ID(processor->id), code, code_msg, processor->peer_id); if (memcmp(code, SC_UNKNOWN_SERVICE, 3) == 0) processor->failure = PROC_NO_SERVICE; else if (memcmp(code, SC_PERM_ERR, 3) == 0) processor->failure = PROC_PERM_ERR; else if (memcmp(code, SC_NETDOWN, 3) == 0) processor->failure = PROC_REMOTE_DEAD; else processor->failure = PROC_BAD_RESP; ccnet_processor_done (processor, FALSE); return; } if (strncmp (code, SC_PROC_KEEPALIVE, 3) == 0) { ccnet_processor_send_update (processor, SC_PROC_ALIVE, SS_PROC_ALIVE, NULL, 0); } else if (strncmp (code, SC_PROC_DEAD, 3) == 0) { ccnet_debug ("[proc] Shutdown processor %s(%d) when peer(%.8s) processor is dead\n", GET_PNAME(processor), PRINT_ID(processor->id), processor->peer_id); processor->failure = PROC_REMOTE_DEAD; ccnet_processor_done (processor, FALSE); } else { CCNET_PROCESSOR_GET_CLASS (processor)->handle_response (processor, code, code_msg, content, clen); } processor->is_active = FALSE; g_object_unref (processor); } void ccnet_processor_handle_sigchld (CcnetProcessor *processor, int status) { CCNET_PROCESSOR_GET_CLASS (processor)->handle_sigchld (processor, status); } void ccnet_processor_send_request (CcnetProcessor *processor, const char *request) { ccnet_client_send_request (processor->session, REQUEST_ID (processor->id), request); } void ccnet_processor_send_request_l (CcnetProcessor *processor, ...) { va_list ap; GString *buf = g_string_new(NULL); char *arg; va_start (ap, processor); arg = va_arg (ap, char *); while (arg) { g_string_append (buf, arg); arg = va_arg (ap, char *); } va_end (ap); ccnet_client_send_request (processor->session, REQUEST_ID (processor->id), buf->str); g_string_free (buf, TRUE); } void ccnet_processor_send_update(CcnetProcessor *processor, const char *code, const char *code_msg, const char *content, int clen) { ccnet_client_send_update (processor->session, UPDATE_ID(processor->id), code, code_msg, content, clen); } void ccnet_processor_send_response(CcnetProcessor *processor, const char *code, const char *code_msg, const char *content, int clen) { ccnet_client_send_response (processor->session, RESPONSE_ID(processor->id), code, code_msg, content, clen); } typedef struct ProcThreadData { CcnetProcessor *proc; ProcThreadFunc func; void *data; ProcThreadDoneFunc done_func; void *result; } ProcThreadData; static void processor_thread_done (void *vdata) { ProcThreadData *tdata = vdata; tdata->proc->thread_running = FALSE; if (tdata->proc->delay_shutdown) ccnet_processor_done (tdata->proc, tdata->proc->was_success); else tdata->done_func (tdata->result); g_free (tdata); } static void * processor_thread_func_wrapper (void *vdata) { ProcThreadData *tdata = vdata; tdata->result = tdata->func (tdata->data); return vdata; } int ccnet_processor_thread_create (CcnetProcessor *processor, CcnetJobManager *job_mgr, ProcThreadFunc func, ProcThreadDoneFunc done_func, void *data) { ProcThreadData *tdata; tdata = g_new(ProcThreadData, 1); tdata->proc = processor; tdata->func = func; tdata->done_func = done_func; tdata->data = data; ccnet_job_manager_schedule_job (job_mgr ? job_mgr : processor->session->job_mgr, processor_thread_func_wrapper, processor_thread_done, tdata); processor->thread_running = TRUE; return 0; } ccnet-6.1.5/lib/rpc-common.h000066400000000000000000000021771317035602700156230ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef RPC_COMMON_H #define RPC_COMMON_H #include "packet.h" #define SC_CLIENT_CALL "301" #define SS_CLIENT_CALL "CLIENT CALL" #define SC_CLIENT_MORE "302" #define SS_CLIENT_MORE "MORE" #define SC_SERVER_RET "311" #define SS_SERVER_RET "SERVER RET" #define SC_SERVER_MORE "312" #define SS_SERVER_MORE "HAS MORE" #define SC_SERVER_ERR "411" #define SS_SERVER_ERR "Fail to invoke the function, check the function" /* MESSAGE_HEADER = SC_SERVER_RET(3) + " " + SS_SERVER_RET(10) + "\n"(1) + "\n"(1) */ #define MESSAGE_HEADER 64 /* leave enough space */ #define MAX_TRANSFER_LENGTH (CCNET_PACKET_MAX_PAYLOAD_LEN - MESSAGE_HEADER) /* Client Server -rpcserver ----------------------> 200 OK <---------------------- 301 Func String ----------------------> 312 HAS MORE <----------------------- 302 MORE ----------------------> 311 SERVER RET <----------------------- */ #endif ccnet-6.1.5/lib/rpc_table.py000066400000000000000000000050401317035602700156750ustar00rootroot00000000000000""" Define RPC functions needed to generate """ # [ , [] ] func_table = [ [ "int", [] ], [ "int", ["int"] ], [ "int", ["int", "int"] ], [ "int", ["int", "string"] ], [ "int", ["int", "string", "int"] ], [ "int", ["int", "string", "string"] ], [ "int", ["int", "string", "int", "int"] ], [ "int", ["string"] ], [ "int", ["string", "int"] ], [ "int", ["string", "int", "string"] ], [ "int", ["string", "int", "string", "string"] ], [ "int", ["string", "int", "string", "int", "int"] ], [ "int", ["string", "string"] ], [ "int", ["string", "string", "string"] ], [ "int", ["string", "string", "int"] ], [ "int", ["string", "string", "int", "int"] ], [ "int", ["string", "string", "string", "string"] ], [ "int", ["string", "string", "string", "string", "string"] ], [ "int", ["string", "string", "string", "string", "string", "string"] ], [ "int", ["string", "string", "string", "string", "string", "string", "string"] ], [ "int", ["string", "int64"]], [ "int", ["int", "int64"]], [ "int", ["int", "string", "int64"]], [ "int64", [] ], [ "int64", ["string"] ], [ "int64", ["int"]], [ "int64", ["int", "string"]], [ "string", [] ], [ "string", ["int"] ], [ "string", ["string"] ], [ "string", ["string", "int"] ], [ "string", ["string", "string"] ], [ "string", ["string", "string", "string"] ], [ "string", ["string", "string", "string", "string"] ], [ "string", ["string", "string", "string", "string", "int"] ], [ "string", ["string", "string", "string", "string", "string"] ], [ "string", ["string", "string", "string", "string", "string", "string"] ], [ "string", ["string", "string", "string", "string", "string", "int"] ], [ "string", ["string", "string", "string", "string", "string", "string", "string", "string", "string"] ], [ "objlist", [] ], [ "objlist", ["int"] ], [ "objlist", ["int", "int"] ], [ "objlist", ["int", "int", "int"] ], [ "objlist", ["string"] ], [ "objlist", ["string", "int"] ], [ "objlist", ["string", "int", "int"] ], [ "objlist", ["string", "int", "int", "string"] ], [ "objlist", ["string", "string"] ], [ "objlist", ["string", "string", "string"] ], [ "objlist", ["string", "string", "int"] ], [ "objlist", ["string", "string", "int", "int"] ], [ "objlist", ["int", "int", "string"] ], [ "object", [] ], [ "object", ["int"] ], [ "object", ["string"] ], [ "object", ["string", "string"] ], ] ccnet-6.1.5/lib/rpcserver-proc.c000066400000000000000000000066541317035602700165240ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include #include #include "searpc-server.h" #include "rpc-common.h" typedef struct { char *buf; int len; int off; } CcnetRpcserverProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_RPCSERVER_PROC, CcnetRpcserverProcPriv)) G_DEFINE_TYPE (CcnetRpcserverProc, ccnet_rpcserver_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { CCNET_PROCESSOR_CLASS (ccnet_rpcserver_proc_parent_class)->release_resource (processor); } static void ccnet_rpcserver_proc_class_init (CcnetRpcserverProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->start = start; proc_class->handle_update = handle_update; proc_class->release_resource = release_resource; proc_class->name = "rpcserver-proc"; g_type_class_add_private (klass, sizeof(CcnetRpcserverProcPriv)); } static void ccnet_rpcserver_proc_init (CcnetRpcserverProc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetRpcserverProcPriv *priv = GET_PRIV (processor); if (memcmp (code, SC_CLIENT_CALL, 3) == 0) { gsize ret_len; char *svc_name = processor->name; char *ret = searpc_server_call_function (svc_name, content, clen, &ret_len); if (ret_len < MAX_TRANSFER_LENGTH) { ccnet_processor_send_response ( processor, SC_SERVER_RET, SS_SERVER_RET, ret, ret_len); g_free (ret); /* ccnet_processor_done (processor, TRUE); */ return; } /* we need to split data into multiple segments */ priv->buf = ret; priv->len = ret_len; priv->off = 0; ccnet_processor_send_response (processor, SC_SERVER_MORE, SS_SERVER_MORE, priv->buf, MAX_TRANSFER_LENGTH); priv->off = MAX_TRANSFER_LENGTH; return; } if (memcmp (code, SC_CLIENT_MORE, 3) == 0) { if (priv->off + MAX_TRANSFER_LENGTH < priv->len) { ccnet_processor_send_response ( processor, SC_SERVER_MORE, SS_SERVER_MORE, priv->buf + priv->off, MAX_TRANSFER_LENGTH); priv->off += MAX_TRANSFER_LENGTH; } else { ccnet_processor_send_response ( processor, SC_SERVER_RET, SS_SERVER_RET, priv->buf + priv->off, priv->len - priv->off); g_free (priv->buf); /* ccnet_processor_done (processor, TRUE); */ } return; } ccnet_processor_send_response (processor, SC_BAD_UPDATE_CODE, SS_BAD_UPDATE_CODE, NULL, 0); g_warning ("[rpc-server] Bad update: %s %s.\n", code, code_msg); if (priv->buf) g_free (priv->buf); ccnet_processor_done (processor, FALSE); } ccnet-6.1.5/lib/rsa.c000066400000000000000000000103251317035602700143230ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include #include #include #include #include #include "rsa.h" #include "utils.h" /* Forward compatibility functions if libssl < 1.1.0. */ #if OPENSSL_VERSION_NUMBER < 0x10100000L int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { /* If the fields n and e in r are NULL, the corresponding input * parameters MUST be non-NULL for n and e. d may be * left NULL (in case only the public key is used). */ if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) return 0; if (n != NULL) { BN_free(r->n); r->n = n; } if (e != NULL) { BN_free(r->e); r->e = e; } if (d != NULL) { BN_free(r->d); r->d = d; } return 1; } void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { if (n != NULL) *n = r->n; if (e != NULL) *e = r->e; if (d != NULL) *d = r->d; } #endif RSA* private_key_to_pub(RSA *priv) { RSA *pub = RSA_new(); const BIGNUM *n, *e; RSA_get0_key (priv, &n, &e, NULL); RSA_set0_key (pub, BN_dup(n), BN_dup(e), NULL); return pub; } GString* public_key_to_gstring(const RSA *rsa) { GString *buf = g_string_new(NULL); unsigned char *temp; char *coded; const BIGNUM *n, *e; RSA_get0_key (rsa, &n, &e, NULL); gsize len = BN_num_bytes(n); temp = malloc(len); BN_bn2bin(n, temp); coded = g_base64_encode(temp, len); g_string_append (buf, coded); g_string_append_c (buf, ' '); g_free(coded); len = BN_num_bytes(e); temp = realloc(temp, len); BN_bn2bin(e, temp); coded = g_base64_encode(temp, len); g_string_append (buf, coded); g_free(coded); free(temp); return buf; } void public_key_append_to_gstring(const RSA *rsa, GString *buf) { unsigned char *temp; char *coded; const BIGNUM *n, *e; RSA_get0_key (rsa, &n, &e, NULL); gsize len = BN_num_bytes(n); temp = malloc(len); BN_bn2bin(n, temp); coded = g_base64_encode(temp, len); g_string_append (buf, coded); g_string_append_c (buf, ' '); g_free(coded); len = BN_num_bytes(e); temp = realloc(temp, len); BN_bn2bin(e, temp); coded = g_base64_encode(temp, len); g_string_append (buf, coded); g_free(coded); free(temp); } RSA* public_key_from_string(char *str) { char *p; unsigned char *num; gsize len; if (!str) return NULL; if ( !(p = strchr(str, ' ')) ) return NULL; *p = '\0'; RSA *key = RSA_new(); BIGNUM *n = NULL, *e = NULL; num = g_base64_decode(str, &len); n = BN_bin2bn(num, len, NULL); if (!n) goto err; g_free(num); num = g_base64_decode(p+1, &len); e = BN_bin2bn(num, len, NULL); if (!e) goto err; g_free(num); RSA_set0_key (key, n, e, NULL); *p = ' '; return key; err: *p = ' '; RSA_free (key); if (n) BN_free (n); if (e) BN_free (e); g_free(num); return NULL; } unsigned char * private_key_decrypt(RSA *key, unsigned char *data, int len, int *decrypt_len) { int size; unsigned char *buf; size = RSA_size(key); buf = g_malloc(size); *decrypt_len = RSA_private_decrypt(len, data, buf, key, RSA_PKCS1_PADDING); return buf; } unsigned char * public_key_encrypt(RSA *key, unsigned char *data, int len, int *encrypt_len) { int size; unsigned char *buf; size = RSA_size(key); buf = g_malloc(size); *encrypt_len = RSA_public_encrypt(len, data, buf, key, RSA_PKCS1_PADDING); return buf; } char * id_from_pubkey (RSA *pubkey) { GString *buf; unsigned char sha1[20]; char *id = g_malloc(41); buf = public_key_to_gstring (pubkey); calculate_sha1 (sha1, buf->str); sha1_to_hex (sha1, id); g_string_free (buf, TRUE); return id; } RSA * generate_private_key(u_int bits) { RSA *private = NULL; private = RSA_generate_key(bits, 35, NULL, NULL); if (private == NULL) g_error ("rsa_generate_private_key: key generation failed."); return private; } ccnet-6.1.5/lib/rsa.h000066400000000000000000000013701317035602700143300ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_RSA_H #define CCNET_RSA_H #include #include #include #include RSA* private_key_to_pub(RSA *priv); GString* public_key_to_gstring(const RSA *rsa); void public_key_append_to_gstring(const RSA *rsa, GString *buf); RSA* public_key_from_string(char *str); unsigned char* private_key_decrypt(RSA *key, unsigned char *data, int len, int *decrypt_len); unsigned char* public_key_encrypt(RSA *key, unsigned char *data, int len, int *encrypt_len); char *id_from_pubkey (RSA *pubkey); RSA* generate_private_key(u_int bits); #endif ccnet-6.1.5/lib/sendcmd-proc.c000066400000000000000000000064641317035602700161250ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include #include #include "ccnet-client.h" #include "sendcmd-proc.h" enum { INIT, REQUEST_SENT, CONNECTED }; typedef struct { int persist : 1; } CcnetSendcmdProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SENDCMD_PROC, CcnetSendcmdProcPriv)) static int send_cmd_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetSendcmdProc, ccnet_sendcmd_proc, CCNET_TYPE_PROCESSOR); static void ccnet_sendcmd_proc_class_init (CcnetSendcmdProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->start = send_cmd_start; proc_class->name = "sendcmd-proc"; proc_class->handle_response = handle_response; g_type_class_add_private (klass, sizeof (CcnetSendcmdProcPriv)); } static void ccnet_sendcmd_proc_init (CcnetSendcmdProc *processor) { CCNET_PROCESSOR (processor)->state = INIT; } static int send_cmd_start (CcnetProcessor *processor, int argc, char **argv) { char buf[256]; CcnetSendcmdProcPriv *priv = GET_PRIV (processor); priv->persist = 0; while (0 < argc && argv[0][0] == '-') { switch (argv[0][1]) { case 'p': priv->persist = 1; break; default: break; } argc--; argv++; } if (priv->persist) { snprintf (buf, 256, "receive-cmd -p"); } else { snprintf (buf, 256, "receive-cmd"); } ccnet_client_send_request (processor->session, REQUEST_ID (processor->id), buf); processor->state = REQUEST_SENT; return 0; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetSendcmdProcPriv *priv = GET_PRIV (processor); CcnetSendcmdProc *proc = (CcnetSendcmdProc *) processor; if (code[0] != '2') { g_warning ("Receive bad response %s %s\n", code, code_msg); } switch (processor->state) { case REQUEST_SENT: processor->state = CONNECTED; return; case CONNECTED: if (proc->rcvrsp_cb) { proc->rcvrsp_cb (code, content, clen, proc->cb_data); } break; default: break; } if (!priv->persist) ccnet_processor_done (processor, TRUE); } int ccnet_sendcmd_proc_send_command (CcnetSendcmdProc *proc, const char *cmd) { CcnetProcessor *processor = CCNET_PROCESSOR (proc); /* if (processor->state != CONNECTED) return -1; */ ccnet_client_send_update (processor->session, UPDATE_ID(processor->id), "200", NULL, cmd, strlen(cmd)+1); /* including '\0' */ return 0; } void ccnet_sendcmd_proc_set_rcvrsp_cb (CcnetSendcmdProc *proc, SendcmdProcRcvrspCallback rcvrsp_cb, void *data) { proc->rcvrsp_cb = rcvrsp_cb; proc->cb_data = data; } ccnet-6.1.5/lib/string-util.h000066400000000000000000000025451317035602700160310ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_STRING_H #define CCNET_STRING_H #include #define END_0(buf,len) (buf[(len)-1] == '\0') static inline int get_version(char *str) { int v; if (str[0] != 'v') return 0; if (sscanf(str+1, "%d", &v) != 1) return 0; return v; } #define sgoto_next(p) do { \ while (*p != ' ' && *p) ++p; \ if (*p != ' ') \ goto error; \ *p = '\0'; \ ++p; \ } while (0) #define sget_len(val, p) do { \ char *tmp = p; \ sgoto_next(p); \ val = atoi(tmp); \ if (val == 0) \ goto error; \ } while (0) /* get a string with format "%s " */ #define sget_str(str, p) do { \ str = p; \ sgoto_next(p); \ } while (0) /* get a string with format "%d %s " */ #define sget_str_with_len(str, p) do { \ int len; \ sget_len(len, p); \ str = p; \ p += len; \ *p = '\0'; \ ++p; \ } while (0) #endif ccnet-6.1.5/lib/threaded-rpcserver-proc.c000066400000000000000000000115151317035602700202720ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include #include #include #include "searpc-server.h" #include "rpc-common.h" #include "job-mgr.h" typedef struct { char *call_buf; gsize call_len; char *buf; gsize len; int off; char *error_message; } CcnetThreadedRpcserverProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_THREADED_RPCSERVER_PROC, CcnetThreadedRpcserverProcPriv)) G_DEFINE_TYPE (CcnetThreadedRpcserverProc, ccnet_threaded_rpcserver_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { CcnetThreadedRpcserverProcPriv *priv = GET_PRIV(processor); g_free (priv->buf); CCNET_PROCESSOR_CLASS (ccnet_threaded_rpcserver_proc_parent_class)->release_resource (processor); } static void ccnet_threaded_rpcserver_proc_class_init (CcnetThreadedRpcserverProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->start = start; proc_class->handle_update = handle_update; proc_class->release_resource = release_resource; proc_class->name = "threaded-rpcserver-proc"; g_type_class_add_private (klass, sizeof(CcnetThreadedRpcserverProcPriv)); } static void ccnet_threaded_rpcserver_proc_init (CcnetThreadedRpcserverProc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } static void * call_function_job (void *vprocessor) { CcnetProcessor *processor = vprocessor; CcnetThreadedRpcserverProcPriv *priv = GET_PRIV(processor); char *svc_name = processor->name; priv->buf = searpc_server_call_function (svc_name, priv->call_buf, priv->call_len, &priv->len); g_free (priv->call_buf); return vprocessor; } static void call_function_done (void *vprocessor) { CcnetProcessor *processor = vprocessor; CcnetThreadedRpcserverProcPriv *priv; priv = GET_PRIV(processor); if (priv->buf) { if (priv->len < MAX_TRANSFER_LENGTH) { ccnet_processor_send_response (processor, SC_SERVER_RET, SS_SERVER_RET, priv->buf, priv->len); g_free (priv->buf); priv->buf = NULL; /* ccnet_processor_done (processor, TRUE); */ return; } /* we need to split data into multiple segments */ ccnet_processor_send_response (processor, SC_SERVER_MORE, SS_SERVER_MORE, priv->buf, MAX_TRANSFER_LENGTH); priv->off = MAX_TRANSFER_LENGTH; } else { char *message = priv->error_message ? priv->error_message : ""; ccnet_processor_send_response (processor, SC_SERVER_ERR, message, NULL, 0); g_free (priv->error_message); ccnet_processor_done (processor, FALSE); } } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetThreadedRpcserverProcPriv *priv = GET_PRIV (processor); if (memcmp (code, SC_CLIENT_CALL, 3) == 0) { priv->call_buf = g_memdup (content, clen); priv->call_len = (gsize)clen; ccnet_processor_thread_create (processor, NULL, call_function_job, call_function_done, processor); return; } if (memcmp (code, SC_CLIENT_MORE, 3) == 0) { if (priv->off + MAX_TRANSFER_LENGTH < priv->len) { ccnet_processor_send_response ( processor, SC_SERVER_MORE, SS_SERVER_MORE, priv->buf + priv->off, MAX_TRANSFER_LENGTH); priv->off += MAX_TRANSFER_LENGTH; } else { ccnet_processor_send_response ( processor, SC_SERVER_RET, SS_SERVER_RET, priv->buf + priv->off, priv->len - priv->off); g_free (priv->buf); priv->buf = NULL; /* ccnet_processor_done (processor, TRUE); */ } return; } ccnet_processor_send_response (processor, SC_BAD_UPDATE_CODE, SS_BAD_UPDATE_CODE, NULL, 0); g_warning ("[rpc-server] Bad update: %s %s.\n", code, code_msg); ccnet_processor_done (processor, FALSE); } ccnet-6.1.5/lib/timer.c000066400000000000000000000033461317035602700146630ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #else #include #endif #include #ifdef CCNET_LIB #include "libccnet_utils.h" #define timeval_from_msec ccnet_util_timeval_from_msec #else #include "utils.h" #endif #include "timer.h" struct CcnetTimer { struct event event; struct timeval tv; TimerCB func; void *user_data; uint8_t inCallback; }; static void timer_callback (evutil_socket_t fd, short event, void *vtimer) { int more; struct CcnetTimer *timer = vtimer; timer->inCallback = 1; more = (*timer->func) (timer->user_data); timer->inCallback = 0; if (more) evtimer_add (&timer->event, &timer->tv); else ccnet_timer_free (&timer); } void ccnet_timer_free (CcnetTimer **ptimer) { CcnetTimer *timer; /* zero out the argument passed in */ g_return_if_fail (ptimer); timer = *ptimer; *ptimer = NULL; /* destroy the timer directly or via the command queue */ if (timer && !timer->inCallback) { event_del (&timer->event); g_free (timer); } } CcnetTimer* ccnet_timer_new (TimerCB func, void *user_data, uint64_t interval_milliseconds) { CcnetTimer *timer = g_new0 (CcnetTimer, 1); timer->tv = timeval_from_msec (interval_milliseconds); timer->func = func; timer->user_data = user_data; evtimer_set (&timer->event, timer_callback, timer); evtimer_add (&timer->event, &timer->tv); return timer; } ccnet-6.1.5/lib/utils.c000066400000000000000000001125251317035602700147030ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include "utils.h" #ifdef WIN32 #include #include #include #include #include #else #include #endif #ifndef WIN32 #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int inet_pton(int af, const char *src, void *dst); struct timeval timeval_from_msec (uint64_t milliseconds) { struct timeval ret; const uint64_t microseconds = milliseconds * 1000; ret.tv_sec = microseconds / 1000000; ret.tv_usec = microseconds % 1000000; return ret; } void rawdata_to_hex (const unsigned char *rawdata, char *hex_str, int n_bytes) { static const char hex[] = "0123456789abcdef"; int i; for (i = 0; i < n_bytes; i++) { unsigned int val = *rawdata++; *hex_str++ = hex[val >> 4]; *hex_str++ = hex[val & 0xf]; } *hex_str = '\0'; } static unsigned hexval(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return ~0; } int hex_to_rawdata (const char *hex_str, unsigned char *rawdata, int n_bytes) { int i; for (i = 0; i < n_bytes; i++) { unsigned int val = (hexval(hex_str[0]) << 4) | hexval(hex_str[1]); if (val & ~0xff) return -1; *rawdata++ = val; hex_str += 2; } return 0; } size_t ccnet_strlcpy (char *dest, const char *src, size_t size) { size_t ret = strlen(src); if (size) { size_t len = (ret >= size) ? size - 1 : ret; memcpy(dest, src, len); dest[len] = '\0'; } return ret; } int checkdir (const char *dir) { struct stat st; #ifdef WIN32 /* remove trailing '\\' */ char *path = g_strdup(dir); char *p = (char *)path + strlen(path) - 1; while (*p == '\\' || *p == '/') *p-- = '\0'; if ((g_stat(dir, &st) < 0) || !S_ISDIR(st.st_mode)) { g_free (path); return -1; } g_free (path); return 0; #else if ((g_stat(dir, &st) < 0) || !S_ISDIR(st.st_mode)) return -1; return 0; #endif } int checkdir_with_mkdir (const char *dir) { #ifdef WIN32 int ret; char *path = g_strdup(dir); char *p = (char *)path + strlen(path) - 1; while (*p == '\\' || *p == '/') *p-- = '\0'; ret = g_mkdir_with_parents(path, 0755); g_free (path); return ret; #else return g_mkdir_with_parents(dir, 0755); #endif } int objstore_mkdir (const char *base) { int ret; int i, j, len; static const char hex[] = "0123456789abcdef"; char subdir[PATH_MAX]; if ( (ret = checkdir_with_mkdir(base)) < 0) return ret; len = strlen(base); memcpy(subdir, base, len); subdir[len] = G_DIR_SEPARATOR; subdir[len+3] = '\0'; for (i = 0; i < 16; i++) { subdir[len+1] = hex[i]; for (j = 0; j < 16; j++) { subdir[len+2] = hex[j]; if ( (ret = checkdir_with_mkdir(subdir)) < 0) return ret; } } return 0; } void objstore_get_path (char *path, const char *base, const char *obj_id) { int len; len = strlen(base); memcpy(path, base, len); path[len] = G_DIR_SEPARATOR; path[len+1] = obj_id[0]; path[len+2] = obj_id[1]; path[len+3] = G_DIR_SEPARATOR; strcpy(path+len+4, obj_id+2); } ssize_t /* Read "n" bytes from a descriptor. */ readn(int fd, void *vptr, size_t n) { size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nread = read(fd, ptr, nleft)) < 0) { if (errno == EINTR) nread = 0; /* and call read() again */ else return(-1); } else if (nread == 0) break; /* EOF */ nleft -= nread; ptr += nread; } return(n - nleft); /* return >= 0 */ } ssize_t /* Write "n" bytes to a descriptor. */ writen(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nwritten = write(fd, ptr, nleft)) <= 0) { if (nwritten < 0 && errno == EINTR) nwritten = 0; /* and call write() again */ else return(-1); /* error */ } nleft -= nwritten; ptr += nwritten; } return(n); } ssize_t /* Read "n" bytes from a descriptor. */ recvn(evutil_socket_t fd, void *vptr, size_t n) { size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { #ifndef WIN32 if ( (nread = read(fd, ptr, nleft)) < 0) #else if ( (nread = recv(fd, ptr, nleft, 0)) < 0) #endif { if (errno == EINTR) nread = 0; /* and call read() again */ else return(-1); } else if (nread == 0) break; /* EOF */ nleft -= nread; ptr += nread; } return(n - nleft); /* return >= 0 */ } ssize_t /* Write "n" bytes to a descriptor. */ sendn(evutil_socket_t fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { #ifndef WIN32 if ( (nwritten = write(fd, ptr, nleft)) <= 0) #else if ( (nwritten = send(fd, ptr, nleft, 0)) <= 0) #endif { if (nwritten < 0 && errno == EINTR) nwritten = 0; /* and call write() again */ else return(-1); /* error */ } nleft -= nwritten; ptr += nwritten; } return(n); } int copy_fd (int ifd, int ofd) { while (1) { char buffer[8192]; ssize_t len = readn (ifd, buffer, sizeof(buffer)); if (!len) break; if (len < 0) { close (ifd); return -1; } if (writen (ofd, buffer, len) < 0) { close (ofd); return -1; } } close(ifd); return 0; } int copy_file (const char *dst, const char *src, int mode) { int fdi, fdo, status; if ((fdi = g_open (src, O_RDONLY | O_BINARY, 0)) < 0) return fdi; fdo = g_open (dst, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, mode); if (fdo < 0 && errno == EEXIST) { close (fdi); return 0; } else if (fdo < 0){ close (fdi); return -1; } status = copy_fd (fdi, fdo); if (close (fdo) != 0) return -1; return status; } char* ccnet_expand_path (const char *src) { #ifdef WIN32 char new_path[PATH_MAX + 1]; char *p = new_path; const char *q = src; memset(new_path, 0, sizeof(new_path)); if (*src == '~') { const char *home = g_get_home_dir(); memcpy(new_path, home, strlen(home)); p += strlen(new_path); q++; } memcpy(p, q, strlen(q)); /* delete the charactor '\' or '/' at the end of the path * because the function stat faied to deal with directory names * with '\' or '/' in the end */ p = new_path + strlen(new_path) - 1; while(*p == '\\' || *p == '/') *p-- = '\0'; return strdup (new_path); #else const char *next_in, *ntoken; char new_path[PATH_MAX + 1]; char *next_out; int len; /* special cases */ if (!src || *src == '\0') return NULL; if (strlen(src) > PATH_MAX) return NULL; next_in = src; next_out = new_path; *next_out = '\0'; if (*src == '~') { /* handle src start with '~' or '~' like '~plt' */ struct passwd *pw = NULL; for ( ; *next_in != '/' && *next_in != '\0'; next_in++) ; len = next_in - src; if (len == 1) { pw = getpwuid (geteuid()); } else { /* copy '~' to new_path */ memcpy (new_path, src, len); new_path[len] = '\0'; pw = getpwnam (new_path + 1); } if (pw == NULL) return NULL; len = strlen (pw->pw_dir); memcpy (new_path, pw->pw_dir, len); next_out = new_path + len; *next_out = '\0'; if (*next_in == '\0') return strdup (new_path); } else if (*src != '/') { getcwd (new_path, PATH_MAX); for ( ; *next_out; next_out++) ; /* to '\0' */ } while (*next_in != '\0') { /* move ntoken to the next not '/' char */ for (ntoken = next_in; *ntoken == '/'; ntoken++) ; for (next_in = ntoken; *next_in != '/' && *next_in != '\0'; next_in++) ; len = next_in - ntoken; if (len == 0) { /* the path ends with '/', keep it */ *next_out++ = '/'; *next_out = '\0'; break; } if (len == 2 && ntoken[0] == '.' && ntoken[1] == '.') { /* '..' */ for (; next_out > new_path && *next_out != '/'; next_out--) ; *next_out = '\0'; } else if (ntoken[0] != '.' || len != 1) { /* not '.' */ *next_out++ = '/'; memcpy (next_out, ntoken, len); next_out += len; *next_out = '\0'; } } /* the final special case */ if (new_path[0] == '\0') { new_path[0] = '/'; new_path[1] = '\0'; } return strdup (new_path); #endif } int calculate_sha1 (unsigned char *sha1, const char *msg) { SHA_CTX c; SHA1_Init(&c); SHA1_Update(&c, msg, strlen(msg)); SHA1_Final(sha1, &c); return 0; } uint32_t ccnet_sha1_hash (const void *v) { /* 31 bit hash function */ const unsigned char *p = v; uint32_t h = 0; int i; for (i = 0; i < 20; i++) h = (h << 5) - h + p[i]; return h; } int ccnet_sha1_equal (const void *v1, const void *v2) { const unsigned char *p1 = v1; const unsigned char *p2 = v2; int i; for (i = 0; i < 20; i++) if (p1[i] != p2[i]) return 0; return 1; } #ifndef WIN32 char* gen_uuid () { char *uuid_str = g_malloc (37); uuid_t uuid; uuid_generate (uuid); uuid_unparse_lower (uuid, uuid_str); return uuid_str; } void gen_uuid_inplace (char *buf) { uuid_t uuid; uuid_generate (uuid); uuid_unparse_lower (uuid, buf); } gboolean is_uuid_valid (const char *uuid_str) { uuid_t uuid; if (uuid_parse (uuid_str, uuid) < 0) return FALSE; return TRUE; } #else char* gen_uuid () { char *uuid_str = g_malloc (37); unsigned char *str = NULL; UUID uuid; UuidCreate(&uuid); UuidToString(&uuid, &str); memcpy(uuid_str, str, 37); RpcStringFree(&str); return uuid_str; } void gen_uuid_inplace (char *buf) { unsigned char *str = NULL; UUID uuid; UuidCreate(&uuid); UuidToString(&uuid, &str); memcpy(buf, str, 37); RpcStringFree(&str); } gboolean is_uuid_valid (const char *uuid_str) { UUID uuid; if (UuidFromString((unsigned char *)uuid_str, &uuid) != RPC_S_OK) return FALSE; return TRUE; } #endif char** strsplit_by_space (char *string, int *length) { char *remainder, *s; int size = 8, num = 0, done = 0; char **array; if (string == NULL || string[0] == '\0') { *length = 0; return NULL; } array = malloc (sizeof(char *) * size); remainder = string; while (!done) { for (s = remainder; *s != ' ' && *s != '\0'; ++s) ; if (*s == '\0') done = 1; else *s = '\0'; array[num++] = remainder; if (!done && num == size) { size <<= 1; array = realloc (array, sizeof(char *) * size); } remainder = s + 1; } *length = num; return array; } char** strsplit_by_char (char *string, int *length, char c) { char *remainder, *s; int size = 8, num = 0, done = 0; char **array; if (string == NULL || string[0] == '\0') { *length = 0; return NULL; } array = malloc (sizeof(char *) * size); remainder = string; while (!done) { for (s = remainder; *s != c && *s != '\0'; ++s) ; if (*s == '\0') done = 1; else *s = '\0'; array[num++] = remainder; if (!done && num == size) { size <<= 1; array = realloc (array, sizeof(char *) * size); } remainder = s + 1; } *length = num; return array; } char* strjoin_n (const char *seperator, int argc, char **argv) { GString *buf; int i; char *str; if (argc == 0) return NULL; buf = g_string_new (argv[0]); for (i = 1; i < argc; ++i) { g_string_append (buf, seperator); g_string_append (buf, argv[i]); } str = buf->str; g_string_free (buf, FALSE); return str; } gboolean is_ipaddr_valid (const char *ip) { unsigned char buf[sizeof(struct in6_addr)]; if (evutil_inet_pton(AF_INET, ip, buf) == 1) return TRUE; if (evutil_inet_pton(AF_INET6, ip, buf) == 1) return TRUE; return FALSE; } void parse_key_value_pairs (char *string, KeyValueFunc func, void *data) { char *line = string, *next, *space; char *key, *value; while (*line) { /* handle empty line */ if (*line == '\n') { ++line; continue; } for (next = line; *next != '\n' && *next; ++next) ; *next = '\0'; for (space = line; space < next && *space != ' '; ++space) ; if (*space != ' ') { g_warning ("Bad key value format: %s\n", line); return; } *space = '\0'; key = line; value = space + 1; func (data, key, value); line = next + 1; } } void parse_key_value_pairs2 (char *string, KeyValueFunc2 func, void *data) { char *line = string, *next, *space; char *key, *value; while (*line) { /* handle empty line */ if (*line == '\n') { ++line; continue; } for (next = line; *next != '\n' && *next; ++next) ; *next = '\0'; for (space = line; space < next && *space != ' '; ++space) ; if (*space != ' ') { g_warning ("Bad key value format: %s\n", line); return; } *space = '\0'; key = line; value = space + 1; if (func(data, key, value) == FALSE) break; line = next + 1; } } /** * handle the empty string problem. */ gchar* ccnet_key_file_get_string (GKeyFile *keyf, const char *category, const char *key) { gchar *v; if (!g_key_file_has_key (keyf, category, key, NULL)) return NULL; v = g_key_file_get_string (keyf, category, key, NULL); if (v != NULL && v[0] == '\0') { g_free(v); return NULL; } return v; } /** * string_list_is_exists: * @str_list: * @string: a C string or %NULL * * Check whether @string is in @str_list. * * returns: %TRUE if @string is in str_list, %FALSE otherwise */ gboolean string_list_is_exists (GList *str_list, const char *string) { GList *ptr; for (ptr = str_list; ptr; ptr = ptr->next) { if (g_strcmp0(string, ptr->data) == 0) return TRUE; } return FALSE; } /** * string_list_append: * @str_list: * @string: a C string (can't be %NULL * * Append @string to @str_list if it is in the list. * * returns: the new start of the list */ GList* string_list_append (GList *str_list, const char *string) { g_return_val_if_fail (string != NULL, str_list); if (string_list_is_exists(str_list, string)) return str_list; str_list = g_list_append (str_list, g_strdup(string)); return str_list; } GList * string_list_append_sorted (GList *str_list, const char *string) { g_return_val_if_fail (string != NULL, str_list); if (string_list_is_exists(str_list, string)) return str_list; str_list = g_list_insert_sorted_with_data (str_list, g_strdup(string), (GCompareDataFunc)g_strcmp0, NULL); return str_list; } GList * string_list_remove (GList *str_list, const char *string) { g_return_val_if_fail (string != NULL, str_list); GList *ptr; for (ptr = str_list; ptr; ptr = ptr->next) { if (strcmp((char *)ptr->data, string) == 0) { g_free (ptr->data); return g_list_delete_link (str_list, ptr); } } return str_list; } void string_list_free (GList *str_list) { GList *ptr = str_list; while (ptr) { g_free (ptr->data); ptr = ptr->next; } g_list_free (str_list); } void string_list_join (GList *str_list, GString *str, const char *seperator) { GList *ptr; if (!str_list) return; ptr = str_list; g_string_append (str, ptr->data); for (ptr = ptr->next; ptr; ptr = ptr->next) { g_string_append (str, seperator); g_string_append (str, (char *)ptr->data); } } GList * string_list_parse (const char *list_in_str, const char *seperator) { if (!list_in_str) return NULL; GList *list = NULL; char **array = g_strsplit (list_in_str, seperator, 0); char **ptr; for (ptr = array; *ptr; ptr++) { list = g_list_prepend (list, g_strdup(*ptr)); } list = g_list_reverse (list); g_strfreev (array); return list; } GList * string_list_parse_sorted (const char *list_in_str, const char *seperator) { GList *list = string_list_parse (list_in_str, seperator); return g_list_sort (list, (GCompareFunc)g_strcmp0); } gboolean string_list_sorted_is_equal (GList *list1, GList *list2) { GList *ptr1 = list1, *ptr2 = list2; while (ptr1 && ptr2) { if (g_strcmp0(ptr1->data, ptr2->data) != 0) break; ptr1 = ptr1->next; ptr2 = ptr2->next; } if (!ptr1 && !ptr2) return TRUE; return FALSE; } char ** ncopy_string_array (char **orig, int n) { char **ret = g_malloc (sizeof(char *) * n); int i = 0; for (; i < n; i++) ret[i] = g_strdup(orig[i]); return ret; } void nfree_string_array (char **array, int n) { int i = 0; for (; i < n; i++) g_free (array[i]); g_free (array); } gint64 get_current_time() { GTimeVal tv; gint64 t; g_get_current_time (&tv); t = tv.tv_sec * (gint64)1000000 + tv.tv_usec; return t; } #ifdef WIN32 int pgpipe (ccnet_pipe_t handles[2]) { SOCKET s; struct sockaddr_in serv_addr; int len = sizeof( serv_addr ); handles[0] = handles[1] = INVALID_SOCKET; if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET ) { g_debug("pgpipe failed to create socket: %d\n", WSAGetLastError()); return -1; } memset( &serv_addr, 0, sizeof( serv_addr ) ); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(0); serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); BOOL reuse = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); if (bind(s, (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR) { g_debug("pgpipe failed to bind: %d\n", WSAGetLastError()); closesocket(s); return -1; } if (listen(s, 1) == SOCKET_ERROR) { g_debug("pgpipe failed to listen: %d\n", WSAGetLastError()); closesocket(s); return -1; } if (getsockname(s, (SOCKADDR *) & serv_addr, &len) == SOCKET_ERROR) { g_debug("pgpipe failed to getsockname: %d\n", WSAGetLastError()); closesocket(s); return -1; } if ((handles[1] = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { g_debug("pgpipe failed to create socket 2: %d\n", WSAGetLastError()); closesocket(s); return -1; } if (connect(handles[1], (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR) { g_debug("pgpipe failed to connect socket: %d\n", WSAGetLastError()); closesocket(s); return -1; } if ((handles[0] = accept(s, (SOCKADDR *) & serv_addr, &len)) == INVALID_SOCKET) { g_debug("pgpipe failed to accept socket: %d\n", WSAGetLastError()); closesocket(handles[1]); handles[1] = INVALID_SOCKET; closesocket(s); return -1; } closesocket(s); return 0; } #endif /* The EVP_EncryptXXX and EVP_DecryptXXX series of functions have a weird choice of returned value. */ #define ENC_SUCCESS 1 #define ENC_FAILURE 0 #define DEC_SUCCESS 1 #define DEC_FAILURE 0 #include #include /* Block size, in bytes. For AES it can only be 16 bytes. */ #define BLK_SIZE 16 #define ENCRYPT_BLK_SIZE BLK_SIZE #define KEY_SIZE 32 int ccnet_generate_cipher (const char *passwd, int plen, unsigned char *key, unsigned char *iv) { int key_len; /* Generate the derived key. We use AES 256 bits key, CBC cipher mode, and SHA1 as the message digest when generating the key. IV is not used in ecb mode, actually. */ key_len = EVP_BytesToKey (EVP_aes_256_cbc(), /* cipher mode */ EVP_sha1(), /* message digest */ NULL, /* salt */ (unsigned char*)passwd, plen, 3, /* iteration times */ key, /* the derived key */ iv); /* IV, initial vector */ /* The key should be 32 bytes long for our 256 bit key. */ if (key_len != KEY_SIZE) { g_warning ("failed to init EVP_CIPHER_CTX.\n"); return -1; } return 0; } int ccnet_encrypt_with_key (char **data_out, int *out_len, const char *data_in, const int in_len, const unsigned char *key, const unsigned char *iv) { *data_out = NULL; *out_len = -1; /* check validation */ if (data_in == NULL || in_len <= 0 || key == NULL || iv == NULL) { g_warning ("Invalid params.\n"); return -1; } EVP_CIPHER_CTX *ctx; int ret; int blks; /* Prepare CTX for encryption. */ ctx = EVP_CIPHER_CTX_new (); ret = EVP_EncryptInit_ex (ctx, EVP_aes_256_cbc(), /* cipher mode */ NULL, /* engine, NULL for default */ key, /* derived key */ iv); /* initial vector */ if (ret == ENC_FAILURE) { g_warning ("error init\n"); EVP_CIPHER_CTX_free (ctx); return -1; } /* Allocating output buffer. */ /* For EVP symmetric encryption, padding is always used __even if__ data size is a multiple of block size, in which case the padding length is the block size. so we have the following: */ blks = (in_len / BLK_SIZE) + 1; *data_out = (char *) g_malloc(blks * BLK_SIZE); if (*data_out == NULL) { g_warning ("failed to allocate the output buffer.\n"); goto enc_error; } int update_len, final_len; /* Do the encryption. */ ret = EVP_EncryptUpdate (ctx, (unsigned char*)*data_out, &update_len, (unsigned char*)data_in, in_len); if (ret == ENC_FAILURE) { g_warning ("error update\n"); goto enc_error; } /* Finish the possible partial block. */ ret = EVP_EncryptFinal_ex (ctx, (unsigned char*)*data_out + update_len, &final_len); *out_len = update_len + final_len; /* out_len should be equal to the allocated buffer size. */ if (ret == ENC_FAILURE || *out_len != (blks * BLK_SIZE)) { goto enc_error; } EVP_CIPHER_CTX_free (ctx); return 0; enc_error: EVP_CIPHER_CTX_free (ctx); *out_len = -1; if (*data_out != NULL) g_free (*data_out); *data_out = NULL; return -1; } int ccnet_decrypt_with_key (char **data_out, int *out_len, const char *data_in, const int in_len, const unsigned char *key, const unsigned char *iv) { /* Check validation. Because padding is always used, in_len must * be a multiple of BLK_SIZE */ if ( data_in == NULL || in_len <= 0 || in_len % BLK_SIZE != 0 || key == NULL || iv == NULL) { g_warning ("Invalid param(s).\n"); return -1; } EVP_CIPHER_CTX *ctx; int ret; *data_out = NULL; *out_len = -1; /* Prepare CTX for decryption. */ ctx = EVP_CIPHER_CTX_new (); ret = EVP_DecryptInit_ex (ctx, EVP_aes_256_cbc(), /* cipher mode */ NULL, /* engine, NULL for default */ key, /* derived key */ iv); /* initial vector */ if (ret == DEC_FAILURE) { EVP_CIPHER_CTX_free (ctx); return -1; } /* Allocating output buffer. */ *data_out = (char *)g_malloc (in_len); if (*data_out == NULL) { g_warning ("failed to allocate the output buffer.\n"); goto dec_error; } int update_len, final_len; /* Do the decryption. */ ret = EVP_DecryptUpdate (ctx, (unsigned char*)*data_out, &update_len, (unsigned char*)data_in, in_len); if (ret == DEC_FAILURE) goto dec_error; /* Finish the possible partial block. */ ret = EVP_DecryptFinal_ex (ctx, (unsigned char*)*data_out + update_len, &final_len); *out_len = update_len + final_len; /* out_len should be smaller than in_len. */ if (ret == DEC_FAILURE || *out_len > in_len) goto dec_error; EVP_CIPHER_CTX_free (ctx); return 0; dec_error: EVP_CIPHER_CTX_free (ctx); *out_len = -1; if (*data_out != NULL) g_free (*data_out); *data_out = NULL; return -1; } /* convert locale specific input to utf8 encoded string */ char *ccnet_locale_to_utf8 (const gchar *src) { if (!src) return NULL; gsize bytes_read = 0; gsize bytes_written = 0; GError *error = NULL; gchar *dst = NULL; dst = g_locale_to_utf8 (src, /* locale specific string */ strlen(src), /* len of src */ &bytes_read, /* length processed */ &bytes_written, /* output length */ &error); if (error) { return NULL; } return dst; } /* convert utf8 input to locale specific string */ char *ccnet_locale_from_utf8 (const gchar *src) { if (!src) return NULL; gsize bytes_read = 0; gsize bytes_written = 0; GError *error = NULL; gchar *dst = NULL; dst = g_locale_from_utf8 (src, /* locale specific string */ strlen(src), /* len of src */ &bytes_read, /* length processed */ &bytes_written, /* output length */ &error); if (error) { return NULL; } return dst; } #ifdef WIN32 static HANDLE get_process_handle (const char *process_name_in) { char name[256]; if (strstr(process_name_in, ".exe")) { snprintf (name, sizeof(name), "%s", process_name_in); } else { snprintf (name, sizeof(name), "%s.exe", process_name_in); } DWORD aProcesses[1024], cbNeeded, cProcesses; if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) return NULL; /* Calculate how many process identifiers were returned. */ cProcesses = cbNeeded / sizeof(DWORD); HANDLE hProcess; HMODULE hMod; char process_name[MAX_PATH]; unsigned int i; for (i = 0; i < cProcesses; i++) { if(aProcesses[i] == 0) continue; hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, aProcesses[i]); if (!hProcess) continue; if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) { GetModuleBaseName(hProcess, hMod, process_name, sizeof(process_name)/sizeof(char)); } if (strcasecmp(process_name, name) == 0) return hProcess; else { CloseHandle(hProcess); } } /* Not found */ return NULL; } gboolean process_is_running (const char *process_name) { HANDLE proc_handle = get_process_handle(process_name); if (proc_handle) { CloseHandle(proc_handle); return TRUE; } else { return FALSE; } } int win32_kill_process (const char *process_name) { HANDLE proc_handle = get_process_handle(process_name); if (proc_handle) { TerminateProcess(proc_handle, 0); CloseHandle(proc_handle); return 0; } else { return -1; } } int win32_spawn_process (char *cmdline_in, char *working_directory) { if (!cmdline_in) return -1; char *cmdline = g_strdup (cmdline_in); STARTUPINFO si; PROCESS_INFORMATION pi; unsigned flags; BOOL success; /* we want to execute seafile without crreating a console window */ flags = CREATE_NO_WINDOW; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK; si.hStdInput = (HANDLE) _get_osfhandle(0); si.hStdOutput = (HANDLE) _get_osfhandle(1); si.hStdError = (HANDLE) _get_osfhandle(2); memset(&pi, 0, sizeof(pi)); success = CreateProcess(NULL, cmdline, NULL, NULL, TRUE, flags, NULL, working_directory, &si, &pi); g_free (cmdline); if (!success) { g_warning ("failed to fork_process: GLE=%lu\n", GetLastError()); return -1; } /* close the handle of thread so that the process object can be freed by * system */ CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return 0; } char * wchar_to_utf8 (const wchar_t *wch) { if (wch == NULL) { return NULL; } char *utf8 = NULL; int bufsize, len; bufsize = WideCharToMultiByte (CP_UTF8, /* multibyte code page */ 0, /* flags */ wch, /* src */ -1, /* src len, -1 for all includes \0 */ utf8, /* dst */ 0, /* dst buf len */ NULL, /* default char */ NULL); /* BOOL flag indicates default char is used */ if (bufsize <= 0) { g_warning ("failed to convert a string from wchar to utf8 0"); return NULL; } utf8 = g_malloc(bufsize); len = WideCharToMultiByte (CP_UTF8, /* multibyte code page */ 0, /* flags */ wch, /* src */ -1, /* src len, -1 for all includes \0 */ utf8, /* dst */ bufsize, /* dst buf len */ NULL, /* default char */ NULL); /* BOOL flag indicates default char is used */ if (len != bufsize) { g_free (utf8); g_warning ("failed to convert a string from wchar to utf8"); return NULL; } return utf8; } wchar_t * wchar_from_utf8 (const char *utf8) { if (utf8 == NULL) { return NULL; } wchar_t *wch = NULL; int bufsize, len; bufsize = MultiByteToWideChar (CP_UTF8, /* multibyte code page */ 0, /* flags */ utf8, /* src */ -1, /* src len, -1 for all includes \0 */ wch, /* dst */ 0); /* dst buf len */ if (bufsize <= 0) { g_warning ("failed to convert a string from wchar to utf8 0"); return NULL; } wch = g_malloc (bufsize * sizeof(wchar_t)); len = MultiByteToWideChar (CP_UTF8, /* multibyte code page */ 0, /* flags */ utf8, /* src */ -1, /* src len, -1 for all includes \0 */ wch, /* dst */ bufsize); /* dst buf len */ if (len != bufsize) { g_free (wch); g_warning ("failed to convert a string from utf8 to wchar"); return NULL; } return wch; } /* Get the commandline arguments in unicode, then convert them to utf8 */ char ** get_argv_utf8 (int *argc) { int i = 0; char **argv = NULL; const wchar_t *cmdline = NULL; wchar_t **argv_w = NULL; cmdline = GetCommandLineW(); argv_w = CommandLineToArgvW (cmdline, argc); if (!argv_w) { printf("failed to CommandLineToArgvW(), GLE=%lu\n", GetLastError()); return NULL; } argv = (char **)malloc (sizeof(char*) * (*argc)); for (i = 0; i < *argc; i++) { argv[i] = wchar_to_utf8 (argv_w[i]); } return argv; } #endif /* ifdef WIN32 */ #ifdef __linux__ /* read the link of /proc/123/exe and compare with `process_name' */ static int find_process_in_dirent(struct dirent *dir, const char *process_name) { char path[512]; /* fisrst construct a path like /proc/123/exe */ if (sprintf (path, "/proc/%s/exe", dir->d_name) < 0) { return -1; } char buf[PATH_MAX]; /* get the full path of exe */ ssize_t l = readlink(path, buf, PATH_MAX); if (l < 0) return -1; buf[l] = '\0'; /* get the base name of exe */ char *base = g_path_get_basename(buf); int ret = strcmp(base, process_name); g_free(base); if (ret == 0) return atoi(dir->d_name); else return -1; } /* read the /proc fs to determine whether some process is running */ gboolean process_is_running (const char *process_name) { DIR *proc_dir = opendir("/proc"); if (!proc_dir) { fprintf (stderr, "failed to open /proc/ dir\n"); return FALSE; } struct dirent *subdir = NULL; while ((subdir = readdir(proc_dir))) { char first = subdir->d_name[0]; /* /proc/[1-9][0-9]* */ if (first > '9' || first < '1') continue; int pid = find_process_in_dirent(subdir, process_name); if (pid > 0) { closedir(proc_dir); return TRUE; } } closedir(proc_dir); return FALSE; } #endif #ifdef __APPLE__ gboolean process_is_running (const char *process_name) { //TODO return FALSE; } #endif char* ccnet_object_type_from_id (const char *object_id) { char *ptr; if ( !(ptr = strchr(object_id, '/')) ) return NULL; return g_strndup(object_id, ptr - object_id); } #ifdef WIN32 /** * In Win32 we need to use _stat64 for files larger than 2GB. _stat64 needs * the `path' argument in gbk encoding. */ #define STAT_STRUCT struct __stat64 #define STAT_FUNC win_stat64_utf8 static inline int win_stat64_utf8 (char *path_u8, STAT_STRUCT *sb) { char *path = ccnet_locale_from_utf8(path_u8); int result = _stat64(path, sb); g_free (path); return result; } #else #define STAT_STRUCT struct stat #define STAT_FUNC stat #endif static gint64 calc_recursively (const char *path, GError **calc_error) { gint64 sum = 0; GError *error = NULL; GDir *folder = g_dir_open(path, 0, &error); if (!folder) { g_set_error (calc_error, CCNET_DOMAIN, 0, "g_open() dir %s failed:%s\n", path, error->message); return -1; } const char *name = NULL; while ((name = g_dir_read_name(folder)) != NULL) { STAT_STRUCT sb; char *full_path= g_build_filename (path, name, NULL); if (STAT_FUNC(full_path, &sb) < 0) { g_set_error (calc_error, CCNET_DOMAIN, 0, "failed to stat on %s: %s\n", full_path, strerror(errno)); g_free(full_path); g_dir_close(folder); return -1; } if (S_ISDIR(sb.st_mode)) { gint64 size = calc_recursively(full_path, calc_error); if (size < 0) { g_free (full_path); g_dir_close (folder); return -1; } sum += size; g_free(full_path); } else if (S_ISREG(sb.st_mode)) { sum += sb.st_size; g_free(full_path); } } g_dir_close (folder); return sum; } gint64 ccnet_calc_directory_size (const char *path, GError **error) { return calc_recursively (path, error); } #ifdef WIN32 /* * strtok_r code directly from glibc.git /string/strtok_r.c since windows * doesn't have it. */ char * strtok_r(char *s, const char *delim, char **save_ptr) { char *token; if(s == NULL) s = *save_ptr; /* Scan leading delimiters. */ s += strspn(s, delim); if(*s == '\0') { *save_ptr = s; return NULL; } /* Find the end of the token. */ token = s; s = strpbrk(token, delim); if(s == NULL) { /* This token finishes the string. */ *save_ptr = strchr(token, '\0'); } else { /* Terminate the token and make *SAVE_PTR point past it. */ *s = '\0'; *save_ptr = s + 1; } return token; } #endif ccnet-6.1.5/lib/utils.h000066400000000000000000000216011317035602700147020ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_UTILS_H #define CCNET_UTILS_H #include #include #include #include #include #include #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #ifdef WIN32 #include #include #ifndef WEXITSTATUS #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) #endif /* Borrowed from libevent */ #define ccnet_pipe_t intptr_t int pgpipe (ccnet_pipe_t handles[2]); #define ccnet_mkdir(a,b) g_mkdir((a),(b)) #define ccnet_pipe(a) pgpipe((a)) #define piperead(a,b,c) recv((a),(b),(c),0) #define pipewrite(a,b,c) send((a),(b),(c),0) #define pipeclose(a) closesocket((a)) static inline int ccnet_rename(const char *oldfile, const char *newfile) { int ret = g_rename (oldfile, newfile); if (ret < 0) { if (errno != EEXIST) return -1; ret = g_unlink(oldfile); if (ret < 0) { g_warning("ccnet_rename failed because g_unlink failed\n"); return -1; } return g_rename(oldfile, newfile); } return 0; } #else #define ccnet_pipe_t int #define ccnet_mkdir(a,b) g_mkdir((a),(b)) #define ccnet_pipe(a) pipe((a)) #define piperead(a,b,c) read((a),(b),(c)) #define pipewrite(a,b,c) write((a),(b),(c)) #define pipeclose(a) close((a)) #define ccnet_rename g_rename #endif #define pipereadn(a,b,c) recvn((a),(b),(c)) #define pipewriten(a,b,c) sendn((a),(b),(c)) #ifndef O_BINARY #define O_BINARY 0 #endif /* for debug */ #ifndef ccnet_warning #define ccnet_warning(fmt, ...) g_warning("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__) #endif #ifndef ccnet_error #define ccnet_error(fmt, ...) g_error("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__) #endif #ifndef ccnet_message #define ccnet_message(fmt, ...) g_message("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__) #endif #define CCNET_DOMAIN g_quark_from_string("ccnet") struct timeval timeval_from_msec (uint64_t milliseconds); size_t ccnet_strlcpy (char *dst, const char *src, size_t size); void rawdata_to_hex (const unsigned char *rawdata, char *hex_str, int n_bytes); int hex_to_rawdata (const char *hex_str, unsigned char *rawdata, int n_bytes); #define sha1_to_hex(sha1, hex) rawdata_to_hex((sha1), (hex), 20) #define hex_to_sha1(hex, sha1) hex_to_rawdata((hex), (sha1), 20) int calculate_sha1 (unsigned char *sha1, const char *msg); int ccnet_sha1_equal (const void *v1, const void *v2); unsigned int ccnet_sha1_hash (const void *v); char* gen_uuid (); void gen_uuid_inplace (char *buf); gboolean is_uuid_valid (const char *uuid_str); /* dir operations */ int checkdir (const char *dir); int checkdir_with_mkdir (const char *path); char* ccnet_expand_path (const char *src); /** * Make directory with 256 sub-directories from '00' to 'ff'. * `base` and subdir will be created if they are not existing. */ int objstore_mkdir (const char *base); void objstore_get_path (char *path, const char *base, const char *obj_id); char** strsplit_by_space (char *string, int *length); /* Read "n" bytes from a descriptor. */ ssize_t readn(int fd, void *vptr, size_t n); ssize_t writen(int fd, const void *vptr, size_t n); /* Read "n" bytes from a socket. */ ssize_t recvn(evutil_socket_t fd, void *vptr, size_t n); ssize_t sendn(evutil_socket_t fd, const void *vptr, size_t n); int copy_fd (int ifd, int ofd); int copy_file (const char *dst, const char *src, int mode); /* string utilities */ char** strsplit_by_char (char *string, int *length, char c); char * strjoin_n (const char *seperator, int argc, char **argv); int is_ipaddr_valid (const char *ip); typedef void (*KeyValueFunc) (void *data, const char *key, char *value); void parse_key_value_pairs (char *string, KeyValueFunc func, void *data); typedef gboolean (*KeyValueFunc2) (void *data, const char *key, const char *value); void parse_key_value_pairs2 (char *string, KeyValueFunc2 func, void *data); gchar* ccnet_key_file_get_string (GKeyFile *keyf, const char *category, const char *key); GList *string_list_append (GList *str_list, const char *string); GList *string_list_append_sorted (GList *str_list, const char *string); GList *string_list_remove (GList *str_list, const char *string); void string_list_free (GList *str_list); gboolean string_list_is_exists (GList *str_list, const char *string); void string_list_join (GList *str_list, GString *strbuf, const char *seperator); GList *string_list_parse (const char *list_in_str, const char *seperator); GList *string_list_parse_sorted (const char *list_in_str, const char *seperator); gboolean string_list_sorted_is_equal (GList *list1, GList *list2); char** ncopy_string_array (char **orig, int n); void nfree_string_array (char **array, int n); /* 64bit time */ gint64 get_current_time(); int ccnet_generate_cipher (const char *passwd, int plen, unsigned char *key, unsigned char *iv); int ccnet_encrypt_with_key (char **data_out, int *out_len, const char *data_in, const int in_len, const unsigned char *key, const unsigned char *iv); int ccnet_decrypt_with_key (char **data_out, int *out_len, const char *data_in, const int in_len, const unsigned char *key, const unsigned char *iv); int ccnet_encrypt (char **data_out, int *out_len, const char *data_in, const int in_len, const char *code, const int code_len); int ccnet_decrypt (char **data_out, int *out_len, const char *data_in, const int in_len, const char *code, const int code_len); /* * Utility functions for converting data to/from network byte order. */ static inline uint64_t hton64(uint64_t val) { uint64_t ret; uint8_t *ptr = (uint8_t *)&ret; ptr[0]=((val)>>56)&0xFF; ptr[1]=((val)>>48)&0xFF; ptr[2]=((val)>>40)&0xFF; ptr[3]=((val)>>32)&0xFF; ptr[4]=((val)>>24)&0xFF; ptr[5]=((val)>>16)&0xFF; ptr[6]=((val)>>8)&0xFF; ptr[7]=(val)&0xFF; return ret; } static inline uint64_t ntoh64(uint64_t val) { uint64_t t64; uint8_t *ptr = (uint8_t *)&val; t64=(ptr[3]+256*(ptr[2]+256*(ptr[1]+256*ptr[0]))); t64<<=32; t64|=((ptr[7]+256*(ptr[6]+256*(ptr[5]+256*ptr[4]))))&0xffffffffU; return t64; } static inline void put64bit(uint8_t **ptr,uint64_t val) { (*ptr)[0]=((val)>>56)&0xFF; (*ptr)[1]=((val)>>48)&0xFF; (*ptr)[2]=((val)>>40)&0xFF; (*ptr)[3]=((val)>>32)&0xFF; (*ptr)[4]=((val)>>24)&0xFF; (*ptr)[5]=((val)>>16)&0xFF; (*ptr)[6]=((val)>>8)&0xFF; (*ptr)[7]=(val)&0xFF; (*ptr)+=8; } static inline void put32bit(uint8_t **ptr,uint32_t val) { (*ptr)[0]=((val)>>24)&0xFF; (*ptr)[1]=((val)>>16)&0xFF; (*ptr)[2]=((val)>>8)&0xFF; (*ptr)[3]=(val)&0xFF; (*ptr)+=4; } static inline void put16bit(uint8_t **ptr,uint16_t val) { (*ptr)[0]=((val)>>8)&0xFF; (*ptr)[1]=(val)&0xFF; (*ptr)+=2; } static inline void put8bit(uint8_t **ptr,uint8_t val) { (*ptr)[0]=(val)&0xFF; (*ptr)++; } static inline uint64_t get64bit(const uint8_t **ptr) { uint64_t t64; t64=((*ptr)[3]+256*((*ptr)[2]+256*((*ptr)[1]+256*(*ptr)[0]))); t64<<=32; t64|=(((*ptr)[7]+256*((*ptr)[6]+256*((*ptr)[5]+256*(*ptr)[4]))))&0xffffffffU; (*ptr)+=8; return t64; } static inline uint32_t get32bit(const uint8_t **ptr) { uint32_t t32; t32=((*ptr)[3]+256*((*ptr)[2]+256*((*ptr)[1]+256*(*ptr)[0]))); (*ptr)+=4; return t32; } static inline uint16_t get16bit(const uint8_t **ptr) { uint32_t t16; t16=(*ptr)[1]+256*(*ptr)[0]; (*ptr)+=2; return t16; } static inline uint8_t get8bit(const uint8_t **ptr) { uint32_t t8; t8=(*ptr)[0]; (*ptr)++; return t8; } /* Convert between local encoding and utf8. Returns the converted * string if success, otherwise return NULL */ char *ccnet_locale_from_utf8 (const gchar *src); char *ccnet_locale_to_utf8 (const gchar *src); /* Detect whether a process with the given name is running right now. */ gboolean process_is_running(const char *name); #ifdef WIN32 int win32_kill_process (const char *process_name_in); int win32_spawn_process (char *cmd, char *wd); char *wchar_to_utf8 (const wchar_t *src); wchar_t *wchar_from_utf8 (const char *src); char **get_argv_utf8 (int *argc); #endif char* ccnet_object_type_from_id (const char *object_id); gint64 ccnet_calc_directory_size (const char *path, GError **error); #ifdef WIN32 char * strtok_r(char *s, const char *delim, char **save_ptr); #endif #endif ccnet-6.1.5/libccnet.pc.in000066400000000000000000000005231317035602700153370ustar00rootroot00000000000000prefix=(DESTDIR)@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libccnet Description: Client library for accessing ccnet service. Version: @VERSION@ Libs: -L${libdir} -lccnet @SEARPC_LIBS@ @LIBEVENT_LIBS@ @LIB_UUID@ Cflags: -I${includedir} @SEARPC_CFLAGS@ @LIBEVENT_CFLAGS@ Requires: gobject-2.0 glib-2.0 ccnet-6.1.5/m4/000077500000000000000000000000001317035602700131435ustar00rootroot00000000000000ccnet-6.1.5/m4/python.m4000066400000000000000000000036141317035602700147320ustar00rootroot00000000000000## this one is commonly used with AM_PATH_PYTHONDIR ... dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]]) dnl Check if a module containing a given symbol is visible to python. AC_DEFUN([AM_CHECK_PYMOD], [AC_REQUIRE([AM_PATH_PYTHON]) py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'` AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1) AC_CACHE_VAL(py_cv_mod_$py_mod_var, [ ifelse([$2],[], [prog=" import sys try: import $1 except ImportError: sys.exit(1) except: sys.exit(0) sys.exit(0)"], [prog=" import $1 $1.$2"]) if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC then eval "py_cv_mod_$py_mod_var=yes" else eval "py_cv_mod_$py_mod_var=no" fi ]) py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"` if test "x$py_val" != xno; then AC_MSG_RESULT(yes) ifelse([$3], [],, [$3 ])dnl else AC_MSG_RESULT(no) ifelse([$4], [],, [$4 ])dnl fi ]) dnl a macro to check for ability to create python extensions dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE]) dnl function also defines PYTHON_INCLUDES AC_DEFUN([AM_CHECK_PYTHON_HEADERS], [AC_REQUIRE([AM_PATH_PYTHON]) AC_MSG_CHECKING(for headers required to compile python extensions) dnl deduce PYTHON_INCLUDES py_prefix=`$PYTHON -c "import sys; print sys.prefix"` py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"` if test -x "$PYTHON-config"; then PYTHON_INCLUDES=`$PYTHON-config --includes 2>/dev/null` else PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}" if test "$py_prefix" != "$py_exec_prefix"; then PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}" fi fi AC_SUBST(PYTHON_INCLUDES) dnl check if the headers exist: save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES" AC_TRY_CPP([#include ],dnl [AC_MSG_RESULT(found) $1],dnl [AC_MSG_RESULT(not found) $2]) CPPFLAGS="$save_CPPFLAGS" ]) ccnet-6.1.5/net/000077500000000000000000000000001317035602700134115ustar00rootroot00000000000000ccnet-6.1.5/net/Makefile.am000066400000000000000000000000221317035602700154370ustar00rootroot00000000000000 SUBDIRS = daemon ccnet-6.1.5/net/common/000077500000000000000000000000001317035602700147015ustar00rootroot00000000000000ccnet-6.1.5/net/common/algorithms.c000066400000000000000000000063471317035602700172300ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "peer.h" #include "session.h" #include "peer-mgr.h" #include "message.h" #include "message-manager.h" #include "proc-factory.h" #include "processors/sendmsg-proc.h" #include "algorithms.h" #define DEBUG_FLAG CCNET_DEBUG_MESSAGE #include "log.h" #if 0 static void notify_sendmsg_success (CcnetSession *session, CcnetMessage *ack_msg, char *destid) { CcnetMessageManager *msg_mgr = session->msg_mgr; CcnetMessage *msg; char buf[128] = {0}; g_assert (ack_msg != NULL); snprintf (buf, sizeof(buf), "%s %s", ack_msg->id, destid); msg = ccnet_message_new (session->base.id, ack_msg->from, ack_msg->app, buf, FLAG_IS_ACK); if (memcmp(session->base.id, ack_msg->from, 40) == 0) ccnet_message_manager_add_msg (msg_mgr, msg, MSG_TYPE_SYS); else ccnet_send_message (session, msg); } static void msg_cb (CcnetProcessor *proc, gboolean success, void *data) { CcnetMessage *msg = data; if (success) notify_sendmsg_success (proc->session, msg, proc->peer->id); } #endif /* 0 */ static void ccnet_send_msg_to_peer (CcnetSession *session, CcnetPeer *peer, CcnetMessage *msg) { CcnetProcessor *processor; CcnetProcFactory *factory = session->proc_factory; if (peer->net_state == PEER_CONNECTED) { processor = ccnet_proc_factory_create_master_processor (factory, "send-msg", peer); ccnet_sendmsg_proc_set_msg (CCNET_SENDMSG_PROC(processor), msg); /* g_signal_connect (processor, "done", */ /* G_CALLBACK(msg_cb), msg); */ ccnet_processor_start (processor, 0, NULL); } } void ccnet_send_message (CcnetSession *session, CcnetMessage *msg) { CcnetPeer *peer; peer = ccnet_peer_manager_get_peer (session->peer_mgr, msg->to); if (peer) { if (peer->is_self) ccnet_message_manager_add_msg (session->msg_mgr, msg, MSG_TYPE_RECV); else ccnet_send_msg_to_peer (session, peer, msg); g_object_unref (peer); } else g_warning ("Invalid peer id %s\n", msg->to); } static gboolean check_message_permission (CcnetSession *session, CcnetMessage *msg) { CcnetPeerManager *peer_mgr = session->peer_mgr; CcnetPeer *from; if (strcmp(msg->app, IPEERMGR_APP) == 0) return TRUE; if (msg->flags & FLAG_IS_ACK) return TRUE; from = ccnet_peer_manager_get_peer (peer_mgr, msg->from); if (!from) return FALSE; /* peer to peer message */ /* TODO: improve performance */ if (ccnet_peer_has_role(from, "MyPeer") || ccnet_peer_has_role(from, "MyRelay") || ccnet_peer_has_role(from, "MyClient")) { g_object_unref (from); return TRUE; } g_object_unref (from); return FALSE; } int ccnet_recv_message (CcnetSession *session, CcnetMessage *msg) { CcnetMessageManager *msg_mgr = session->msg_mgr; if (check_message_permission(session, msg) == FALSE) return -1; ccnet_message_manager_add_msg (msg_mgr, msg, MSG_TYPE_RECV); return 0; } ccnet-6.1.5/net/common/algorithms.h000066400000000000000000000004261317035602700172250ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_ALGORITHMS_H #define CCNET_ALGORITHMS_H void ccnet_send_message (CcnetSession *session, CcnetMessage *msg); int ccnet_recv_message (CcnetSession *session, CcnetMessage *msg); #endif ccnet-6.1.5/net/common/ccnet-config.c000066400000000000000000000050551317035602700174110ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "ccnet-config.h" static gboolean get_value (sqlite3_stmt *stmt, void *data) { char **p_value = data; *p_value = g_strdup((char *) sqlite3_column_text (stmt, 0)); /* Only one result. */ return FALSE; } static char * config_get_string (sqlite3 *config_db, const char *key) { char sql[256]; char *value = NULL; snprintf (sql, sizeof(sql), "SELECT value FROM Config WHERE key='%s';", key); if (sqlite_foreach_selected_row (config_db, sql, get_value, &value) < 0) return NULL; return value; } char * ccnet_session_config_get_string (CcnetSession *session, const char *key) { return (config_get_string (session->config_db, key)); } int ccnet_session_config_get_int (CcnetSession *session, const char *key, gboolean *exists) { char *value; int ret; value = config_get_string (session->config_db, key); if (!value) { *exists = FALSE; return -1; } *exists = TRUE; ret = atoi (value); g_free (value); return ret; } int ccnet_session_config_set_string (CcnetSession *session, const char *key, const char *value) { char sql[256]; snprintf (sql, sizeof(sql), "REPLACE INTO Config VALUES ('%s', '%s');", key, value); if (sqlite_query_exec (session->config_db, sql) < 0) return -1; return 0; } int ccnet_session_config_set_int (CcnetSession *session, const char *key, int value) { char sql[256]; snprintf (sql, sizeof(sql), "REPLACE INTO Config VALUES ('%s', %d);", key, value); if (sqlite_query_exec (session->config_db, sql) < 0) return -1; return 0; } sqlite3 * ccnet_session_config_open_db (const char *ccnet_dir) { sqlite3 *db; char *db_path; db_path = g_build_filename (ccnet_dir, "config.db", NULL); if (sqlite_open_db (db_path, &db) < 0) return NULL; g_free (db_path); /* * Values are stored in text. You should convert it * back to integer if needed when you read it from * db. */ char *sql = "CREATE TABLE IF NOT EXISTS Config (" "key TEXT PRIMARY KEY, " "value TEXT);"; sqlite_query_exec (db, sql); return db; } ccnet-6.1.5/net/common/ccnet-config.h000066400000000000000000000020311317035602700174050ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef SEAFILE_CONFIG_H #define SEAFILE_CONFIG_H #include "session.h" #include "db.h" /* * Returns: config value in string. The string should be freed by caller. */ char * ccnet_session_config_get_string (CcnetSession *session, const char *key); /* * Returns: * If key exists, @exists will be set to TRUE and returns the value; * otherwise, @exists will be set to FALSE and returns -1. */ int ccnet_session_config_get_int (CcnetSession *session, const char *key, gboolean *exists); int ccnet_session_config_set_string (CcnetSession *session, const char *key, const char *value); int ccnet_session_config_set_int (CcnetSession *session, const char *key, int value); sqlite3 * ccnet_session_config_open_db (const char *ccnet_dir); #endif ccnet-6.1.5/net/common/ccnet-db.c000066400000000000000000000626741317035602700165430ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include "ccnet-db.h" #ifdef WIN32 #include #define sleep(n) Sleep(1000 * (n)) #endif #define MAX_GET_CONNECTION_RETRIES 3 struct CcnetDB { int type; ConnectionPool_T pool; }; struct CcnetDBRow { ResultSet_T res; }; CcnetDB * ccnet_db_new_mysql (const char *host, const char *port, const char *user, const char *passwd, const char *db_name, const char *unix_socket, gboolean use_ssl, const char *charset, int max_connections) { CcnetDB *db; GString *url; URL_T zdb_url; gboolean has_param = FALSE; db = g_new0 (CcnetDB, 1); if (!db) { g_warning ("Failed to alloc db structure.\n"); return NULL; } char *passwd_esc = g_uri_escape_string (passwd, NULL, FALSE); url = g_string_new (""); g_string_append_printf (url, "mysql://%s:%s@%s:%s/", user, passwd_esc, host, port); if (db_name) g_string_append (url, db_name); if (unix_socket) { g_string_append_printf (url, "?unix-socket=%s", unix_socket); has_param = TRUE; } if (use_ssl) { g_string_append_printf (url, "%suse-ssl=true", has_param?"&":"?"); has_param = TRUE; } if (charset) { g_string_append_printf (url, "%scharset=%s", has_param?"&":"?", charset); has_param = TRUE; } g_free (passwd_esc); zdb_url = URL_new (url->str); db->pool = ConnectionPool_new (zdb_url); if (!db->pool) { g_warning ("Failed to create db connection pool.\n"); g_string_free (url, TRUE); g_free (db); return NULL; } ConnectionPool_setMaxConnections (db->pool, max_connections); ConnectionPool_start (db->pool); db->type = CCNET_DB_TYPE_MYSQL; return db; } CcnetDB * ccnet_db_new_pgsql (const char *host, const char *user, const char *passwd, const char *db_name, const char *unix_socket) { CcnetDB *db; GString *url; URL_T zdb_url; db = g_new0 (CcnetDB, 1); if (!db) { g_warning ("Failed to alloc db structure.\n"); return NULL; } url = g_string_new (""); g_string_append_printf (url, "postgresql://%s:%s@%s/", user, passwd, host); if (db_name) g_string_append (url, db_name); if (unix_socket) g_string_append_printf (url, "?unix-socket=%s", unix_socket); zdb_url = URL_new (url->str); db->pool = ConnectionPool_new (zdb_url); if (!db->pool) { g_warning ("Failed to create db connection pool.\n"); g_string_free (url, TRUE); g_free (db); return NULL; } ConnectionPool_start (db->pool); db->type = CCNET_DB_TYPE_PGSQL; return db; } CcnetDB * ccnet_db_new_sqlite (const char *db_path) { CcnetDB *db; GString *url; URL_T zdb_url; db = g_new0 (CcnetDB, 1); if (!db) { g_warning ("Failed to alloc db structure.\n"); return NULL; } url = g_string_new (""); g_string_append_printf (url, "sqlite://%s", db_path); zdb_url = URL_new (url->str); db->pool = ConnectionPool_new (zdb_url); if (!db->pool) { g_warning ("Failed to create db connection pool.\n"); g_string_free (url, TRUE); g_free (db); return NULL; } ConnectionPool_start (db->pool); db->type = CCNET_DB_TYPE_SQLITE; return db; } void ccnet_db_free (CcnetDB *db) { ConnectionPool_stop (db->pool); ConnectionPool_free (&db->pool); g_free (db); } int ccnet_db_type (CcnetDB *db) { return db->type; } static Connection_T get_db_connection (CcnetDB *db) { Connection_T conn; int retries = 0; conn = ConnectionPool_getConnection (db->pool); /* If max_connections of the pool has been reached, retry 3 times * and then return NULL. */ while (!conn) { if (retries++ == MAX_GET_CONNECTION_RETRIES) { g_warning ("Too many concurrent connections. " "Failed to create new connection.\n"); goto out; } sleep (1); conn = ConnectionPool_getConnection (db->pool); } if (!conn) g_warning ("Failed to create new connection.\n"); out: return conn; } int ccnet_db_query (CcnetDB *db, const char *sql) { Connection_T conn = get_db_connection (db); if (!conn) return -1; /* Handle zdb "exception"s. */ TRY Connection_execute (conn, "%s", sql); Connection_close (conn); RETURN (0); CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return -1; END_TRY; /* Should not be reached. */ return 0; } gboolean ccnet_db_check_for_existence (CcnetDB *db, const char *sql) { Connection_T conn; ResultSet_T result; gboolean ret = TRUE; conn = get_db_connection (db); if (!conn) { return FALSE; } TRY result = Connection_executeQuery (conn, "%s", sql); CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return FALSE; END_TRY; TRY if (!ResultSet_next (result)) ret = FALSE; CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return FALSE; END_TRY; Connection_close (conn); return ret; } int ccnet_db_foreach_selected_row (CcnetDB *db, const char *sql, CcnetDBRowFunc callback, void *data) { Connection_T conn; ResultSet_T result; CcnetDBRow ccnet_row; int n_rows = 0; conn = get_db_connection (db); if (!conn) return -1; TRY result = Connection_executeQuery (conn, "%s", sql); CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return -1; END_TRY; ccnet_row.res = result; TRY while (ResultSet_next (result)) { n_rows++; if (!callback (&ccnet_row, data)) break; } CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return -1; END_TRY; Connection_close (conn); return n_rows; } const char * ccnet_db_row_get_column_text (CcnetDBRow *row, guint32 idx) { g_return_val_if_fail (idx < ResultSet_getColumnCount(row->res), NULL); return ResultSet_getString (row->res, idx+1); } int ccnet_db_row_get_column_int (CcnetDBRow *row, guint32 idx) { g_return_val_if_fail (idx < ResultSet_getColumnCount(row->res), -1); return ResultSet_getInt (row->res, idx+1); } gint64 ccnet_db_row_get_column_int64 (CcnetDBRow *row, guint32 idx) { g_return_val_if_fail (idx < ResultSet_getColumnCount(row->res), -1); return ResultSet_getLLong (row->res, idx+1); } int ccnet_db_get_int (CcnetDB *db, const char *sql) { int ret = -1; Connection_T conn; ResultSet_T result; CcnetDBRow ccnet_row; conn = get_db_connection (db); if (!conn) return -1; TRY result = Connection_executeQuery (conn, "%s", sql); CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return -1; END_TRY; ccnet_row.res = result; TRY if (ResultSet_next (result)) ret = ccnet_db_row_get_column_int (&ccnet_row, 0); CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return -1; END_TRY; Connection_close (conn); return ret; } gint64 ccnet_db_get_int64 (CcnetDB *db, const char *sql) { gint64 ret = -1; Connection_T conn; ResultSet_T result; CcnetDBRow ccnet_row; conn = get_db_connection (db); if (!conn) return -1; TRY result = Connection_executeQuery (conn, "%s", sql); CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return -1; END_TRY; ccnet_row.res = result; TRY if (ResultSet_next (result)) ret = ccnet_db_row_get_column_int64 (&ccnet_row, 0); CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return -1; END_TRY; Connection_close (conn); return ret; } char * ccnet_db_get_string (CcnetDB *db, const char *sql) { char *ret = NULL; const char *s; Connection_T conn; ResultSet_T result; CcnetDBRow ccnet_row; conn = get_db_connection (db); if (!conn) return NULL; TRY result = Connection_executeQuery (conn, "%s", sql); CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return NULL; END_TRY; ccnet_row.res = result; TRY if (ResultSet_next (result)) { s = ccnet_db_row_get_column_text (&ccnet_row, 0); ret = g_strdup(s); } CATCH (SQLException) g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message); Connection_close (conn); return NULL; END_TRY; Connection_close (conn); return ret; } gboolean pgsql_index_exists (CcnetDB *db, const char *index_name) { char sql[256]; snprintf (sql, sizeof(sql), "SELECT 1 FROM pg_class WHERE relname='%s'", index_name); return ccnet_db_check_for_existence (db, sql); } char * ccnet_db_escape_string (CcnetDB *db, const char *from) { const char *p = from; char *to, *q; to = g_malloc0 (2*strlen(from)+1); q = to; while (*p != '\0') { if (*p == '\'' || *p == '\\' || *p == '"') { *q = *p; *(++q) = *p; } else *q = *p; ++p; ++q; } return to; } struct CcnetDBStatement { PreparedStatement_T p; Connection_T conn; }; typedef struct CcnetDBStatement CcnetDBStatement; CcnetDBStatement * ccnet_db_prepare_statement (CcnetDB *db, const char *sql) { PreparedStatement_T p; CcnetDBStatement *ret = g_new0 (CcnetDBStatement, 1); Connection_T conn = get_db_connection (db); if (!conn) { g_free (ret); return NULL; } TRY p = Connection_prepareStatement (conn, "%s", sql); ret->p = p; ret->conn = conn; RETURN (ret); CATCH (SQLException) g_warning ("Error prepare statement %s: %s.\n", sql, Exception_frame.message); g_free (ret); Connection_close (conn); return NULL; END_TRY; /* Should not be reached. */ return NULL; } void ccnet_db_statement_free (CcnetDBStatement *p) { Connection_close (p->conn); g_free (p); } int ccnet_db_statement_set_int (CcnetDBStatement *p, int idx, int x) { TRY PreparedStatement_setInt (p->p, idx, x); RETURN (0); CATCH (SQLException) g_warning ("Error set int in prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; return -1; } int ccnet_db_statement_set_string (CcnetDBStatement *p, int idx, const char *s) { TRY PreparedStatement_setString (p->p, idx, s); RETURN (0); CATCH (SQLException) g_warning ("Error set string in prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; return -1; } int ccnet_db_statement_set_int64 (CcnetDBStatement *p, int idx, gint64 x) { TRY PreparedStatement_setLLong (p->p, idx, (long long)x); RETURN (0); CATCH (SQLException) g_warning ("Error set int64 in prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; return -1; } static int set_parameters_va (CcnetDBStatement *p, int n, va_list args) { int i; const char *type; for (i = 0; i < n; ++i) { type = va_arg (args, const char *); if (strcmp(type, "int") == 0) { int x = va_arg (args, int); if (ccnet_db_statement_set_int (p, i+1, x) < 0) return -1; } else if (strcmp (type, "int64") == 0) { gint64 x = va_arg (args, gint64); if (ccnet_db_statement_set_int64 (p, i+1, x) < 0) return -1; } else if (strcmp (type, "string") == 0) { const char *s = va_arg (args, const char *); if (ccnet_db_statement_set_string (p, i+1, s) < 0) return -1; } else { g_warning ("BUG: invalid prep stmt parameter type %s.\n", type); g_return_val_if_reached (-1); } } return 0; } int ccnet_db_statement_query (CcnetDB *db, const char *sql, int n, ...) { CcnetDBStatement *p; volatile int ret = 0; p = ccnet_db_prepare_statement (db, sql); if (!p) return -1; va_list args; va_start (args, n); if (set_parameters_va (p, n, args) < 0) { ccnet_db_statement_free (p); va_end (args); return -1; } va_end (args); TRY PreparedStatement_execute (p->p); CATCH (SQLException) g_warning ("Error execute prep stmt: %s.\n", Exception_frame.message); ret = -1; END_TRY; ccnet_db_statement_free (p); return ret; } gboolean ccnet_db_statement_exists (CcnetDB *db, const char *sql, int n, ...) { CcnetDBStatement *p; ResultSet_T result; volatile gboolean ret = TRUE; p = ccnet_db_prepare_statement (db, sql); if (!p) return FALSE; va_list args; va_start (args, n); if (set_parameters_va (p, n, args) < 0) { ccnet_db_statement_free (p); va_end (args); return FALSE; } va_end (args); TRY result = PreparedStatement_executeQuery (p->p); CATCH (SQLException) g_warning ("Error exec prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return FALSE; END_TRY; TRY if (!ResultSet_next (result)) ret = FALSE; CATCH (SQLException) g_warning ("Error get next result from prep stmt: %s.\n", Exception_frame.message); ret = FALSE; END_TRY; ccnet_db_statement_free (p); return ret; } int ccnet_db_statement_foreach_row (CcnetDB *db, const char *sql, CcnetDBRowFunc callback, void *data, int n, ...) { CcnetDBStatement *p; ResultSet_T result; CcnetDBRow ccnet_row; volatile int n_rows = 0; p = ccnet_db_prepare_statement (db, sql); if (!p) return -1; va_list args; va_start (args, n); if (set_parameters_va (p, n, args) < 0) { ccnet_db_statement_free (p); va_end (args); return -1; } va_end (args); TRY result = PreparedStatement_executeQuery (p->p); CATCH (SQLException) g_warning ("Error exec prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return -1; END_TRY; ccnet_row.res = result; TRY while (ResultSet_next (result)) { n_rows++; if (!callback (&ccnet_row, data)) break; } CATCH (SQLException) g_warning ("Error get next result for prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return -1; END_TRY; ccnet_db_statement_free (p); return n_rows; } int ccnet_db_statement_get_int (CcnetDB *db, const char *sql, int n, ...) { CcnetDBStatement *p; volatile int ret = -1; ResultSet_T result; CcnetDBRow ccnet_row; p = ccnet_db_prepare_statement (db, sql); if (!p) return -1; va_list args; va_start (args, n); if (set_parameters_va (p, n, args) < 0) { ccnet_db_statement_free (p); va_end (args); return -1; } va_end (args); TRY result = PreparedStatement_executeQuery (p->p); CATCH (SQLException) g_warning ("Error exec prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return -1; END_TRY; ccnet_row.res = result; TRY if (ResultSet_next (result)) ret = ccnet_db_row_get_column_int (&ccnet_row, 0); CATCH (SQLException) g_warning ("Error get next result for prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return -1; END_TRY; ccnet_db_statement_free (p); return ret; } gint64 ccnet_db_statement_get_int64 (CcnetDB *db, const char *sql, int n, ...) { CcnetDBStatement *p; volatile gint64 ret = -1; ResultSet_T result; CcnetDBRow ccnet_row; p = ccnet_db_prepare_statement (db, sql); if (!p) return -1; va_list args; va_start (args, n); if (set_parameters_va (p, n, args) < 0) { ccnet_db_statement_free (p); va_end (args); return -1; } va_end (args); TRY result = PreparedStatement_executeQuery (p->p); CATCH (SQLException) g_warning ("Error exec prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return -1; END_TRY; ccnet_row.res = result; TRY if (ResultSet_next (result)) ret = ccnet_db_row_get_column_int64 (&ccnet_row, 0); CATCH (SQLException) g_warning ("Error get next result for prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return -1; END_TRY; ccnet_db_statement_free (p); return ret; } char * ccnet_db_statement_get_string (CcnetDB *db, const char *sql, int n, ...) { CcnetDBStatement *p; char *ret = NULL; const char *s; ResultSet_T result; CcnetDBRow ccnet_row; p = ccnet_db_prepare_statement (db, sql); if (!p) return NULL; va_list args; va_start (args, n); if (set_parameters_va (p, n, args) < 0) { ccnet_db_statement_free (p); va_end (args); return NULL; } va_end (args); TRY result = PreparedStatement_executeQuery (p->p); CATCH (SQLException) g_warning ("Error exec prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return NULL; END_TRY; ccnet_row.res = result; TRY if (ResultSet_next (result)) { s = ccnet_db_row_get_column_text (&ccnet_row, 0); ret = g_strdup(s); } CATCH (SQLException) g_warning ("Error get next result for prep stmt: %s.\n", Exception_frame.message); ccnet_db_statement_free (p); return NULL; END_TRY; ccnet_db_statement_free (p); return ret; } /* Transaction */ struct CcnetDBTrans { Connection_T conn; }; CcnetDBTrans * ccnet_db_begin_transaction (CcnetDB *db) { Connection_T conn; CcnetDBTrans *trans; trans = g_new0 (CcnetDBTrans, 1); if (!trans) return NULL; conn = get_db_connection (db); if (!conn) { g_free (trans); return NULL; } trans->conn = conn; TRY Connection_beginTransaction (trans->conn); CATCH (SQLException) ccnet_warning ("Start transaction failed: %s.\n", Exception_frame.message); Connection_close (trans->conn); g_free (trans); return NULL; END_TRY; return trans; } void ccnet_db_trans_close (CcnetDBTrans *trans) { Connection_close (trans->conn); g_free (trans); } int ccnet_db_commit (CcnetDBTrans *trans) { Connection_T conn = trans->conn; TRY Connection_commit (conn); CATCH (SQLException) ccnet_warning ("Commit failed: %s.\n", Exception_frame.message); return -1; END_TRY; return 0; } int ccnet_db_rollback (CcnetDBTrans *trans) { Connection_T conn = trans->conn; TRY Connection_rollback (conn); CATCH (SQLException) ccnet_warning ("Rollback failed: %s.\n", Exception_frame.message); return -1; END_TRY; return 0; } static int trans_statement_set_int (PreparedStatement_T p, int idx, int x) { TRY PreparedStatement_setInt (p, idx, x); RETURN (0); CATCH (SQLException) ccnet_warning ("Error set int in prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; return -1; } static int trans_statement_set_string (PreparedStatement_T p, int idx, const char *s) { TRY PreparedStatement_setString (p, idx, s); RETURN (0); CATCH (SQLException) ccnet_warning ("Error set string in prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; return -1; } static int trans_statement_set_int64 (PreparedStatement_T p, int idx, gint64 x) { TRY PreparedStatement_setLLong (p, idx, (long long)x); RETURN (0); CATCH (SQLException) ccnet_warning ("Error set int64 in prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; return -1; } static int trans_set_parameters_va (PreparedStatement_T p, int n, va_list args) { int i; const char *type; for (i = 0; i < n; ++i) { type = va_arg (args, const char *); if (strcmp(type, "int") == 0) { int x = va_arg (args, int); if (trans_statement_set_int (p, i+1, x) < 0) return -1; } else if (strcmp (type, "int64") == 0) { gint64 x = va_arg (args, gint64); if (trans_statement_set_int64 (p, i+1, x) < 0) return -1; } else if (strcmp (type, "string") == 0) { const char *s = va_arg (args, const char *); if (trans_statement_set_string (p, i+1, s) < 0) return -1; } else { ccnet_warning ("BUG: invalid prep stmt parameter type %s.\n", type); g_return_val_if_reached (-1); } } return 0; } static PreparedStatement_T trans_prepare_statement (Connection_T conn, const char *sql) { PreparedStatement_T p; TRY p = Connection_prepareStatement (conn, "%s", sql); RETURN (p); CATCH (SQLException) ccnet_warning ("Error prepare statement %s: %s.\n", sql, Exception_frame.message); return NULL; END_TRY; /* Should not be reached. */ return NULL; } int ccnet_db_trans_query (CcnetDBTrans *trans, const char *sql, int n, ...) { PreparedStatement_T p; p = trans_prepare_statement (trans->conn, sql); if (!p) return -1; va_list args; va_start (args, n); if (trans_set_parameters_va (p, n, args) < 0) { va_end (args); return -1; } va_end (args); /* Handle zdb "exception"s. */ TRY PreparedStatement_execute (p); RETURN (0); CATCH (SQLException) ccnet_warning ("Error exec prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; /* Should not be reached. */ return 0; } gboolean ccnet_db_trans_check_for_existence (CcnetDBTrans *trans, const char *sql, gboolean *db_err, int n, ...) { ResultSet_T result; gboolean ret = TRUE; *db_err = FALSE; PreparedStatement_T p; p = trans_prepare_statement (trans->conn, sql); if (!p) { *db_err = TRUE; return FALSE; } va_list args; va_start (args, n); if (trans_set_parameters_va (p, n, args) < 0) { *db_err = TRUE; va_end (args); return -1; } va_end (args); TRY result = PreparedStatement_executeQuery (p); CATCH (SQLException) ccnet_warning ("Error exec prep stmt: %s.\n", Exception_frame.message); *db_err = TRUE; return FALSE; END_TRY; TRY if (!ResultSet_next (result)) ret = FALSE; CATCH (SQLException) ccnet_warning ("Error get next result for prep stmt: %s.\n", Exception_frame.message); *db_err = TRUE; return FALSE; END_TRY; return ret; } int ccnet_db_trans_foreach_selected_row (CcnetDBTrans *trans, const char *sql, CcnetDBRowFunc callback, void *data, int n, ...) { ResultSet_T result; CcnetDBRow ccnet_row; int n_rows = 0; PreparedStatement_T p; p = trans_prepare_statement (trans->conn, sql); if (!p) return FALSE; va_list args; va_start (args, n); if (trans_set_parameters_va (p, n, args) < 0) { va_end (args); return -1; } va_end (args); TRY result = PreparedStatement_executeQuery (p); CATCH (SQLException) ccnet_warning ("Error exec prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; ccnet_row.res = result; TRY while (ResultSet_next (result)) { n_rows++; if (!callback (&ccnet_row, data)) break; } CATCH (SQLException) ccnet_warning ("Error get next result for prep stmt: %s.\n", Exception_frame.message); return -1; END_TRY; return n_rows; } ccnet-6.1.5/net/common/ccnet-db.h000066400000000000000000000077541317035602700165460ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_DB_H #define CCNET_DB_H #include "db.h" #ifdef CCNET_SERVER #define DB_SQLITE "sqlite" #define DB_MYSQL "mysql" #define DB_PGSQL "pgsql" enum { CCNET_DB_TYPE_SQLITE, CCNET_DB_TYPE_MYSQL, CCNET_DB_TYPE_PGSQL, }; typedef struct CcnetDB CcnetDB; typedef struct CcnetDBRow CcnetDBRow; typedef gboolean (*CcnetDBRowFunc) (CcnetDBRow *, void *); CcnetDB * ccnet_db_new_mysql (const char *host, const char *port, const char *user, const char *passwd, const char *db, const char *unix_socket, gboolean use_ssl, const char *charset, int max_connections); CcnetDB * ccnet_db_new_pgsql (const char *host, const char *user, const char *passwd, const char *db, const char *unix_socket); CcnetDB * ccnet_db_new_sqlite (const char *db_path); void ccnet_db_free (CcnetDB *db); int ccnet_db_type (CcnetDB *db); int ccnet_db_query (CcnetDB *db, const char *sql); gboolean ccnet_db_check_for_existence (CcnetDB *db, const char *sql); int ccnet_db_foreach_selected_row (CcnetDB *db, const char *sql, CcnetDBRowFunc callback, void *data); const char * ccnet_db_row_get_column_text (CcnetDBRow *row, guint32 idx); int ccnet_db_row_get_column_int (CcnetDBRow *row, guint32 idx); gint64 ccnet_db_row_get_column_int64 (CcnetDBRow *row, guint32 idx); int ccnet_db_get_int (CcnetDB *db, const char *sql); gint64 ccnet_db_get_int64 (CcnetDB *db, const char *sql); char * ccnet_db_get_string (CcnetDB *db, const char *sql); gboolean pgsql_index_exists (CcnetDB *db, const char *index_name); char * ccnet_db_escape_string (CcnetDB *db, const char *from); /* Prepared statements */ int ccnet_db_statement_query (CcnetDB *db, const char *sql, int n, ...); gboolean ccnet_db_statement_exists (CcnetDB *db, const char *sql, int n, ...); int ccnet_db_statement_foreach_row (CcnetDB *db, const char *sql, CcnetDBRowFunc callback, void *data, int n, ...); int ccnet_db_statement_get_int (CcnetDB *db, const char *sql, int n, ...); gint64 ccnet_db_statement_get_int64 (CcnetDB *db, const char *sql, int n, ...); char * ccnet_db_statement_get_string (CcnetDB *db, const char *sql, int n, ...); typedef struct CcnetDBTrans CcnetDBTrans; CcnetDBTrans * ccnet_db_begin_transaction (CcnetDB *db); void ccnet_db_trans_close (CcnetDBTrans *trans); int ccnet_db_commit (CcnetDBTrans *trans); int ccnet_db_rollback (CcnetDBTrans *trans); int ccnet_db_trans_query (CcnetDBTrans *trans, const char *sql, int n, ...); gboolean ccnet_db_trans_check_for_existence (CcnetDBTrans *trans, const char *sql, gboolean *db_err, int n, ...); int ccnet_db_trans_foreach_selected_row (CcnetDBTrans *trans, const char *sql, CcnetDBRowFunc callback, void *data, int n, ...); #else #define CcnetDB sqlite3 #define CcnetDBRow sqlite3_stmt #define ccnet_db_query sqlite_query_exec #define ccnet_db_free sqlite_close_db #define ccnet_db_begin_transaction sqlite_begin_transaction #define ccnet_db_end_transaction sqlite_end_transaction #define ccnet_db_check_for_existence sqlite_check_for_existence #define ccnet_db_foreach_selected_row sqlite_foreach_selected_row #define ccnet_db_row_get_column_text sqlite3_column_text #define ccnet_db_row_get_column_int sqlite3_column_int #define ccnet_db_row_get_column_int64 sqlite3_column_int64 #define ccnet_db_get_int sqlite_get_int #define ccnet_db_get_int64 sqlite_get_int64 #define ccnet_db_get_string sqlite_get_string #define ccnet_sql_printf sqlite3_mprintf #define ccnet_sql_free sqlite3_free #endif // CCNET_SERVER #endif ccnet-6.1.5/net/common/common.h000066400000000000000000000010661317035602700163450ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef COMMON_H #define COMMON_H #ifdef HAVE_CONFIG_H #include #endif #include #include #include /* uint32_t */ #include /* size_t */ #include #include #include #include "option.h" #ifndef ULLONG_MAX #define ULLONG_MAX 18446744073709551615ULL #endif #define IPEERMGR_APP "IPeerMgr" #include #include "utils.h" #include #endif ccnet-6.1.5/net/common/connect-mgr.c000066400000000000000000000476221317035602700172740ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include "net.h" #include "packet.h" #include "packet-io.h" #include "peer.h" #include "session.h" #include "handshake.h" #include "message.h" #include "peer-mgr.h" #include "connect-mgr.h" #include "message-manager.h" #include "proc-factory.h" #define MAX_RECONNECTIONS_PER_PULSE 5 #define LISTEN_INTERVAL 1000 /* 1s */ #define RECONNECT_PERIOD_MSEC 10000 #define DEBUG_FLAG CCNET_DEBUG_CONNECTION #include "log.h" extern void ccnet_peer_set_net_state (CcnetPeer *peer, int net_state); extern gboolean ccnet_peer_manager_on_peer_resolved (CcnetPeerManager *manager, CcnetPeer *peer); extern void ccnet_peer_manager_on_peer_resolve_failed (CcnetPeerManager *manager, CcnetPeer *peer); static void dns_lookup_peer (CcnetPeer* peer); CcnetConnManager * ccnet_conn_manager_new (CcnetSession *session) { CcnetConnManager *manager; manager = g_new0 (CcnetConnManager, 1); manager->session = session; return manager; } #if 0 /* Note: The handshake timeout is 10s. * So intervals[0] must be larger than 10s to * prevent simultaneously connection tryings. * Actually any value larger than 10 is ok. * Here we just set it to 20s. */ static int intervals[] = { 20, 30, 60, 15 * 60, 30 * 60, 60 * 60, }; static int get_reconnect_interval_secs (const CcnetPeer *peer) { if (peer->is_relay) return intervals[0]; int index = MIN (peer->num_fails, G_N_ELEMENTS(intervals) - 1); return intervals[index]; } #endif void start_keepalive (CcnetPeer *peer) { CcnetProcessor *processor; CcnetProcFactory *factory = peer->manager->session->proc_factory; processor = ccnet_proc_factory_create_master_processor (factory, "keepalive2", peer); if (processor == NULL) { ccnet_warning ("Create keepalive2 processor failed\n"); return; } ccnet_processor_startl (processor, NULL); } static void on_peer_connected (CcnetPeer *peer, CcnetPacketIO *io) { g_return_if_fail (peer->net_state == PEER_DOWN); ccnet_peer_set_io (peer, io); ccnet_peer_set_net_state (peer, PEER_CONNECTED); start_keepalive (peer); } static void notify_found_peer (CcnetSession *session, CcnetPeer *peer) { char buf[128]; sprintf (buf, "found %s\n", peer->id); CcnetMessage *message = ccnet_message_new (session->base.id, session->base.id, "System", buf, 0); ccnet_message_manager_add_msg (session->msg_mgr, message, MSG_TYPE_SYS); } static void on_get_resolve_peer_pub_info_done (CcnetProcessor *processor, gboolean success, void *data) { if (success) { gboolean should_continue; should_continue = ccnet_peer_manager_on_peer_resolved ( processor->peer->manager, processor->peer); if (!should_continue) return; start_keepalive (processor->peer); } else { ccnet_message ("Get resolved peer pub info failed\n"); ccnet_peer_manager_on_peer_resolve_failed ( processor->peer->manager, processor->peer); } } static void on_resolve_peer_connected (CcnetPeer *peer, CcnetPacketIO *io) { CcnetProcessor *processor; CcnetProcFactory *factory = peer->manager->session->proc_factory; ccnet_peer_set_io (peer, io); ccnet_peer_set_net_state (peer, PEER_CONNECTED); processor = ccnet_proc_factory_create_master_processor ( factory, "get-pubinfo", peer); if (processor == NULL) { ccnet_warning ("Create get-pubinfo processor failed\n"); ccnet_peer_shutdown (peer); return; } g_signal_connect (processor, "done", G_CALLBACK(on_get_resolve_peer_pub_info_done), NULL); ccnet_processor_startl (processor, NULL); } static void on_get_unauth_peer_pub_info_done (CcnetProcessor *processor, gboolean success, void *data) { if (success) { notify_found_peer (processor->session, processor->peer); start_keepalive (processor->peer); } else ccnet_peer_shutdown (processor->peer); } static void on_unauthed_peer_connected (CcnetPeer *peer, CcnetPacketIO *io) { CcnetProcessor *processor; CcnetProcFactory *factory = peer->manager->session->proc_factory; ccnet_peer_set_io (peer, io); ccnet_peer_set_net_state (peer, PEER_CONNECTED); processor = ccnet_proc_factory_create_master_processor ( factory, "get-pubinfo", peer); if (processor == NULL) { ccnet_warning ("Create get-pubinfo processor failed\n"); ccnet_peer_shutdown (peer); return; } g_signal_connect (processor, "done", G_CALLBACK(on_get_unauth_peer_pub_info_done), NULL); ccnet_processor_startl (processor, NULL); } static void set_peer_address_from_socket(CcnetPeer *peer, CcnetPacketIO *io) { if (peer == NULL || io == NULL) return; if (peer->addr_str) g_free (peer->addr_str); struct sockaddr_in addr; socklen_t len = sizeof(struct sockaddr_in); int socket = io->socket; getpeername (socket, (struct sockaddr *)&addr, &len); char *p = inet_ntoa (addr.sin_addr); peer->addr_str = strdup(p); } static void myHandshakeDoneCB (CcnetHandshake *handshake, CcnetPacketIO *io, int is_connected, const char *peer_id, void *vmanager) { CcnetConnManager *manager = vmanager; CcnetPeerManager *peerMgr = manager->session->peer_mgr; CcnetPeer *peer; if (!is_connected) { if (ccnet_packet_io_is_incoming (io)) { ccnet_warning ("[conn] incoming handshake fails.\n"); ccnet_packet_io_free (io); return; } /* temporally use peer, so don't need to increase the reference */ peer = handshake->peer; if (peer->num_fails == 0) { /* print error for the first time */ ccnet_message ("[Conn] peer %s(%.10s) connection fails\n", peer->name, peer->id); } else { ccnet_debug ("[Conn] peer %s(%.10s) connection fails\n", peer->name, peer->id); } if (peer->net_state == PEER_CONNECTED) { ccnet_debug ("[Conn] But Peer %s(%.10s) is already connected me.\n", peer->name, peer->id); } else if (peer->net_state == PEER_DOWN){ ccnet_peer_shutdown(peer); } ccnet_packet_io_free (io); peer->num_fails++; peer->in_connection = 0; return; } if (!ccnet_packet_io_is_incoming (io)) { peer = handshake->peer; peer->in_connection = 0; if (peer->to_resolve) { if (!peer_id_valid(peer_id)) { /* TODO: Remove the peer */ ccnet_warning ("[Conn] Resolving: Received invalid peer id\n"); return; } ccnet_debug ("[Conn] Resolving: Peer %.8s is resolved\n", peer_id); memcpy (peer->id, peer_id, 40); peer->id[40] = '\0'; on_resolve_peer_connected (peer, io); return; } /* ref for using the peer below */ g_object_ref (peer); } else { /* incoming */ if (!peer_id_valid (peer_id)) { ccnet_warning ("Invalid peer (no-id) connecting\n"); ccnet_packet_io_free (io); return; } peer = ccnet_peer_manager_get_peer (peerMgr, peer_id); if (!peer) { ccnet_message ("Unknown peer %s connecting\n", peer_id); peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (peerMgr, peer); set_peer_address_from_socket(peer, io); peer->last_up = time(NULL); on_unauthed_peer_connected (peer, io); g_object_unref (peer); return; } if (peer->net_state == PEER_CONNECTED) { ccnet_message ("[Conn] Peer %s (%.10s) is already connected." "But a new handshake comes in. Reconnect this peer.\n", peer->name, peer->id); ccnet_peer_shutdown_no_delay (peer); } set_peer_address_from_socket(peer, io); peer->last_up = time(NULL); } /* hold a reference on the peer */ ccnet_message ("[Conn] Peer %s (%.10s) connected\n", peer->name, peer->id); peer->num_fails = 0; on_peer_connected (peer, io); g_object_unref (peer); } /** * return %TRUE if an outgoing connection is started, %FALSE otherwise. * * When peer's ip address is not looked up yet, an dns request will be sent, * and when dns done, this function will be called again. */ gboolean ccnet_conn_manager_connect_peer (CcnetConnManager *manager, CcnetPeer *peer) { CcnetPacketIO *io; /* int interval; */ const char *addr = NULL; int port = 0; if (peer->in_connection) return FALSE; /* time_t now = time(NULL); */ if (peer->net_state == PEER_CONNECTED) return FALSE; if (peer->dns_addr) addr = peer->dns_addr; else if (!peer->redirected) { if (!peer->public_addr) goto err_connect; if (is_valid_ipaddr(peer->public_addr)) addr = peer->public_addr; else { dns_lookup_peer (peer); return TRUE; /* same as out going is started */ } } else { if (!peer->redirect_addr) goto err_connect; if (is_valid_ipaddr(peer->redirect_addr)) addr = peer->redirect_addr; else { dns_lookup_peer (peer); return TRUE; /* same as out going is started */ } } if (!addr) goto err_connect; if (!peer->redirected) port = peer->public_port; else port = peer->redirect_port; ccnet_peer_update_address (peer, addr, port); /* interval = get_reconnect_interval_secs (peer); */ /* if (now - peer->last_try_time < interval) { */ /* ccnet_debug ("[Conn] Less than interval: (%d - %d = %d, %d)\n", */ /* now, peer->last_try_time, now - peer->last_try_time, */ /* interval); */ /* return FALSE; */ /* } */ /* peer->last_try_time = now; */ if (peer->num_fails == 0) { /* print log for the first time */ ccnet_message ("[Conn] Start outgoing connect to %s(%.10s) %s:%d\n", peer->name, peer->id, addr, port); } else { ccnet_debug ("[Conn] Start outgoing connect to %s(%.10s) %s:%d\n", peer->name, peer->id, addr, port); } io = ccnet_packet_io_new_outgoing (manager->session, addr, port); if (io == NULL) { /* ccnet_warning ("Failed to create socket for peer %s (%.10s)\n", peer->name, peer->id); */ goto err_connect; } else { peer->in_connection = 1; ccnet_handshake_new (manager->session, peer, io, myHandshakeDoneCB, manager); return TRUE; } err_connect: peer->num_fails++; return FALSE; } static void reconnect_peer (CcnetConnManager *manager, CcnetPeer *peer) { if (peer->net_state == PEER_CONNECTED || peer->in_connection) return; /* if (peer->public_addr == NULL) { ccnet_warning ("[conn-mgr] A peer without public_ip and " "domain is entered in conn_list\n"); return; } */ ccnet_conn_manager_connect_peer (manager, peer); } static int reconnect_pulse (void *vmanager) { CcnetConnManager *manager = vmanager; /* int conn = 0; */ GList *ptr; #ifndef CCNET_SERVER GList *peers = ccnet_peer_manager_get_peers_with_role ( manager->session->peer_mgr, "MyRelay"); for (ptr = peers; ptr; ptr = ptr->next) { CcnetPeer *peer = ptr->data; if (peer->redirected) { if (peer->num_fails > 2) ccnet_peer_unset_redirect (peer); } reconnect_peer (manager, peer); g_object_unref (peer); } g_list_free (peers); #endif for (ptr = manager->conn_list; ptr; ptr = ptr->next) { CcnetPeer *peer = ptr->data; if (peer->redirected) { if (peer->num_fails > 2) ccnet_peer_unset_redirect (peer); } reconnect_peer (manager, peer); } /* peers = ccnet_peer_manager_get_peers_with_role ( manager->session->peer_mgr, "MyPeer"); for (ptr = peers; ptr; ptr = ptr->next) { CcnetPeer *peer = ptr->data; if (peer->is_self) continue; if (!peer->is_relay && !ccnet_peer_is_mypeer(peer)) continue; if (ccnet_conn_manager_connect_peer (manager, peer) == FALSE) continue; if (++conn >= MAX_RECONNECTIONS_PER_PULSE) break; } g_list_free (peers); */ /* TODO: teer down connections */ return TRUE; } void ccnet_conn_manager_add_incoming (CcnetConnManager *manager, struct sockaddr_storage *cliaddr, size_t addrlen, evutil_socket_t socket) { CcnetPacketIO *io; io = ccnet_packet_io_new_incoming (manager->session, cliaddr, socket); ccnet_handshake_new (manager->session, NULL, io, myHandshakeDoneCB, manager); } static int listen_pulse (void * vmanager) { CcnetConnManager *manager = vmanager; for ( ;; ) /* check for new incoming peer connections */ { evutil_socket_t socket; struct sockaddr_storage cliaddr; socklen_t len = sizeof (struct sockaddr_storage); if (manager->bind_socket < 0) break; if ((socket = ccnet_net_accept (manager->bind_socket, &cliaddr, &len, 1)) < 0) break; ccnet_conn_manager_add_incoming (manager, &cliaddr, len, socket); } return TRUE; } #ifndef CCNET_SERVER #endif /* ifndef CCNET_SERVER */ void ccnet_conn_listen_init (CcnetConnManager *manager) { evutil_socket_t socket; CcnetSession *session = manager->session; if (session->base.public_port == 0) { ccnet_message ("Do not listen for incoming peers\n"); return; } socket = ccnet_net_bind_tcp (session->base.public_port, 1); if (socket >= 0) { ccnet_message ("Opened port %d to listen for " "incoming peer connections\n", session->base.public_port); manager->bind_socket = socket; listen (manager->bind_socket, 5); } else { ccnet_error ("Couldn't open port %d to listen for " "incoming peer connections (errno %d - %s)", session->base.public_port, errno, strerror(errno) ); exit (1); } manager->listen_timer = ccnet_timer_new (listen_pulse, manager, LISTEN_INTERVAL); } typedef struct DNSLookupData { CcnetPeer *peer; char *addr_str; } DNSLookupData; static void * dns_lookup (void *vdata) { DNSLookupData *data = vdata; struct evutil_addrinfo hints; struct evutil_addrinfo *answer = NULL; int err; void *addr; char *addr_str; socklen_t size; /* Build the hints to tell getaddrinfo how to act. */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; /* only use IPv4 now. */ hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; /* We want a TCP socket */ /* Only return addresses we can use. */ hints.ai_flags = EVUTIL_AI_ADDRCONFIG; /* Look up the hostname. */ err = evutil_getaddrinfo(data->peer->public_addr, NULL, &hints, &answer); if (err != 0) { ccnet_warning("Error while resolving '%s': %s\n", data->peer->public_addr, evutil_gai_strerror(err)); return vdata; } /* just use the first answer */ if (answer->ai_family == AF_INET) { size = INET_ADDRSTRLEN; addr = &((struct sockaddr_in *)(answer->ai_addr))->sin_addr; } else if (answer->ai_family == AF_INET6) { size = INET6_ADDRSTRLEN; addr = &((struct sockaddr_in6 *)(answer->ai_addr))->sin6_addr; } else goto out; addr_str = (char *)calloc(size, sizeof(char)); if (addr_str == NULL) { ccnet_error("Out of memory\n"); goto out; } if (!evutil_inet_ntop(answer->ai_family, addr, addr_str, size)) { ccnet_warning("Peer %s domain name %s lookup fail\n", data->peer->name, data->peer->public_addr); free(addr_str); goto out; } data->addr_str = addr_str; out: evutil_freeaddrinfo (answer); return vdata; } static void dns_lookup_cb (void *result) { DNSLookupData *data = result; CcnetPeer *peer = data->peer; if (!data->addr_str) { ccnet_warning ("DNS lookup failed for peer %.10s(%s).\n", data->peer->id, data->peer->public_addr); g_free (data); return; } g_free(peer->dns_addr); peer->dns_addr = g_strdup (data->addr_str); peer->dns_done = 1; ccnet_conn_manager_connect_peer (peer->manager->session->connMgr, peer); free(data->addr_str); g_free (data); } static void dns_lookup_peer (CcnetPeer* peer) { DNSLookupData *data; if (peer->dns_done) return; data = g_new0 (DNSLookupData, 1); data->peer = peer; ccnet_job_manager_schedule_job (peer->manager->session->job_mgr, dns_lookup, dns_lookup_cb, data); } void ccnet_conn_manager_start (CcnetConnManager *manager) { #ifdef CCNET_SERVER ccnet_conn_listen_init (manager); #endif manager->reconnect_timer = ccnet_timer_new (reconnect_pulse, manager, RECONNECT_PERIOD_MSEC); } void ccnet_conn_manager_stop (CcnetConnManager *manager) { evutil_closesocket (manager->bind_socket); manager->bind_socket = 0; ccnet_timer_free (&manager->reconnect_timer); ccnet_timer_free (&manager->listen_timer); } void ccnet_conn_manager_add_to_conn_list (CcnetConnManager *manager, CcnetPeer *peer) { if (g_list_find (manager->conn_list, peer)) { ccnet_warning ("[Conn] peer %s(%.8s) is already in conn_list\n", peer->name, peer->id); return; } manager->conn_list = g_list_prepend (manager->conn_list, peer); g_object_ref (peer); } void ccnet_conn_manager_remove_from_conn_list (CcnetConnManager *manager, CcnetPeer *peer) { /* we can't directly use g_list_remove, since we have to call * g_object_unref, if the peer is actually in the list */ if (!g_list_find (manager->conn_list, peer)) return; manager->conn_list = g_list_remove (manager->conn_list, peer); g_object_unref (peer); } void ccnet_conn_manager_cancel_conn (CcnetConnManager *manager, const char *addr, int port) { GList *ptr; for (ptr = manager->conn_list; ptr; ptr = ptr->next) { CcnetPeer *peer = ptr->data; if (g_strcmp0(peer->public_addr, addr) == 0 && peer->public_port == port) { manager->conn_list = g_list_delete_link (manager->conn_list, ptr); if (peer->to_resolve) { ccnet_peer_manager_on_peer_resolve_failed ( manager->session->peer_mgr, peer); } g_object_unref (peer); break; } } } ccnet-6.1.5/net/common/connect-mgr.h000066400000000000000000000023641317035602700172730ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_CONNECTION_MANAGER #define CCNET_CONNECTION_MANAGER #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #include "timer.h" typedef struct CcnetConnManager CcnetConnManager; struct CcnetConnManager { CcnetSession *session; CcnetTimer *reconnect_timer; CcnetTimer *listen_timer; evutil_socket_t bind_socket; GList *conn_list; }; CcnetConnManager *ccnet_conn_manager_new (CcnetSession *session); void ccnet_conn_manager_start (CcnetConnManager *manager); void ccnet_conn_manager_stop (CcnetConnManager *manager); gboolean ccnet_conn_manager_connect_peer (CcnetConnManager *manager, CcnetPeer *peer); void ccnet_conn_manager_add_to_conn_list (CcnetConnManager *manager, CcnetPeer *peer); void ccnet_conn_manager_remove_from_conn_list (CcnetConnManager *manager, CcnetPeer *peer); void ccnet_conn_manager_cancel_conn (CcnetConnManager *manager, const char *addr, int port); #endif ccnet-6.1.5/net/common/getgateway.c000066400000000000000000000160761317035602700172200ustar00rootroot00000000000000/* $Id: getgateway.c,v 1.12 2008/10/06 10:04:16 nanard Exp $ */ /* libnatpmp * Copyright (c) 2007-2008, Thomas BERNARD * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include /* There is no portable method to get the default route gateway. * So below are three differents functions implementing this. * Parsing /proc/net/route is for linux. * sysctl is the way to access such informations on BSD systems. * Many systems should provide route information through raw PF_ROUTE * sockets. */ #ifdef WIN32 #define USE_WIN32 #undef USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE #undef USE_PROC_NET_ROUTE #endif #ifdef __linux__ #define USE_PROC_NET_ROUTE #undef USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE #endif #ifdef BSD #undef USE_PROC_NET_ROUTE #define USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE #endif #ifdef __APPLE__ #undef USE_PROC_NET_ROUTE #undef USE_SOCKET_ROUTE #define USE_SYSCTL_NET_ROUTE #endif #if (defined(sun) && defined(__SVR4)) #undef USE_PROC_NET_ROUTE #define USE_SOCKET_ROUTE #undef USE_SYSCTL_NET_ROUTE #endif #ifdef USE_SYSCTL_NET_ROUTE #include #include #include #include #endif #ifdef USE_SOCKET_ROUTE #include #include #include #include #include #endif #include "getgateway.h" #ifndef WIN32 #define SUCCESS (0) #define FAILED (-1) #endif #ifdef WIN32 #include #include #include #include #include "net.h" #else #include #include #include #endif #include #include "log.h" /* * get default gateway and then judge it * reverse ip: * 10.0.0.0/8 * 172.16.0.0/12 * 192.168.0.0/16 */ int in_nat(void) { #ifdef WIN32 //return 0; #endif struct in_addr addr; int one, two; char *ip; if (getdefaultgateway(&addr.s_addr) == -1) { fprintf(stderr, "Could not get default gateway\n"); return -1; } ip = inet_ntoa(addr); ccnet_message ("ip = %s\n", ip); sscanf(ip, "%d.%d", &one, &two); if (10 == one) return 1; else if (172 == one && 16 == two) return 1; else if (192 == one && 168 == two) return 1; else return 0; } #ifdef USE_PROC_NET_ROUTE int getdefaultgateway(in_addr_t * addr) { long d, g; char buf[256]; int line = 0; FILE * f; char * p; f = fopen("/proc/net/route", "r"); if(!f) return FAILED; while(fgets(buf, sizeof(buf), f)) { if(line > 0) { p = buf; while(*p && !isspace(*p)) p++; while(*p && isspace(*p)) p++; if(sscanf(p, "%lx%lx", &d, &g)==2) { if(d == 0) { /* default */ *addr = g; fclose(f); return SUCCESS; } } } line++; } /* default route not found ! */ if(f) fclose(f); return FAILED; } #endif /* #ifdef USE_PROC_NET_ROUTE */ #ifdef USE_SYSCTL_NET_ROUTE #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) int getdefaultgateway(in_addr_t * addr) { #if 0 /* net.route.0.inet.dump.0.0 ? */ int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0, 0/*tableid*/}; #endif /* net.route.0.inet.flags.gateway */ int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY}; size_t l; char * buf, * p; struct rt_msghdr * rt; struct sockaddr * sa; struct sockaddr * sa_tab[RTAX_MAX]; int i; int r = FAILED; if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) { return FAILED; } if(l>0) { buf = malloc(l); if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { free(buf); return FAILED; } for(p=buf; prtm_msglen) { rt = (struct rt_msghdr *)p; sa = (struct sockaddr *)(rt + 1); for(i=0; irtm_addrs & (1 << i)) { sa_tab[i] = sa; sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); } else { sa_tab[i] = NULL; } } if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) && sa_tab[RTAX_DST]->sa_family == AF_INET && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) { if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) { *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr; r = SUCCESS; } } } free(buf); } return r; } #endif /* #ifdef USE_SYSCTL_NET_ROUTE */ #ifdef USE_SOCKET_ROUTE /* Thanks to Darren Kenny for this code */ #define NEXTADDR(w, u) \ if (rtm_addrs & (w)) {\ l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\ } #define rtm m_rtmsg.m_rtm struct { struct rt_msghdr m_rtm; char m_space[512]; } m_rtmsg; int getdefaultgateway(in_addr_t *addr) { int s, seq, l, rtm_addrs, i; pid_t pid; struct sockaddr so_dst, so_mask; char *cp = m_rtmsg.m_space; struct sockaddr *gate = NULL, *sa; struct rt_msghdr *msg_hdr; pid = getpid(); seq = 0; rtm_addrs = RTA_DST | RTA_NETMASK; memset(&so_dst, 0, sizeof(so_dst)); memset(&so_mask, 0, sizeof(so_mask)); memset(&rtm, 0, sizeof(struct rt_msghdr)); rtm.rtm_type = RTM_GET; rtm.rtm_flags = RTF_UP | RTF_GATEWAY; rtm.rtm_version = RTM_VERSION; rtm.rtm_seq = ++seq; rtm.rtm_addrs = rtm_addrs; so_dst.sa_family = AF_INET; so_mask.sa_family = AF_INET; NEXTADDR(RTA_DST, so_dst); NEXTADDR(RTA_NETMASK, so_mask); rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; s = socket(PF_ROUTE, SOCK_RAW, 0); if (write(s, (char *)&m_rtmsg, l) < 0) { close(s); return FAILED; } do { l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); close(s); msg_hdr = &rtm; cp = ((char *)(msg_hdr + 1)); if (msg_hdr->rtm_addrs) { for (i = 1; i; i <<= 1) if (i & msg_hdr->rtm_addrs) { sa = (struct sockaddr *)cp; if (i == RTA_GATEWAY ) gate = sa; cp += sizeof(struct sockaddr); } } else { return FAILED; } if (gate != NULL ) { *addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr; return SUCCESS; } else { return FAILED; } } #endif /* #ifdef USE_SOCKET_ROUTE */ #ifdef USE_WIN32 int getdefaultgateway(in_addr_t *addr) { MIB_IPFORWARDROW ip_forward; memset(&ip_forward, 0, sizeof(ip_forward)); if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR) return -1; *addr = ip_forward.dwForwardNextHop; return 0; } #endif ccnet-6.1.5/net/common/getgateway.h000066400000000000000000000024111317035602700172110ustar00rootroot00000000000000/* $Id: getgateway.h,v 1.3 2008/07/02 22:33:06 nanard Exp $ */ /* libnatpmp * Copyright (c) 2007, Thomas BERNARD * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __GETGATEWAY_H__ #define __GETGATEWAY_H__ #include #ifdef WIN32 typedef unsigned long in_addr_t; #else #include #endif /* in_nat() : * return value : * 1 : in a nat network * 0 : not * -1: not connected to a network */ int in_nat(void); /* getdefaultgateway() : * return value : * 0 : success * -1 : failure */ int getdefaultgateway(in_addr_t * addr); #endif ccnet-6.1.5/net/common/handshake.c000066400000000000000000000144531317035602700170020ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #ifdef WIN32 #include #else #include #endif #include "peer.h" #include "packet-io.h" #include "session.h" #include "handshake.h" #define DEBUG_FLAG CCNET_DEBUG_CONNECTION #include "log.h" #define HANDSHAKE_TIMEOUT 10 /* The purpose of handshake is to obtain the peer's Peer ID. Handshake Protocol: Master Slave Master's Peer ID INIT -----------------------------> ID_SENT Slave's Peer ID <---------------------------- ID_RECEIVED ACK ----------------------------> DONE DONE */ enum { UNKNOWN = 0, INIT, ID_SENT, ID_RECEIVED }; static void ccnet_handshake_done (CcnetHandshake *handshake, int isOK); static void send_handshake_message (CcnetHandshake *handshake) { const char *id = handshake->session->base.id; char buf[256]; ccnet_packet *packet = (ccnet_packet *)buf; packet->header.version = 1; packet->header.type = CCNET_MSG_HANDSHAKE; memcpy (packet->data, id, 40); packet->header.length = 40; packet->header.id = 0; ccnet_packet_io_write_packet (handshake->io, packet); if (handshake->peer) ccnet_debug ("[Conn] Outgoing: Send my id to %s(%.10s)\n", handshake->peer->name, handshake->peer->id); else ccnet_debug ("[Conn] Incoming: Send my id to %.10s\n", handshake->id); } static void send_ack (CcnetHandshake *handshake) { ccnet_packet packet; packet.header.version = 1; packet.header.type = CCNET_MSG_OK; packet.header.length = 0; packet.header.id = 0; ccnet_packet_io_write_packet (handshake->io, &packet); ccnet_debug ("[Conn] Outgoing: Send ack to %s(%.10s)\n", handshake->peer->name, handshake->peer->id); } static void read_peer_id (CcnetHandshake *handshake, ccnet_packet *packet) { uint16_t len; char *id; /* get id */ len = packet->header.length; id = g_malloc (len + 1); memcpy (id, packet->data, len); id[len] = '\0'; handshake->id = id; if (handshake->state == INIT) { /* we are the slave */ ccnet_debug ("[Conn] Incoming: Read peer id %.8s\n", id); send_handshake_message (handshake); handshake->state = ID_RECEIVED; } else if (handshake->state == ID_SENT) { /* we are the master */ ccnet_debug ("[Conn] Outgoing: Read peer %s id %.8s\n", handshake->peer->name, id); if (g_strcmp0 (handshake->peer->id, handshake->id) != 0) { ccnet_warning ("[Conn] Received peer id does not match.\n"); ccnet_handshake_done (handshake, FALSE); return; } send_ack (handshake); ccnet_handshake_done (handshake, TRUE); } } static void read_ok (CcnetHandshake *handshake, ccnet_packet *packet) { if (packet->header.type != CCNET_MSG_OK) { ccnet_warning ("[Conn] Read wrong ack format\n"); ccnet_handshake_done (handshake, FALSE); } else { ccnet_debug ("[Conn] Incoming: Read ack (%.10s)\n", handshake->id); ccnet_handshake_done (handshake, TRUE); } return; } static void canRead (ccnet_packet *packet, void *arg) { CcnetHandshake *handshake = (CcnetHandshake *)arg; ccnet_debug("current state is %d\n", handshake->state); switch (handshake->state) { case INIT: read_peer_id (handshake, packet); break; case ID_SENT: read_peer_id (handshake, packet); break; case ID_RECEIVED: read_ok (handshake, packet); break; default: g_return_if_reached (); } } static void fire_done_func (CcnetHandshake *handshake, int is_connected) { const char * peer_id; peer_id = is_connected ? handshake->id : NULL; (*handshake->doneCB) (handshake, handshake->io, is_connected, peer_id, handshake->doneUserData); } static void ccnet_handshake_done (CcnetHandshake *handshake, int isOK) { /* ccnet_message ("handshakeDone: %s\n", isOK ? "connected" : "aborting"); */ ccnet_debug ("[Conn] HandshakeDone %s\n", isOK ? "connected" : "aborting"); ccnet_packet_io_set_iofuncs (handshake->io, NULL, NULL, NULL, NULL); fire_done_func (handshake, isOK); if (handshake->peer) g_object_unref (handshake->peer); g_free (handshake->id); g_free (handshake); } void ccnet_handshake_abort (CcnetHandshake * handshake) { ccnet_handshake_done (handshake, FALSE); } #include static void gotError (struct bufferevent * evbuf, short what, void *arg) { CcnetHandshake * handshake = (CcnetHandshake *) arg; /* if the error happened while we were sending a public key, we might * have encountered a peer that doesn't do encryption... reconnect and * try a plaintext handshake */ /* ccnet_warning ("libevent got an error on peer %s what==%d, errno=%d (%s)\n", handshake->peer ? handshake->peer->name : "(no-id)", (int)what, errno, strerror(errno)); */ ccnet_handshake_abort (handshake); } CcnetHandshake* ccnet_handshake_new (CcnetSession *session, CcnetPeer *peer, CcnetPacketIO *io, handshakeDoneCB doneCB, void *doneUserData) { CcnetHandshake * handshake; handshake = g_new0 (CcnetHandshake, 1); handshake->peer = peer; if (peer) g_object_ref (peer); handshake->io = io; handshake->doneCB = doneCB; handshake->doneUserData = doneUserData; handshake->session = session; ccnet_packet_io_set_timeout_secs (io, HANDSHAKE_TIMEOUT); ccnet_packet_io_set_iofuncs (handshake->io, canRead, NULL, gotError, handshake); if (ccnet_packet_io_is_incoming (handshake->io)) handshake->state = INIT; else { send_handshake_message (handshake); handshake->state = ID_SENT; } return handshake; } ccnet-6.1.5/net/common/handshake.h000066400000000000000000000021141317035602700167760ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_HANDSHAKE_H #define CCNET_HANDSHAKE_H struct CcnetPacketIO; typedef struct CcnetHandshake CcnetHandshake; #include "peer.h" typedef void (*handshakeDoneCB) (CcnetHandshake *handshake, CcnetPacketIO *io, int isConnected, const char *peerId, void *userData); struct CcnetHandshake { char *id; /* the peer id */ CcnetPeer *peer; /* only valid if it is outgoing */ CcnetPacketIO *io; struct CcnetSession *session; uint8_t state; handshakeDoneCB doneCB; void *doneUserData; }; CcnetHandshake* ccnet_handshake_new (CcnetSession *session, CcnetPeer *peer, CcnetPacketIO *io, handshakeDoneCB doneCB, void *doneUserData); #endif ccnet-6.1.5/net/common/log.c000066400000000000000000000074351317035602700156370ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include #include "log.h" #include "utils.h" #include "session.h" #include "message.h" #include "message-manager.h" extern CcnetSession *session; /* message with greater log levels will be ignored */ static int ccnet_log_level; static char *logfile; static FILE *logfp; static void ccnet_log (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { time_t t; struct tm *tm; char buf[256]; /* CcnetMessage *ccnet_message; */ int len; if (log_level > ccnet_log_level) return; t = time(NULL); tm = localtime(&t); len = strftime (buf, 256, "[%x %X] ", tm); fputs (buf, logfp); fputs (message, logfp); fflush (logfp); /* Note, log module starts earlier than session, only * send syslog when session exists */ if (log_level <= G_LOG_LEVEL_MESSAGE && session) { int n = strlen (message); int max = 256 - len - 1; if (n > max) n = max; memcpy (buf + len, message, n); buf[len + n] = '\0'; } /* if (log_level < G_LOG_LEVEL_MESSAGE) { g_on_error_stack_trace (NULL); } */ } static int get_debug_level(const char *str, int default_level) { if (strcmp(str, "debug") == 0) return G_LOG_LEVEL_DEBUG; if (strcmp(str, "info") == 0) return G_LOG_LEVEL_INFO; if (strcmp(str, "warning") == 0) return G_LOG_LEVEL_WARNING; return default_level; } int ccnet_log_init (const char *_logfile, const char *debug_level_str) { g_log_set_handler (NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, ccnet_log, NULL); /* write all warnings from lib/ into ccnet.log */ g_log_set_handler ("Ccnet", G_LOG_LEVEL_WARNING, ccnet_log, NULL); /* record all log message */ ccnet_log_level = get_debug_level(debug_level_str, G_LOG_LEVEL_INFO); if (strcmp(_logfile, "-") == 0) { logfp = stdout; logfile = g_strdup (_logfile); } else { logfile = ccnet_expand_path (_logfile); if ((logfp = g_fopen (logfile, "a+")) == NULL) { ccnet_message ("Failed to open file %s\n", logfile); return -1; } } return 0; } int ccnet_log_reopen () { FILE *fp, *oldfp; if (strcmp(logfile, "-") == 0) return 0; if ((fp = g_fopen (logfile, "a+")) == NULL) { ccnet_message ("Failed to open file %s\n", logfile); return -1; } //TODO: check file's health oldfp = logfp; logfp = fp; if (fclose(oldfp) < 0) { ccnet_message ("Failed to close file %s\n", logfile); return -1; } return 0; } static CcnetDebugFlags debug_flags = 0; static GDebugKey debug_keys[] = { { "Peer", CCNET_DEBUG_PEER }, { "Processor", CCNET_DEBUG_PROCESSOR }, { "Netio", CCNET_DEBUG_NETIO }, { "Message", CCNET_DEBUG_MESSAGE }, { "Connection", CCNET_DEBUG_CONNECTION }, { "Other", CCNET_DEBUG_OTHER }, }; gboolean ccnet_debug_flag_is_set (CcnetDebugFlags flag) { return (debug_flags & flag) != 0; } void ccnet_debug_set_flags (CcnetDebugFlags flags) { ccnet_message ("Set debug flags %#x\n", flags); debug_flags |= flags; } void ccnet_debug_set_flags_string (const gchar *flags_string) { guint nkeys = G_N_ELEMENTS (debug_keys); if (flags_string) ccnet_debug_set_flags ( g_parse_debug_string (flags_string, debug_keys, nkeys)); } void ccnet_debug_impl (CcnetDebugFlags flag, const gchar *format, ...) { if (flag & debug_flags) { va_list args; va_start (args, format); g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args); va_end (args); } } ccnet-6.1.5/net/common/log.h000066400000000000000000000025251317035602700156370ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_LOG_H #define CCNET_LOG_H #ifndef ccnet_warning #define ccnet_warning(fmt, ...) g_warning("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__) #endif #ifndef ccnet_error #define ccnet_error(fmt, ...) g_error("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__) #endif #ifndef ccnet_message #define ccnet_message(fmt, ...) g_message("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__) #endif int ccnet_log_init (const char *logfile, const char *log_level_str); int ccnet_log_reopen (); typedef enum { CCNET_DEBUG_PEER = 1 << 1, CCNET_DEBUG_PROCESSOR = 1 << 2, CCNET_DEBUG_NETIO = 1 << 3, CCNET_DEBUG_CONNECTION = 1 << 4, CCNET_DEBUG_MESSAGE = 1 << 5, CCNET_DEBUG_OTHER = 1 << 6, } CcnetDebugFlags; gboolean ccnet_debug_flag_is_set (CcnetDebugFlags flag); void ccnet_debug_set_flags (CcnetDebugFlags flag); void ccnet_debug_set_flags_string (const gchar *flags_string); void ccnet_debug_impl (CcnetDebugFlags flag, const gchar *format, ...); #define ccnet_debug(format, ...) #endif /* CCNET_LOG_H */ #undef ccnet_debug #define ccnet_debug(format, ...) #ifdef DEBUG_FLAG #undef ccnet_debug #define ccnet_debug(fmt, ...) \ ccnet_debug_impl (DEBUG_FLAG, "%.15s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__) #endif /* DEBUG_FLAG */ ccnet-6.1.5/net/common/message-manager.c000066400000000000000000000105521317035602700201040ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "ccnet-db.h" #include "timer.h" #include "peer.h" #include "session.h" #include "processors/mqserver-proc.h" #include "message.h" #include "message-manager.h" #include "peer-mgr.h" #define DEBUG_FLAG CCNET_DEBUG_MESSAGE #include "log.h" struct MessageManagerPriv { GHashTable *subscribers; #ifdef CCNET_SERVER #endif }; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_MESSAGE_MANAGER, MessageManagerPriv)) G_DEFINE_TYPE (CcnetMessageManager, ccnet_message_manager, G_TYPE_OBJECT); static void ccnet_message_manager_class_init (CcnetMessageManagerClass *class) { /* GObjectClass *object_class; */ g_type_class_add_private (class, sizeof (MessageManagerPriv)); } static void ccnet_message_manager_init (CcnetMessageManager *manager) { manager->priv = GET_PRIV(manager); } CcnetMessageManager * ccnet_message_manager_new (CcnetSession *session) { CcnetMessageManager *manager; manager = g_object_new (CCNET_TYPE_MESSAGE_MANAGER, NULL); manager->session = session; manager->priv->subscribers = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL); return manager; } int ccnet_message_manager_start (CcnetMessageManager *manager) { return 0; } static gboolean handle_inner_message (CcnetMessageManager *manager, CcnetMessage *msg) { if (strcmp(msg->app, IPEERMGR_APP) == 0) { ccnet_peer_manager_receive_message (manager->session->peer_mgr, msg); return TRUE; } return FALSE; } int ccnet_message_manager_add_msg(CcnetMessageManager *manager, CcnetMessage *msg, int msg_type) { MessageManagerPriv *priv = manager->priv; GList *app_subscribers, *ptr; CcnetProcessor *processor; switch (msg_type) { case MSG_TYPE_RECV: if (handle_inner_message(manager, msg)) break; app_subscribers = g_hash_table_lookup (priv->subscribers, msg->app); if (!app_subscribers) break; ptr = app_subscribers; while (ptr) { processor = ptr->data; ccnet_mqserver_proc_put_message (processor, msg); ptr = ptr->next; } break; case MSG_TYPE_SYS: app_subscribers = g_hash_table_lookup (priv->subscribers, msg->app); if (!app_subscribers) break; ptr = app_subscribers; while (ptr) { processor = ptr->data; ccnet_mqserver_proc_put_message (processor, msg); ptr = ptr->next; } break; } return 0; } int ccnet_message_manager_subscribe_app (CcnetMessageManager *manager, CcnetProcessor *mq_proc, int n_app, char **apps) { MessageManagerPriv *priv = manager->priv; GList *app_subscribers; int i; for (i = 0; i < n_app; ++i) { ccnet_debug ("[Msg] subscribe app %s\n", apps[i]); app_subscribers = g_hash_table_lookup (priv->subscribers, apps[i]); app_subscribers = g_list_prepend (app_subscribers, mq_proc); g_hash_table_replace (priv->subscribers, g_strdup (apps[i]), app_subscribers); } return 0; } int ccnet_message_manager_unsubscribe_app (CcnetMessageManager *manager, CcnetProcessor *mq_proc, int n_app, char **apps) { MessageManagerPriv *priv = manager->priv; GList *app_subscribers; int i; int ret = 0; for (i = 0; i < n_app; ++i) { app_subscribers = g_hash_table_lookup (priv->subscribers, apps[i]); if (!app_subscribers) { ccnet_warning ("cannot unsubscribe from app %s, " "no such app subscribed.\n", apps[i]); ret = -1; continue; } ccnet_debug ("[Msg] unsubscribe app %s\n", apps[i]); app_subscribers = g_list_remove (app_subscribers, mq_proc); if (app_subscribers) g_hash_table_replace (priv->subscribers, g_strdup (apps[i]), app_subscribers); else g_hash_table_remove (priv->subscribers, apps[i]); } return ret; } ccnet-6.1.5/net/common/message-manager.h000066400000000000000000000037101317035602700201070ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_MESSAGE_MANAGER_H #define CCNET_MESSAGE_MANAGER_H #include #define CCNET_TYPE_MESSAGE_MANAGER (ccnet_message_manager_get_type ()) #define CCNET_MESSAGE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CCNET_TYPE_MESSAGE_MANAGER, CcnetMessageManager)) #define CCNET_MESSAGE_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CCNET_TYPE_MESSAGE_MANAGER, CcnetMessageManagerClass)) #define CCNET_IS_MESSAGE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CCNET_TYPE_MESSAGE_MANAGER)) #define CCNET_IS_MESSAGE_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CCNET_TYPE_MESSAGE_MANAGER)) #define CCNET_MESSAGE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CCNET_TYPE_MESSAGE_MANAGER, CcnetMessageManagerClass)) typedef struct _CcnetMessageManager CcnetMessageManager; typedef struct _CcnetMessageManagerClass CcnetMessageManagerClass; typedef struct MessageManagerPriv MessageManagerPriv; struct _CcnetMessageManager { GObject parent_instance; CcnetSession *session; MessageManagerPriv *priv; }; struct _CcnetMessageManagerClass { GObjectClass parent_class; }; GType ccnet_message_manager_get_type (void); CcnetMessageManager* ccnet_message_manager_new (CcnetSession *session); int ccnet_message_manager_start (CcnetMessageManager *manager); int ccnet_message_manager_add_msg(CcnetMessageManager *manager, CcnetMessage *msg, int msg_type); int ccnet_message_manager_subscribe_app (CcnetMessageManager *manager, CcnetProcessor *mq_proc, int n_app, char **apps); int ccnet_message_manager_unsubscribe_app (CcnetMessageManager *manager, CcnetProcessor *mq_proc, int n_app, char **apps); #endif ccnet-6.1.5/net/common/message.c000066400000000000000000000155201317035602700164740ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include "message.h" #include "ccnet-db.h" #include "string-util.h" static CcnetMessage * ccnet_message_new_full (const char *from, const char *to, const char *app, const char *body, time_t ctime, time_t rtime, const char *id, char flags) { CcnetMessage *message = g_new0 (CcnetMessage, 1); g_return_val_if_fail (flags >= 0, NULL); g_return_val_if_fail (from != NULL && to != NULL && app != NULL, NULL); message->flags = flags; memcpy (message->from, from, 40); message->from[40] = '\0'; memcpy (message->to, to, 40); /* ok if strlen(to) == 36 */ message->to[40] = '\0'; message->app = g_intern_string(app); message->body = g_strdup(body); message->ctime = (ctime ? ctime : time(NULL)); message->rtime = rtime; message->id = (id ? g_strdup (id) : gen_uuid()); message->ref_count = 1; return message; } CcnetMessage * ccnet_message_new (const char *from, const char *to, const char *app, const char *body, char flags) { return ccnet_message_new_full (from, to, app, body, 0, 0, NULL, flags); } void ccnet_message_ref (CcnetMessage *message) { message->ref_count++; } void ccnet_message_unref (CcnetMessage *message) { if (--message->ref_count == 0) ccnet_message_free (message); } void ccnet_message_free (CcnetMessage *message) { g_free (message->id); g_free (message->body); g_free (message); } void ccnet_message_to_string_buf_local (CcnetMessage *msg, GString *buf) { g_string_printf (buf, "%d %s %s %s %d %d %s %s", msg->flags, msg->from, msg->to, msg->id, (int)msg->ctime, (int)msg->rtime, msg->app, msg->body); } void ccnet_message_to_string_buf (CcnetMessage *msg, GString *buf) { g_string_printf (buf, "%d %s %s %s %d %s %s", msg->flags, msg->from, msg->to, msg->id, (int)msg->ctime, msg->app, msg->body); } CcnetMessage * ccnet_message_from_string (char *buf, int len) { char flags; char *from_id, *to_id, *msg_id, *body, *p, *time, *app; int ctime, rcv_time = 0; CcnetMessage *message; g_return_val_if_fail (END_0(buf,len), NULL); p = buf; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; flags = atoi (buf); from_id = ++p; p += 40; if (*p != ' ') goto error; *p = '\0'; to_id = ++p; p += 40; /* SHA-1 */ if (*p != ' ') goto error; *p = '\0'; msg_id = ++p; p += 36; if (*p != ' ') goto error; *p = '\0'; time = ++p; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; ctime = atoi (time); app = ++p; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; body = p + 1; message = ccnet_message_new_full (from_id, to_id, app, body, ctime, rcv_time, msg_id, flags); return message; error: return NULL; } CcnetMessage * ccnet_message_from_string_local (char *buf, int len) { int flags; char *from_id, *to_id, *msg_id, *body, *p, *time, *app; int ctime, rcv_time = 0; CcnetMessage *message; g_return_val_if_fail (END_0(buf,len), NULL); p = buf; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; flags = atoi (buf); from_id = ++p; p += 40; if (*p != ' ') goto error; *p = '\0'; to_id = ++p; p += 40; /* SHA-1 */ if (*p != ' ') goto error; *p = '\0'; msg_id = ++p; p += 36; if (*p != ' ') goto error; *p = '\0'; time = ++p; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; ctime = atoi (time); time = ++p; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; rcv_time = atoi (time); app = ++p; while (*p != ' ' && *p) ++p; if (*p != ' ') goto error; *p = '\0'; body = p + 1; message = ccnet_message_new_full (from_id, to_id, app, body, ctime, rcv_time, msg_id, flags); return message; error: return NULL; } #if 0 CcnetMessage * ccnet_message_from_db_stmt (CcnetDBRow *stmt) { const char *msg_id, *from, *to, *app, *body, *bloom; int ctime, rtime; char flags; CcnetMessage *message; flags = ccnet_db_row_get_column_int (stmt, MSG_DB_COLUMN_FLAGS); msg_id = (char *)ccnet_db_row_get_column_text (stmt, MSG_DB_COLUMN_MSG_ID); from = (char *)ccnet_db_row_get_column_text (stmt, MSG_DB_COLUMN_FROM_ID); to = (char *)ccnet_db_row_get_column_text (stmt, MSG_DB_COLUMN_TO_ID); bloom = (char *)ccnet_db_row_get_column_text (stmt, MSG_DB_COLUMN_BLOOM); ctime = ccnet_db_row_get_column_int (stmt, MSG_DB_COLUMN_CTIME); rtime = ccnet_db_row_get_column_int (stmt, MSG_DB_COLUMN_RTIME); app = (char *)ccnet_db_row_get_column_text (stmt, MSG_DB_COLUMN_APP); body = (char *)ccnet_db_row_get_column_text (stmt, MSG_DB_COLUMN_BODY); app = g_intern_string(app); message = ccnet_message_new_full (from, to, app, body, ctime, rtime, msg_id, flags); message->db_id = ccnet_db_row_get_column_int64 (stmt, MSG_DB_COLUMN_DB_ID); if (bloom) message->bloom = g_strdup(bloom); else message->bloom = 0; return message; } void ccnet_message_to_db (CcnetDB *db, const char *table, CcnetMessage *message) { char *sql; sql = ccnet_sql_printf ("INSERT INTO %s VALUES (" "NULL, %u, '%s', '%s', '%s', %Q, %u, %u, %Q, %Q);", table, message->flags, message->id, message->from, message->to, message->bloom, /* may be NULL */ message->ctime, message->rtime, message->app, message->body); ccnet_db_query (db, sql); ccnet_sql_free (sql); } #endif /* 0 */ ccnet-6.1.5/net/common/message.h000066400000000000000000000034421317035602700165010ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_MESSAGE_H #define CCNET_MESSAGE_H #include "common.h" #include "ccnet-db.h" enum { MSG_TYPE_RECV, MSG_TYPE_SYS, }; enum { MSG_DB_COLUMN_DB_ID = 0, MSG_DB_COLUMN_FLAGS, /* "%u" */ MSG_DB_COLUMN_MSG_ID, /* "%s" */ MSG_DB_COLUMN_FROM_ID, /* "%s" */ MSG_DB_COLUMN_TO_ID, /* "%s" */ MSG_DB_COLUMN_BLOOM, /* "%s" */ MSG_DB_COLUMN_CTIME, /* %u */ MSG_DB_COLUMN_RTIME, /* %u */ MSG_DB_COLUMN_APP, /* %s */ MSG_DB_COLUMN_BODY, /* %s */ NUM_MSG_DB_COLUMNS }; #define MESSAGE_ID_LEN 36 typedef struct _CcnetMessage CcnetMessage; #define FLAG_IS_ERROR 0x02 #define FLAG_IS_ACK 0x08 #define FLAG_IS_RENDEZVOUS 0x10 struct _CcnetMessage { int ref_count; gint64 db_id; char flags; char *id; /* UUID */ char from[41]; char to[41]; int ctime; /* creation time */ int rtime; /* receive time */ const char *app; /* application */ char *body; }; CcnetMessage* ccnet_message_new (const char *from, const char *to, const char *app, const char *body, char flags); void ccnet_message_free (CcnetMessage *msg); void ccnet_message_ref (CcnetMessage *); void ccnet_message_unref (CcnetMessage *); void ccnet_message_to_string_buf (CcnetMessage *msg, GString *buf); void ccnet_message_to_string_buf_local (CcnetMessage *msg, GString *buf); CcnetMessage *ccnet_message_from_string (char *buf, int len); CcnetMessage *ccnet_message_from_string_local (char *buf, int len); #endif ccnet-6.1.5/net/common/packet-io.c000066400000000000000000000164631317035602700167330ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #ifdef WIN32 #include #else #include #include #endif #include "net.h" #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #else #include #endif #include #include #include #include "session.h" #include "packet-io.h" #include "log.h" #define IO_TIMEOUT_SECS 8 /* The watermark of the underlying evbuffer. When there are more data than * this value is remained in evbuffer, the read event will be removed. * So, it must be greater than the max length of a single ccnet packet. */ #define CCNET_RDBUF 100000 static void didWriteWrapper (struct bufferevent *e, void *user_data) { CcnetPacketIO * c = (CcnetPacketIO *) user_data; if (c->didWrite) c->didWrite (e, c->user_data); } static void canReadWrapper (struct bufferevent *e, void *user_data) { CcnetPacketIO *c = user_data; ccnet_packet *packet; uint32_t len; g_return_if_fail (sizeof(ccnet_header) == CCNET_PACKET_LENGTH_HEADER); c->handling = 1; /* We have set up the low watermark. The following must be true. */ g_return_if_fail (EVBUFFER_LENGTH (e->input) >= CCNET_PACKET_LENGTH_HEADER); if (c->canRead == NULL) { c->handling = 0; return; } while (1) { packet = (ccnet_packet *) EVBUFFER_DATA (e->input); if (packet->header.type == CCNET_MSG_ENCPACKET) len = ntohl (packet->header.id); else len = ntohs (packet->header.length); if (EVBUFFER_LENGTH (e->input) - CCNET_PACKET_LENGTH_HEADER < len) break; /* wait for more data */ /* byte order, from network to host */ packet->header.length = len; packet->header.id = ntohl (packet->header.id); c->canRead (packet, c->user_data); /* PacketIO may be scheduled to free in the previous call */ if (c->schedule_free) { c->schedule_free = 0; c->handling = 0; ccnet_packet_io_free (c); return; } evbuffer_drain (e->input, len + CCNET_PACKET_LENGTH_HEADER); if(EVBUFFER_LENGTH(e->input) >= CCNET_PACKET_LENGTH_HEADER) continue; break; } c->handling = 0; } static void gotErrorWrapper (struct bufferevent *e, short what, void *user_data) { CcnetPacketIO *c = user_data; if (c->gotError) c->gotError (e, what, c->user_data); } void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t); static CcnetPacketIO* ccnet_packet_io_new (struct CcnetSession *session, const struct sockaddr_storage *addr, int is_incoming, evutil_socket_t socket) { CcnetPacketIO *io; io = g_new0 (CcnetPacketIO, 1); io->session = session; io->socket = socket; io->is_incoming = is_incoming; if (addr) { io->addr = g_malloc(sizeof(struct sockaddr_storage)); memcpy (io->addr, addr, sizeof(struct sockaddr_storage)); } io->bufev = bufferevent_socket_new (NULL, io->socket, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb (io->bufev, canReadWrapper, didWriteWrapper, gotErrorWrapper, io); bufferevent_enable (io->bufev, EV_READ | EV_WRITE); bufferevent_setwatermark (io->bufev, EV_READ, CCNET_PACKET_LENGTH_HEADER, CCNET_RDBUF); /* do not BEV_OPT_CLOSE_ON_FREE, since ccnet_packet_io_free() will * handle it */ /* io->bufev = bufferevent_socket_new (NULL, io->socket, 0); */ /* bufferevent_setcb (io->bufev, canReadWrapper, didWriteWrapper, */ /* gotErrorWrapper, io); */ /* io->bufev = bufferevent_new (io->socket, */ /* canReadWrapper, */ /* didWriteWrapper, */ /* gotErrorWrapper, */ /* io); */ /* bufferevent_setwatermark (io->bufev, EV_READ, CCNET_PACKET_LENGTH_HEADER, */ /* CCNET_RDBUF); */ /* bufferevent_enable (io->bufev, EV_READ | EV_WRITE); */ return io; } CcnetPacketIO* ccnet_packet_io_new_incoming (CcnetSession *session, struct sockaddr_storage *addr, evutil_socket_t socket) { return ccnet_packet_io_new (session, addr, TRUE, socket); } CcnetPacketIO* ccnet_packet_io_new_outgoing (CcnetSession *session, const char *addr_str, uint16_t port) { struct sockaddr_storage addr; evutil_socket_t socket; if (sock_pton(addr_str, port, &addr) < 0) { ccnet_warning ("wrong addresss format %s\n", addr_str); return NULL; } socket = ccnet_net_open_tcp ((struct sockaddr *)&addr, TRUE); /*if (socket < 0) ccnet_warning ("opening tcp connection fails: %s\n", strerror(errno)); */ return socket < 0 ? NULL : ccnet_packet_io_new (session, &addr, FALSE, socket); } void ccnet_packet_io_free (CcnetPacketIO *io) { if (io) { if (io->handling) { io->schedule_free = 1; return; } if (io->addr) g_free (io->addr); io->canRead = NULL; io->didWrite = NULL; io->gotError = NULL; bufferevent_free (io->bufev); /* fprintf (stderr, "close fd %d\n", io->socket); */ /* close (io->socket); */ g_free (io); } } CcnetSession* ccnet_packet_io_get_session (CcnetPacketIO *io) { return io->session; } void ccnet_packet_io_try_read (CcnetPacketIO *io) { if(EVBUFFER_LENGTH(io->bufev->input)) canReadWrapper (io->bufev, io); } void ccnet_packet_io_set_iofuncs (CcnetPacketIO *io, ccnet_can_read_cb readcb, ccnet_did_write_cb writecb, ccnet_net_error_cb errcb, void *user_data) { io->canRead = readcb; io->didWrite = writecb; io->gotError = errcb; io->user_data = user_data; } int ccnet_packet_io_is_incoming (const CcnetPacketIO *c) { return c->is_incoming ? 1 : 0; } void ccnet_packet_io_set_timeout_secs (CcnetPacketIO *io, int secs) { io->timeout = secs; bufferevent_settimeout (io->bufev, io->timeout, io->timeout); if (secs == 0) /* have to remove the original events */ bufferevent_disable (io->bufev, EV_READ | EV_WRITE); bufferevent_enable (io->bufev, EV_READ | EV_WRITE); /* struct timeval tv; */ /* tv.tv_sec = secs; */ /* tv.tv_usec = 0; */ /* if (secs != 0) */ /* bufferevent_set_timeouts (io->bufev, &tv, NULL); */ /* else */ /* bufferevent_set_timeouts (io->bufev, NULL, NULL); */ } void ccnet_packet_io_write_packet (CcnetPacketIO *io, ccnet_packet *packet) { int len; len = packet->header.length + CCNET_PACKET_LENGTH_HEADER; packet->header.length = htons (packet->header.length); packet->header.id = htonl (packet->header.id); bufferevent_write (io->bufev, packet, len); } ccnet-6.1.5/net/common/packet-io.h000066400000000000000000000043601317035602700167310ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PACKET_IO_H #define CCNET_PACKET_IO_H #include "packet.h" #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #else #include #endif /* struct evbuffer; */ /* for libevent2 */ struct evbuffer; struct bufferevent; struct CcnetSession; struct ccnet_packet; typedef void (*ccnet_can_read_cb)(struct ccnet_packet *, void* user_data); typedef void (*ccnet_did_write_cb)(struct bufferevent *, void *); typedef void (*ccnet_net_error_cb)(struct bufferevent *, short what, void *); typedef struct CcnetPacketIO CcnetPacketIO; struct CcnetPacketIO { unsigned int is_incoming : 1; unsigned int handling : 1; /* handling event from this IO */ unsigned int schedule_free : 1; int timeout; struct sockaddr *addr; evutil_socket_t socket; struct CcnetSession *session; struct bufferevent *bufev; ccnet_can_read_cb canRead; ccnet_did_write_cb didWrite; ccnet_net_error_cb gotError; void *user_data; }; CcnetPacketIO* ccnet_packet_io_new_outgoing (struct CcnetSession *session, const char *addr_str, uint16_t port); CcnetPacketIO* ccnet_packet_io_new_incoming (struct CcnetSession *session, struct sockaddr_storage *addr, evutil_socket_t socket); void ccnet_packet_io_free (CcnetPacketIO *io); struct CcnetSession* ccnet_packet_io_get_session (CcnetPacketIO *io); int ccnet_packet_io_reconnect (CcnetPacketIO *io); int ccnet_packet_io_is_incoming (const CcnetPacketIO *io); void ccnet_packet_io_set_timeout_secs (CcnetPacketIO *io, int secs); void ccnet_packet_io_write_packet (CcnetPacketIO *io, ccnet_packet *packet); void ccnet_packet_io_set_iofuncs (CcnetPacketIO *io, ccnet_can_read_cb readcb, ccnet_did_write_cb writecb, ccnet_net_error_cb errcb, void *user_data); #endif ccnet-6.1.5/net/common/peer-mgr.c000066400000000000000000000644151317035602700165750ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include #include #include "timer.h" #include "ccnet-db.h" #include "net.h" #include "peer.h" #include "session.h" #include "ccnet-config.h" #include "peer-mgr.h" #include "peermgr-message.h" #include "connect-mgr.h" #include "algorithms.h" #include "utils.h" #ifdef CCNET_DAEMON #include "daemon-session.h" #endif #define DEBUG_FLAG CCNET_DEBUG_PEER #include "log.h" #define NOTIFY_MSEC 5000 /* 5s */ #define DEFAULT_NOTIFY_INTERVAL 86400 * 2 #define SAVING_INTERVAL_MSEC 10000 #define PEER_GC_TIMEOUT 3*60 #define PEERDB_NAME "peer-db" struct CcnetPeerManagerPriv { CcnetDB *db; CcnetTimer *timer; /* the list of peers to be resolved */ GList *resolve_peers; }; enum { ADDED_SIG, DELETING_SIG, PEER_AUTH_DONE_SIG, LAST_SIGNAL }; G_DEFINE_TYPE (CcnetPeerManager, ccnet_peer_manager, G_TYPE_OBJECT); static guint signals[LAST_SIGNAL] = { 0 }; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_PEER_MANAGER, CcnetPeerManagerPriv)) /* static int notify_pulse (CcnetPeerManager *manager); */ static int open_db (CcnetPeerManager *manager); static void save_peer_addr(CcnetPeerManager *manager, CcnetPeer *peer); static void remove_peer_roles(CcnetPeerManager *manager, char *peer_id); void ccnet_peer_manager_load_peerdb (CcnetPeerManager *manager); static void ccnet_peer_manager_class_init (CcnetPeerManagerClass *klass) { signals[ADDED_SIG] = g_signal_new ("peer-added", CCNET_TYPE_PEER_MANAGER, G_SIGNAL_RUN_LAST, 0, /* no class singal handler */ NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[DELETING_SIG] = g_signal_new ("peer-deleting", CCNET_TYPE_PEER_MANAGER, G_SIGNAL_RUN_LAST, 0, /* no class singal handler */ NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[PEER_AUTH_DONE_SIG] = g_signal_new ("peer-auth-done", CCNET_TYPE_PEER_MANAGER, G_SIGNAL_RUN_LAST, 0, /* no class singal handler */ NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); g_type_class_add_private (klass, sizeof (CcnetPeerManagerPriv)); } static void ccnet_peer_manager_init (CcnetPeerManager *manager) { manager->priv = GET_PRIV (manager); } CcnetPeerManager* ccnet_peer_manager_new (CcnetSession *session) { CcnetPeerManager *manager; manager = g_object_new (CCNET_TYPE_PEER_MANAGER, NULL); manager->session = session; manager->peer_hash = g_hash_table_new (g_str_hash, g_str_equal); return manager; } int ccnet_peer_manager_prepare (CcnetPeerManager *manager) { CcnetPeer *peer; CcnetSession *session = manager->session; /* peer point to myself */ peer = ccnet_peer_new (session->base.id); peer->name = (char *)session->base.name; peer->public_port = session->base.public_port; peer->port = session->base.public_port; peer->service_url = session->base.service_url; peer->pubkey = session->pubkey; /* set to -1 so it will not be saved in to_string() */ peer->net_state = -1; peer->is_self = 1; peer->manager = manager; g_hash_table_insert (manager->peer_hash, peer->id, peer); session->myself = peer; return 0; } void ccnet_peer_manager_free (CcnetPeerManager *manager) { g_free (manager->peerdb_path); g_object_unref (manager); } GList * ccnet_peer_manager_get_peer_list (CcnetPeerManager *manager) { return g_hash_table_get_values (manager->peer_hash); } GList* ccnet_peer_manager_get_peers_with_role (CcnetPeerManager *manager, const char *role) { GHashTableIter iter; gpointer key, value; CcnetPeer *peer; GList *list = 0; g_hash_table_iter_init (&iter, manager->peer_hash); while (g_hash_table_iter_next (&iter, &key, &value)) { peer = value; if (ccnet_peer_has_role(peer, role)) { list = g_list_prepend (list, peer); g_object_ref (peer); } } return list; } static void add_peer (CcnetPeerManager *manager, CcnetPeer *peer) { peer->manager = manager; g_object_ref (peer); g_hash_table_insert (manager->peer_hash, peer->id, peer); if (!peer->is_self) { g_signal_emit (manager, signals[ADDED_SIG], 0, peer); } } void ccnet_peer_manager_add_peer (CcnetPeerManager *manager, CcnetPeer *peer) { add_peer (manager, peer); peer->need_saving = 1; } static void delete_peer(CcnetPeerManager *manager, CcnetPeer *peer) { char *path; /* delete peer conf file from peer-db */ path = g_build_filename(manager->peerdb_path, peer->id, NULL); if (g_unlink(path) < 0) ccnet_warning("delete file %s error\n", path); g_hash_table_remove (manager->peer_hash, peer->id); remove_peer_roles (manager, peer->id); g_signal_emit (manager, signals[DELETING_SIG], 0, peer); g_object_unref (peer); g_free(path); } void ccnet_peer_manager_remove_peer (CcnetPeerManager *manager, CcnetPeer *peer) { ccnet_peer_shutdown (peer); delete_peer(manager, peer); } CcnetPeer * ccnet_peer_manager_add_resolve_peer (CcnetPeerManager *manager, const char *ip_or_domain, uint16_t port) { CcnetPeer *peer; g_return_val_if_fail (ip_or_domain != NULL, NULL); g_return_val_if_fail (port != 0, NULL); peer = ccnet_peer_new (NON_RESOLVED_PEERID); peer->public_addr = g_strdup (ip_or_domain); peer->public_port = port; peer->to_resolve = 1; peer->manager = manager; manager->priv->resolve_peers = g_list_prepend ( manager->priv->resolve_peers, peer); g_object_ref (peer); ccnet_conn_manager_add_to_conn_list (manager->session->connMgr, peer); ccnet_conn_manager_connect_peer (manager->session->connMgr, peer); return peer; } GList * ccnet_peer_manager_get_resolve_peers (CcnetPeerManager *manager) { GList *ret, *ptr; ret = g_list_copy(manager->priv->resolve_peers); for (ptr = ret; ptr; ptr = ptr->next) { g_object_ref ((CcnetPeer*)ptr->data); } return ret; } /* This function is intend to do valid check after peer's ID is resolved. This function is called when peer's ID is resolved, peer's public info is fetched, and connection is established. Return TRUE if start_keepalive() should be called after this function's return. Return FALSE otherwise. */ gboolean ccnet_peer_manager_on_peer_resolved (CcnetPeerManager *manager, CcnetPeer *peer) { peer->to_resolve = 0; ccnet_conn_manager_remove_from_conn_list (manager->session->connMgr, peer); save_peer_addr (manager, peer); CcnetPeer *old_peer; old_peer = ccnet_peer_manager_get_peer (manager, peer->id); if (old_peer) { if (old_peer->net_state == PEER_CONNECTED) { /* Actually this can't happen, because the otherside won't let you connect, * if you already has a connection to it. */ /* use old peer instead */ ccnet_warning ("[Peer Resolve] Resolved an already exists peer.\n"); g_object_unref (old_peer); return FALSE; } else { ccnet_warning ("[Peer Resolve] Resolved an exists peer, replace it.\n"); ccnet_peer_manager_remove_peer (manager, old_peer); g_object_unref (old_peer); } } manager->priv->resolve_peers = g_list_remove ( manager->priv->resolve_peers, peer); g_object_unref (peer); ccnet_peer_manager_add_peer (manager, peer); if (peer->intend_role) { ccnet_peer_manager_add_role (manager, peer, peer->intend_role); g_free (peer->intend_role); } if (peer->want_tobe_relay) { ccnet_peer_manager_add_role (manager, peer, "MyRelay"); } return TRUE; } void ccnet_peer_manager_on_peer_resolve_failed (CcnetPeerManager *manager, CcnetPeer *peer) { ccnet_peer_shutdown (peer); ccnet_conn_manager_remove_from_conn_list (manager->session->connMgr, peer); manager->priv->resolve_peers = g_list_remove ( manager->priv->resolve_peers, peer); g_object_unref (peer); } /* -------- Peer Database Management ---------------- */ static void check_db_table (CcnetDB *db) { char *sql; sql = "CREATE TABLE IF NOT EXISTS PeerAddr (peer_id CHAR(41) " "PRIMARY KEY, addr VARCHAR(15), port INTEGER)"; ccnet_db_query (db, sql); sql = "CREATE TABLE IF NOT EXISTS PeerRole (peer_id CHAR(41) PRIMARY KEY," "roles TEXT, timestamp BIGINT)"; ccnet_db_query (db, sql); } static CcnetDB * open_sqlite_db (CcnetPeerManager *manager) { CcnetDB *db = NULL; char *db_dir; char *db_path; db_dir = g_build_filename (manager->session->config_dir, "PeerMgr", NULL); if (checkdir_with_mkdir(db_dir) < 0) { ccnet_error ("Cannot open db dir %s: %s\n", db_dir, strerror(errno)); g_free (db_dir); return NULL; } g_free (db_dir); db_path = g_build_filename (manager->session->config_dir, "PeerMgr", "peermgr.db", NULL); #ifdef CCNET_SERVER db = ccnet_db_new_sqlite (db_path); #else if (sqlite_open_db (db_path, &db) < 0) db = NULL; #endif g_free (db_path); return db; } static int open_db (CcnetPeerManager *manager) { CcnetDB *db; db = open_sqlite_db (manager); if (!db) return -1; manager->priv->db = db; check_db_table (db); return 0; } static gboolean load_peer_addr_cb (CcnetDBRow *row, void *data) { CcnetPeer *peer = (CcnetPeer *)data; char *addr = (char *) ccnet_db_row_get_column_text (row, 0); int port = ccnet_db_row_get_column_int (row, 1); peer->public_addr = g_strdup(addr); peer->public_port = port; return FALSE; } static void load_peer_addr(CcnetPeerManager *manager, CcnetPeer *peer) { char sql[256]; if (!peer || !peer->id) return; snprintf (sql, 256, "SELECT addr, port FROM PeerAddr WHERE peer_id='%s'", peer->id); ccnet_db_foreach_selected_row (manager->priv->db, sql, load_peer_addr_cb, peer); } static void save_peer_addr(CcnetPeerManager *manager, CcnetPeer *peer) { /* char sql[256]; if (!peer || !peer->id) return; if (peer->public_addr) { snprintf (sql, 256, "REPLACE INTO PeerAddr VALUES ('%s', '%s', '%d')", peer->id, peer->public_addr, peer->public_port); } else { snprintf (sql, 256, "DELETE FROM PeerAddr WHERE peer_id='%s'", peer->id); } ccnet_db_query (manager->priv->db, sql); */ } static gboolean load_peer_role_cb (CcnetDBRow *row, void *data) { CcnetPeer *peer = (CcnetPeer *)data; char *roles = (char *) ccnet_db_row_get_column_text (row, 0); ccnet_peer_set_roles (peer, roles); return FALSE; } static void load_peer_role(CcnetPeerManager *manager, CcnetPeer *peer) { char sql[256]; if (!peer) return; snprintf (sql, 256, "SELECT roles FROM PeerRole" " where peer_id = '%s'", peer->id); ccnet_db_foreach_selected_row (manager->priv->db, sql, load_peer_role_cb, peer); } static CcnetPeer* _load_peer (CcnetPeerManager *manager, const char *path) { GError *error = NULL; CcnetPeer *peer; char *content; g_file_get_contents (path, &content, NULL, &error); if (error != NULL) { /* ccnet_debug ("Load peer info from %s error: %s\n", */ /* path, error->message); */ return NULL; } peer = ccnet_peer_from_string (content); if (!peer) { ccnet_warning ("Load peer info from %s error\n", path); g_free (content); return NULL; } load_peer_addr (manager, peer); load_peer_role (manager, peer); add_peer (manager, peer); peer->last_down = time(NULL); g_free (content); return peer; } void ccnet_peer_manager_set_peer_public_addr (CcnetPeerManager *manager, CcnetPeer *peer, const char *addr, int port) { int need_save = 0; if (port == 0) port = DEFAULT_PORT; if (!addr) { if (peer->public_addr) { g_free (peer->public_addr); peer->public_addr = NULL; need_save = 1; } } else if (!peer->public_addr || g_strcmp0 (peer->public_addr, addr) != 0){ g_free (peer->public_addr); peer->public_addr = g_strdup (addr); need_save = 1; } if (port > 0 && port != peer->public_port) { peer->public_port = port; need_save = 1; } if (need_save) save_peer_addr (manager, peer); } static void remove_peer_roles(CcnetPeerManager *manager, char *peer_id) { /* char sql[256]; if (!peer_id) return; snprintf (sql, 256, "DELETE FROM PeerRole WHERE peer_id = '%s'", peer_id); ccnet_db_query (manager->priv->db, sql); */ } static void save_peer_roles (CcnetPeerManager *manager, CcnetPeer *peer) { /* char sql[512]; CcnetDB *db = manager->priv->db; GString *buf = g_string_new (NULL); ccnet_peer_get_roles_str(peer, buf); snprintf (sql, 512, "REPLACE INTO PeerRole VALUES ('%s', '%s', " "%"G_GINT64_FORMAT")", peer->id, buf->str, get_current_time()); ccnet_db_query (db, sql); g_string_free (buf, TRUE); */ } void ccnet_peer_manager_add_role (CcnetPeerManager *manager, CcnetPeer *peer, const char *role) { ccnet_peer_add_role (peer, role); save_peer_roles (manager, peer); } void ccnet_peer_manager_remove_role (CcnetPeerManager *manager, CcnetPeer *peer, const char *role) { ccnet_peer_remove_role (peer, role); save_peer_roles (manager, peer); } CcnetPeer* ccnet_peer_manager_load_peer_by_id (CcnetPeerManager *manager, const char *peer_id) { char path[PATH_MAX]; g_return_val_if_fail (strlen(peer_id) == 40, NULL); sprintf (path, "%s" G_DIR_SEPARATOR_S "%s", manager->peerdb_path, peer_id); return _load_peer (manager, path); } static void prune_peers (CcnetPeerManager *manager) { GList *peers, *ptr; peers = g_hash_table_get_values (manager->peer_hash); for (ptr = peers; ptr; ptr = ptr->next) { CcnetPeer *peer = ptr->data; if (peer->is_self) continue; if (peer->role_list == NULL) { ccnet_debug ("Removed peer %s\n", peer->id); delete_peer (manager, peer); } } g_list_free (peers); } void ccnet_peer_manager_load_peerdb (CcnetPeerManager *manager) { const char *dname; GDir *dp; char buf[PATH_MAX]; manager->peerdb_path = g_build_filename (manager->session->config_dir, PEERDB_NAME, NULL); char *peerdb = manager->peerdb_path; open_db(manager); if (checkdir_with_mkdir(peerdb) < 0) { ccnet_warning ("Could not open or make peer-db.\n"); return; } if ((dp = g_dir_open (peerdb, 0, NULL)) == NULL) { ccnet_warning ("Can't open peer database %s: %s.\n", peerdb, strerror (errno)); return; } while ((dname = g_dir_read_name(dp)) != NULL) { if (strlen(dname) != 40) continue; sprintf (buf, "%s/%s", peerdb, dname); if (!g_file_test(buf, G_FILE_TEST_IS_REGULAR)) { ccnet_warning ("%s is not a regular file\n", buf); continue; } CcnetPeer *peer = _load_peer (manager, buf); g_object_unref (peer); } g_dir_close(dp); prune_peers (manager); } CcnetPeer * ccnet_peer_manager_get_peer (CcnetPeerManager *manager, const char *peer_id) { CcnetPeer *peer; peer = g_hash_table_lookup (manager->peer_hash, peer_id); if (peer) g_object_ref (peer); return peer; } CcnetPeer* ccnet_peer_manager_get_peer_by_name (CcnetPeerManager *manager, const char *name) { GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, manager->peer_hash); while (g_hash_table_iter_next (&iter, &key, &value)) { CcnetPeer *peer = value; if (peer->name == NULL) continue; if (strcmp(name, peer->name) == 0) { g_object_ref (peer); return peer; } } return NULL; } void ccnet_peer_manager_add_local_peer (CcnetPeerManager *manager, CcnetPeer *peer) { g_return_if_fail (peer->is_local); peer->manager = manager; manager->local_peers = g_list_append (manager->local_peers, peer); g_object_ref (peer); } void ccnet_peer_manager_remove_local_peer (CcnetPeerManager *manager, CcnetPeer *peer) { g_return_if_fail (peer->is_local); manager->local_peers = g_list_remove (manager->local_peers, peer); g_object_unref (peer); } static void save_peer (CcnetPeerManager *manager, CcnetPeer *peer) { /* char *path = NULL; FILE *fp; path = g_build_filename (manager->peerdb_path, peer->id, NULL); GString *str = ccnet_peer_to_string (peer); if ((fp = g_fopen (path, "wb")) == NULL) { ccnet_warning ("Can't save peer info: %s\n", strerror(errno)); goto err; } fputs (str->str, fp); fclose (fp); err: g_string_free (str, TRUE); g_free (path); */ } static int save_pulse (void * vmanager) { CcnetPeerManager *manager = vmanager; GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, manager->peer_hash); while (g_hash_table_iter_next (&iter, &key, &value)) { CcnetPeer *peer = value; #ifdef CCNET_SERVER /* clean peers in memory */ if (peer->role_list == NULL) { if (peer->net_state == PEER_DOWN && !peer->in_shutdown && !peer->in_connection) { time_t now = time(NULL); if (now < peer->last_down + PEER_GC_TIMEOUT) continue; g_hash_table_iter_remove (&iter); g_object_unref (peer); } } #endif if (peer->role_list == NULL) continue; if (peer->need_saving) { ccnet_debug ("[Peer] Saving peer %s(%.8s) to db\n", peer->name, peer->id); save_peer (manager, peer); peer->need_saving = 0; } } return TRUE; } void ccnet_peer_manager_start (CcnetPeerManager *manager) { ccnet_timer_new (save_pulse, manager, SAVING_INTERVAL_MSEC); /* manager->priv->notify_timer = ccnet_timer_new ((TimerCB)notify_pulse, */ /* manager, NOTIFY_MSEC); */ } static void shutdown_peer (gpointer key, gpointer value, gpointer user_data) { CcnetPeer *peer = value; if (!peer->is_self) ccnet_peer_shutdown (peer); } void ccnet_peer_manager_on_exit (CcnetPeerManager *manager) { save_pulse (manager); g_hash_table_foreach (manager->peer_hash, shutdown_peer, manager); } /* -------- peermgr message handling -------- */ #ifdef CCNET_SERVER #include "server-session.h" #include "user-mgr.h" #endif /* CCNET_SERVER */ void ccnet_peer_manager_send_ready_message (CcnetPeerManager *manager, CcnetPeer *peer) { CcnetMessage *ready_message = NULL; char buf[256]; snprintf (buf, 256, "v%d\n%s\n", PEERMGR_VERSION, SERVICE_READY); ready_message = ccnet_message_new (manager->session->base.id, peer->id, IPEERMGR_APP, buf, 0); ccnet_send_message (manager->session, ready_message); ccnet_message_unref (ready_message); } static void handle_service_ready_message (CcnetPeerManager *manager, CcnetMessage *msg, char *body) { CcnetPeer *peer = ccnet_peer_manager_get_peer (manager, msg->from); peer->is_ready = 1; ccnet_debug ("[peer] Received ready from peer %s(%.8s)\n", peer->name, peer->id); g_object_unref (peer); } static void notify_peer_role (CcnetPeerManager *manager, CcnetPeer *peer) { ccnet_debug ("[PeerMgr] Notify roles to peer %s(%.8s)\n", peer->name, peer->id); GString *msgbuf = g_string_new(NULL); g_string_append_printf (msgbuf, "v%d\n%s\n", PEERMGR_VERSION, ROLE_NOTIFY); ccnet_peer_get_roles_str (peer, msgbuf); g_string_append (msgbuf, "\n"); CcnetMessage *msg = ccnet_message_new (manager->session->base.id, peer->id, IPEERMGR_APP, msgbuf->str, 0); ccnet_send_message (manager->session, msg); ccnet_message_unref (msg); g_string_free (msgbuf, TRUE); } void ccnet_peer_manager_notify_peer_role (CcnetPeerManager *manager, CcnetPeer *peer) { /* notify_peer_role (manager, peer); */ } static void handle_role_notify_message (CcnetPeerManager *manager, CcnetMessage *msg, char *body) { ccnet_debug ("[PeerMgr] Receive role notify message\n"); char *roles, *ptr; roles = body; if ( (ptr = strchr (body, '\n')) == NULL) { ccnet_message ("[PeerMgr] Parse role notify message error\n"); return; } *ptr = '\0'; CcnetPeer *peer = ccnet_peer_manager_get_peer (manager, msg->from); if (!peer) { return; } GList *role_list = string_list_parse_sorted (roles, ","); if (!string_list_sorted_is_equal (role_list, peer->myrole_list)) { ccnet_peer_set_myroles (peer, roles); } string_list_free (role_list); g_object_unref (peer); } static int redirect (CcnetPeer *peer) { ccnet_peer_shutdown (peer); ccnet_debug("[PeerMgr] connect redirect destination %s(%.8s): %s:%d\n", peer->name, peer->id, peer->redirect_addr, peer->redirect_port); ccnet_conn_manager_connect_peer (peer->manager->session->connMgr, peer); g_object_unref (peer); return FALSE; } static void schedule_redirect (CcnetPeerManager *manager, CcnetPeer *peer) { g_object_ref (peer); ccnet_timer_new ((TimerCB)redirect, peer, 1); } static void handle_redirect_message (CcnetPeerManager *manager, CcnetMessage *msg, char *body) { int port; char *p, *addr; CcnetPeer *from; int len; ccnet_debug ("[PeerMgr] Receive redirect message from %.8s\n", msg->from); len = strlen(body); if (body[len-1] != '\n') { ccnet_message ("[PeerMgr] Bad formatted redirect msg: not end with '\\n'\n"); return; } body[len-1] = '\0'; addr = body; if ( (p = strchr(body, ':')) == NULL) { ccnet_message ("[PeerMgr] Bad formatted redirect msg: port missing\n"); return; } *p = '\0'; port = atoi(p+1); if (port <= 0) { ccnet_message ("[PeerMgr] Bad formatted redirect msg: wrong port\n"); return; } from = ccnet_peer_manager_get_peer (manager, msg->from); ccnet_peer_set_redirect (from, addr, port); /* note: can shutdown the connection during this event iteration, * must schedule it */ schedule_redirect (manager, from); g_object_unref (from); } void ccnet_peer_manager_receive_message (CcnetPeerManager *manager, CcnetMessage *msg) { guint16 version; char *type; char *body; if (parse_peermgr_message (msg, &version, &type, &body) < 0) { ccnet_message ("Invalid peermgr message from %.8s\n", msg->from); return; } if (version != PEERMGR_VERSION) { ccnet_message ("Incompatible peermgr message version %d from %.8s\n", version, msg->from); return; } if (strcmp(type, ROLE_NOTIFY) == 0) handle_role_notify_message (manager, msg, body); else if (strcmp(type, SERVICE_READY) == 0) handle_service_ready_message (manager, msg, body); else if (strcmp(type, PEER_REDIRECT) == 0) handle_redirect_message (manager, msg, body); } static void send_redirect_message (CcnetPeerManager *manager, CcnetPeer *peer, CcnetPeer *to) { CcnetMessage *msg = NULL; char buf[256]; if (!to->public_addr || to->public_port == 0) { ccnet_warning ("[peer] Redirect to peer %s(%.8s) has an invalid address\n", to->name, to->id); return; } snprintf (buf, 256, "v%d\n%s\n%s:%d\n", PEERMGR_VERSION, PEER_REDIRECT, to->public_addr, to->public_port); msg = ccnet_message_new (manager->session->base.id, peer->id, IPEERMGR_APP, buf, 0); ccnet_send_message (manager->session, msg); ccnet_message_unref (msg); } void ccnet_peer_manager_redirect_peer (CcnetPeerManager *manager, CcnetPeer *peer, CcnetPeer *to) { ccnet_debug ("[PeerMgr] redirect peer %s(%.8s) to %s(%.8s)\n", peer->name, peer->id, to->name, to->id); send_redirect_message (manager, peer, to); return; } void ccnet_peer_manager_on_peer_session_key_sent (CcnetPeerManager *manager, CcnetPeer *peer) { g_signal_emit_by_name (manager, "peer-auth-done", peer); } void ccnet_peer_manager_on_peer_session_key_received (CcnetPeerManager *manager, CcnetPeer *peer) { g_signal_emit_by_name (manager, "peer-auth-done", peer); } ccnet-6.1.5/net/common/peer-mgr.h000066400000000000000000000110051317035602700165650ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PEER_MGR_H #define CCNET_PEER_MGR_H #include #include #include "peer.h" #define CCNET_TYPE_PEER_MANAGER (ccnet_peer_manager_get_type ()) #define CCNET_PEER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_PEER_MANAGER, CcnetPeerManager)) #define CCNET_IS_PEER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_PEER_MANAGER)) #define CCNET_PEER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_PEER_MANAGER, CcnetPeerManagerClass)) #define CCNET_IS_PEER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_PEER_MANAGER)) #define CCNET_PEER_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_PEER_MANAGER, CcnetPeerManagerClass)) typedef struct _CcnetPeerManager CcnetPeerManager; typedef struct _CcnetPeerManagerClass CcnetPeerManagerClass; typedef struct CcnetPeerManagerPriv CcnetPeerManagerPriv; struct _CcnetPeerManager { GObject parent_instance; CcnetSession *session; char *peerdb_path; GHashTable *peer_hash; GList *local_peers; guint32 connected_peer; CcnetPeerManagerPriv *priv; }; struct _CcnetPeerManagerClass { GObjectClass parent_class; }; GType ccnet_peer_manager_get_type (void); CcnetPeerManager* ccnet_peer_manager_new (CcnetSession *); int ccnet_peer_manager_prepare (CcnetPeerManager *manager); void ccnet_peer_manager_free (CcnetPeerManager *manager); void ccnet_peer_manager_start (CcnetPeerManager *manager); void ccnet_peer_manager_on_exit (CcnetPeerManager *manager); void ccnet_peer_manager_add_peer (CcnetPeerManager *manager, CcnetPeer *peer); void ccnet_peer_manager_remove_peer (CcnetPeerManager *manager, CcnetPeer *peer); CcnetPeer* ccnet_peer_manager_get_peer (CcnetPeerManager *manager, const char *peer_id); CcnetPeer* ccnet_peer_manager_get_peer_by_name (CcnetPeerManager *manager, const char *name); GList* ccnet_peer_manager_get_peer_list (CcnetPeerManager *manager); GList* ccnet_peer_manager_get_peers_with_role (CcnetPeerManager *manager, const char *role); void ccnet_peer_manager_add_role (CcnetPeerManager *manager, CcnetPeer *peer, const char *role); void ccnet_peer_manager_remove_role (CcnetPeerManager *manager, CcnetPeer *peer, const char *role); void ccnet_peer_manager_add_local_peer (CcnetPeerManager *manager, CcnetPeer *peer); void ccnet_peer_manager_remove_local_peer (CcnetPeerManager *manager, CcnetPeer *peer); struct _CcnetMessage; void ccnet_peer_manager_receive_message (CcnetPeerManager *manager, struct _CcnetMessage *msg); void ccnet_peer_manager_notify_peer_role (CcnetPeerManager *manager, CcnetPeer *peer); void ccnet_peer_manager_set_peer_public_addr (CcnetPeerManager *manager, CcnetPeer *peer, const char *addr, int port); #ifdef CCNET_SERVER void ccnet_peer_manager_send_bind_status (CcnetPeerManager *manager, const char *peer_id, const char *result); #endif /* CCNET_SERVER */ /* function of resolving peer */ CcnetPeer * ccnet_peer_manager_add_resolve_peer (CcnetPeerManager *manager, const char *ip_or_domain, uint16_t port); GList * ccnet_peer_manager_get_resolve_peers (CcnetPeerManager *manager); void ccnet_peer_manager_redirect_peer (CcnetPeerManager *manager, CcnetPeer *peer, CcnetPeer *to); void ccnet_peer_manager_send_ready_message (CcnetPeerManager *manager, CcnetPeer *peer); void ccnet_peer_manager_on_peer_session_key_sent (CcnetPeerManager *manager, CcnetPeer *peer); void ccnet_peer_manager_on_peer_session_key_received (CcnetPeerManager *manager, CcnetPeer *peer); #endif ccnet-6.1.5/net/common/peer.c000066400000000000000000001004171317035602700160030ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #include #else #include #endif #include #include #ifdef WIN32 #include #else #include #include #endif #include "net.h" #include #include "timer.h" #include "peer.h" #include "packet-io.h" #include "rsa.h" #include "session.h" #include "peer-mgr.h" #include "perm-mgr.h" #include "processor.h" #include "proc-factory.h" #include "processors/service-proxy-proc.h" #include "connect-mgr.h" #include "utils.h" #define DEBUG_FLAG CCNET_DEBUG_PEER #include "log.h" enum { DOWN_SIG, /* connection down */ AUTH_DONE_SIG, /* peer become reachable and the auth state is AUTH_FULL, see keepalive-proc */ AUTH_UPDATED_SIG, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; #define OBJECT_TYPE_STRING "peer" #include "../lib/peer-common.h" void ccnet_peer_set_net_state (CcnetPeer *peer, int net_state); static void ccnet_peer_finalize (GObject *object); static void shutdown_processors (CcnetPeer *peer); static void set_property (GObject *object, guint property_id, const GValue *v, GParamSpec *pspec) { set_property_common (object, property_id, v, pspec); } void ccnet_peer_finalize (GObject *object) { CcnetPeer *peer = CCNET_PEER (object); g_free (peer->name); g_free (peer->addr_str); g_free (peer->service_url); g_hash_table_unref (peer->processors); g_free (peer->session_key); evbuffer_free (peer->packet); if (peer->pubkey) RSA_free (peer->pubkey); G_OBJECT_CLASS(ccnet_peer_parent_class)->finalize (object); } void ccnet_peer_free (CcnetPeer *peer) { ccnet_peer_shutdown (peer); g_object_unref (peer); } static void ccnet_peer_class_init (CcnetPeerClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = ccnet_peer_finalize; gobject_class->get_property = get_property; gobject_class->set_property = set_property; define_properties (gobject_class); signals[AUTH_DONE_SIG] = g_signal_new ("auth-done", CCNET_TYPE_PEER, G_SIGNAL_RUN_LAST, 0, /* no class singal handler */ NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[DOWN_SIG] = g_signal_new ("down", CCNET_TYPE_PEER, G_SIGNAL_RUN_LAST, 0, /* no class singal handler */ NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[AUTH_UPDATED_SIG] = g_signal_new ("auth-updated", CCNET_TYPE_PEER, G_SIGNAL_RUN_LAST, 0, /* no class singal handler */ NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void ccnet_peer_init (CcnetPeer *peer) { } CcnetPeer* ccnet_peer_new (const char *id) { CcnetPeer *peer; g_return_val_if_fail (strlen(id) == 40, NULL); peer = g_object_new (CCNET_TYPE_PEER, NULL); memcpy (peer->id, id, 40); peer->id[40] = '\0'; peer->net_state = PEER_DOWN; peer->public_port = 0; peer->processors = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); peer->reqID = CCNET_USER_ID_START; peer->packet = evbuffer_new (); return peer; } inline static void append_string_property (GString *buf, const char *name, const char *value) { if (value && value[0]) g_string_append_printf (buf, "%s %s\n", name, value); } inline static void append_int_property (GString *buf, const char *name, int value) { if (value != -1) g_string_append_printf (buf, "%s %d\n", name, value); } inline static void append_int64_property (GString *buf, const char *name, gint64 value) { g_string_append_printf (buf, "%s %"G_GINT64_FORMAT"\n", name, value); } GString* ccnet_peer_to_string (CcnetPeer *peer) { GString *buf = g_string_new (NULL); g_string_append (buf, "peer/"); g_string_append (buf, peer->id); g_string_append (buf, "\n"); append_string_property (buf, "name", peer->name); append_string_property (buf, "service-url", peer->service_url); if (peer->pubkey) { GString *str = public_key_to_gstring(peer->pubkey); g_string_append_printf (buf, "%s %s\n", "pubkey", str->str); g_string_free(str, TRUE); } return buf; } static void parse_field (CcnetPeer *peer, const char *key, char *value) { if (strcmp(key, "name") == 0) { g_free (peer->name); peer->name = g_strdup(value); return; } if (strcmp(key, "service-url") == 0) { g_free (peer->service_url); peer->service_url = g_strdup(value); return; } if (strcmp(key, "pubkey") == 0) { if (peer->pubkey) RSA_free(peer->pubkey); peer->pubkey = public_key_from_string (value); return; } } CcnetPeer* ccnet_peer_from_string (char *content) { CcnetPeer *peer = NULL; char *ptr, *start = content; if ( !(ptr = strchr(start, '\n')) ) return NULL; *ptr = '\0'; char *object_id = start; start = ptr + 1; char *object_type = ccnet_object_type_from_id (object_id); if (g_strcmp0(object_type, OBJECT_TYPE_STRING) != 0) goto out; char *pure_id = object_id + strlen(object_type) + 1; if (!peer_id_valid(pure_id)) { ccnet_warning ("Wrong peer id %s\n", pure_id); goto out; } peer = ccnet_peer_new (pure_id); parse_key_value_pairs ( start, (KeyValueFunc)parse_field, peer); out: g_free (object_type); return peer; } void ccnet_peer_update_from_string (CcnetPeer *peer, char *content) { char *ptr, *start = content; if ( !(ptr = strchr(start, '\n')) ) return; *ptr = '\0'; char *object_id = start; start = ptr + 1; char *object_type = ccnet_object_type_from_id (object_id); if (strcmp(object_type, OBJECT_TYPE_STRING) != 0) goto out; char *pure_id = object_id + strlen(object_type) + 1; g_return_if_fail (strcmp(pure_id, peer->id) == 0); parse_key_value_pairs ( start, (KeyValueFunc)parse_field, peer); peer->need_saving = 1; out: g_free (object_type); } void ccnet_peer_set_net_state (CcnetPeer *peer, int net_state) { /* do not need saving */ if (peer->net_state == net_state) return; ccnet_debug ("[Peer] Peer %s(%.8s) net state changed: %s->%s\n", peer->name, peer->id, ccnet_peer_get_net_state_string(peer->net_state), ccnet_peer_get_net_state_string(net_state)); peer->last_net_state = peer->net_state; if (net_state == PEER_DOWN) { if (!peer->is_local) --peer->manager->connected_peer; } else if (!peer->is_local) ++peer->manager->connected_peer; if (net_state == PEER_CONNECTED && !peer->io->is_incoming) g_object_set (peer, "can-connect", 1, NULL); g_object_set (peer, "net-state", net_state, NULL); } static void ccnet_peer_set_addr_str (CcnetPeer *peer, const char *addr_str) { /* do not need saving */ if (!addr_str) return; if (peer->addr_str && strcmp(addr_str, peer->addr_str) == 0) return; g_object_set (peer, "ip", addr_str, NULL); ccnet_debug ("[Peer] Updated peer %s(%.10s) address %s\n", peer->name, peer->id, addr_str); } void ccnet_peer_update_address (CcnetPeer *peer, const char *addr_str, unsigned short port) { if (!is_valid_ipaddr (addr_str)) return; ccnet_peer_set_addr_str (peer, addr_str); if (port == 0) return; peer->port = port; } void ccnet_peer_set_pubkey (CcnetPeer *peer, char *str) { g_object_set (peer, "pubkey", str, NULL); if (!peer->pubkey) ccnet_warning("Wrong public key format\n"); peer->need_saving = 1; } int ccnet_peer_prepare_channel_encryption (CcnetPeer *peer) { if (!peer->session_key) return -1; if ( ccnet_generate_cipher(peer->session_key, strlen(peer->session_key), peer->key, peer->iv) < 0) return -1; peer->encrypt_channel = 1; return 0; } /* -------- role management -------- */ void ccnet_peer_add_role (CcnetPeer *peer, const char *role) { if (!ccnet_peer_has_role(peer, role)) { peer->role_list = string_list_append_sorted ( peer->role_list, role); } } void ccnet_peer_remove_role (CcnetPeer *peer, const char *role) { g_return_if_fail (role != NULL); if (!string_list_is_exists(peer->role_list, role)) return; peer->role_list = string_list_remove (peer->role_list, role); } gboolean ccnet_peer_has_role (CcnetPeer *peer, const char *role) { return string_list_is_exists(peer->role_list, role); } gboolean ccnet_peer_has_my_role (CcnetPeer *peer, const char *role) { return string_list_is_exists(peer->myrole_list, role); } void ccnet_peer_set_roles (CcnetPeer *peer, const char *roles) { GList *role_list = string_list_parse_sorted (roles, ","); string_list_free (peer->role_list); peer->role_list = role_list; } void ccnet_peer_set_myroles (CcnetPeer *peer, const char *roles) { GList *role_list = string_list_parse_sorted (roles, ","); string_list_free (peer->myrole_list); peer->myrole_list = role_list; /* ccnet_debug ("[Peer] Myrole on %s(%.8s) is set to %s\n", */ /* peer->id, peer->name, roles); */ } void ccnet_peer_get_roles_str (CcnetPeer *peer, GString* buf) { string_list_join (peer->role_list, buf, ","); } void ccnet_peer_get_myroles_str (CcnetPeer *peer, GString* buf) { string_list_join (peer->myrole_list, buf, ","); } /* ----------- Packet Handling & Networking --------------------- */ static void remove_write_callbacks (CcnetPeer *peer) { g_list_foreach (peer->write_cbs, (GFunc)g_free, NULL); g_list_free (peer->write_cbs); } static void _peer_shutdown (CcnetPeer *peer) { peer->in_shutdown = 1; if (peer->net_state == PEER_CONNECTED) { peer->last_down = time(NULL); ccnet_packet_io_free (peer->io); peer->io = NULL; g_object_set (peer, "can-connect", 0, NULL); } peer->is_ready = 0; g_free (peer->dns_addr); peer->dns_addr = NULL; peer->dns_done = 0; /* clear session key when peer down */ peer->encrypt_channel = 0; g_free (peer->session_key); peer->session_key = NULL; ccnet_debug ("Shutdown all processors for peer %s\n", peer->name); shutdown_processors (peer); remove_write_callbacks (peer); ccnet_peer_set_net_state (peer, PEER_DOWN); g_signal_emit (peer, signals[DOWN_SIG], 0); peer->in_shutdown = 0; } int shutdown_peer (CcnetPeer *peer) { _peer_shutdown (peer); peer->shutdown_scheduled = 0; g_object_unref (peer); return FALSE; } static void schedule_shutdown (CcnetPeer *peer) { if (peer->shutdown_scheduled) return; g_object_ref (peer); ccnet_timer_new ((TimerCB)shutdown_peer, peer, 1); peer->shutdown_scheduled = 1; } void ccnet_peer_shutdown (CcnetPeer *peer) { schedule_shutdown (peer); } void ccnet_peer_shutdown_no_delay (CcnetPeer *peer) { if (!peer->shutdown_scheduled) { peer->shutdown_scheduled = 1; _peer_shutdown (peer); peer->shutdown_scheduled = 0; } } static void create_remote_processor (CcnetPeer *peer, CcnetPeer *remote_peer, int req_id, int argc, char **argv) { CcnetProcessor *processor; CcnetProcFactory *factory = peer->manager->session->proc_factory; processor = ccnet_proc_factory_create_slave_processor ( factory,"service-proxy", peer, req_id); ccnet_processor_start (processor, 0, NULL); ccnet_service_proxy_invoke_remote (processor, remote_peer, argc, argv); } static void create_local_processor (CcnetPeer *peer, int req_id, int argc, char **argv) { CcnetProcessor *processor; CcnetProcFactory *factory = peer->manager->session->proc_factory; processor = ccnet_proc_factory_create_slave_processor ( factory, argv[0], peer, req_id); if (processor) { ccnet_processor_start (processor, argc-1, argv+1); } else { CcnetService *service; service = ccnet_session_get_service (peer->manager->session, argv[0]); if (service != NULL) { processor = ccnet_proc_factory_create_slave_processor ( factory, "service-proxy", peer, req_id); ccnet_processor_start (processor, 0, NULL); ccnet_service_proxy_invoke_local (processor, service->provider, argc, argv); } else { ccnet_peer_send_response (peer, req_id, SC_UNKNOWN_SERVICE, SS_UNKNOWN_SERVICE, NULL, 0); ccnet_debug ("Unknown service %s invoke by %s(%.8s)\n", argv[0], peer->name, peer->id); } } } static void create_processor (CcnetPeer *peer, int req_id, int argc, char **argv) { CcnetSession *session = peer->manager->session; if (strcmp(argv[0], "remote") == 0) { /* we have check this before (in permission checking) */ CcnetPeer *remote_peer; remote_peer = ccnet_peer_manager_get_peer (peer->manager, argv[1]); if (!remote_peer) { ccnet_peer_send_response (peer, req_id, SC_UNKNOWN_PEER, SS_UNKNOWN_PEER, NULL, 0); ccnet_warning ("Unknown remote peer in invoking remote service\n"); return; } /* if (remote_peer->net_state == PEER_DOWN) { */ /* ccnet_peerSendResponse (peer, req_id, SC_PEER_UNREACHABLE, */ /* SS_PEER_UNREACHABLE, NULL, 0); */ /* ccnet_warning ("Unreachable remote peer in invoking remote service\n"); */ /* return; */ /* } */ /* To simplify caller's logic, we allow starting a remote processor to * local host. Translate this call into a local one. */ if (session->myself == remote_peer) { create_local_processor (peer, req_id, argc-2, argv+2); g_object_unref (remote_peer); return; } create_remote_processor (peer, remote_peer, req_id, argc-2, argv+2); g_object_unref (remote_peer); return; } create_local_processor (peer, req_id, argc, argv); } static void handle_request (CcnetPeer *peer, int req_id, char *data, int len) { char *msg; gchar **commands; gchar **pcmd; int i, perm; /* TODO: remove string copy */ if (len < 1) return; msg = g_malloc (len+1); memcpy (msg, data, len); msg[len] = '\0'; commands = g_strsplit_set (msg, " \t", 10); for (i=0, pcmd = commands; *pcmd; pcmd++) i++; if (i <= 0) return; g_free (msg); /* permission checking */ if (!peer->is_local) { perm = ccnet_perm_manager_check_permission(peer->manager->session->perm_mgr, peer, commands[0], req_id, i, commands); if (perm == PERM_CHECK_ERROR) { ccnet_peer_send_response (peer, req_id, SC_PERM_ERR, SS_PERM_ERR, NULL, 0); goto ret; } else if (perm == PERM_CHECK_DELAY) { ccnet_peer_send_response (peer, req_id, SC_PERM_ERR, SS_PERM_ERR, NULL, 0); goto ret; } else if (perm == PERM_CHECK_NOSERVICE) { ccnet_peer_send_response (peer, req_id, SC_UNKNOWN_SERVICE_IN_PERM, SS_UNKNOWN_SERVICE_IN_PERM, NULL, 0); goto ret; } } /* check duplication request */ CcnetProcessor *processor; processor = ccnet_peer_get_processor (peer, SLAVE_ID(req_id)); if (processor != NULL) { ccnet_warning ("Received duplication request, id is %d\n", req_id); goto ret; } create_processor (peer, req_id, i, commands); ret: g_strfreev (commands); } static void handle_response (CcnetPeer *peer, int req_id, char *data, int len) { CcnetProcessor *processor; char *code, *code_msg = 0, *content = 0; int clen; char *ptr, *end; if (len < 4) goto error; code = data; ptr = data + 3; if (*ptr == '\n') { /* no code_msg */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); goto parsed; } if (*ptr != ' ') goto error; *ptr++ = '\0'; code_msg = ptr; end = data + len; for (ptr = data; *ptr != '\n' && ptr != end; ptr++) ; if (ptr == end) /* must end with '\n' */ goto error; /* if (*(ptr-1) == '\r') */ /* *(ptr-1) = '\0'; */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); parsed: processor = ccnet_peer_get_processor (peer, MASTER_ID (req_id)); if (processor == NULL) { /* do nothing if receiving SC_PROC_DEAD and the processor on * this side is also not present. Otherwise send SC_PROC_DEAD */ if (memcmp(code, SC_PROC_DEAD, 3) != 0) { ccnet_debug ("Delayed response from %s(%.10s), id is %d, %s %s\n", peer->name, peer->id, req_id, code, code_msg); ccnet_peer_send_update (peer, req_id, SC_PROC_DEAD, SS_PROC_DEAD, NULL, 0); } return; } /* if (!peer->is_local) */ /* ccnet_debug ("[RECV] handle_response %s id is %d, %s %s\n", */ /* GET_PNAME(processor), PRINT_ID(processor->id), */ /* code, code_msg); */ peer->in_processor_call = 1; ccnet_processor_handle_response (processor, code, code_msg, content, clen); peer->in_processor_call = 0; return; error: ccnet_warning ("Bad response format from %s\n", peer->id); } static void handle_update (CcnetPeer *peer, int req_id, char *data, int len) { CcnetProcessor *processor; char *code, *code_msg = 0, *content = 0; int clen; char *ptr, *end; if (len < 4) goto error; code = data; ptr = data + 3; if (*ptr == '\n') { /* no code_msg */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); goto parsed; } if (*ptr != ' ') goto error; *ptr++ = '\0'; code_msg = ptr; end = data + len; for (ptr = data; *ptr != '\n' && ptr != end; ptr++) ; if (ptr == end) /* must end with '\n' */ goto error; /* if (*(ptr-1) == '\r') */ /* *(ptr-1) = '\0'; */ *ptr++ = '\0'; content = ptr; clen = len - (ptr - data); parsed: processor = ccnet_peer_get_processor (peer, SLAVE_ID(req_id)); if (processor == NULL) { if (memcmp(code, SC_PROC_DEAD, 3) != 0 && memcmp(code, SC_PROC_DONE, 3) != 0) { ccnet_debug ("Delayed update from %s(%.8s), id is %d, %s %s\n", peer->name, peer->id, req_id, code, code_msg); ccnet_peer_send_response (peer, req_id, SC_PROC_DEAD, SS_PROC_DEAD, NULL, 0); } return; } /* if (!peer->is_local) */ /* ccnet_debug ("[RECV] handle_update %s id is %d, %s %s\n", */ /* GET_PNAME(processor), PRINT_ID(processor->id), */ /* code, code_msg); */ peer->in_processor_call = 1; ccnet_processor_handle_update (processor, code, code_msg, content, clen); peer->in_processor_call = 0; return; error: ccnet_warning ("Bad update format from %s\n", peer->id); } static void handle_packet (ccnet_packet *packet, CcnetPeer *peer) { switch (packet->header.type) { case CCNET_MSG_REQUEST: handle_request (peer, packet->header.id, packet->data, packet->header.length); break; case CCNET_MSG_RESPONSE: handle_response (peer, packet->header.id, packet->data, packet->header.length); break; case CCNET_MSG_UPDATE: handle_update (peer, packet->header.id, packet->data, packet->header.length); break; default: ccnet_warning ("Unknown header type %d\n", packet->header.type); }; } static void canRead (ccnet_packet *packet, void *vpeer) { CcnetPeer *peer = vpeer; g_object_ref (peer); /* if (!peer->is_local) */ /* ccnet_debug ("[RECV] Recieve packat from %s type is %d, id is %d\n", */ /* peer->id, packet->header.type, packet->header.id); */ if (packet->header.id == 0) return; if (packet->header.type != CCNET_MSG_ENCPACKET) { handle_packet (packet, peer); } else { /* ccnet_debug ("receive an encrypt packet\n"); */ if (!peer->session_key) { ccnet_debug("Receive a encrypted packet from %s(%.8s) while " "not having session key \n", peer->name, peer->id); goto out; } char *data; int len; int ret; ret = ccnet_decrypt_with_key (&data, &len, packet->data, packet->header.id, peer->key, peer->iv); if (ret < 0) ccnet_warning ("[SEND] decryption error for peer %s(%.8s) \n", peer->name, peer->id); else { ccnet_packet *new_pac = (ccnet_packet *)data; /* byte order, from network to host */ new_pac->header.length = ntohs(new_pac->header.length); new_pac->header.id = ntohl (new_pac->header.id); handle_packet (new_pac, peer); g_free (data); } } out: g_object_unref (peer); } struct WriteCallback { int removing : 1; PeerWriteCallback func; void *user_data; }; void ccnet_peer_add_write_callback (CcnetPeer *peer, PeerWriteCallback func, void *user_data) { if (peer->net_state == PEER_CONNECTED) { struct WriteCallback *wcb = g_new0 (struct WriteCallback, 1); wcb->func = func; wcb->user_data = user_data; peer->write_cbs = g_list_prepend (peer->write_cbs, wcb); } else { ccnet_warning ("add_write_callback error: Peer not reachable\n"); } } void ccnet_peer_remove_write_callback (CcnetPeer *peer, PeerWriteCallback func, void *user_data) { GList *ptr; for (ptr = peer->write_cbs; ptr; ptr = ptr->next) { struct WriteCallback *wcb = ptr->data; if (wcb->func == func && wcb->user_data == user_data) { peer->write_cbs = g_list_delete_link (peer->write_cbs, ptr); g_free (wcb); return; } } } static void didWrite(struct bufferevent * evin, void * vpeer) { CcnetPeer *peer = vpeer; GList *ptr; g_object_ref (peer); peer->in_writecb = 1; for (ptr = peer->write_cbs; ptr; ) { struct WriteCallback *wcb = ptr->data; GList *cur = ptr; ptr = ptr->next; if (wcb->func(peer, wcb->user_data) == FALSE) { peer->write_cbs = g_list_delete_link (peer->write_cbs, cur); g_free (wcb); } } peer->in_writecb = 0; g_object_unref (peer); } static void gotError (struct bufferevent *evbuf, short what, void *vpeer) { CcnetPeer *peer = vpeer; g_object_ref (peer); /* ccnet_warning ("libevent got an error on peer %s what==%d, errno=%d (%s)\n", */ /* peer->name, (int)what, errno, strerror(errno)); */ if (what & EVBUFFER_TIMEOUT) { ccnet_warning ("libevent got a timeout for peer %s(%.8s), what=%hd, timeout secs=%ld\n", peer->name, peer->id, what, *((time_t *)&(evbuf->timeout_read))); ccnet_message ("Peer %s (%.10s) down for timeout\n", peer->name, peer->id); peer->num_fails++; ccnet_peer_shutdown (peer); } if (what & (EVBUFFER_EOF | EVBUFFER_ERROR)) { if (what & EVBUFFER_ERROR) ccnet_warning ("libevent got an error! what=%hd, errno=%d (%s)\n", what, errno, strerror(errno)); if (peer->is_local) { ccnet_message ("Local peer down\n"); ccnet_peer_shutdown (peer); ccnet_session_unregister_service (peer->manager->session, peer); ccnet_peer_manager_remove_local_peer (peer->manager, peer); } else { ccnet_message ("[Net Error] Peer %s (%.10s) down\n", peer->name, peer->id); peer->num_fails++; ccnet_peer_shutdown (peer); } } g_object_unref (peer); } /* static void */ /* ccnet_peer_reset_io (CcnetPeer *peer) */ /* { */ /* ccnet_packet_io_set_timeout_secs (peer->io, 0); /\* disable timeout *\/ */ /* ccnet_packet_io_set_iofuncs (peer->io, canRead, didWrite, gotError, peer); */ /* } */ void ccnet_peer_set_io (CcnetPeer *peer, CcnetPacketIO *io) { peer->io = io; /* libevent remove a previous timeout seems not work in libevent 2.0, so we have to disable timeout by set it to a large value */ if (!peer->is_local) ccnet_packet_io_set_timeout_secs (peer->io, 10000); ccnet_packet_io_set_iofuncs (peer->io, canRead, didWrite, gotError, peer); } int ccnet_peer_get_request_id (CcnetPeer *peer) { return (++peer->reqID); } #undef DEBUG_FLAG /* #define DEBUG_FLAG CCNET_DEBUG_NETIO */ #include "log.h" void ccnet_peer_packet_prepare (const CcnetPeer *peer, int type, int id) { ccnet_header header; header.version = 1; header.type = type; header.length = 0; header.id = htonl (id); evbuffer_add (peer->packet, &header, sizeof (header)); } void ccnet_peer_packet_write_string (const CcnetPeer *peer, const char *str) { int len; len = strlen(str); evbuffer_add (peer->packet, str, len); } void ccnet_peer_packet_finish (const CcnetPeer *peer) { ccnet_header *header; header = (ccnet_header *) EVBUFFER_DATA(peer->packet); header->length = htons (EVBUFFER_LENGTH(peer->packet) - CCNET_PACKET_LENGTH_HEADER); } void ccnet_peer_packet_send (const CcnetPeer *peer) { int ret = 0; if (peer->is_local) { bufferevent_write_buffer (peer->io->bufev, peer->packet); return; } if (peer->net_state == PEER_CONNECTED) { if (!peer->encrypt_channel) { ret = bufferevent_write_buffer (peer->io->bufev, peer->packet); } else { ccnet_header enc_header; char *data = (char *)EVBUFFER_DATA(peer->packet); uint32_t len = EVBUFFER_LENGTH(peer->packet); char *enc_data; int enc_len; ret = ccnet_encrypt_with_key (&enc_data, &enc_len, data, len, peer->key, peer->iv); if (ret < 0) { ccnet_warning ("[SEND] encryption error for sending packet " "to peer %s(%.8s) \n", peer->name, peer->id); evbuffer_drain (peer->packet, EVBUFFER_LENGTH(peer->packet)); return; } enc_header.version = 1; enc_header.type = CCNET_MSG_ENCPACKET; enc_header.length = 0; enc_header.id = htonl(enc_len); bufferevent_write (peer->io->bufev, &enc_header, sizeof (enc_header)); bufferevent_write (peer->io->bufev, enc_data, enc_len); g_free (enc_data); evbuffer_drain (peer->packet, EVBUFFER_LENGTH(peer->packet)); } if (ret < 0) ccnet_warning ("[SEND] bufferevent failed to send packet to peer(%.8s) \n", peer->id); } else { ccnet_warning ("Unable to send packet when peer is not connected.\n"); evbuffer_drain (peer->packet, EVBUFFER_LENGTH(peer->packet)); } } void ccnet_peer_packet_finish_send (const CcnetPeer *peer) { ccnet_peer_packet_finish (peer); ccnet_peer_packet_send (peer); } void ccnet_peer_send_request (const CcnetPeer *peer, int req_id, const char *req) { if (!peer->is_local) ccnet_debug ("[network] Send a request: id %d, cmd %s\n", req_id, req); ccnet_peer_packet_prepare (peer, CCNET_MSG_REQUEST, req_id); ccnet_peer_packet_write_string (peer, req); ccnet_peer_packet_finish_send (peer); } void ccnet_peer_send_response (const CcnetPeer *peer, int req_id, const char *code, const char *reason, const char *content, int clen) { if ( (strlen(code) != 3) || !isdigit(code[0]) || !isdigit(code[1]) || !isdigit(code[1]) ) { ccnet_warning ("Bad code number\n"); return; } g_return_if_fail (clen < 65536); ccnet_peer_packet_prepare (peer, CCNET_MSG_RESPONSE, req_id); /* code line */ evbuffer_add (peer->packet, code, 3); if (reason) { evbuffer_add (peer->packet, " ", 1); ccnet_peer_packet_write_string (peer, reason); } evbuffer_add (peer->packet, "\n", 1); if (content) evbuffer_add (peer->packet, content, clen); ccnet_peer_packet_finish_send (peer); if (!peer->is_local) ccnet_debug ("[SEND] Send a response: id %d code %s %s\n", req_id, code, reason); } void ccnet_peer_send_update (const CcnetPeer *peer, int req_id, const char *code, const char *reason, const char *content, int clen) { ccnet_peer_packet_prepare (peer, CCNET_MSG_UPDATE, req_id); /* code line */ evbuffer_add (peer->packet, code, 3); if (reason) { evbuffer_add (peer->packet, " ", 1); ccnet_peer_packet_write_string (peer, reason); } evbuffer_add (peer->packet, "\n", 1); if (content) evbuffer_add (peer->packet, content, clen); ccnet_peer_packet_finish_send (peer); if (!peer->is_local) ccnet_debug ("[SEND] Send an update: id %d code %s %s\n", req_id, code, reason?reason:"NULL"); } /* ---------------- Processors ---------------- */ #undef DEBUG_FLAG #define DEBUG_FLAG CCNET_DEBUG_PROCESSOR #include "log.h" void ccnet_peer_add_processor (CcnetPeer *peer, CcnetProcessor *processor) { if (!peer->is_local) ccnet_debug ("[Proc] Add %s(%d) to peer %s\n", GET_PNAME(processor), PRINT_ID(processor->id), peer->name); g_hash_table_insert (peer->processors, (gpointer)(long)processor->id, processor); processor->detached = 0; } void ccnet_peer_remove_processor (CcnetPeer *peer, CcnetProcessor *processor) { /* ccnet_debug ("[Proc] Remove %s(%d) from peer %s\n", GET_PNAME(processor), */ /* PRINT_ID(processor->id), peer->name); */ g_hash_table_remove (peer->processors, (gpointer)(long)processor->id); processor->detached = 1; } CcnetProcessor * ccnet_peer_get_processor (CcnetPeer *peer, unsigned int id) { return g_hash_table_lookup (peer->processors, (gpointer)(long)id); } static void shutdown_processors (CcnetPeer *peer) { ccnet_proc_factory_shutdown_processors ( peer->manager->session->proc_factory, peer); } /* -------- redirect related code -------- */ void ccnet_peer_set_redirect (CcnetPeer *peer, const char *addr, uint16_t port) { g_return_if_fail (peer->redirected == 0); peer->redirected = 1; peer->redirect_addr = g_strdup (addr); peer->redirect_port = port; } void ccnet_peer_unset_redirect (CcnetPeer *peer) { peer->redirected = 0; g_free (peer->redirect_addr); peer->redirect_port = 0; } ccnet-6.1.5/net/common/peer.h000066400000000000000000000141441317035602700160110ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PEER_H #define CCNET_PEER_H #include #include #include #include "processor.h" #define CCNET_TYPE_PEER (ccnet_peer_get_type ()) #define CCNET_PEER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_PEER, CcnetPeer)) #define CCNET_IS_PEER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_PEER)) #define CCNET_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_PEER, CcnetPeerClass)) #define CCNET_IS_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_PEER)) #define CCNET_PEER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_PEER, CcnetPeerClass)) enum { PEER_DOWN, PEER_CONNECTED }; typedef struct _CcnetPeer CcnetPeer; typedef struct _CcnetPeerClass CcnetPeerClass; struct CcnetPacketIO; #define NON_RESOLVED_PEERID "0000000000000000000000000000000000000000" struct _CcnetUser; struct _CcnetPeer { GObject parent_instance; /* fields from pubinfo */ char id[41]; RSA *pubkey; char *session_key; unsigned char key[32]; unsigned char iv[32]; char *name; /* hostname */ char *public_addr; uint16_t public_port; /* port from pubinfo */ char *service_url; /* fields not from pubinfo */ char *addr_str; /* hold the ip actually used in connection */ uint16_t port; char *redirect_addr; uint16_t redirect_port; char *dns_addr; /* address solved by dns */ int net_state; GList *role_list; GList *myrole_list; /* my role on this peer */ char *intend_role; /* used in peer resolving */ unsigned int is_self : 1; unsigned int is_local : 1; unsigned int can_connect : 1; unsigned int in_local_network : 1; unsigned int is_ready : 1; unsigned int dns_done : 1; unsigned int need_saving : 1; unsigned int want_tobe_relay : 1; /* is the peer used as relay */ unsigned int in_shutdown : 1; unsigned int shutdown_scheduled : 1; unsigned int in_writecb : 1; unsigned int in_connection : 1; unsigned int keepalive_sending : 1; unsigned int to_resolve : 1; /* the peer's identity need to be resolved, * we only have its IP address now. */ unsigned int redirected : 1; unsigned int cluster_member : 1; unsigned int in_processor_call : 1; unsigned int encrypt_channel : 1; struct CcnetPacketIO *io; int last_net_state; /* for connection management */ time_t last_down; /* for peer gc in relay */ int num_fails; int reqID; struct _CcnetPeerManager *manager; struct evbuffer *packet; GHashTable *processors; GList *write_cbs; int last_mult_recv; /* statistics */ time_t last_up; }; struct _CcnetPeerClass { GObjectClass parent_class; }; GType ccnet_peer_get_type (void); CcnetPeer* ccnet_peer_from_string (char *content); void ccnet_peer_update_from_string (CcnetPeer *peer, char *string); GString * ccnet_peer_to_string (CcnetPeer *peer); CcnetPeer* ccnet_peer_new (const char *id); void ccnet_peer_free (CcnetPeer *peer); void ccnet_peer_shutdown (CcnetPeer *peer); void ccnet_peer_shutdown_no_delay (CcnetPeer *peer); int ccnet_peer_get_request_id (CcnetPeer *peer); void ccnet_peer_add_processor (CcnetPeer *peer, CcnetProcessor *processor); void ccnet_peer_remove_processor (CcnetPeer *peer, CcnetProcessor *processor); CcnetProcessor * ccnet_peer_get_processor (CcnetPeer *peer, unsigned int id); void ccnet_peer_set_net_state (CcnetPeer *peer, int net_state); void ccnet_peer_update_address (CcnetPeer *peer, const char *addr_str, uint16_t port); void ccnet_peer_set_pubkey (CcnetPeer *peer, char *str); int ccnet_peer_prepare_channel_encryption (CcnetPeer *peer); /* role management */ void ccnet_peer_set_roles (CcnetPeer *peer, const char *roles); void ccnet_peer_set_myroles (CcnetPeer *peer, const char *roles); void ccnet_peer_get_roles_str (CcnetPeer *peer, GString *buf); void ccnet_peer_get_myroles_str (CcnetPeer *peer, GString *buf); void ccnet_peer_add_role (CcnetPeer *peer, const char *role); void ccnet_peer_remove_role (CcnetPeer *peer, const char *role); gboolean ccnet_peer_has_role (CcnetPeer *peer, const char *role); gboolean ccnet_peer_has_my_role (CcnetPeer *peer, const char *role); /* */ typedef gboolean (*PeerWriteCallback) (CcnetPeer *peer, void *user_data); void ccnet_peer_add_write_callback (CcnetPeer *peer, PeerWriteCallback func, void *user_data); void ccnet_peer_remove_write_callback (CcnetPeer *peer, PeerWriteCallback func, void *user_data); /* IO */ void ccnet_peer_send_request (const CcnetPeer *peer, int req_id, const char *req); void ccnet_peer_send_response (const CcnetPeer *peer, int req_id, const char *code, const char *reason, const char *content, int clen); void ccnet_peer_send_update (const CcnetPeer *peer, int req_id, const char *code, const char *reason, const char *content, int clen); /* middle level IO */ void ccnet_peer_set_io (CcnetPeer *peer, struct CcnetPacketIO *io); void ccnet_peer_set_redirect (CcnetPeer *peer, const char *addr, uint16_t port); void ccnet_peer_unset_redirect (CcnetPeer *peer); #endif ccnet-6.1.5/net/common/peermgr-message.c000066400000000000000000000017621317035602700201360ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "session.h" #include "peer.h" #include "peer-mgr.h" #include "utils.h" #include "peermgr-message.h" #define DEBUG_FLAG CCNET_DEBUG_PEER #include "log.h" /* Protocol v1: PeermgrMessage format: v\n \n [content] For example: v1\n role-notify\n MyPeer\n */ int parse_peermgr_message (CcnetMessage *msg, guint16 *version, char **type, char **body) { char *end, *start; int v; if (!msg->body) return -1; /* version */ if (msg->body[0] != 'v') return -1; start = msg->body + 1; if ( !(end = strchr(start, '\n')) ) return -1; *end = '\0'; if ((v = atoi(start)) == 0) return -1; *version = v; /* type */ *type = start = end + 1; if ( !(end = strchr(start, '\n')) ) return -1; *end = '\0'; *body = start = end + 1; return 0; } ccnet-6.1.5/net/common/peermgr-message.h000066400000000000000000000010151317035602700201320ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PEERMGR_MESSAGE_H #define CCNET_PEERMGR_MESSAGE_H #include "message.h" #define PEERMGR_VERSION 3 #define BIND_QUERY "bind-query" #define BIND_STATUS "bind-status" #define ROLE_NOTIFY "role-notify" #define SERVICE_READY "service-ready" #define PEER_REDIRECT "redirect" int parse_peermgr_message (CcnetMessage *msg, guint16 *version, char **type, char **body); #endif ccnet-6.1.5/net/common/perm-mgr.c000066400000000000000000000126771317035602700166100ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "peer.h" #include "session.h" #include "peer-mgr.h" #include "perm-mgr.h" #define DEBUG_FLAG CCNET_DEBUG_OTHER #include "log.h" /* Give an user and a service, for each role of this user: 1. find the service group, 2. use hash table 'role2groups' to find the permitted groups to this role, 3. check whether the given group in the list of groups. */ struct _CcnetPermManagerPriv { GHashTable *serv2group; /* service to group map */ GHashTable *role2groups; /* role -> list of groups */ GList *anonymous_groups; /* permitted groups to anonymous user. */ }; struct ServiceGroup { const char *service; const char *group; }; /* only service that can be accessed from network peers should list here, * service accessed only by local peers do not need be list here. */ struct ServiceGroup service_groups[] = { { "put-pubinfo", "basic" }, { "put-user", "basic" }, { "keepalive2", "basic" }, { "receive-session-key", "basic" }, { "receive-skey2", "basic" }, { "receive-msg", "basic" }, { "echo", "basic" }, { "ccnet-rpcserver", "rpc-inner" }, #ifdef CCNET_SERVER { "recvlogin", "basic" }, { "recvlogout", "basic" }, { "receive-profile", "relay-service" }, #endif { NULL, NULL }, }; struct RolePerm { const char *role; const char *group; }; typedef struct RolePermList { GList *list; } RolePermList; struct RolePerm role_perms[] = { { "MyClient", "seafserv" }, { "MyClient", "relay-service" }, { "MyAdmin", "rpc-inner" }, { "ClusterMember", "seafserv-inner" }, { "BlockClient", "seablock" }, { NULL, NULL }, }; CcnetPermManager * ccnet_perm_manager_new (CcnetSession *session) { CcnetPermManager *mgr = g_new0 (CcnetPermManager, 1); mgr->priv = g_new0 (CcnetPermManagerPriv, 1); mgr->session = session; mgr->priv->serv2group = g_hash_table_new (g_str_hash, g_str_equal); mgr->priv->role2groups = g_hash_table_new (g_str_hash, g_str_equal); return mgr; } static void populate_default_items(CcnetPermManager *mgr); int ccnet_perm_manager_prepare (CcnetPermManager *mgr) { populate_default_items (mgr); return 0; } static void populate_default_items (CcnetPermManager *mgr) { struct ServiceGroup *sg; for (sg = service_groups; sg->service; sg++) { g_hash_table_insert (mgr->priv->serv2group, g_strdup(sg->service), g_strdup(sg->group)); } struct RolePerm *rp; for (rp = role_perms; rp->role; rp++) { RolePermList *list; list = g_hash_table_lookup (mgr->priv->role2groups, rp->role); if (!list) { list = g_new0(RolePermList, 1); g_hash_table_insert (mgr->priv->role2groups, g_strdup(rp->role), list); } list->list = g_list_prepend (list->list, g_strdup(rp->group)); } } static inline const char * get_service_group(CcnetPermManager *mgr, const char *service) { return g_hash_table_lookup (mgr->priv->serv2group, service); } int check_role_permission(CcnetPermManager *mgr, const char *role, const char *group) { RolePermList *rplist; GList *ptr; rplist = g_hash_table_lookup (mgr->priv->role2groups, role); if (!rplist) return PERM_CHECK_ERROR; for (ptr = rplist->list; ptr; ptr = ptr->next) { if (strcmp(ptr->data, group) == 0) return PERM_CHECK_OK; } return PERM_CHECK_ERROR; } /* for unit test */ int ccnet_perm_manager_check_role_permission(CcnetPermManager *mgr, const char *role, const char *group) { return check_role_permission (mgr, role, group); } int ccnet_perm_manager_check_permission (CcnetPermManager *mgr, CcnetPeer *peer, const char *req, int req_id, int argc, char **argv) { const char *group = get_service_group (mgr, req); if (!group) return PERM_CHECK_NOSERVICE; if (g_strcmp0(group, "basic") == 0) return PERM_CHECK_OK; if (peer->is_local) return PERM_CHECK_OK; if (g_strcmp0(group, "inner") == 0) return PERM_CHECK_ERROR; if (g_strcmp0 (group, "self") == 0) { if (g_strcmp0 (peer->id, mgr->session->base.id) == 0) /* myself user */ return PERM_CHECK_OK; else return PERM_CHECK_ERROR; } GList *ptr; for (ptr = peer->role_list; ptr; ptr = ptr->next) { if (check_role_permission(mgr, ptr->data, group) == PERM_CHECK_OK) return PERM_CHECK_OK; } return PERM_CHECK_ERROR; } int ccnet_perm_manager_register_service (CcnetPermManager *mgr, const char *service, const char *group, CcnetPeer *peer) { if (g_hash_table_lookup (mgr->priv->serv2group, service)) return -1; ccnet_debug ("[perm-mgr] register service %s %s\n", service, group); g_hash_table_insert (mgr->priv->serv2group, g_strdup(service), g_strdup(group)); return 0; } ccnet-6.1.5/net/common/perm-mgr.h000066400000000000000000000024401317035602700166000ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef SEAF_PERM_MGR_H #define SEAF_PERM_MGR_H #include enum { PERM_CHECK_ERROR = -1, PERM_CHECK_OK = 0, PERM_CHECK_DELAY = 1, PERM_CHECK_NOSERVICE = 2, }; typedef struct _CcnetPermManager CcnetPermManager; typedef struct _CcnetPermManagerPriv CcnetPermManagerPriv; struct _CcnetPermManager { CcnetSession *session; CcnetPermManagerPriv *priv; }; CcnetPermManager* ccnet_perm_manager_new (CcnetSession *session); int ccnet_perm_manager_prepare (CcnetPermManager *mgr); int ccnet_perm_manager_check_permission (CcnetPermManager *mgr, CcnetPeer *peer, const char *req, int req_id, int argc, char **argv); int ccnet_perm_manager_check_role_permission(CcnetPermManager *mgr, const char *role, const char *group); int ccnet_perm_manager_register_service (CcnetPermManager *mgr, const char *svc_name, const char *group, CcnetPeer *peer); #endif ccnet-6.1.5/net/common/proc-factory.c000066400000000000000000000245401317035602700174620ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include "peer.h" #include "session.h" #include "processor.h" #include "proc-factory.h" #include "peer-mgr.h" #include "timer.h" #include "processors/keepalive2-proc.h" #include "processors/rcvcmd-proc.h" #include "processors/service-proxy-proc.h" #include "processors/service-stub-proc.h" #include "processors/sendsessionkey-proc.h" #include "processors/recvsessionkey-proc.h" #include "processors/sendsessionkey-v2-proc.h" #include "processors/recvsessionkey-v2-proc.h" #define DEBUG_FLAG CCNET_DEBUG_PROCESSOR #include "log.h" #include "utils.h" /* Note, timeout here must be larger than the timeout of keepalive-proc * * Here, we only handle problems which happen when tcp connection is ok but * processors are dead or not created by peer. * * */ /* The timeout of keepalive-proc is 180s now. */ #define DEFAULT_NO_PACKET_TIMEOUT 10 /* 10 seconds */ #define KEEPALIVE_PULSE 5 * 1000 /* 5 seconds */ #define CONNECTION_TIMEOUT 182 #define MAX_PROCS_KEEPALIVE 5 /* we check 5 proc for each peer at most */ typedef struct { GHashTable *proc_type_table; } CcnetProcFactoryPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_PROC_FACTORY, CcnetProcFactoryPriv)) G_DEFINE_TYPE (CcnetProcFactory, ccnet_proc_factory, G_TYPE_OBJECT); static void ccnet_proc_factory_class_init (CcnetProcFactoryClass *klass) { g_type_class_add_private (klass, sizeof (CcnetProcFactoryPriv)); } static void ccnet_proc_factory_init (CcnetProcFactory *factory) { CcnetProcFactoryPriv *priv = GET_PRIV (factory); priv->proc_type_table = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL); } void ccnet_proc_factory_register_processor (CcnetProcFactory *factory, const char *serv_name, GType type) { CcnetProcFactoryPriv *priv = GET_PRIV (factory); CcnetProcessorClass *proc_class = (CcnetProcessorClass *)g_type_class_ref(type); g_type_class_unref (proc_class); g_hash_table_insert (priv->proc_type_table, g_strdup (serv_name), (gpointer) type); } GType ccnet_getpubinfo_proc_get_type (); GType ccnet_putpubinfo_proc_get_type (); GType ccnet_sendmsg_proc_get_type (); GType ccnet_rcvmsg_proc_get_type (); GType ccnet_rcvcmd_proc_get_type (); GType ccnet_getperm_proc_get_type (); GType ccnet_keepalive2_proc_get_type (); GType ccnet_mqserver_proc_get_type (); GType ccnet_service_proxy_proc_get_type (); GType ccnet_service_stub_proc_get_type (); GType ccnet_sync_relay_proc_get_type (); GType ccnet_sync_relay_slave_proc_get_type (); GType ccnet_rpcserver_proc_get_type (); GType ccnet_echo_proc_get_type (); CcnetProcFactory * ccnet_proc_factory_new (CcnetSession *session) { CcnetProcFactory *factory; factory = g_object_new (CCNET_TYPE_PROC_FACTORY, NULL); factory->session = session; factory->no_packet_timeout = DEFAULT_NO_PACKET_TIMEOUT; factory->procs = NULL; /* register fundamental processors */ /* FIXME: These processor types shall be regitered by managers */ ccnet_proc_factory_register_processor (factory, "get-pubinfo", ccnet_getpubinfo_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "put-pubinfo", ccnet_putpubinfo_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "send-msg", ccnet_sendmsg_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "receive-msg", ccnet_rcvmsg_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "receive-cmd", ccnet_rcvcmd_proc_get_type ()); /* ccnet_proc_factory_register_processor (factory, "receive-event", */ /* ccnet_rcvevent_proc_get_type ()); */ ccnet_proc_factory_register_processor (factory, "keepalive2", ccnet_keepalive2_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "send-session-key", ccnet_sendsessionkey_proc_get_type()); ccnet_proc_factory_register_processor (factory, "receive-session-key", ccnet_recvsessionkey_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "send-skey2", ccnet_sendskey2_proc_get_type()); ccnet_proc_factory_register_processor (factory, "receive-skey2", ccnet_recvskey2_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "mq-server", ccnet_mqserver_proc_get_type ()); ccnet_proc_factory_register_processor (factory, "service-proxy", ccnet_service_proxy_proc_get_type()); ccnet_proc_factory_register_processor (factory, "service-stub", ccnet_service_stub_proc_get_type()); ccnet_proc_factory_register_processor (factory, "ccnet-rpcserver", ccnet_rpcserver_proc_get_type()); /* if (session->is_relay) { ccnet_proc_factory_register_processor (factory, "sync-relay-slave", ccnet_sync_relay_slave_proc_get_type()); } else { ccnet_proc_factory_register_processor (factory, "sync-relay", ccnet_sync_relay_proc_get_type()); } */ ccnet_proc_factory_register_processor (factory, "echo", ccnet_echo_proc_get_type ()); return factory; } void ccnet_proc_factory_start (CcnetProcFactory *factory) { /* factory->keepalive_timer = ccnet_timer_new ( */ /* (TimerCB) keepalive_pulse, factory, KEEPALIVE_PULSE); */ } static GType ccnet_proc_factory_get_proc_type (CcnetProcFactory *factory, const char *serv_name) { CcnetProcFactoryPriv *priv = GET_PRIV (factory); return (GType) g_hash_table_lookup (priv->proc_type_table, serv_name); } static inline CcnetProcessor * create_processor_common (CcnetProcFactory *factory, const char *serv_name, CcnetPeer *peer, int req_id) { GType type; CcnetProcessor *processor; type = ccnet_proc_factory_get_proc_type (factory, serv_name); if (type == 0) { return NULL; } processor = g_object_new (type, NULL); processor->peer = peer; g_object_ref (peer); processor->session = factory->session; processor->id = req_id; /* Set the real processor name. * This may be different from the processor class name. */ processor->name = g_strdup(serv_name); if (!peer->is_local) ccnet_debug ("Create processor %s(%d) %s\n", GET_PNAME(processor), PRINT_ID(processor->id), processor->name); ccnet_peer_add_processor (processor->peer, processor); factory->procs_alive_cnt++; return processor; } CcnetProcessor * ccnet_proc_factory_create_slave_processor (CcnetProcFactory *factory, const char *serv_name, CcnetPeer *peer, int req_id) { return create_processor_common(factory, serv_name, peer, SLAVE_ID (req_id)); } CcnetProcessor * ccnet_proc_factory_create_master_processor (CcnetProcFactory *factory, const char *serv_name, CcnetPeer *peer) { return create_processor_common ( factory, serv_name, peer, MASTER_ID(ccnet_peer_get_request_id (peer)) ); } static void inline recycle (CcnetProcFactory *factory, CcnetProcessor *processor) { factory->procs_alive_cnt--; #ifdef DEBUG_PROC if (strcmp(GET_PNAME(processor), "rpcserver-proc") != 0) { /* ignore rpcserver-proc */ CcnetProc *proc = ccnet_proc_new(); g_object_set (proc, "name", GET_PNAME(processor), "peer-name", processor->peer->name, "ctime", (int) processor->start_time, "dtime", (int) time(NULL), NULL); factory->procs = g_list_prepend (factory->procs, proc); } #endif /* TODO: implement processor pool */ g_object_unref (processor); } void ccnet_proc_factory_recycle (CcnetProcFactory *factory, CcnetProcessor *processor) { recycle (factory, processor); } static void shutdown_processor (CcnetProcessor *processor, char *code, char *code_msg) { /* Send an error message to shutdown the processor. * If it's a proxy or stub proc, it'll first relay the message. */ if (!IS_SLAVE (processor)) { ccnet_processor_handle_response (processor, code, code_msg, NULL, 0); } else { ccnet_processor_handle_update (processor, code, code_msg, NULL, 0); } } void ccnet_proc_factory_shutdown_processors (CcnetProcFactory *factory, CcnetPeer *peer) { GList *list, *ptr; CcnetProcessor *processor; char *code = g_strdup (SC_NETDOWN); char *code_msg = g_strdup (SS_NETDOWN); list = g_hash_table_get_values (peer->processors); for (ptr = list; ptr; ptr = ptr->next) { processor = CCNET_PROCESSOR (ptr->data); processor->detached = TRUE; shutdown_processor (processor, code, code_msg); } g_hash_table_remove_all (peer->processors); g_list_free (list); g_free (code); g_free (code_msg); } void ccnet_proc_factory_set_keepalive_timeout (CcnetProcFactory *factory, int timeout) { factory->no_packet_timeout = timeout; } /* Don't send keepalive or reclaim inactive processors. */ #if 0 static gint compare_procs (gconstpointer a, gconstpointer b) { const CcnetProcessor *proc_a = a, *proc_b = b; return (proc_a->t_keepalive_sent - proc_b->t_keepalive_sent); } #endif /* 0 */ ccnet-6.1.5/net/common/proc-factory.h000066400000000000000000000047211317035602700174660ustar00rootroot00000000000000#ifndef CCNET_PROC_FACTORY_H #define CCNET_PROC_FACTORY_H #include #include "processor.h" #include "ccnet-object.h" #define CCNET_TYPE_PROC_FACTORY (ccnet_proc_factory_get_type ()) #define CCNET_PROC_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_PROC_FACTORY, CcnetProcFactory)) #define CCNET_IS_PROC_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_PROC_FACTORY)) #define CCNET_PROC_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_PROC_FACTORY, CcnetProcFactoryClass)) #define CCNET_IS_PROC_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_PROC_FACTORY)) #define CCNET_PROC_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_PROC_FACTORY, CcnetProcFactoryClass)) typedef struct _CcnetProcFactory CcnetProcFactory; typedef struct _CcnetProcFactoryClass CcnetProcFactoryClass; struct _CcnetProcFactory { GObject parent_instance; /* protected */ struct CcnetSession *session; int procs_alive_cnt; /*number of processors alive*/ GList *procs; /* TODO: need to recyle the space * when it grows verylarge */ /* do keepalive if not receiving packet in `no_packet_timeout`, * default is 30 seconds */ int no_packet_timeout; }; struct _CcnetProcFactoryClass { GObjectClass parent_class; }; GType ccnet_proc_factory_get_type (void); CcnetProcFactory *ccnet_proc_factory_new (CcnetSession *session); void ccnet_proc_factory_start (CcnetProcFactory *factory); void ccnet_proc_factory_register_processor (CcnetProcFactory *facotry, const char *serv_name, GType proc_type); void ccnet_proc_factory_recycle(CcnetProcFactory *factory, CcnetProcessor *processor); void ccnet_proc_factory_shutdown_processors ( CcnetProcFactory *factory, CcnetPeer *peer); CcnetProcessor *ccnet_proc_factory_create_master_processor ( CcnetProcFactory *factory, const char *serv_name, CcnetPeer *peer); CcnetProcessor *ccnet_proc_factory_create_slave_processor ( CcnetProcFactory *factory, const char *serv_name, CcnetPeer *peer, int req_id); void ccnet_proc_factory_set_keepalive_timeout (CcnetProcFactory *factory, int timeout); #endif ccnet-6.1.5/net/common/processor.c000066400000000000000000000361271317035602700170750ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "timer.h" #include "peer.h" #include "processor.h" #include "session.h" #include "connect-mgr.h" #include "proc-factory.h" #include "utils.h" #ifdef CCNET_SERVER #include "server-session.h" #include "job-mgr.h" #endif #include "processors/keepalive2-proc.h" #include "processors/service-proxy-proc.h" #include "processors/service-stub-proc.h" #define DEBUG_FLAG CCNET_DEBUG_PROCESSOR #include "log.h" enum { DONE_SIG, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (CcnetProcessor, ccnet_processor, G_TYPE_OBJECT); static void default_shutdown (CcnetProcessor *processor); static void default_release_resource (CcnetProcessor *processor); static void ccnet_processor_class_init (CcnetProcessorClass *klass) { /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ klass->start = NULL; klass->handle_update = NULL; klass->handle_response = NULL; klass->shutdown = default_shutdown; klass->release_resource = default_release_resource; signals[DONE_SIG] = g_signal_new ("done", CCNET_TYPE_PROCESSOR, G_SIGNAL_RUN_LAST, 0, /* no class singal handler */ NULL, NULL, /* no accumulator */ g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); } static void ccnet_processor_init (CcnetProcessor *processor) { } int ccnet_processor_start (CcnetProcessor *processor, int argc, char **argv) { /* set this value to now even if this is a master processor and has not received any packet yet for simplifying the keepalive logic. */ time_t now = time(NULL); processor->start_time = now; if (IS_SLAVE(processor)) processor->t_packet_recv = now; else processor->t_packet_recv = 0; processor->failure = PROC_NOTSET; if (processor->peer->net_state != PEER_CONNECTED) { if (IS_SLAVE(processor)) { ccnet_processor_send_response (processor, SC_NETDOWN, SS_NETDOWN, NULL, 0); } processor->failure = PROC_NETDOWN; ccnet_processor_done (processor, FALSE); return -1; } return CCNET_PROCESSOR_GET_CLASS (processor)->start ( processor, argc, argv); } int ccnet_processor_startl (CcnetProcessor *processor, ...) { va_list ap; int argc = 0; char **argv = g_malloc (sizeof(char *) * 10); char *arg; int max = 10; int ret; va_start (ap, processor); arg = va_arg (ap, char *); while (arg) { if (argc >= max) { max *= 2; argv = g_realloc (argv, sizeof(char *) * max); } argv[argc++] = arg; arg = va_arg (ap, char *); } va_end (ap); ret = ccnet_processor_start (processor, argc, argv); g_free (argv); return ret; } static void default_shutdown (CcnetProcessor *processor) { processor->err_code = ERR_INTR; } static void default_release_resource(CcnetProcessor *processor) { if (processor->retry_timer) ccnet_timer_free (&processor->retry_timer); g_free (processor->name); if (processor->peer) { g_object_unref (processor->peer); processor->peer = NULL; } } /* should be called before recycle */ void ccnet_processor_release_resource(CcnetProcessor *processor) { CCNET_PROCESSOR_GET_CLASS (processor)->release_resource(processor); } /* * processor->detached is set in two places: * 1. ccnet_peer_remove_process(), which is called when one processor is done; * 2. ccnet_proc_factory_shutdown_processors(), which is called when peer shutdown. * * There are two shutdown/done situation: * 1. processor thread is not running; * 2. processor thread was running, now it's a delayed shutdown. * * When ccnet_processor_done() is called while worker thread is running, * the current state is saved in processor->detached, processor->was_success. * After the thread is done, ccnet_processor_done() will be called again * with the same state. */ void ccnet_processor_done (CcnetProcessor *processor, gboolean success) { if (processor->thread_running) { processor->delay_shutdown = TRUE; processor->was_success = success; return; } if (processor->state == STATE_IN_SHUTDOWN) { return; } processor->state = STATE_IN_SHUTDOWN; if (processor->failure == PROC_NOTSET) processor->failure = PROC_DONE; if (!processor->peer->is_local) ccnet_debug ("Processsor %s(%d) done %d\n", GET_PNAME(processor), PRINT_ID(processor->id), success); if (!processor->detached && success) { if (!IS_SLAVE (processor)) { ccnet_processor_send_update (processor, SC_PROC_DONE, SS_PROC_DONE, NULL, 0); } } g_signal_emit (processor, signals[DONE_SIG], 0, success); if (!processor->detached) { ccnet_peer_remove_processor (processor->peer, processor); } ccnet_processor_release_resource (processor); ccnet_proc_factory_recycle (processor->session->proc_factory, processor); } void ccnet_processor_error (CcnetProcessor *processor, const char *error_code, const char *error_string) { ccnet_processor_send_response ( processor, error_code, error_string, NULL, 0); ccnet_processor_done (processor, FALSE); } static void ccnet_processor_keep_alive_response (CcnetProcessor *processor); void ccnet_processor_handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (code[0] == '5' || code[0] == '4') { ccnet_debug ("[Proc] Shutdown processor %s(%d) for bad update: %s %s\n", GET_PNAME(processor), PRINT_ID(processor->id), code, code_msg); /* Proxy proc should relay the message before it shuts down. */ if (CCNET_IS_SERVICE_PROXY_PROC(processor) || CCNET_IS_SERVICE_STUB_PROC(processor)) { CCNET_PROCESSOR_GET_CLASS (processor)->handle_update ( processor, code, code_msg, content, clen); } if (memcmp(code, SC_UNKNOWN_SERVICE, 3) == 0) processor->failure = PROC_NO_SERVICE; else if (memcmp(code, SC_PERM_ERR, 3) == 0) processor->failure = PROC_PERM_ERR; else if (memcmp(code, SC_CON_TIMEOUT, 3) == 0) processor->failure = PROC_CON_TIMEOUT; else if (memcmp(code, SC_KEEPALIVE_TIMEOUT, 3) == 0) processor->failure = PROC_TIMEOUT; else if (memcmp(code, SC_NETDOWN, 3) == 0) processor->failure = PROC_NETDOWN; else processor->failure = PROC_BAD_RESP; ccnet_processor_done (processor, FALSE); return; } processor->t_packet_recv = time(NULL); if (memcmp (code, SC_PROC_KEEPALIVE, 3) == 0) { ccnet_processor_keep_alive_response (processor); } else if (memcmp (code, SC_PROC_ALIVE, 3) == 0) { /* ccnet_debug ("[Proc] received alive update (%d)\n", PRINT_ID(processor->id)); */ /* do nothing */ } else if (memcmp (code, SC_PROC_DEAD, 3) == 0) { ccnet_debug ("[Proc] Shutdown processor %s(%d) when remote processor dies\n", GET_PNAME(processor), PRINT_ID(processor->id)); if (CCNET_IS_SERVICE_PROXY_PROC(processor) || CCNET_IS_SERVICE_STUB_PROC(processor)) { CCNET_PROCESSOR_GET_CLASS (processor)->handle_update ( processor, code, code_msg, content, clen); } processor->failure = PROC_REMOTE_DEAD; ccnet_processor_done (processor, FALSE); } else if (memcmp (code, SC_PROC_DONE, 3) == 0) { ccnet_debug ("[Proc] Shutdown processor %s(%d) when master done\n", GET_PNAME(processor), PRINT_ID(processor->id)); if (CCNET_IS_SERVICE_PROXY_PROC(processor) || CCNET_IS_SERVICE_STUB_PROC(processor)) { CCNET_PROCESSOR_GET_CLASS (processor)->handle_update ( processor, code, code_msg, content, clen); } ccnet_processor_done (processor, TRUE); } else CCNET_PROCESSOR_GET_CLASS (processor)->handle_update (processor, code, code_msg, content, clen); } void ccnet_processor_handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if ((code[0] == '5' || code[0] == '4') && !CCNET_IS_KEEPALIVE2_PROC(processor)) { ccnet_debug ("[Proc] peer %.10s, Shutdown processor %s(%d) for bad response: %s %s\n", processor->peer->id, GET_PNAME(processor), PRINT_ID(processor->id), code, code_msg); /* Stub proc should relay the message before it shuts down. */ if (CCNET_IS_SERVICE_PROXY_PROC(processor) || CCNET_IS_SERVICE_STUB_PROC(processor)) { CCNET_PROCESSOR_GET_CLASS (processor)->handle_response ( processor, code, code_msg, content, clen); } if (memcmp(code, SC_UNKNOWN_SERVICE, 3) == 0) processor->failure = PROC_NO_SERVICE; else if (memcmp(code, SC_PERM_ERR, 3) == 0) processor->failure = PROC_PERM_ERR; else if (memcmp(code, SC_CON_TIMEOUT, 3) == 0) processor->failure = PROC_CON_TIMEOUT; else if (memcmp(code, SC_KEEPALIVE_TIMEOUT, 3) == 0) processor->failure = PROC_TIMEOUT; else if (memcmp(code, SC_NETDOWN, 3) == 0) processor->failure = PROC_NETDOWN; else processor->failure = PROC_BAD_RESP; ccnet_processor_done (processor, FALSE); return; } processor->t_packet_recv = time(NULL); if (memcmp (code, SC_PROC_KEEPALIVE, 3) == 0) { ccnet_processor_keep_alive_response (processor); } else if (memcmp (code, SC_PROC_ALIVE, 3) == 0) { /* do nothing */ } else if (memcmp (code, SC_PROC_DEAD, 3) == 0) { ccnet_debug ("[Proc] Shutdown processor %s(%d) when remote processor dies\n", GET_PNAME(processor), PRINT_ID(processor->id)); if (CCNET_IS_SERVICE_PROXY_PROC(processor) || CCNET_IS_SERVICE_STUB_PROC(processor)) { CCNET_PROCESSOR_GET_CLASS (processor)->handle_response ( processor, code, code_msg, content, clen); } processor->failure = PROC_REMOTE_DEAD; ccnet_processor_done (processor, FALSE); } else CCNET_PROCESSOR_GET_CLASS (processor)->handle_response (processor, code, code_msg, content, clen); } void ccnet_processor_handle_sigchld (CcnetProcessor *processor, int status) { CCNET_PROCESSOR_GET_CLASS (processor)->handle_sigchld (processor, status); } void ccnet_processor_send_request (CcnetProcessor *processor, const char *request) { ccnet_peer_send_request (processor->peer, REQUEST_ID (processor->id), request); } void ccnet_processor_send_request_l (CcnetProcessor *processor, ...) { va_list ap; GString *buf = g_string_new(NULL); char *arg; va_start (ap, processor); arg = va_arg (ap, char *); while (arg) { g_string_append (buf, arg); arg = va_arg (ap, char *); } va_end (ap); ccnet_peer_send_request (processor->peer, REQUEST_ID (processor->id), buf->str); g_string_free (buf, TRUE); } void ccnet_processor_send_update (CcnetProcessor *processor, const char *code, const char *code_msg, const char *content, int clen) { ccnet_peer_send_update (processor->peer, UPDATE_ID(processor->id), code, code_msg, content, clen); } void ccnet_processor_send_error_update (CcnetProcessor *processor, const char *code, const char *code_msg) { ccnet_peer_send_update (processor->peer, UPDATE_ID(processor->id), code, code_msg, NULL, 0); } void ccnet_processor_send_response (CcnetProcessor *processor, const char *code, const char *code_msg, const char *content, int clen) { ccnet_peer_send_response (processor->peer, RESPONSE_ID (processor->id), code, code_msg, content, clen); } void ccnet_processor_keep_alive (CcnetProcessor *processor) { if (IS_SLAVE (processor)) ccnet_processor_send_response (processor, SC_PROC_KEEPALIVE, SS_PROC_KEEPALIVE, NULL, 0); else ccnet_processor_send_update (processor, SC_PROC_KEEPALIVE, SS_PROC_KEEPALIVE, NULL, 0); processor->t_keepalive_sent = time (NULL); } static void ccnet_processor_keep_alive_response (CcnetProcessor *processor) { if (IS_SLAVE (processor)) ccnet_processor_send_response (processor, SC_PROC_ALIVE, SS_PROC_ALIVE, NULL, 0); else ccnet_processor_send_update (processor, SC_PROC_ALIVE, SS_PROC_ALIVE, NULL, 0); } #ifdef CCNET_SERVER typedef struct ProcThreadData { CcnetProcessor *proc; ProcThreadFunc func; void *data; ProcThreadDoneFunc done_func; void *result; } ProcThreadData; static void processor_thread_done (void *vdata) { ProcThreadData *tdata = vdata; tdata->proc->thread_running = FALSE; if (tdata->proc->delay_shutdown) ccnet_processor_done (tdata->proc, tdata->proc->was_success); else tdata->done_func (tdata->result); g_free (tdata); } static void * processor_thread_func_wrapper (void *vdata) { ProcThreadData *tdata = vdata; tdata->result = tdata->func (tdata->data); return vdata; } int ccnet_processor_thread_create (CcnetProcessor *processor, CcnetJobManager *job_mgr, ProcThreadFunc func, ProcThreadDoneFunc done_func, void *data) { ProcThreadData *tdata; tdata = g_new(ProcThreadData, 1); tdata->proc = processor; tdata->func = func; tdata->done_func = done_func; tdata->data = data; ccnet_job_manager_schedule_job (job_mgr ? job_mgr : processor->session->job_mgr, processor_thread_func_wrapper, processor_thread_done, tdata); processor->thread_running = TRUE; return 0; } #endif /* CCNET_SERVER */ ccnet-6.1.5/net/common/processor.h000066400000000000000000000153371317035602700171020ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PROCESSOR_H #define CCNET_PROCESSOR_H #include #include #include struct CcnetSession; struct _CcnetPeer; struct CcnetTimer; #define CCNET_TYPE_PROCESSOR (ccnet_processor_get_type ()) #define CCNET_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_PROCESSOR, CcnetProcessor)) #define CCNET_IS_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_PROCESSOR)) #define CCNET_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_PROCESSOR, CcnetProcessorClass)) #define CCNET_IS_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_PROCESSOR)) #define CCNET_PROCESSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_PROCESSOR, CcnetProcessorClass)) typedef struct _CcnetProcessor CcnetProcessor; typedef struct _CcnetProcessorClass CcnetProcessorClass; /* err_code values */ enum { ERR_NONE = 0, ERR_INTR, ERR_ARG, ERR_MAX, }; struct _CcnetProcessor { GObject parent_instance; struct _CcnetPeer *peer; struct CcnetSession *session; char *name; /* highest bit = 0, master; highest bit = 1, slave */ unsigned int id; int state; int failure; int mode; struct CcnetTimer *retry_timer; int num_retry; int err_code; time_t start_time; /* Set to 1 if removed from peer->processors */ unsigned int detached : 1; /* last time when a packet received */ time_t t_packet_recv; time_t t_keepalive_sent; gboolean thread_running; /* If proc is shut down when a thread is running, delay it until * the thread is done. The current state is saved to was_success. * The thread done callback checks delay_shutdown * attribute and if this is TRUE, the callback * calls processor_done(processor, was_success). */ gboolean delay_shutdown; gboolean was_success; }; enum { STATE_IN_SHUTDOWN = 1 << 8, STATE_RECYCLED, }; enum { PROC_NOTSET, PROC_DONE, PROC_REMOTE_DEAD, PROC_NO_SERVICE, PROC_PERM_ERR, PROC_BAD_RESP, /* code[0] =='5' || '4' */ PROC_NETDOWN, PROC_CON_TIMEOUT, PROC_TIMEOUT, }; #define SLAVE_MASK 0x80000000 #define REQUEST_ID_MASK 0x7fffffff #define REQUEST_ID(processor_id) ((processor_id) & REQUEST_ID_MASK) #define UPDATE_ID(processor_id) ((processor_id) & REQUEST_ID_MASK) #define RESPONSE_ID(processor_id) ((processor_id) & REQUEST_ID_MASK) #define SLAVE_ID(request_id) ((request_id) | SLAVE_MASK) #define MASTER_ID(request_id) (request_id) #define PRINT_ID(processor_id) ((processor_id) & SLAVE_MASK) ? \ - REQUEST_ID(processor_id) : REQUEST_ID(processor_id) #define IS_SLAVE(processor) ((processor)->id & SLAVE_MASK) #define GET_PNAME(processor) CCNET_PROCESSOR_GET_CLASS(processor)->name struct _CcnetProcessorClass { GObjectClass parent_class; char *name; /* pure virtual function */ int (*start) (CcnetProcessor *processor, int argc, char **argv); void (*handle_update) (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); void (*handle_response) (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); void (*handle_sigchld) (CcnetProcessor *processor, int status); void (*shutdown) (CcnetProcessor *processor); void (*release_resource) (CcnetProcessor *processor); }; GType ccnet_processor_get_type (); int ccnet_processor_start (CcnetProcessor *processor, int argc, char **argv); int ccnet_processor_startl (CcnetProcessor *processor, ...) G_GNUC_NULL_TERMINATED; void ccnet_processor_done (CcnetProcessor *processor, gboolean success); void ccnet_processor_handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); void ccnet_processor_handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); void ccnet_processor_handle_sigchld (CcnetProcessor *processor, int status); void ccnet_processor_error (CcnetProcessor *processor, const char *error_code, const char *error_string); void ccnet_processor_send_request (CcnetProcessor *processor, const char *request); void ccnet_processor_send_request_l (CcnetProcessor *processor, ...) G_GNUC_NULL_TERMINATED; void ccnet_processor_send_update(CcnetProcessor *processor, const char *code, const char *code_msg, const char *content, int clen); void ccnet_processor_send_error_update (CcnetProcessor *processor, const char *code, const char *code_msg); void ccnet_processor_send_response(CcnetProcessor *processor, const char *code, const char *code_msg, const char *content, int clen); void ccnet_processor_keep_alive (CcnetProcessor *processor); /* The thread func should return the result back by return (void *)result; The result will be passed to ProcThreadDoneFunc. In the done func, the caller should check whether processor->delay_shutdown is TRUE. If it is, you should call processor_done(). */ typedef void* (*ProcThreadFunc)(void *data); typedef void (*ProcThreadDoneFunc)(void *result); struct _CcnetJobManager; /* * @job_mgr: the thread pool to create the worker thread. * If it's NULL, processor->session->job_mgr will be used. */ int ccnet_processor_thread_create (CcnetProcessor *processor, struct _CcnetJobManager *job_mgr, ProcThreadFunc func, ProcThreadDoneFunc done_func, void *data); #endif ccnet-6.1.5/net/common/processors/000077500000000000000000000000001317035602700171035ustar00rootroot00000000000000ccnet-6.1.5/net/common/processors/echo-proc.c000066400000000000000000000052611317035602700211320ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "peer.h" #include "session.h" #include "echo-proc.h" #define DEBUG_FLAG CCNET_DEBUG_PROCESSOR #include "log.h" #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_ECHO_PROC, CcnetEchoProcPriv)) G_DEFINE_TYPE (CcnetEchoProc, ccnet_echo_proc, CCNET_TYPE_PROCESSOR); static int echo_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { /* should always chain up */ CCNET_PROCESSOR_CLASS(ccnet_echo_proc_parent_class)->release_resource (processor); } static void echo_shutdown (CcnetProcessor *processor) { /* The processor is shutdown. */ /* the release_resource() will be called after calling shutdown(), * so only do things that release_resource() does not do. */ /* Do not chain up here. */ } static void ccnet_echo_proc_class_init (CcnetEchoProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "echo-proc"; proc_class->start = echo_start; proc_class->handle_response = handle_response; proc_class->shutdown = echo_shutdown; proc_class->release_resource = release_resource; } static void ccnet_echo_proc_init (CcnetEchoProc *processor) { } static int echo_start (CcnetProcessor *processor, int argc, char **argv) { if (IS_SLAVE(processor)) { char buf[256]; int len; len = sprintf (buf, "%s %s", processor->session->base.name, processor->session->base.id); ccnet_processor_send_response (processor, "300", "", buf, len + 1); return 0; } ccnet_processor_send_request (processor, "echo"); return 0; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (memcmp(code, "300", 3) == 0) { if (content[clen-1] != '\0') { ccnet_processor_done (processor, FALSE); return; } fprintf (stderr, "Receive echo response: %s\n", content); ccnet_processor_done (processor, TRUE); } else { /* code and code_msg are ended with '\0' */ ccnet_warning ("Bad response from peer %s(%.8s), %s:%s\n", processor->peer->name, processor->peer->id, code, code_msg); ccnet_processor_done (processor, FALSE); } } ccnet-6.1.5/net/common/processors/echo-proc.h000066400000000000000000000021331317035602700211320ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_ECHO_PROC_H #define CCNET_ECHO_PROC_H #include #include "processor.h" #define CCNET_TYPE_ECHO_PROC (ccnet_echo_proc_get_type ()) #define CCNET_ECHO_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_ECHO_PROC, CcnetEchoProc)) #define CCNET_IS_ECHO_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_ECHO_PROC)) #define CCNET_ECHO_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_ECHO_PROC, CcnetEchoProcClass)) #define CCNET_IS_ECHO_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_ECHO_PROC)) #define CCNET_ECHO_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_ECHO_PROC, CcnetEchoProcClass)) typedef struct _CcnetEchoProc CcnetEchoProc; typedef struct _CcnetEchoProcClass CcnetEchoProcClass; struct _CcnetEchoProc { CcnetProcessor parent_instance; }; struct _CcnetEchoProcClass { CcnetProcessorClass parent_class; }; GType ccnet_echo_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/getpubinfo-proc.c000066400000000000000000000036411317035602700223560ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "peer.h" #include "getpubinfo-proc.h" #define DEBUG_FLAG CCNET_DEBUG_CONNECTION #include "log.h" /* * get peer's public info */ static int get_pubinfo_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetGetpubinfoProc, ccnet_getpubinfo_proc, CCNET_TYPE_PROCESSOR) static void ccnet_getpubinfo_proc_class_init (CcnetGetpubinfoProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ proc_class->name = "getpubinfo-proc"; proc_class->start = get_pubinfo_start; proc_class->handle_response = handle_response; } static void ccnet_getpubinfo_proc_init (CcnetGetpubinfoProc *processor) { } static int get_pubinfo_start (CcnetProcessor *processor, int argc, char **argv) { ccnet_processor_send_request (processor, "put-pubinfo"); return 0; } static void parse_pubinfo (CcnetProcessor *processor, char *content, int clen) { g_return_if_fail (content[clen-1] == '\0'); ccnet_peer_update_from_string (processor->peer, content); } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (code[0] != '2') { ccnet_warning ("[Getpubinfo] Receive bad response %s: %s\n", code, code_msg); ccnet_processor_done (processor, FALSE); return; } parse_pubinfo (processor, content, clen); ccnet_processor_done (processor, TRUE); } ccnet-6.1.5/net/common/processors/getpubinfo-proc.h000066400000000000000000000023521317035602700223610ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_GETPUBINFO_PROC_H #define CCNET_GETPUBINFO_PROC_H #include #include "processor.h" #define CCNET_TYPE_GETPUBINFO_PROC (ccnet_getpubinfo_proc_get_type ()) #define CCNET_GETPUBINFO_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_GETPUBINFO_PROC, CcnetGetpubinfoProc)) #define CCNET_IS_GETPUBINFO_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_GETPUBINFO_PROC)) #define CCNET_GETPUBINFO_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_GETPUBINFO_PROC, CcnetGetpubinfoProcClass)) #define CCNET_IS_GETPUBINFO_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_GETPUBINFO_PROC)) #define CCNET_GETPUBINFO_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_GETPUBINFO_PROC, CcnetGetpubinfoProcClass)) typedef struct _CcnetGetpubinfoProc CcnetGetpubinfoProc; typedef struct _CcnetGetpubinfoProcClass CcnetGetpubinfoProcClass; struct _CcnetGetpubinfoProc { CcnetProcessor parent_instance; }; struct _CcnetGetpubinfoProcClass { CcnetProcessorClass parent_class; }; GType ccnet_getpubinfo_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/keepalive-proc.c000066400000000000000000000603671317035602700221710ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include #include "keepalive-proc.h" #include "peer.h" #include "session.h" #include "peer-mgr.h" #include "processor.h" #include "proc-factory.h" #include "timer.h" #include "rsa.h" #include "string-util.h" #include "utils.h" #define DEBUG_FLAG CCNET_DEBUG_CONNECTION #include "log.h" /* Since we use only tcp, packet should not be lost, MAX_NUM_RETRY set to 1, and set a large time (3min). */ #define KEEPALIVE_INTERVAL 180000 /* 3min */ #define MAX_NUM_RETRY 1 #define MY_VERSION 2 /* Select the version according to version used in the other peer. * -1 if v_other is not supported. */ static int get_used_version(int v_other) { if (v_other != 2) return -1; return 2; } enum { INIT, WAIT_PUBKEY, WAIT_CHALLENGE, WAIT_KEEPALIVE, WAIT_PUBKEY_USER, WAIT_CHALLENGE_USER, FULL }; /* protocol v1: state keepalive v2 INIT -----------------> x (packet loss) <----------------- start keepalive OK v2 310 WAIT_PUBKEY -----------------> (optional) <----------------- 311 random_buf WAIT_CHALLENGE -----------------> <----------------- 320 WAIT_PUBKEY_USER -----------------> (optional) <----------------- 321 random_buf WAIT_CHALLENGE_USER -----------------> <----------------- 300 auth-state WAIT_KEEPALIVE -----------------> <----------------- OK FULL (keepalive interval) 300 auth-state WAIT_KEEPALIVE -----------------> <----------------- OK FULL (keepalive interval) .... */ #define SC_BAD_KEEPALIVE "400" #define SS_BAD_KEEPALIVE "Bad keepalive format" #define SC_BAD_CHALLENGE "411" #define SS_BAD_CHALLENGE "Bad challenge format" #define SC_DECRYPT_ERROR "412" #define SS_DECRYPT_ERROR "Decrypt error" typedef struct { unsigned char random_buf[40]; int used_version; int count; } CcnetKeepaliveProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_KEEPALIVE_PROC, CcnetKeepaliveProcPriv)) #define USE_PRIV CcnetKeepaliveProcPriv *priv = GET_PRIV (processor); G_DEFINE_TYPE (CcnetKeepaliveProc, ccnet_keepalive_proc, CCNET_TYPE_PROCESSOR) static int keepalive_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void reset_timeout(CcnetProcessor *processor); static void proc_shutdown (CcnetProcessor *processor) { CcnetPeer *peer = processor->peer; if (IS_SLAVE(processor)) return; if (peer->net_state == PEER_INDIRECT) { /* In indirect connection, we may receive SC_PROC_DEAD, * which cause shutdown be called. */ /* detach from the peer */ ccnet_peer_remove_processor (processor->peer, processor); ccnet_peer_shutdown (peer); peer->num_fails++; } else { /* Otherwise the shutdown of keepalive is only be called in * peer shutdown */ } } static void release_resource(CcnetProcessor *processor) { processor->peer->keepalive_sending = 0; /* should always chain up */ CCNET_PROCESSOR_CLASS(ccnet_keepalive_proc_parent_class)->release_resource (processor); } static void ccnet_keepalive_proc_class_init (CcnetKeepaliveProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "keepalive-proc"; proc_class->start = keepalive_start; proc_class->handle_response = handle_response; proc_class->handle_update = handle_update; proc_class->shutdown = proc_shutdown; proc_class->release_resource = release_resource; g_type_class_add_private (klass, sizeof(CcnetKeepaliveProcPriv)); } static void ccnet_keepalive_proc_init (CcnetKeepaliveProc *processor) { } static void send_keepalive(CcnetProcessor *processor) { USE_PRIV; CcnetPeer *peer = processor->peer; CcnetUser *user = ccnet_peer_get_user(peer); GString *buf = g_string_new(NULL); GString *cntstr = g_string_new(NULL); g_string_append_printf(cntstr, "%d", priv->count++); g_string_append_printf (buf, "timestamp %"G_GINT64_FORMAT"\n", processor->session->timestamp); if (user) g_string_append_printf (buf, "role-timestamp %"G_GINT64_FORMAT"\n", user->myrole_timestamp); ccnet_processor_send_update (processor, "300", cntstr->str, buf->str, buf->len + 1); /* ccnet_debug ("[Keepalive] Send keepavlie to peer %.8s #%s\n", */ /* processor->peer->id, cntstr->str); */ g_string_free (buf, TRUE); g_string_free (cntstr, TRUE); processor->state = WAIT_KEEPALIVE; } static void send_request(CcnetProcessor *processor) { char buf[64]; snprintf (buf, 64, "keepalive v%d", MY_VERSION); ccnet_processor_send_request (processor, buf); } static void close_processor_in_timeout(CcnetProcessor *processor) { CcnetPeer *peer = processor->peer; ccnet_debug ("[Conn] keepalive timeout current state is %d\n", processor->state); ccnet_processor_done (processor, FALSE); ccnet_peer_shutdown (peer); peer->num_fails++; } static int timeout_cb(CcnetProcessor *processor) { /* Since we set MAX_NUM_RETRY to 1, actually, there will be no retry. */ if (processor->state == INIT) { if (++processor->num_retry < MAX_NUM_RETRY) { send_request(processor); return TRUE; } else { close_processor_in_timeout(processor); return FALSE; } } if (processor->state == WAIT_PUBKEY || processor->state == WAIT_CHALLENGE) { close_processor_in_timeout(processor); return FALSE; } if (processor->state == WAIT_KEEPALIVE) { if (++processor->num_retry < MAX_NUM_RETRY) { send_keepalive (processor); return TRUE; } else { close_processor_in_timeout(processor); return FALSE; } } if (processor->state == FULL) { processor->num_retry = 0; send_keepalive(processor); return TRUE; } return FALSE; } static void reset_timeout(CcnetProcessor *processor) { if (processor->retry_timer) ccnet_timer_free(&processor->retry_timer); processor->retry_timer = ccnet_timer_new ((TimerCB)timeout_cb, processor, KEEPALIVE_INTERVAL); } static void close_processor(CcnetProcessor *processor) { CcnetPeer *peer = processor->peer; ccnet_timer_free (&processor->retry_timer); ccnet_processor_done (processor, FALSE); ccnet_peer_shutdown (peer); peer->num_fails++; } static int keepalive_start (CcnetProcessor *processor, int argc, char **argv) { CcnetKeepaliveProcPriv *priv = GET_PRIV (processor); if (IS_SLAVE(processor)) { char buf[16]; int v, len; if (argc == 0) { priv->used_version = 0; ccnet_processor_send_response (processor, SC_VERSION_MISMATCH, SS_VERSION_MISMATCH, NULL, 0); ccnet_processor_done (processor, FALSE); return 0; } else { v = get_version(argv[0]); if ((priv->used_version = get_used_version(v)) == -1) { ccnet_processor_send_response (processor, SC_VERSION_MISMATCH, SS_VERSION_MISMATCH, NULL, 0); ccnet_processor_done (processor, FALSE); return 0; } len = snprintf (buf, 16, "v%d", priv->used_version); ccnet_processor_send_response (processor, SC_OK, SS_OK, buf, len + 1); return 0; } } /* master */ priv->count = 0; processor->state = INIT; processor->peer->keepalive_sending = 1; send_request (processor); reset_timeout (processor); return 0; } struct Handler { const char *code; void (*handler) (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); }; struct Handler * get_handler (char *code, struct Handler *tab) { struct Handler *c; for (c = tab; c->code; c++) { if (c->code[0] == code[0] && c->code[1] == code[1] && c->code[2] == code[2]) return c; } return NULL; } static void recv_keepalive_rsp(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void recv_ok(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void recv_pubkey(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void verify_challenge(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void recv_pubkey_user(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void verify_challenge_user(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static struct Handler rsp_handler_tab[] = { { "200", recv_ok }, { "300", recv_keepalive_rsp }, { "310", recv_pubkey }, { "311", verify_challenge }, { "320", recv_pubkey_user }, { "321", verify_challenge_user }, { 0 }, }; static void send_challenge(CcnetProcessor *processor) { CcnetKeepaliveProcPriv *priv = GET_PRIV (processor); ccnet_debug ("[Keepalive] Send peer challenge to %s(%.8s)\n", processor->peer->name, processor->peer->id); CcnetPeer *peer = processor->peer; unsigned char *buf; int len; RAND_pseudo_bytes (priv->random_buf, 40); buf = public_key_encrypt (peer->pubkey, priv->random_buf, 40, &len); ccnet_processor_send_update (processor, "311", NULL, (char *)buf, len); g_free(buf); processor->state = WAIT_CHALLENGE; reset_timeout (processor); } static void get_pubkey(CcnetProcessor *processor) { ccnet_processor_send_update (processor, "310", NULL, NULL, 0); processor->state = WAIT_PUBKEY; reset_timeout(processor); } static void get_pubkey_user(CcnetProcessor *processor) { ccnet_processor_send_update (processor, "320", NULL, NULL, 0); processor->state = WAIT_PUBKEY_USER; reset_timeout(processor); } static void send_challenge_user(CcnetProcessor *processor, CcnetUser *user) { CcnetKeepaliveProcPriv *priv = GET_PRIV (processor); unsigned char *buf; int len; ccnet_debug ("[Keepalive] Send user challenge to %.8s\n", processor->peer->id); RAND_pseudo_bytes (priv->random_buf, 40); buf = public_key_encrypt (user->pubkey, priv->random_buf, 40, &len); ccnet_processor_send_update (processor, "321", NULL, (char *)buf, len); g_free(buf); processor->state = WAIT_CHALLENGE_USER; reset_timeout (processor); } static void recv_ok(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { USE_PRIV; if (processor->state != INIT) { close_processor(processor); return; } /* check version */ if (clen != 0) { int v = get_version(content); if ((priv->used_version = get_used_version(v)) == -1) { ccnet_processor_send_error_update(processor, SC_VERSION_MISMATCH, SS_VERSION_MISMATCH); close_processor(processor); return; } } else { ccnet_processor_send_error_update(processor, SC_VERSION_MISMATCH, SS_VERSION_MISMATCH); close_processor(processor); return; } if (processor->peer->net_state == PEER_DOWN) ccnet_peer_set_net_state (processor->peer, PEER_INDIRECT); if (processor->peer->pubkey) send_challenge(processor); else get_pubkey(processor); } static void recv_pubkey(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (clen == 0 || content[clen-1] != '\0') { ccnet_debug ("[Conn] Bad public key format\n"); close_processor (processor); return; } ccnet_peer_set_pubkey (processor->peer, content); if (processor->peer->pubkey == NULL) { ccnet_debug ("[Conn] Bad public key format\n"); close_processor (processor); return; } send_challenge (processor); } static void recv_keepalive_rsp(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { /* ccnet_debug ("[Keepalive] Receive keepalive responese from peer %.8s #%s\n", */ /* processor->peer->id, code_msg); */ processor->state = FULL; if (processor->peer->net_state == PEER_CONNECTED && processor->peer->num_fails > 0) processor->peer->num_fails--; } static void verify_challenge(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetKeepaliveProcPriv *priv = GET_PRIV (processor); ccnet_debug ("[Conn] Verify Peer Challenge\n"); if (clen != 40 || memcmp(content, priv->random_buf, 40) != 0) { ccnet_debug ("[Conn] Peer Challenge failed\n"); close_processor(processor); return; } CcnetUser *user = ccnet_peer_get_user(processor->peer); if (!user) { ccnet_debug ("[Conn] No user for this peer, go to auth done\n"); processor->peer->auth_done = 1; g_signal_emit_by_name (processor->peer, "auth-done"); send_keepalive (processor); reset_timeout (processor); return; } if (user->pubkey) send_challenge_user(processor, user); else get_pubkey_user(processor); } static void recv_pubkey_user(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (clen == 0 || content[clen-1] != '\0') { ccnet_debug ("[Conn] Bad public key format\n"); close_processor (processor); return; } CcnetUser *user = ccnet_peer_get_user(processor->peer); ccnet_user_set_pubkey (user, content); if (user->pubkey == NULL) { ccnet_debug ("[Conn] Bad public key format\n"); close_processor (processor); return; } send_challenge_user (processor, user); } static void verify_challenge_user(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetKeepaliveProcPriv *priv = GET_PRIV (processor); ccnet_debug ("[Conn] Verify User Challenge\n"); if (clen != 40 || memcmp(content, priv->random_buf, 40) != 0) { ccnet_debug ("[Keepalive] Challenge failed\n"); close_processor(processor); return; } processor->peer->auth_done = 1; g_signal_emit_by_name (processor->peer, "auth-done"); send_keepalive (processor); reset_timeout (processor); } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (code[0] == '4' || code[0] == '5') { ccnet_warning ("[Keepalive] Error from peer %s %s\n", code, code_msg); close_processor (processor); return; } struct Handler *handler = get_handler(code, rsp_handler_tab); if (!handler) { ccnet_processor_send_update (processor, SC_BAD_RESPONSE_CODE, SS_BAD_RESPONSE_CODE, NULL, 0); close_processor (processor); return; } handler->handler(processor, code, code_msg, content, clen); } /* static void start_keepalive (CcnetProcFactory *factory, CcnetPeer *peer) { CcnetProcessor *processor; processor = ccnet_proc_factory_create_master_processor ( factory, "keepalive", peer); if (processor == NULL) { ccnet_warning ("Create keepalive processor failed\n"); return; } ccnet_processor_startl (processor, NULL); } */ /* update handle */ static void receive_keepalive(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void send_pubkey(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void response_challenge(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void send_pubkey_user(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void response_challenge_user(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static struct Handler update_handler_tab[] = { { "300", receive_keepalive }, { "310", send_pubkey }, { "311", response_challenge }, { "320", send_pubkey_user }, { "321", response_challenge_user }, { 0 }, }; static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (code[0] == '4' || code[0] == '5') { ccnet_warning ("[Keepalive] Error from peer %s %s\n", code, code_msg); ccnet_processor_done(processor, FALSE); return; } struct Handler *handler = get_handler(code, update_handler_tab); if (!handler) { ccnet_processor_send_response (processor, SC_BAD_UPDATE_CODE, SS_BAD_UPDATE_CODE, NULL, 0); ccnet_processor_done(processor, FALSE); return; } handler->handler(processor, code, code_msg, content, clen); } static void get_peer_pubinfo (CcnetPeer *peer) { CcnetProcessor *newp; CcnetProcFactory *factory = peer->manager->session->proc_factory; newp = ccnet_proc_factory_create_master_processor (factory, "get-pubinfo", peer); if (newp == NULL) { ccnet_warning ("Create get pubinfo processor failed\n"); return; } ccnet_processor_startl (newp, NULL); } static void get_user_pubinfo (CcnetPeer *peer) { CcnetProcessor *newp; CcnetProcFactory *factory = peer->manager->session->proc_factory; newp = ccnet_proc_factory_create_master_processor (factory, "get-user", peer); if (newp == NULL) { ccnet_warning ("Create get user info processor failed\n"); return; } ccnet_processor_startl (newp, NULL); } static void update_from_key_value (void *vpeer, const char *key, const char *value) { CcnetPeer *peer = vpeer; if (strcmp(key, "timestamp") == 0) { gint64 timestamp = g_ascii_strtoll(value, NULL, 10); if (timestamp > peer->timestamp) get_peer_pubinfo (peer); CcnetUser *user = ccnet_peer_get_user(peer); if (!user || timestamp > user->timestamp) get_user_pubinfo (peer); } if (strcmp(key, "role-timestamp") == 0) { CcnetUser *user = ccnet_peer_get_user(peer); if (!user) return; gint64 timestamp = g_ascii_strtoll (value, NULL, 10); if (timestamp < user->role_timestamp) { ccnet_peer_manager_notify_peer_role (peer->manager, peer); } } } static void receive_keepalive(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetPeer *peer = processor->peer; if (clen == 0 || content[clen-1] != '\0' || content[clen-2] != '\n') { ccnet_processor_send_response ( processor, SC_BAD_KEEPALIVE, SS_BAD_KEEPALIVE, NULL, 0); ccnet_processor_done (processor, FALSE); return; } parse_key_value_pairs (content, update_from_key_value, peer); /* ccnet_debug ("[Keepalive] Receive keepalive from %.8s #%s\n", */ /* processor->peer->id, code_msg); */ ccnet_processor_send_response ( processor, code, code_msg, NULL, 0); /* Peer discovered us, so we try to discover peer too. * Used in indirect connection vie Relay */ /* if (peer->net_state == PEER_DOWN && peer->relay_list != NULL) { if (!peer->keepalive_sending) start_keepalive (processor->session->proc_factory, peer); } */ } static void send_pubkey(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { GString *str; str = public_key_to_gstring(processor->session->pubkey); ccnet_processor_send_response (processor, code, "", str->str, str->len+1); } static void response_challenge(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { unsigned char *buf; int decrypt_len; if (clen == 0) { ccnet_warning("Peer %s(%.8s) send bad format challenge\n", processor->peer->name, processor->peer->id); ccnet_processor_send_response ( processor, SC_BAD_CHALLENGE, SS_BAD_CHALLENGE, NULL, 0); ccnet_processor_done(processor, FALSE); return; } buf = private_key_decrypt(processor->session->privkey, (unsigned char *)content, clen, &decrypt_len); if (decrypt_len < 0) { ccnet_processor_send_response ( processor, SC_DECRYPT_ERROR, SS_DECRYPT_ERROR, NULL, 0); ccnet_processor_done(processor, FALSE); } else ccnet_processor_send_response ( processor, code, "", (char *)buf, decrypt_len); g_free(buf); } static void send_pubkey_user(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { GString *str; str = public_key_to_gstring(processor->session->user_pubkey); ccnet_processor_send_response (processor, code, "", str->str, str->len+1); } static void response_challenge_user(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { unsigned char *buf; int decrypt_len; if (clen == 0) { ccnet_warning("Peer %s(%.8s) send bad format challenge\n", processor->peer->name, processor->peer->id); ccnet_processor_send_response ( processor, SC_BAD_CHALLENGE, SS_BAD_CHALLENGE, NULL, 0); ccnet_processor_done(processor, FALSE); return; } buf = private_key_decrypt(processor->session->user_privkey, (unsigned char *)content, clen, &decrypt_len); if (decrypt_len < 0) { ccnet_processor_send_response ( processor, SC_DECRYPT_ERROR, SS_DECRYPT_ERROR, NULL, 0); ccnet_processor_done(processor, FALSE); } else ccnet_processor_send_response ( processor, code, "", (char *)buf, decrypt_len); g_free(buf); } ccnet-6.1.5/net/common/processors/keepalive-proc.h000066400000000000000000000023261317035602700221650ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_GETPEERINFO_PROC_H #define CCNET_GETPEERINFO_PROC_H #include #include "processor.h" #define CCNET_TYPE_KEEPALIVE_PROC (ccnet_keepalive_proc_get_type ()) #define CCNET_KEEPALIVE_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_KEEPALIVE_PROC, CcnetKeepaliveProc)) #define CCNET_IS_KEEPALIVE_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_KEEPALIVE_PROC)) #define CCNET_KEEPALIVE_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_KEEPALIVE_PROC, CcnetKeepaliveProcClass)) #define CCNET_IS_KEEPALIVE_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_KEEPALIVE_PROC)) #define CCNET_KEEPALIVE_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_KEEPALIVE_PROC, CcnetKeepaliveProcClass)) typedef struct _CcnetKeepaliveProc CcnetKeepaliveProc; typedef struct _CcnetKeepaliveProcClass CcnetKeepaliveProcClass; struct _CcnetKeepaliveProc { CcnetProcessor parent_instance; }; struct _CcnetKeepaliveProcClass { CcnetProcessorClass parent_class; }; GType ccnet_keepalive_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/keepalive2-proc.c000066400000000000000000000413371317035602700222470ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include #include "keepalive2-proc.h" #include "peer.h" #include "session.h" #include "peer-mgr.h" #include "processor.h" #include "proc-factory.h" #include "timer.h" #include "rsa.h" #include "string-util.h" #include "utils.h" #define DEBUG_FLAG CCNET_DEBUG_CONNECTION #include "log.h" /* Since we use only tcp, packet should not be lost, set a large time (3min). */ #define KEEPALIVE_INTERVAL 180000 /* 3min */ enum { INIT, WAIT_PUBKEY, WAIT_CHALLENGE, WAIT_KEEPALIVE, FULL }; /* protocol: state keepalive2 INIT -----------------> <----------------- start keepalive OK 310 WAIT_PUBKEY -----------------> (optional) <----------------- 311 random_buf WAIT_CHALLENGE -----------------> <----------------- 300 WAIT_KEEPALIVE -----------------> <----------------- OK FULL (keepalive interval) 300 WAIT_KEEPALIVE -----------------> <----------------- OK FULL (keepalive interval) .... */ #define SC_BAD_KEEPALIVE "400" #define SS_BAD_KEEPALIVE "Bad keepalive format" #define SC_BAD_CHALLENGE "411" #define SS_BAD_CHALLENGE "Bad challenge format" #define SC_DECRYPT_ERROR "412" #define SS_DECRYPT_ERROR "Decrypt error" typedef struct { unsigned char random_buf[40]; int count; } CcnetKeepalive2ProcPriv; extern CcnetSession *session; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_KEEPALIVE2_PROC, CcnetKeepalive2ProcPriv)) #define USE_PRIV CcnetKeepalive2ProcPriv *priv = GET_PRIV (processor); G_DEFINE_TYPE (CcnetKeepalive2Proc, ccnet_keepalive2_proc, CCNET_TYPE_PROCESSOR) static int keepalive2_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void reset_timeout(CcnetProcessor *processor); static void get_peer_pubinfo (CcnetPeer *peer); static void proc_shutdown (CcnetProcessor *processor) { CcnetPeer *peer = processor->peer; if (IS_SLAVE(processor)) return; /* The shutdown of keepalive is only be called in * peer shutdown */ /* g_assert (peer->in_shutdown); */ if (!peer->in_shutdown) ccnet_warning ("Shutdown keepalive is not called from peer_shutdown\n"); } static void release_resource(CcnetProcessor *processor) { processor->peer->keepalive_sending = 0; /* should always chain up */ CCNET_PROCESSOR_CLASS(ccnet_keepalive2_proc_parent_class)->release_resource (processor); } static void ccnet_keepalive2_proc_class_init (CcnetKeepalive2ProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "keepalive2-proc"; proc_class->start = keepalive2_start; proc_class->handle_response = handle_response; proc_class->handle_update = handle_update; proc_class->shutdown = proc_shutdown; proc_class->release_resource = release_resource; g_type_class_add_private (klass, sizeof(CcnetKeepalive2ProcPriv)); } static void ccnet_keepalive2_proc_init (CcnetKeepalive2Proc *processor) { } static void send_keepalive(CcnetProcessor *processor) { USE_PRIV; char cntstr[64]; sprintf(cntstr, "%d", priv->count++); ccnet_processor_send_update (processor, "300", cntstr, NULL, 0); /* ccnet_debug ("[Keepalive] Send keepavlie to peer %.8s #%s\n", */ /* processor->peer->id, cntstr->str); */ processor->state = WAIT_KEEPALIVE; } static void send_request(CcnetProcessor *processor) { char buf[64]; snprintf (buf, 64, "keepalive2"); ccnet_processor_send_request (processor, buf); } static void close_processor_in_timeout(CcnetProcessor *processor) { CcnetPeer *peer = processor->peer; ccnet_debug ("[Conn] keepalive timeout current state is %d\n", processor->state); ccnet_processor_done (processor, FALSE); ccnet_peer_shutdown (peer); peer->num_fails++; } static int timeout_cb(CcnetProcessor *processor) { if (processor->state == FULL) { send_keepalive(processor); return TRUE; } close_processor_in_timeout(processor); return FALSE; } static void reset_timeout(CcnetProcessor *processor) { if (processor->retry_timer) ccnet_timer_free(&processor->retry_timer); processor->retry_timer = ccnet_timer_new ((TimerCB)timeout_cb, processor, KEEPALIVE_INTERVAL); } static void close_processor(CcnetProcessor *processor) { CcnetPeer *peer = processor->peer; ccnet_timer_free (&processor->retry_timer); ccnet_processor_done (processor, FALSE); ccnet_peer_shutdown (peer); peer->num_fails++; } static int keepalive2_start (CcnetProcessor *processor, int argc, char **argv) { CcnetKeepalive2ProcPriv *priv = GET_PRIV (processor); if (IS_SLAVE(processor)) { ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } /* master */ priv->count = 0; processor->state = INIT; processor->peer->keepalive_sending = 1; send_request (processor); reset_timeout (processor); return 0; } struct Handler { const char *code; void (*handler) (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); }; struct Handler * get_handler (char *code, struct Handler *tab) { struct Handler *c; for (c = tab; c->code; c++) { if (c->code[0] == code[0] && c->code[1] == code[1] && c->code[2] == code[2]) return c; } return NULL; } static void recv_keepalive_rsp(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void recv_ok(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void recv_pubkey(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void verify_challenge(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static struct Handler rsp_handler_tab[] = { { "200", recv_ok }, { "300", recv_keepalive_rsp }, { "310", recv_pubkey }, { "311", verify_challenge }, { 0 }, }; static void send_challenge(CcnetProcessor *processor) { CcnetKeepalive2ProcPriv *priv = GET_PRIV (processor); ccnet_debug ("[Keepalive] Before send challenge, check valid of id\n"); char *id = id_from_pubkey(processor->peer->pubkey); if (g_strcmp0(id, processor->peer->id) != 0) { ccnet_debug ("[Keepalive] Peer id not conform to public key: %s %s\n", id, processor->peer->id); close_processor (processor); g_free (id); return; } g_free (id); ccnet_debug ("[Keepalive] Send peer challenge to %s(%.8s)\n", processor->peer->name, processor->peer->id); CcnetPeer *peer = processor->peer; unsigned char *buf; int len; RAND_pseudo_bytes (priv->random_buf, 40); buf = public_key_encrypt (peer->pubkey, priv->random_buf, 40, &len); if (len < 0) { ccnet_debug ("[Keepalive] Failed to encrypt challenge " "with peer %s(%.8s)'s pubkey\n", peer->name, peer->id); close_processor (processor); g_free (buf); return; } ccnet_processor_send_update (processor, "311", NULL, (char *)buf, len); g_free(buf); processor->state = WAIT_CHALLENGE; reset_timeout (processor); } static void get_pubkey(CcnetProcessor *processor) { ccnet_processor_send_update (processor, "310", NULL, NULL, 0); processor->state = WAIT_PUBKEY; reset_timeout(processor); } static void recv_ok(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (processor->state != INIT) { close_processor(processor); return; } if (processor->peer->pubkey) { ccnet_debug ("[Keepalive] Receive ok, send challenge\n"); send_challenge(processor); } else { ccnet_debug ("[Keepalive] Receive ok, get pubkey\n"); get_pubkey(processor); } } static void recv_pubkey(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (processor->state != WAIT_PUBKEY) { ccnet_debug ("[Keepalive] Receive public key not in WAIT_PUBKEY state\n"); close_processor (processor); return; } if (clen == 0 || content[clen-1] != '\0') { ccnet_debug ("[Keepalive] Bad public key format\n"); close_processor (processor); return; } ccnet_peer_set_pubkey (processor->peer, content); if (processor->peer->pubkey == NULL) { ccnet_debug ("[Keepalive] Bad public key format\n"); close_processor (processor); return; } ccnet_debug ("[Keepalive] Receive pubkey, send challenge\n"); send_challenge (processor); } static void recv_keepalive_rsp(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { /* ccnet_debug ("[Keepalive] Receive keepalive responese from peer %.8s #%s\n", */ /* processor->peer->id, code_msg); */ processor->state = FULL; } static void on_send_skey_done (CcnetProcessor *processor, gboolean success, void *data) { if (!success && !processor->peer->in_shutdown) { /* try the old version */ CcnetProcessor *p; CcnetProcFactory *factory = processor->session->proc_factory; CcnetPeer *peer = processor->peer; if (peer->session_key) { ccnet_warning ("peer %s already has session key\n", peer->id); return; } p = ccnet_proc_factory_create_master_processor ( factory, "send-session-key", peer); if (!p) { ccnet_warning ("create send session key processor failed\n"); return; } if (ccnet_processor_startl (p, NULL) < 0) { ccnet_warning ("start send session key processor failed\n"); return; } } } static void send_session_key (CcnetPeer *peer) { CcnetProcessor *processor; CcnetProcFactory *factory = peer->manager->session->proc_factory; if (peer->session_key) { ccnet_warning ("peer %s already has session key\n", peer->id); return; } processor = ccnet_proc_factory_create_master_processor ( factory, "send-skey2", peer); if (!processor) { ccnet_warning ("create send session key processor failed\n"); return; } g_signal_connect (processor, "done", G_CALLBACK(on_send_skey_done), NULL); if (ccnet_processor_startl (processor, NULL) < 0) { ccnet_warning ("start send session key processor failed\n"); return; } } static void verify_challenge(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetKeepalive2ProcPriv *priv = GET_PRIV (processor); if (clen != 40 || memcmp(content, priv->random_buf, 40) != 0) { ccnet_debug ("[Conn] Peer Challenge failed\n"); close_processor(processor); return; } ccnet_debug ("[Keepalive] Verify Peer Challenge\n"); get_peer_pubinfo (processor->peer); /* ccnet_peer_manager_notify_peer_role (processor->peer->manager, */ /* processor->peer); */ if (strcmp(session->base.id, processor->peer->id) < 0) send_session_key (processor->peer); send_keepalive (processor); reset_timeout (processor); return; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (code[0] == '4' || code[0] == '5') { ccnet_warning ("[Keepalive] Error from peer %s %s\n", code, code_msg); close_processor (processor); return; } struct Handler *handler = get_handler(code, rsp_handler_tab); if (!handler) { ccnet_processor_send_update (processor, SC_BAD_RESPONSE_CODE, SS_BAD_RESPONSE_CODE, NULL, 0); close_processor (processor); return; } handler->handler(processor, code, code_msg, content, clen); } /* update handle */ static void receive_keepalive(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void send_pubkey(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void response_challenge(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static struct Handler update_handler_tab[] = { { "300", receive_keepalive }, { "310", send_pubkey }, { "311", response_challenge }, { 0 }, }; static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (code[0] == '4' || code[0] == '5') { ccnet_warning ("[Keepalive] Error from peer %s %s\n", code, code_msg); ccnet_processor_done(processor, FALSE); return; } struct Handler *handler = get_handler(code, update_handler_tab); if (!handler) { ccnet_processor_send_response (processor, SC_BAD_UPDATE_CODE, SS_BAD_UPDATE_CODE, NULL, 0); ccnet_processor_done(processor, FALSE); return; } handler->handler(processor, code, code_msg, content, clen); } static void get_peer_pubinfo (CcnetPeer *peer) { CcnetProcessor *newp; CcnetProcFactory *factory = peer->manager->session->proc_factory; newp = ccnet_proc_factory_create_master_processor (factory, "get-pubinfo", peer); if (newp == NULL) { ccnet_warning ("Create get pubinfo processor failed\n"); return; } ccnet_processor_startl (newp, NULL); } static void receive_keepalive(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { /* ccnet_debug ("[Keepalive] Receive keepalive from %.8s #%s\n", */ /* processor->peer->id, code_msg); */ ccnet_processor_send_response ( processor, code, code_msg, NULL, 0); } static void send_pubkey(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { GString *str; str = public_key_to_gstring(processor->session->pubkey); ccnet_processor_send_response (processor, code, "", str->str, str->len+1); } static void response_challenge(CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { unsigned char *buf; int decrypt_len; if (clen == 0) { ccnet_warning("Peer %s(%.8s) send bad format challenge\n", processor->peer->name, processor->peer->id); ccnet_processor_send_response ( processor, SC_BAD_CHALLENGE, SS_BAD_CHALLENGE, NULL, 0); ccnet_processor_done(processor, FALSE); return; } buf = private_key_decrypt(processor->session->privkey, (unsigned char *)content, clen, &decrypt_len); if (decrypt_len < 0) { ccnet_processor_send_response ( processor, SC_DECRYPT_ERROR, SS_DECRYPT_ERROR, NULL, 0); ccnet_processor_done(processor, FALSE); } else ccnet_processor_send_response ( processor, code, "", (char *)buf, decrypt_len); g_free(buf); } ccnet-6.1.5/net/common/processors/keepalive2-proc.h000066400000000000000000000023521317035602700222460ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_KEEPALIVE2_PROC_H #define CCNET_KEEPALIVE2_PROC_H #include #include "processor.h" #define CCNET_TYPE_KEEPALIVE2_PROC (ccnet_keepalive2_proc_get_type ()) #define CCNET_KEEPALIVE2_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_KEEPALIVE2_PROC, CcnetKeepalive2Proc)) #define CCNET_IS_KEEPALIVE2_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_KEEPALIVE2_PROC)) #define CCNET_KEEPALIVE2_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_KEEPALIVE2_PROC, CcnetKeepalive2ProcClass)) #define CCNET_IS_KEEPALIVE2_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_KEEPALIVE2_PROC)) #define CCNET_KEEPALIVE2_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_KEEPALIVE2_PROC, CcnetKeepalive2ProcClass)) typedef struct _CcnetKeepalive2Proc CcnetKeepalive2Proc; typedef struct _CcnetKeepalive2ProcClass CcnetKeepalive2ProcClass; struct _CcnetKeepalive2Proc { CcnetProcessor parent_instance; }; struct _CcnetKeepalive2ProcClass { CcnetProcessorClass parent_class; }; GType ccnet_keepalive2_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/mqserver-proc.c000066400000000000000000000103141317035602700220530ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "peer.h" #include "message.h" #include "session.h" #include "message-manager.h" #include "mqserver-proc.h" #include "algorithms.h" #define DEBUG_FLAG CCNET_DEBUG_MESSAGE #include "log.h" #define SC_MSG "300" enum { INIT, READY }; typedef struct { int n_app; char **apps; int subscribed : 1; } MqserverProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_MQSERVER_PROC, MqserverProcPriv)) static int mq_server_start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetMqserverProc, ccnet_mqserver_proc, CCNET_TYPE_PROCESSOR) static void subscribe_message (CcnetProcessor *processor) { MqserverProcPriv *priv = GET_PRIV (processor); CcnetMessageManager *msg_mgr = processor->session->msg_mgr; priv->subscribed = 1; ccnet_message_manager_subscribe_app (msg_mgr, processor, priv->n_app, priv->apps); } static void unsubscribe_message (CcnetProcessor *processor) { MqserverProcPriv *priv = GET_PRIV (processor); CcnetMessageManager *msg_mgr = processor->session->msg_mgr; if (priv->subscribed) ccnet_message_manager_unsubscribe_app (msg_mgr, processor, priv->n_app, priv->apps); } static void release_resource (CcnetProcessor *processor) { int i; MqserverProcPriv *priv = GET_PRIV (processor); unsubscribe_message(processor); for (i = 0; i < priv->n_app; ++i) g_free (priv->apps[i]); g_free (priv->apps); memset (priv, 0, sizeof(MqserverProcPriv)); CCNET_PROCESSOR_CLASS(ccnet_mqserver_proc_parent_class)->release_resource(processor); } static void ccnet_mqserver_proc_class_init (CcnetMqserverProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); /* GObjectClass *object_class = G_OBJECT_CLASS (klass); */ proc_class->name = "mqserver-proc"; proc_class->start = mq_server_start; proc_class->handle_update = handle_update; proc_class->release_resource = release_resource; g_type_class_add_private (klass, sizeof (MqserverProcPriv)); } static void ccnet_mqserver_proc_init (CcnetMqserverProc *processor) { } static int mq_server_start (CcnetProcessor *processor, int argc, char **argv) { MqserverProcPriv *priv = GET_PRIV (processor); int i; priv->n_app = argc; priv->apps = g_new (char*, argc); for (i = 0; i < argc; ++i) priv->apps[i] = g_strdup (argv[i]); subscribe_message (processor); ccnet_processor_send_response (processor, "200", "OK", NULL, 0); return 0; } static void send_message (CcnetProcessor *processor, CcnetMessage *message) { GString *buf = g_string_new (NULL); ccnet_message_to_string_buf_local (message, buf); ccnet_processor_send_response (processor, SC_MSG, NULL, buf->str, buf->len+1); g_string_free (buf, TRUE); } void ccnet_mqserver_proc_put_message (CcnetProcessor *processor, CcnetMessage *message) { send_message (processor, message); } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { /* MqserverProcPriv *priv = GET_PRIV (processor); */ /* CcnetMessageManager *msg_mgr = processor->session->messageMgr; */ if (code[0] != '3') { ccnet_warning ("received bad update: %s %s", code, code_msg); return; } if (code[2] == '0') { /* SC_MSG */ CcnetMessage *msg; msg = ccnet_message_from_string_local (content, clen); /* ccnet_debug ("[msg] send msg: %.10s\n", msg->body); */ ccnet_send_message (processor->session, msg); ccnet_message_unref (msg); } else if (code[2] == '1') { /* SC_UNSUBSCRIBE */ ccnet_processor_done (processor, TRUE); return; } ccnet_processor_send_response (processor, "200", "OK", NULL, 0); } ccnet-6.1.5/net/common/processors/mqserver-proc.h000066400000000000000000000025201317035602700220600ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_MQSERVER_PROC_H #define CCNET_MQSERVER_PROC_H #include #include "processor.h" #include "message.h" #define CCNET_TYPE_MQSERVER_PROC (ccnet_mqserver_proc_get_type ()) #define CCNET_MQSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_MQSERVER_PROC, CcnetMqserverProc)) #define CCNET_IS_MQSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_MQSERVER_PROC)) #define CCNET_MQSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_MQSERVER_PROC, CcnetMqserverProcClass)) #define CCNET_IS_MQSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_MQSERVER_PROC)) #define CCNET_MQSERVER_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_MQSERVER_PROC, CcnetMqserverProcClass)) typedef struct _CcnetMqserverProc CcnetMqserverProc; typedef struct _CcnetMqserverProcClass CcnetMqserverProcClass; struct _CcnetMqserverProc { CcnetProcessor parent_instance; }; struct _CcnetMqserverProcClass { CcnetProcessorClass parent_class; }; GType ccnet_mqserver_proc_get_type (); void ccnet_mqserver_proc_put_message (CcnetProcessor *processor, CcnetMessage *message); #endif ccnet-6.1.5/net/common/processors/putpubinfo-proc.c000066400000000000000000000031201317035602700223770ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "peer.h" #include "session.h" #include "putpubinfo-proc.h" #define DEBUG_FLAG CCNET_DEBUG_CONNECTION #include "log.h" static int put_pubinfo_start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetPutpubinfoProc, ccnet_putpubinfo_proc, CCNET_TYPE_PROCESSOR) static void ccnet_putpubinfo_proc_class_init (CcnetPutpubinfoProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ proc_class->name = "putpubinfo-proc"; proc_class->start = put_pubinfo_start; proc_class->handle_update = handle_update; } static void ccnet_putpubinfo_proc_init (CcnetPutpubinfoProc *processor) { } static void put_pubinfo (CcnetProcessor *processor) { GString *str = ccnet_peer_to_string (processor->session->myself); ccnet_processor_send_response (processor, "200", "OK", str->str, str->len+1); ccnet_processor_done (processor, TRUE); g_string_free (str, TRUE); } static int put_pubinfo_start (CcnetProcessor *processor, int argc, char **argv) { put_pubinfo (processor); return 0; } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { return; } ccnet-6.1.5/net/common/processors/putpubinfo-proc.h000066400000000000000000000023521317035602700224120ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_PUTPUBINFO_PROC_H #define CCNET_PUTPUBINFO_PROC_H #include #include "processor.h" #define CCNET_TYPE_PUTPUBINFO_PROC (ccnet_putpubinfo_proc_get_type ()) #define CCNET_PUTPUBINFO_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_PUTPUBINFO_PROC, CcnetPutpubinfoProc)) #define CCNET_IS_PUTPUBINFO_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_PUTPUBINFO_PROC)) #define CCNET_PUTPUBINFO_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_PUTPUBINFO_PROC, CcnetPutpubinfoProcClass)) #define CCNET_IS_PUTPUBINFO_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_PUTPUBINFO_PROC)) #define CCNET_PUTPUBINFO_PROC_PUT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_PUTPUBINFO_PROC, CcnetPutpubinfoProcClass)) typedef struct _CcnetPutpubinfoProc CcnetPutpubinfoProc; typedef struct _CcnetPutpubinfoProcClass CcnetPutpubinfoProcClass; struct _CcnetPutpubinfoProc { CcnetProcessor parent_instance; }; struct _CcnetPutpubinfoProcClass { CcnetProcessorClass parent_class; }; GType ccnet_putpubinfo_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/rcvcmd-proc.c000066400000000000000000000754771317035602700215120ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include #include "rcvcmd-proc.h" #include "peer.h" #include "session.h" #include "peer-mgr.h" #include "connect-mgr.h" #include "proc-factory.h" #include "message.h" #include "message-manager.h" #include "algorithms.h" #include "utils.h" #include "net.h" #include "log.h" #ifdef CCNET_CLUSTER #include "cluster-mgr.h" #endif #ifdef CCNET_DAEMON #include "daemon-session.h" #endif #define SC_UNKNONW_CMD "400" #define SS_UNKNONW_CMD "Unknown Command" #define SC_BAD_PACKET_FMT "401" #define SS_BAD_PACKET_FMT "Bad Packet Format" #define SC_BAD_CMD_FMT "402" #define SS_BAD_CMD_FMT "Bad Command Format" #define SC_NO_MSG "403" #define SS_NO_MSG "Message Not Exist" #define SC_NO_PEER "410" #define SS_NO_PEER "No Such Peer" #define SC_NO_PROCESSOR "411" #define SS_NO_PROCESSOR "No Such Processor" #define SC_NO_USER "413" #define SS_NO_USER "No Such User" #define SC_NO_GROUP "430" #define SS_NO_GROUP "No Such Group" #define PARSE_OPTIONS \ do { \ context = g_option_context_new (NULL); \ g_option_context_add_main_entries (context, cmd_entries, NULL); \ if (!g_option_context_parse (context, &argc, &argv, &error)) { \ g_print ("option parsing failed: %s\n", error->message); \ return -1; \ } \ } while (0) enum { INIT }; typedef struct { int persist : 1; } CcnetRcvcmdProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_RCVCMD_PROC, CcnetRcvcmdProcPriv)) static int rcv_cmd_start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetRcvcmdProc, ccnet_rcvcmd_proc, CCNET_TYPE_PROCESSOR) static void ccnet_rcvcmd_proc_class_init (CcnetRcvcmdProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "rcvcmd-proc"; proc_class->start = rcv_cmd_start; proc_class->handle_update = handle_update; g_type_class_add_private (klass, sizeof (CcnetRcvcmdProcPriv)); } static void ccnet_rcvcmd_proc_init (CcnetRcvcmdProc *processor) { } static int rcv_cmd_start (CcnetProcessor *processor, int argc, char **argv) { CcnetRcvcmdProcPriv *priv = GET_PRIV (processor); priv->persist = 0; while (0 < argc && argv[0][0] == '-') { switch (argv[0][1]) { case 'p': priv->persist = 1; break; default: break; } argc--; argv++; } ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } struct cmd { char *name; int (*handler) (CcnetProcessor *, int argc, char **argv); }; static int shutdown_session (CcnetProcessor *, int, char **); static int register_service (CcnetProcessor *, int, char **); static int echo (CcnetProcessor *, int, char **); static int list_proc (CcnetProcessor *, int, char **); static int set_timeout (CcnetProcessor *, int, char **); static int add_role (CcnetProcessor *, int, char **); static int set_addr (CcnetProcessor *, int, char **); static int add_peer (CcnetProcessor *, int, char **); static int delete_peer (CcnetProcessor *, int, char **); static int delete_role (CcnetProcessor *, int, char **); static int connect_peer (CcnetProcessor *, int, char **); static int disconnect_peer (CcnetProcessor *, int, char **); static int conn_cancel (CcnetProcessor *, int, char **); static int invoke_echo (CcnetProcessor *, int, char **); #ifdef CCNET_CLUSTER static int add_member (CcnetProcessor *, int, char **); static int add_master (CcnetProcessor *, int, char **); static int redirect_peer (CcnetProcessor *, int, char **); #endif #ifdef CCNET_DAEMON static int add_relay (CcnetProcessor *, int, char **); #endif static struct cmd cmdtab[] = { { "shutdown", shutdown_session }, { "register-service", register_service }, { "echo", echo }, { "list-proc", list_proc }, { "set-timeout", set_timeout }, { "add-role", add_role }, { "add-peer", add_peer }, { "del-peer", delete_peer }, { "del-role", delete_role }, { "set-addr", set_addr }, #ifdef CCNET_DAEMON { "add-relay", add_relay }, #endif #ifdef CCNET_CLUSTER { "add-member", add_member }, { "add-master", add_master }, { "redirect-peer", redirect_peer }, #endif /* { "group-create", create_group }, */ /* { "group-follow", follow_group }, */ /* { "group-unfollow", unfollow_group }, */ /* { "group-show", show_group }, */ /* { "group-add-member", add_group_member }, */ /* { "group-del-member", delete_group_member }, */ /* { "group-del-follower", delete_group_follower }, */ /* { "group-add-maintainer", add_group_maintainer }, */ { "connect", connect_peer }, { "disconnect", disconnect_peer }, { "conn-cancel", conn_cancel }, { "invoke-echo", invoke_echo }, { 0 }, }; struct cmd * getcmd (char *name) { char *p, *q; struct cmd *c, *found; int nmatches, longest; longest = 0; nmatches = 0; found = 0; for (c = cmdtab; (p = c->name); c++) { for (q = name; *q == *p++; q++) if (*q == 0) /* exact match? */ return c; if (!*q) { /* the name was a prefix */ if (q - name > longest) { longest = q - name; nmatches = 1; found = c; } else if (q - name == longest) nmatches++; } } if (nmatches > 1) return (struct cmd *)-1; return found; } static void handle_command (CcnetProcessor *processor, char *line) { gchar **commands; gchar **pcmd; struct cmd *c; int i; commands = g_strsplit_set (line, " \t", 10); for (i = 0, pcmd = commands; *pcmd; pcmd++) i++; if (i == 0) { g_strfreev (commands); return; } /* puts (commands[0]); */ c = getcmd (commands[0]); if (c == NULL) { ccnet_processor_send_response (processor, SC_UNKNONW_CMD, SS_UNKNONW_CMD, NULL, 0); } else c->handler (processor, i, commands); g_strfreev (commands); } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetRcvcmdProcPriv *priv = GET_PRIV (processor); if (content[clen-1] != '\0') { ccnet_processor_send_response (processor, SC_BAD_PACKET_FMT, SS_BAD_PACKET_FMT, NULL, 0); if (!priv->persist) ccnet_processor_done (processor, FALSE); return; } handle_command (processor, content); if (!priv->persist) ccnet_processor_done (processor, TRUE); } int shutdown_session (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; ccnet_processor_send_response (processor, SC_OK, NULL, NULL, 0); ccnet_session_on_exit (processor->session); exit (0); return 0; } static int register_service (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; int ret = 0; char *group = "inner"; if (argc < 1) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (argc >= 2) group = argv[1]; ret = ccnet_session_register_service (processor->session, argv[0], group, processor->peer); if (ret < 0) ccnet_processor_send_response (processor, SC_SERV_EXISTED, SS_SERV_EXISTED, NULL, 0); else ccnet_processor_send_response (processor, SC_OK, NULL, NULL, 0); return 0; } static int echo (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; if (argc == 1) { ccnet_processor_send_response (processor, SC_OK, "", argv[0], strlen(argv[0])+1); } else { ccnet_processor_send_response (processor, SC_OK, "", "Hello", strlen("Hello")+1); } return 0; } static int list_proc (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; CcnetPeerManager *peerMgr; CcnetPeer *peer; CcnetProcessor *proc; GList *peerlist, *peeriter; GList *proclist, *prociter; GString *buf = g_string_new (NULL); peerMgr = processor->session->peer_mgr; peerlist = ccnet_peer_manager_get_peer_list (peerMgr); for (peeriter=peerlist; peeriter; peeriter=peeriter->next) { peer = (CcnetPeer *)(peeriter->data); proclist = g_hash_table_get_values (peer->processors); for (prociter=proclist; prociter; prociter = prociter->next) { proc = (CcnetProcessor *)(prociter->data); g_string_append_printf (buf, "%d\t%s\n", PRINT_ID(proc->id), GET_PNAME(proc)); } g_list_free (proclist); } g_list_free (peerlist); ccnet_processor_send_response (processor, SC_OK, SS_OK, buf->str, buf->len); g_string_free (buf, TRUE); return 0; } static int set_timeout (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; if (argc < 2) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (strcmp("proc-keepalive-timeout", argv[0]) == 0) { ccnet_proc_factory_set_keepalive_timeout ( processor->session->proc_factory, atoi(argv[1])); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } ccnet_processor_send_response (processor, "401", "No such timer", NULL, 0); return -1; } static int set_addr (CcnetProcessor *processor, int argc, char **argv) { CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer; int port = DEFAULT_PORT; argc--; argv++; if (argc < 2) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (argc > 2) { port = atoi (argv[2]); if (port <= 0) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, "Invalid port", NULL, 0); return -1; } } peer = ccnet_peer_manager_get_peer (mgr, argv[0]); if (!peer) { ccnet_processor_send_response (processor, "400", "Load peer error", NULL, 0); return -1; } ccnet_peer_manager_set_peer_public_addr (mgr, peer, argv[1], port); ccnet_processor_send_response (processor, SC_OK, SS_OK, peer->id, 41); g_object_unref (peer); return 0; } #ifdef CCNET_DAEMON /* add-relay [--id ] [--addr ] */ static int add_relay (CcnetProcessor *processor, int argc, char **argv) { CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer = NULL; char *peer_id = NULL; char *addr_port = NULL; char *role = NULL; char *addr; uint16_t port; int ret; GOptionContext *context; GError *error = NULL; GOptionEntry cmd_entries[] = { { .long_name = "id", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &peer_id, .description = "the peer id", .arg_description = NULL }, { .long_name = "addr", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &addr_port, .description = "the address and port of the peer", .arg_description = NULL }, { NULL }, }; PARSE_OPTIONS; /* check addr_port and peer id */ if (addr_port) { addr = addr_port; char *p; if ( (p = strchr(addr_port, ':')) == NULL) { port = DEFAULT_PORT; } else { *p = '\0'; port = atoi(p+1); if (port == 0) { ccnet_processor_send_response ( processor, "400", "Invalid Address", NULL, 0); ret = -1; goto out; } } } if (peer_id) { if (!peer_id_valid(peer_id)) { ccnet_processor_send_response ( processor, "400", "Invalid Peer ID", NULL, 0); ret = -1; goto out; } } if (addr_port && peer_id) { peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { ccnet_message("Add server %.8s %s:%d\n", peer_id, addr, port); peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (mgr, peer); ccnet_peer_manager_set_peer_public_addr (mgr, peer, addr, port); ccnet_peer_manager_add_role (mgr, peer, "MyRelay"); ccnet_conn_manager_connect_peer (processor->session->connMgr, peer); } ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ret = 0; goto out; } /* only addr */ if (addr_port) { peer = ccnet_peer_manager_add_resolve_peer ( processor->session->peer_mgr, addr, port); peer->want_tobe_relay = 1; ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ret = 0; goto out; } /* only id */ if (peer_id) { peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (mgr, peer); } ccnet_peer_manager_add_role (mgr, peer, "MyRelay"); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ret = 0; goto out; } ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); ret = -1; out: g_free (addr_port); g_free (role); g_free (peer_id); if (peer) g_object_unref (peer); return ret; } #endif static int add_role (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer; if (argc != 2) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (strlen(argv[0]) != 40) { ccnet_processor_send_response (processor, "400", "Peer id must be of length 40", NULL, 0); return -1; } peer = ccnet_peer_manager_get_peer (mgr, argv[0]); if (!peer) { ccnet_processor_send_response (processor, SC_NO_PEER, SS_NO_PEER, NULL, 0); return -1; } ccnet_peer_manager_add_role (mgr, peer, argv[1]); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); g_object_unref (peer); return 0; } static int delete_role (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer; if (argc != 2) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (strlen(argv[0]) != 40) { ccnet_processor_send_response (processor, "400", "Peer id must be of length 40", NULL, 0); return -1; } peer = ccnet_peer_manager_get_peer (mgr, argv[0]); if (!peer) { ccnet_processor_send_response (processor, SC_NO_PEER, SS_NO_PEER, NULL, 0); return -1; } ccnet_peer_manager_remove_role (mgr, peer, argv[1]); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); g_object_unref (peer); return 0; } /* add-peer [--id ] [--addr ] [--role ] */ static int add_peer (CcnetProcessor *processor, int argc, char **argv) { CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer = NULL; char *peer_id = NULL; char *addr_port = NULL; char *role = NULL; char *addr; uint16_t port; int ret; GOptionContext *context; GError *error = NULL; GOptionEntry cmd_entries[] = { { .long_name = "id", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &peer_id, .description = "the peer id", .arg_description = NULL }, { .long_name = "addr", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &addr_port, .description = "the address and port of the peer", .arg_description = NULL }, { .long_name = "role", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &role, .description = "the role of the peer", .arg_description = NULL }, { NULL }, }; PARSE_OPTIONS; /* check addr_port and peer id */ if (addr_port) { addr = addr_port; char *p; if ( (p = strchr(addr_port, ':')) == NULL) { port = DEFAULT_PORT; } else { *p = '\0'; port = atoi(p+1); if (port == 0) { ccnet_processor_send_response ( processor, "400", "Invalid Address", NULL, 0); ret = -1; goto out; } } } if (peer_id) { if (!peer_id_valid(peer_id)) { ccnet_processor_send_response ( processor, "400", "Invalid Peer ID", NULL, 0); ret = -1; goto out; } } if (addr_port && peer_id) { peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (mgr, peer); } ccnet_peer_manager_set_peer_public_addr (mgr, peer, addr, port); if (role) ccnet_peer_manager_add_role (mgr, peer, role); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ret = 0; goto out; } /* only addr */ if (addr_port) { peer = ccnet_peer_manager_add_resolve_peer ( processor->session->peer_mgr, addr, port); g_free (peer->intend_role); peer->intend_role = g_strdup(role); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ret = 0; goto out; } /* only id */ if (peer_id) { peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (peer) { ret = 0; goto out; } peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (mgr, peer); if (role) ccnet_peer_manager_add_role (mgr, peer, role); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ret = 0; goto out; } ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); ret = -1; out: g_free (addr_port); g_free (role); g_free (peer_id); if (peer) g_object_unref (peer); return ret; } static int delete_peer (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer; if (argc < 1) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (strlen(argv[0]) != 40) { ccnet_processor_send_response (processor, "400", "Peer id must be of length 40", NULL, 0); return -1; } peer = ccnet_peer_manager_get_peer (mgr, argv[0]); if (peer) { ccnet_peer_manager_remove_peer (mgr, peer); g_object_unref (peer); } ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } static int connect_peer (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; CcnetPeerManager *mgr = processor->session->peer_mgr; char *peer_id; CcnetPeer *peer; if (argc != 1) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (strlen(argv[0]) != 40) { ccnet_processor_send_response (processor, "400", "Peer id must be of length 40", NULL, 0); return -1; } peer_id = argv[0]; peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { ccnet_processor_send_response ( processor, "400", "Can not find peer", NULL, 0); return -1; } ccnet_conn_manager_add_to_conn_list (processor->session->connMgr, peer); ccnet_conn_manager_connect_peer (processor->session->connMgr, peer); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); g_object_unref (peer); return 0; } static int disconnect_peer (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; CcnetPeerManager *mgr = processor->session->peer_mgr; char *peer_id; CcnetPeer *peer; if (argc != 1) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (strlen(argv[0]) != 40) { ccnet_processor_send_response (processor, "400", "Peer id must be of length 40", NULL, 0); return -1; } peer_id = argv[0]; peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { ccnet_processor_send_response ( processor, "400", "Can not find peer", NULL, 0); return -1; } ccnet_conn_manager_remove_from_conn_list (processor->session->connMgr, peer); ccnet_peer_shutdown (peer); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); g_object_unref (peer); return 0; } static int conn_cancel (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; if (argc != 2) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } int port = atoi(argv[1]); ccnet_conn_manager_cancel_conn (processor->session->connMgr, argv[0], port); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } static int invoke_echo (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer; if (argc != 1) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (!peer_id_valid(argv[0])) { ccnet_processor_send_response (processor, "400", "Invalid peer id", NULL, 0); return -1; } peer = ccnet_peer_manager_get_peer (mgr, argv[0]); if (!peer) { ccnet_processor_send_response ( processor, "400", "Can not find peer", NULL, 0); return -1; } CcnetProcessor *proc; proc = ccnet_proc_factory_create_master_processor ( processor->session->proc_factory, "echo", peer); ccnet_processor_start (proc, 0, NULL); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); g_object_unref (peer); return 0; } #ifdef CCNET_CLUSTER extern CcnetClusterManager *cluster_mgr; /* add-member [--id ] */ static int add_member (CcnetProcessor *processor, int argc, char **argv) { CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer = NULL; char *peer_id = NULL; char *addr_port = NULL; char *addr; uint16_t port; int ret; GOptionContext *context; GError *error = NULL; GOptionEntry cmd_entries[] = { { .long_name = "id", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &peer_id, .description = "the peer id", .arg_description = NULL }, { .long_name = "addr", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &addr_port, .description = "the address and port of the peer", .arg_description = NULL }, { NULL }, }; PARSE_OPTIONS; if (!peer_id) { ccnet_processor_send_response ( processor, "400", "Must specify Peer ID", NULL, 0); ret = -1; goto out; } if (!peer_id_valid(peer_id)) { ccnet_processor_send_response ( processor, "400", "Invalid Peer ID", NULL, 0); ret = -1; goto out; } /* check addr_port and peer id */ if (addr_port) { addr = addr_port; char *p; if ( (p = strchr(addr_port, ':')) == NULL) { port = DEFAULT_PORT; } else { *p = '\0'; port = atoi(p+1); if (port == 0) { ccnet_processor_send_response ( processor, "400", "Invalid Address", NULL, 0); ret = -1; goto out; } } } peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (mgr, peer); } if (addr) ccnet_peer_manager_set_peer_public_addr (mgr, peer, addr, port); ccnet_peer_manager_add_role (mgr, peer, "ClusterMember"); ccnet_cluster_manager_add_member (cluster_mgr, peer); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ret = 0; goto out; out: g_free (peer_id); if (peer) g_object_unref (peer); return ret; } /* add-master [--id ] [--addr ] */ static int add_master (CcnetProcessor *processor, int argc, char **argv) { CcnetPeerManager *mgr = processor->session->peer_mgr; CcnetPeer *peer = NULL; char *peer_id = NULL; char *addr_port = NULL; char *addr; uint16_t port; int ret; GOptionContext *context; GError *error = NULL; GOptionEntry cmd_entries[] = { { .long_name = "id", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &peer_id, .description = "the peer id", .arg_description = NULL }, { .long_name = "addr", .short_name = 0, .flags = 0, .arg = G_OPTION_ARG_STRING, .arg_data = &addr_port, .description = "the address and port of the peer", .arg_description = NULL }, { NULL }, }; PARSE_OPTIONS; if (!peer_id) { ccnet_processor_send_response ( processor, "400", "Must specify Peer ID", NULL, 0); ret = -1; goto out; } if (!peer_id_valid(peer_id)) { ccnet_processor_send_response ( processor, "400", "Invalid Peer ID", NULL, 0); ret = -1; goto out; } /* check addr_port and peer id */ if (addr_port) { addr = addr_port; char *p; if ( (p = strchr(addr_port, ':')) == NULL) { port = DEFAULT_PORT; } else { *p = '\0'; port = atoi(p+1); if (port == 0) { ccnet_processor_send_response ( processor, "400", "Invalid Address", NULL, 0); ret = -1; goto out; } } } peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (mgr, peer); } if (addr) ccnet_peer_manager_set_peer_public_addr (mgr, peer, addr, port); ccnet_peer_manager_add_role (mgr, peer, "ClusterMaster"); ccnet_cluster_manager_add_master (cluster_mgr, peer); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ret = 0; goto out; out: g_free (addr); g_free (peer_id); if (peer) g_object_unref (peer); return ret; } static int redirect_peer (CcnetProcessor *processor, int argc, char **argv) { argc--; argv++; CcnetPeerManager *mgr = processor->session->peer_mgr; char *peer_id, *to_id; CcnetPeer *peer, *to; if (argc != 2) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); return -1; } if (!peer_id_valid(argv[0]) || !peer_id_valid(argv[1])) { ccnet_processor_send_response (processor, "400", "Invalid peer id", NULL, 0); return -1; } peer_id = argv[0]; to_id = argv[1]; peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { ccnet_processor_send_response ( processor, "400", "Can not find peer", NULL, 0); return -1; } to = ccnet_peer_manager_get_peer (mgr, to_id); if (!to) { g_object_unref (peer); ccnet_processor_send_response ( processor, "400", "Can not redirect destination peer", NULL, 0); return -1; } ccnet_peer_manager_redirect_peer (mgr, peer, to); ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); g_object_unref (peer); g_object_unref (to); return 0; } #endif ccnet-6.1.5/net/common/processors/rcvcmd-proc.h000066400000000000000000000022121317035602700214700ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_RCVCMD_PROC_H #define CCNET_RCVCMD_PROC_H #include #include "processor.h" #define CCNET_TYPE_RCVCMD_PROC (ccnet_rcvcmd_proc_get_type ()) #define CCNET_RCVCMD_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_RCVCMD_PROC, CcnetRcvcmdProc)) #define CCNET_IS_RCVCMD_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_RCVCMD_PROC)) #define CCNET_RCVCMD_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_RCVCMD_PROC, CcnetRcvcmdProcClass)) #define CCNET_IS_RCVCMD_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_RCVCMD_PROC)) #define CCNET_RCVCMD_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_RCVCMD_PROC, CcnetRcvcmdProcClass)) typedef struct _CcnetRcvcmdProc CcnetRcvcmdProc; typedef struct _CcnetRcvcmdProcClass CcnetRcvcmdProcClass; struct _CcnetRcvcmdProc { CcnetProcessor parent_instance; }; struct _CcnetRcvcmdProcClass { CcnetProcessorClass parent_class; }; GType ccnet_rcvcmd_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/rcvmsg-proc.c000066400000000000000000000046761317035602700215260ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "peer.h" #include "message.h" #include "session.h" #include "message-manager.h" #include "peer-mgr.h" #include "rcvmsg-proc.h" #include "algorithms.h" #define DEBUG_FLAG CCNET_DEBUG_MESSAGE #include "log.h" static int rcv_msg_start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetRcvmsgProc, ccnet_rcvmsg_proc, CCNET_TYPE_PROCESSOR) static void ccnet_rcvmsg_proc_class_init (CcnetRcvmsgProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "rcvmsg-proc"; proc_class->start = rcv_msg_start; proc_class->handle_update = handle_update; } static void ccnet_rcvmsg_proc_init (CcnetRcvmsgProc *processor) { } static int rcv_msg_start (CcnetProcessor *processor, int argc, char **argv) { ccnet_processor_send_response (processor, "200", "OK", NULL, 0); return 0; } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetMessage *msg; if (processor->peer->is_local) { msg = ccnet_message_from_string_local (content, clen); ccnet_send_message (processor->session, msg); ccnet_message_unref (msg); } else { msg = ccnet_message_from_string (content, clen); if (!msg) { g_warning ("Wrong message format.\n"); ccnet_processor_done (processor, FALSE); return; } msg->rtime = time(NULL); ccnet_debug ("[msg] Received a message : %s - %.10s\n", msg->app, msg->body); int ret = ccnet_recv_message (processor->session, msg); if (ret == -1) { ccnet_message ("[msg] Message from %.8s permission error\n", msg->from); ccnet_processor_send_response (processor, SC_PERM_ERR, SS_PERM_ERR, NULL, 0); ccnet_processor_done (processor, TRUE); ccnet_message_unref (msg); return; } ccnet_message_unref (msg); } ccnet_processor_send_response (processor, "200", "OK", NULL, 0); ccnet_processor_done (processor, TRUE); } ccnet-6.1.5/net/common/processors/rcvmsg-proc.h000066400000000000000000000022121317035602700215130ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_RCVMSG_PROC_H #define CCNET_RCVMSG_PROC_H #include #include "processor.h" #define CCNET_TYPE_RCVMSG_PROC (ccnet_rcvmsg_proc_get_type ()) #define CCNET_RCVMSG_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_RCVMSG_PROC, CcnetRcvmsgProc)) #define CCNET_IS_RCVMSG_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_RCVMSG_PROC)) #define CCNET_RCVMSG_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_RCVMSG_PROC, CcnetRcvmsgProcClass)) #define CCNET_IS_RCVMSG_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_RCVMSG_PROC)) #define CCNET_RCVMSG_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_RCVMSG_PROC, CcnetRcvmsgProcClass)) typedef struct _CcnetRcvmsgProc CcnetRcvmsgProc; typedef struct _CcnetRcvmsgProcClass CcnetRcvmsgProcClass; struct _CcnetRcvmsgProc { CcnetProcessor parent_instance; }; struct _CcnetRcvmsgProcClass { CcnetProcessorClass parent_class; }; GType ccnet_rcvmsg_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/recvsessionkey-proc.c000066400000000000000000000111241317035602700232630ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "session.h" #include "common.h" #include "processor.h" #include "peer.h" #include "peer-mgr.h" #include "log.h" #include "rsa.h" #include "recvsessionkey-proc.h" extern CcnetSession *session; #define SC_SESSION_KEY "300" #define SS_SESSION_KEY "session key" #define SC_ALREADY_HAS_KEY "301" #define SS_ALREADY_HAS_KEY "already has your session key" #define SC_BAD_KEY "302" #define SS_BAD_KEY "bad session key" G_DEFINE_TYPE (CcnetRecvsessionkeyProc, ccnet_recvsessionkey_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { CCNET_PROCESSOR_CLASS (ccnet_recvsessionkey_proc_parent_class)->release_resource (processor); } static void ccnet_recvsessionkey_proc_class_init (CcnetRecvsessionkeyProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "receive-session-key"; proc_class->start = start; proc_class->handle_update = handle_update; proc_class->release_resource = release_resource; } static void ccnet_recvsessionkey_proc_init (CcnetRecvsessionkeyProc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { if (argc != 0) { ccnet_processor_send_response (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } if (processor->peer->session_key) { ccnet_processor_send_response (processor, SC_ALREADY_HAS_KEY, SS_ALREADY_HAS_KEY, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } ccnet_processor_send_response (processor, SC_SESSION_KEY, SS_SESSION_KEY, NULL, 0); return 0; } static unsigned char * decrypt_data (CcnetPeer *peer, const char *content, int clen, int *len_p) { RSA *privkey = session->privkey; unsigned char *buf; buf = private_key_decrypt(privkey, (unsigned char *)content, clen, len_p); if (*len_p <= 0) { ccnet_warning ("failed to decrypt session key from peer %.10s", peer->id); g_free (buf); buf = NULL; } return buf; } static gboolean update_peer_session_key (CcnetPeer *peer, const char *content, int clen) { char *buf; int key_len = 0; if (peer->session_key) { ccnet_warning ("[recv session key] peer %.10s already has a session key", peer->id); return FALSE; } buf = (char *)decrypt_data (peer, content, clen, &key_len); if (buf) { peer->session_key = g_strndup(buf, key_len); g_free (buf); return TRUE; } else { ccnet_warning ("faied to decrypt session key"); return FALSE; } } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (strcmp(code, SC_SESSION_KEY) == 0) { if (processor->peer->session_key) { ccnet_processor_send_response (processor, SC_ALREADY_HAS_KEY, SS_ALREADY_HAS_KEY, NULL, 0); ccnet_processor_done (processor, TRUE); } else if (update_peer_session_key (processor->peer, content, clen)) { ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); ccnet_peer_manager_on_peer_session_key_received (processor->peer->manager, processor->peer); ccnet_processor_done (processor, TRUE); } else { ccnet_processor_send_response (processor, SC_BAD_KEY, SS_BAD_KEY, NULL, 0); ccnet_processor_done (processor, FALSE); } } else { ccnet_warning ("[recv session key] bad update %s:%s\n", code, code_msg); ccnet_processor_done (processor, FALSE); } } ccnet-6.1.5/net/common/processors/recvsessionkey-proc.h000066400000000000000000000024651317035602700233000ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_RECVSESSIONKEY_PROC_H #define CCNET_RECVSESSIONKEY_PROC_H #include #define CCNET_TYPE_RECVSESSIONKEY_PROC (ccnet_recvsessionkey_proc_get_type ()) #define CCNET_RECVSESSIONKEY_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_RECVSESSIONKEY_PROC, CcnetRecvsessionkeyProc)) #define CCNET_IS_RECVSESSIONKEY_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_RECVSESSIONKEY_PROC)) #define CCNET_RECVSESSIONKEY_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_RECVSESSIONKEY_PROC, CcnetRecvsessionkeyProcClass)) #define IS_CCNET_RECVSESSIONKEY_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_RECVSESSIONKEY_PROC)) #define CCNET_RECVSESSIONKEY_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_RECVSESSIONKEY_PROC, CcnetRecvsessionkeyProcClass)) typedef struct _CcnetRecvsessionkeyProc CcnetRecvsessionkeyProc; typedef struct _CcnetRecvsessionkeyProcClass CcnetRecvsessionkeyProcClass; struct _CcnetRecvsessionkeyProc { CcnetProcessor parent_instance; }; struct _CcnetRecvsessionkeyProcClass { CcnetProcessorClass parent_class; }; GType ccnet_recvsessionkey_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/recvsessionkey-v2-proc.c000066400000000000000000000130101317035602700236040ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "session.h" #include "common.h" #include "processor.h" #include "peer.h" #include "peer-mgr.h" #include "log.h" #include "rsa.h" #include "recvsessionkey-v2-proc.h" extern CcnetSession *session; #define SC_SESSION_KEY "300" #define SS_SESSION_KEY "session key" #define SC_ALREADY_HAS_KEY "301" #define SS_ALREADY_HAS_KEY "already has your session key" #define SC_NO_ENCRYPT "303" #define SS_NO_ENCRYPT "Donot encrypt channel" #define SC_BAD_KEY "400" #define SS_BAD_KEY "bad session key" typedef struct { int encrypt_channel; } CcnetRecvskey2ProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_RECVSKEY2_PROC, CcnetRecvskey2ProcPriv)) #define USE_PRIV \ CcnetRecvskey2ProcPriv *priv = GET_PRIV(processor); G_DEFINE_TYPE (CcnetRecvskey2Proc, ccnet_recvskey2_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { CCNET_PROCESSOR_CLASS (ccnet_recvskey2_proc_parent_class)->release_resource (processor); } static void ccnet_recvskey2_proc_class_init (CcnetRecvskey2ProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "receive-skey2"; proc_class->start = start; proc_class->handle_update = handle_update; proc_class->release_resource = release_resource; g_type_class_add_private (klass, sizeof (CcnetRecvskey2ProcPriv)); } static void ccnet_recvskey2_proc_init (CcnetRecvskey2Proc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { USE_PRIV; if (processor->peer->session_key) { ccnet_processor_send_response (processor, SC_ALREADY_HAS_KEY, SS_ALREADY_HAS_KEY, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } if (argc == 1 && g_strcmp0(argv[0], "--enc-channel") == 0) priv->encrypt_channel = 1; else priv->encrypt_channel = 0; ccnet_processor_send_response (processor, SC_SESSION_KEY, SS_SESSION_KEY, NULL, 0); return 0; } static unsigned char * decrypt_data (CcnetPeer *peer, const char *content, int clen, int *len_p) { RSA *privkey = session->privkey; unsigned char *buf; buf = private_key_decrypt(privkey, (unsigned char *)content, clen, len_p); if (*len_p <= 0) { ccnet_warning ("failed to decrypt session key from peer %.10s", peer->id); g_free (buf); buf = NULL; } return buf; } static gboolean update_peer_session_key (CcnetPeer *peer, const char *content, int clen) { char *buf; int key_len = 0; buf = (char *)decrypt_data (peer, content, clen, &key_len); if (buf) { peer->session_key = g_strndup(buf, key_len); g_free (buf); return TRUE; } else { ccnet_warning ("faied to decrypt session key"); return FALSE; } } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { USE_PRIV; if (strcmp(code, SC_SESSION_KEY) == 0) { if (processor->peer->session_key) { ccnet_processor_send_response (processor, SC_ALREADY_HAS_KEY, SS_ALREADY_HAS_KEY, NULL, 0); ccnet_processor_done (processor, TRUE); return; } if (update_peer_session_key (processor->peer, content, clen) < 0) { ccnet_processor_send_response (processor, SC_BAD_KEY, SS_BAD_KEY, NULL, 0); ccnet_processor_done (processor, FALSE); return; } if (priv->encrypt_channel) { /* peer ask to encrypt channel, check whether we want it too */ if (ccnet_session_should_encrypt_channel(processor->session)) { /* send the ok reply first */ ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); /* now setup encryption */ if (ccnet_peer_prepare_channel_encryption (processor->peer) < 0) /* this is very rare, we just print a warning */ ccnet_warning ("Error in prepare channel encryption\n"); } else ccnet_processor_send_response ( processor, SC_NO_ENCRYPT, SS_NO_ENCRYPT, NULL, 0); } else ccnet_processor_send_response ( processor, SC_OK, SS_OK, NULL, 0); ccnet_peer_manager_on_peer_session_key_received (processor->peer->manager, processor->peer); ccnet_processor_done (processor, TRUE); return; } ccnet_warning ("[recv session key] bad update %s:%s\n", code, code_msg); ccnet_processor_done (processor, FALSE); } ccnet-6.1.5/net/common/processors/recvsessionkey-v2-proc.h000066400000000000000000000022751317035602700236240ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_RECVSKEY2_PROC_H #define CCNET_RECVSKEY2_PROC_H #include #define CCNET_TYPE_RECVSKEY2_PROC (ccnet_recvskey2_proc_get_type ()) #define CCNET_RECVSKEY2_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_RECVSKEY2_PROC, CcnetRecvskey2Proc)) #define CCNET_IS_RECVSKEY2_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_RECVSKEY2_PROC)) #define CCNET_RECVSKEY2_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_RECVSKEY2_PROC, CcnetRecvskey2ProcClass)) #define IS_CCNET_RECVSKEY2_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_RECVSKEY2_PROC)) #define CCNET_RECVSKEY2_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_RECVSKEY2_PROC, CcnetRecvskey2ProcClass)) typedef struct _CcnetRecvskey2Proc CcnetRecvskey2Proc; typedef struct _CcnetRecvskey2ProcClass CcnetRecvskey2ProcClass; struct _CcnetRecvskey2Proc { CcnetProcessor parent_instance; }; struct _CcnetRecvskey2ProcClass { CcnetProcessorClass parent_class; }; GType ccnet_recvskey2_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/rpcserver-proc.c000066400000000000000000000101331317035602700222210ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include "rpcserver-proc.h" #include "rpc-common.h" #define DEBUG_FLAG CCNET_DEBUG_PEER #include "log.h" typedef struct { char *buf; int len; int off; /* struct timeval start; */ } CcnetRpcserverProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_RPCSERVER_PROC, CcnetRpcserverProcPriv)) G_DEFINE_TYPE (CcnetRpcserverProc, ccnet_rpcserver_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { /* CcnetRpcserverProcPriv *priv = GET_PRIV (processor); */ /* struct timeval end, intv; */ /* gettimeofday(&end, NULL); */ /* timersub(&end, &priv->start, &intv); */ /* fprintf (stdout, "[rpcserver] Time spend in proc: %ds %dus\n", */ /* intv.tv_sec, intv.tv_usec); */ CCNET_PROCESSOR_CLASS (ccnet_rpcserver_proc_parent_class)->release_resource (processor); } static void ccnet_rpcserver_proc_class_init (CcnetRpcserverProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->start = start; proc_class->handle_update = handle_update; proc_class->release_resource = release_resource; proc_class->name = "rpcserver-proc"; g_type_class_add_private (klass, sizeof(CcnetRpcserverProcPriv)); } static void ccnet_rpcserver_proc_init (CcnetRpcserverProc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { /* CcnetRpcserverProcPriv *priv = GET_PRIV (processor); */ /* gettimeofday(&priv->start, NULL); */ ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetRpcserverProcPriv *priv = GET_PRIV (processor); if (memcmp (code, SC_CLIENT_CALL, 3) == 0) { gsize ret_len; char *svc_name = processor->name; char *ret = searpc_server_call_function (svc_name, content, clen, &ret_len); if (ret_len < MAX_TRANSFER_LENGTH) { ccnet_processor_send_response ( processor, SC_SERVER_RET, SS_SERVER_RET, ret, ret_len); g_free (ret); /* ccnet_processor_done (processor, TRUE); */ return; } /* we need to split data into multiple segments */ priv->buf = ret; priv->len = ret_len; priv->off = 0; /* fprintf (stderr, "Send %d\n", MAX_TRANSFER_LENGTH); */ ccnet_processor_send_response (processor, SC_SERVER_MORE, SS_SERVER_MORE, priv->buf, MAX_TRANSFER_LENGTH); priv->off = MAX_TRANSFER_LENGTH; return; } if (memcmp (code, SC_CLIENT_MORE, 3) == 0) { if (priv->off + MAX_TRANSFER_LENGTH < priv->len) { /* fprintf (stderr, "Send %d\n", MAX_TRANSFER_LENGTH); */ ccnet_processor_send_response ( processor, SC_SERVER_MORE, SS_SERVER_MORE, priv->buf + priv->off, MAX_TRANSFER_LENGTH); priv->off += MAX_TRANSFER_LENGTH; } else { /* fprintf (stderr, "Send %d\n", priv->len - priv->off); */ ccnet_processor_send_response ( processor, SC_SERVER_RET, SS_SERVER_RET, priv->buf + priv->off, priv->len - priv->off); g_free (priv->buf); /* ccnet_processor_done (processor, TRUE); */ } return; } ccnet_processor_send_response (processor, SC_BAD_UPDATE_CODE, SS_BAD_UPDATE_CODE, NULL, 0); ccnet_warning ("[rpc-server] Bad update: %s %s.\n", code, code_msg); if (priv->buf) g_free (priv->buf); ccnet_processor_done (processor, FALSE); } ccnet-6.1.5/net/common/processors/rpcserver-proc.h000066400000000000000000000023231317035602700222300ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_RPCSERVER_PROC_H #define CCNET_RPCSERVER_PROC_H #include #include "processor.h" #define CCNET_TYPE_RPCSERVER_PROC (ccnet_rpcserver_proc_get_type ()) #define CCNET_RPCSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_RPCSERVER_PROC, CcnetRpcserverProc)) #define CCNET_IS_RPCSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_RPCSERVER_PROC)) #define CCNET_RPCSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_RPCSERVER_PROC, CcnetRpcserverProcClass)) #define IS_CCNET_RPCSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_RPCSERVER_PROC)) #define CCNET_RPCSERVER_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_RPCSERVER_PROC, CcnetRpcserverProcClass)) typedef struct _CcnetRpcserverProc CcnetRpcserverProc; typedef struct _CcnetRpcserverProcClass CcnetRpcserverProcClass; struct _CcnetRpcserverProc { CcnetProcessor parent_instance; }; struct _CcnetRpcserverProcClass { CcnetProcessorClass parent_class; }; GType ccnet_rpcserver_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/sample-master-proc.c000066400000000000000000000141041317035602700227620ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "timer.h" #include "peer.h" #include "session.h" #include "sample-master-proc.h" #define DEBUG_FLAG CCNET_DEBUG_PROCESSOR #include "log.h" enum { INIT, REQUEST_SEND, CONNECTED, }; typedef struct { GHashTable *registered; int rate; } CcnetSampleProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SAMPLE_PROC, CcnetSampleProcPriv)) G_DEFINE_TYPE (CcnetSampleProc, ccnet_sample_proc, CCNET_TYPE_PROCESSOR); static int sample_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void disconnect_signals (CcnetProcessor *processor) { } static void set_property (GObject *object, guint property_id, const GValue *v, GParamSpec *pspec) { CcnetSampleProcPriv *priv = GET_PRIV(object); switch (property_id) { case P_RATE: priv->rate = g_value_get_int (v); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void get_property (GObject *object, guint property_id, GValue *v, GParamSpec *pspec) { CcnetSampleProcPriv *priv = GET_PRIV(object); switch (property_id) { case P_RATE: g_value_set_int (v, priv->rate); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void release_resource(CcnetProcessor *processor) { /* Release the resource hold by this processor here. * * It will always be called either when the processor is shutdown * abnormally (via call ccnet_processor_shutdown()), * or when it finishes its task normally (via call ccnet_processor_done()). * * Note, you must release `all the timers' and `disconnect all the signals'. * The `retry_timer' will be freed by the default_release_resource() * in chain up. */ CcnetSampleProcPriv *priv = GET_PRIV (processor); /* clean the items in hash table, but do not unref the hash table self. */ g_hash_table_remove_all (priv->registered); /* if your processor connected any signals, disconnect it here */ disconnect_signals (processor); /* should always chain up */ CCNET_PROCESSOR_CLASS(ccnet_sample_proc_parent_class)->release_resource (processor); } static void shutdown (CcnetProcessor *processor) { /* The processor is shutdown abnormally. */ /* the release_resource() will be called after calling shutdown(), * so only do things that release_resource() does not do. */ /* Do not chain up here. */ } static void finalize (GObject *gobject); static void ccnet_sample_proc_class_init (CcnetSampleProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); proc_class->name = "sample-master-proc"; proc_class->start = sample_start; proc_class->handle_response = handle_response; proc_class->shutdown = shutdown; proc_class->release_resource = release_resource; gobject_class->set_property = set_property; gobject_class->get_property = get_property; gobject_class->finalize = finalize; g_object_class_install_property (gobject_class, P_RATE, g_param_spec_int ( "rate", NULL, "Transfer Rate", 0, INT_MAX, 0, G_PARAM_READWRITE)); g_type_class_add_private (klass, sizeof (CcnetSendfileProcPriv)); } static void ccnet_sample_proc_init (CcnetSampleProc *processor) { /* * The processor used be used multi-times for different peers. * And this function will only be called once. * * So only initialize things that will be used cross sessions. * * Normally, use start() for initialization, and use release_resouce() * for finalization. */ CcnetSampleProcPriv *priv = GET_PRIV (processor); priv->registered = g_hash_table_new (g_direct_hash, g_direct_equal); } static void finalize (GObject *gobject) { /* undo the things init() do */ CcnetSampleProcPriv *priv = GET_PRIV (processor); g_hash_table_unref (priv->registered); G_OBJECT_CLASS (ccnet_sample_proc_parent_class)->finalize (gobject); } static int timeout_cb(CcnetProcessor *processor) { ccnet_warning ("sample slave does not reponse to us\n"); ccnet_processor_done (processor, FALSE); /* return FALSE to cancel the timer */ return FALSE; } static int sample_start (CcnetProcessor *processor, int argc, char **argv) { CcnetSampleProcPriv *priv = GET_PRIV (processor); /* initialization here */ priv->rate = DEFAULT_RATE; processor->state = INIT; /* send request */ ccnet_processor_send_request (processor, "sample-slave"); processor->state = REQUEST_SENT; /* for convenient, the processor provide a retry_timer, you can * use it for other purpose. This timer will be freed automatically * in the default_shutdown() of CcnetProcessor base class. * * So if you override the default_shutdown(), you should * free the timer yourself. */ processor->retry_timer = ccnet_timer_new ((TimerCB)timeout_cb, processor, 10 * 1000); return 0; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (memcpy(code, "200", 3) == 0) { ccnet_processor_send_update (processor, "200", "OK", "sample update", strlen("sample update") + 1); ccnet_processor_done (processor, TRUE); } else { /* code and code_msg are ended with '\0' */ ccnet_warning ("Bad response from peer %s(%.8s), %s:%s\n", processor->peer->name, processor->peer->id, code, code_msg); ccnet_processor_done (processor, FALSE); } } ccnet-6.1.5/net/common/processors/sample-master-proc.h000066400000000000000000000022131317035602700227650ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SAMPLE_PROC_H #define CCNET_SAMPLE_PROC_H #include #include "processor.h" #define CCNET_TYPE_SAMPLE_PROC (ccnet_sample_proc_get_type ()) #define CCNET_SAMPLE_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SAMPLE_PROC, CcnetSampleProc)) #define CCNET_IS_SAMPLE_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SAMPLE_PROC)) #define CCNET_SAMPLE_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SAMPLE_PROC, CcnetSampleProcClass)) #define CCNET_IS_SAMPLE_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SAMPLE_PROC)) #define CCNET_SAMPLE_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SAMPLE_PROC, CcnetSampleProcClass)) typedef struct _CcnetSampleProc CcnetSampleProc; typedef struct _CcnetSampleProcClass CcnetSampleProcClass; struct _CcnetSampleProc { CcnetProcessor parent_instance; }; struct _CcnetSampleProcClass { CcnetProcessorClass parent_class; }; GType ccnet_sample_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/sample-slave-proc.c000066400000000000000000000073121317035602700226040ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "sample-slave-proc.h" #include "peer.h" #include "session.h" #define DEBUG_FLAG CCNET_DEBUG_PROCESSOR #include "log.h" enum { INIT }; typedef struct { int rate; } CcnetSampleSlaveProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SAMPLE_SLAVE_PROC, CcnetSampleSlaveProcPriv)) G_DEFINE_TYPE (CcnetSampleSlaveProc, ccnet_sample_slave_proc, CCNET_TYPE_PROCESSOR) static int sample_slave_start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { /* Release the resource hold by this processor here. * * It will always be called either when the processor is shutdown * abnormally (via call ccnet_processor_shutdown()), * or when it finishes its task normally (via call ccnet_processor_done()). * * Note, you must release `all the timers' and `disconnect all the signals'. * The `retry_timer' will be freed by the default_release_resource() * in chain up. */ /* should always chain up */ CCNET_PROCESSOR_CLASS(ccnet_sample_slave_proc_parent_class)->release_resource (gobject); } static void shutdown (CcnetProcessor *processor) { /* The processor is shutdown abnormally. */ /* the release_resource() will be called after calling shutdown(), * so only do things that release_resource() does not do. */ /* Do not chain up here. */ } static void ccnet_sample_slave_proc_class_init (CcnetSampleSlaveProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); proc_class->name = "sample-slave-proc"; proc_class->start = sample_slave_start; proc_class->handle_update = handle_update; proc_class->shutdown = shutdown; gobject_class->finalize = sample_slave_finalize; g_type_class_add_private (klass, sizeof(CcnetSampleSlaveProcPriv)); } static void ccnet_sample_slave_proc_init (CcnetSampleSlaveProc *processor) { /* * The processor used be used multi-times for different peers. * And this function will only be called once. * * So only initialize things that will be used cross sessions. * * Normally, use start() for initialization, and use release_resouce() * for finalization. */ } static void shutdown (CcnetProcessor *processor) { /* The processor is shutdown abnormally. */ /* the release_resource() will be called after calling shutdown(), * so only do things that release_resource() does not do. */ /* Do not chain up here. */ } static int sample_slave_start (CcnetProcessor *processor, int argc, char **argv) { CcnetSampleSlaveProcPriv *priv = GET_PRIV (processor); priv->rate = DEFAULT_RATE; processor->state = INIT; ccnet_processor_send_response (processor, "200", "OK", "sample response", strlen("sample response") + 1); return 0; } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (memcpy(code, "200", 3) == 0) { ccnet_processor_done (processor, TRUE); } else { /* code and code_msg are ended with '\0' */ ccnet_warning ("Bad update from peer %s(%.8s), %s:%s\n", processor->peer->name, processor->peer->id, code, code_msg); ccnet_processor_done (processor, FALSE); } } ccnet-6.1.5/net/common/processors/sample-slave-proc.h000066400000000000000000000024171317035602700226120ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SAMPLESLAVE_PROC_H #define CCNET_SAMPLESLAVE_PROC_H #include #include "processor.h" #define CCNET_TYPE_SAMPLE_SLAVE_PROC (ccnet_sample_slave_proc_get_type ()) #define CCNET_SAMPLE_SLAVE_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SAMPLE_SLAVE_PROC, CcnetSampleSlaveProc)) #define CCNET_IS_SAMPLE_SLAVE_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SAMPLE_SLAVE_PROC)) #define CCNET_SAMPLE_SLAVE_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SAMPLE_SLAVE_PROC, CcnetSampleSlaveProcClass)) #define CCNET_IS_SAMPLE_SLAVE_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SAMPLE_SLAVE_PROC)) #define CCNET_SAMPLE_SLAVE_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SAMPLE_SLAVE_PROC, CcnetSampleSlaveProcClass)) typedef struct _CcnetSampleSlaveProc CcnetSampleSlaveProc; typedef struct _CcnetSampleSlaveProcClass CcnetSampleSlaveProcClass; struct _CcnetSampleSlaveProc { CcnetProcessor parent_instance; }; struct _CcnetSampleSlaveProcClass { CcnetProcessorClass parent_class; }; GType ccnet_sample_slave_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/sendmsg-proc.c000066400000000000000000000057461317035602700216640ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include "session.h" #include "peer.h" #include "message.h" #include "sendmsg-proc.h" #include "message-manager.h" #define DEBUG_FLAG CCNET_DEBUG_MESSAGE #include "log.h" enum { REQUEST_SENT, CONNECTED }; typedef struct { CcnetMessage *message; } CcnetSendmsgProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SENDMSG_PROC, CcnetSendmsgProcPriv)) static int send_msg_start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetSendmsgProc, ccnet_sendmsg_proc, CCNET_TYPE_PROCESSOR) static void release_resource(CcnetProcessor *processor) { CcnetSendmsgProcPriv *priv = GET_PRIV (processor); ccnet_message_unref (priv->message); CCNET_PROCESSOR_CLASS (ccnet_sendmsg_proc_parent_class)->release_resource (processor); } static void ccnet_sendmsg_proc_class_init (CcnetSendmsgProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); /* GObjectClass *object_class = G_OBJECT_CLASS (klass); */ proc_class->name = "sendmsg-proc"; proc_class->start = send_msg_start; proc_class->handle_response = handle_response; proc_class->release_resource = release_resource; g_type_class_add_private (klass, sizeof (CcnetSendmsgProcPriv)); } static void ccnet_sendmsg_proc_init (CcnetSendmsgProc *processor) { } static int send_msg_start (CcnetProcessor *processor, int argc, char **argv) { char buf[256]; int len; len = snprintf (buf, 256, "receive-msg"); ccnet_processor_send_request (processor, buf); processor->state = REQUEST_SENT; return 0; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetSendmsgProcPriv *priv = GET_PRIV (processor); GString *msg_buf; switch (processor->state) { case REQUEST_SENT: processor->state = CONNECTED; char save_flags = priv->message->flags; msg_buf = g_string_new (NULL); ccnet_message_to_string_buf (priv->message, msg_buf); ccnet_processor_send_update (processor, "200", NULL, msg_buf->str, msg_buf->len+1); /* including '\0' */ g_string_free (msg_buf, TRUE); priv->message->flags = save_flags; break; case CONNECTED: ccnet_processor_done (processor, TRUE); break; default: break; } } int ccnet_sendmsg_proc_set_msg (CcnetSendmsgProc *sendmsg_proc, CcnetMessage *message) { CcnetSendmsgProcPriv *priv = GET_PRIV (sendmsg_proc); priv->message = message; ccnet_message_ref (message); return 0; } ccnet-6.1.5/net/common/processors/sendmsg-proc.h000066400000000000000000000024311317035602700216550ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SENDMSG_PROC_H #define CCNET_SENDMSG_PROC_H #include #include "processor.h" #define CCNET_TYPE_SENDMSG_PROC (ccnet_sendmsg_proc_get_type ()) #define CCNET_SENDMSG_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SENDMSG_PROC, CcnetSendmsgProc)) #define CCNET_IS_SENDMSG_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SENDMSG_PROC)) #define CCNET_SENDMSG_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SENDMSG_PROC, CcnetSendmsgProcClass)) #define CCNET_IS_SENDMSG_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SENDMSG_PROC)) #define CCNET_SENDMSG_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SENDMSG_PROC, CcnetSendmsgProcClass)) typedef struct _CcnetSendmsgProc CcnetSendmsgProc; typedef struct _CcnetSendmsgProcClass CcnetSendmsgProcClass; struct _CcnetSendmsgProc { CcnetProcessor parent_instance; }; struct _CcnetSendmsgProcClass { CcnetProcessorClass parent_class; }; GType ccnet_sendmsg_proc_get_type (); int ccnet_sendmsg_proc_set_msg (CcnetSendmsgProc *sendmsg_proc, CcnetMessage *msg); #endif ccnet-6.1.5/net/common/processors/sendsessionkey-proc.c000066400000000000000000000120501317035602700232540ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* After we get a peer's pubkey, we generate a session key (symmetric) to encrypt important data. receive-session-key A ---------------------------> B SC_SESSION_KEY (ask for session key) <--------------------------- SC_SESSION_KEY (encrypted with B's pubkey) ----------------------------> SC_OK <------------------------------- */ #include #include #include "session.h" #include "common.h" #include "processor.h" #include "peer-mgr.h" #include "peer.h" #include "log.h" #include "rsa.h" #include "sendsessionkey-proc.h" #define SC_SESSION_KEY "300" #define SS_SESSION_KEY "session key" #define SC_ALREADY_HAS_KEY "301" #define SS_ALREADY_HAS_KEY "already has your session key" #define SC_BAD_KEY "302" #define SS_BAD_KEY "bad session key" enum { INIT = 0, REQUEST_SENT, SESSION_KEY_SENT, }; typedef struct { char key[40]; int state; } CcnetSendsessionkeyProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SENDSESSIONKEY_PROC, CcnetSendsessionkeyProcPriv)) #define USE_PRIV \ CcnetSendsessionkeyProcPriv *priv = GET_PRIV(processor); G_DEFINE_TYPE (CcnetSendsessionkeyProc, ccnet_sendsessionkey_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { CCNET_PROCESSOR_CLASS (ccnet_sendsessionkey_proc_parent_class)->release_resource (processor); } static void ccnet_sendsessionkey_proc_class_init (CcnetSendsessionkeyProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "send-session-key"; proc_class->start = start; proc_class->handle_response = handle_response; proc_class->release_resource = release_resource; g_type_class_add_private (klass, sizeof (CcnetSendsessionkeyProcPriv)); } static void ccnet_sendsessionkey_proc_init (CcnetSendsessionkeyProc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { USE_PRIV; if (argc != 0) { ccnet_processor_done (processor, FALSE); return -1; } if (processor->peer->session_key) { ccnet_warning ("peer %.10s already has session key\n", processor->peer->id); ccnet_processor_done (processor, FALSE); return -1; } ccnet_processor_send_request (processor, "receive-session-key"); priv->state = REQUEST_SENT; return 0; } /* random bytes -> sha1 -> pubkey_encrypt -> transmit to peer */ static unsigned char * generate_session_key (CcnetProcessor *processor, int *len_p) { USE_PRIV; CcnetPeer *peer = processor->peer; unsigned char sha1[20]; unsigned char *enc_out = NULL; unsigned char random_buf[40]; SHA_CTX s; RAND_pseudo_bytes (random_buf, sizeof(random_buf)); SHA1_Init (&s); SHA1_Update (&s, random_buf, sizeof(random_buf)); SHA1_Final (sha1, &s); rawdata_to_hex (sha1, priv->key, 20); enc_out = public_key_encrypt (peer->pubkey, (unsigned char *)priv->key, 40, len_p); if (*len_p <= 0) { g_free (enc_out); return NULL; } return enc_out; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { USE_PRIV; if (strcmp(code, SC_SESSION_KEY) == 0 && priv->state == REQUEST_SENT) { unsigned char *enc_out = NULL; int len = 0; enc_out = generate_session_key(processor, &len); if (enc_out) { ccnet_processor_send_update (processor, SC_SESSION_KEY, SS_SESSION_KEY, (char *)enc_out, len); g_free (enc_out); priv->state = SESSION_KEY_SENT; } else { ccnet_warning ("failed to generate session key for peer %.10s\n", processor->peer->id); ccnet_processor_done (processor, FALSE); } } else if (strcmp(code, SC_OK) == 0 && priv->state == SESSION_KEY_SENT) { processor->peer->session_key = g_strndup(priv->key, 40); ccnet_peer_manager_on_peer_session_key_sent (processor->peer->manager, processor->peer); ccnet_processor_done (processor, TRUE); } else if (strcmp(code, SC_ALREADY_HAS_KEY) == 0) { /* already has session key, skip */ ccnet_processor_done (processor, TRUE); } else { ccnet_warning ("[send session key] bad response %s:%s\n", code, code_msg); ccnet_processor_done (processor, FALSE); } } ccnet-6.1.5/net/common/processors/sendsessionkey-proc.h000066400000000000000000000024651317035602700232720ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SENDSESSIONKEY_PROC_H #define CCNET_SENDSESSIONKEY_PROC_H #include #define CCNET_TYPE_SENDSESSIONKEY_PROC (ccnet_sendsessionkey_proc_get_type ()) #define CCNET_SENDSESSIONKEY_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SENDSESSIONKEY_PROC, CcnetSendsessionkeyProc)) #define CCNET_IS_SENDSESSIONKEY_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SENDSESSIONKEY_PROC)) #define CCNET_SENDSESSIONKEY_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SENDSESSIONKEY_PROC, CcnetSendsessionkeyProcClass)) #define IS_CCNET_SENDSESSIONKEY_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SENDSESSIONKEY_PROC)) #define CCNET_SENDSESSIONKEY_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SENDSESSIONKEY_PROC, CcnetSendsessionkeyProcClass)) typedef struct _CcnetSendsessionkeyProc CcnetSendsessionkeyProc; typedef struct _CcnetSendsessionkeyProcClass CcnetSendsessionkeyProcClass; struct _CcnetSendsessionkeyProc { CcnetProcessor parent_instance; }; struct _CcnetSendsessionkeyProcClass { CcnetProcessorClass parent_class; }; GType ccnet_sendsessionkey_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/sendsessionkey-v2-proc.c000066400000000000000000000130341317035602700236040ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* After we get a peer's pubkey, we generate a session key (symmetric) to encrypt important data. receive-skey-v2 [--enc-channel] A -------------------------------------------> B SC_SESSION_KEY <------------------------------- SC_SESSION_KEY (encrypted with B's pubkey) ----------------------------> SC_OK_ENCRYPT Or SC_NO_ENCRYPT <------------------------------------------ */ #include #include #include "session.h" #include "common.h" #include "processor.h" #include "peer-mgr.h" #include "peer.h" #include "log.h" #include "rsa.h" #include "sendsessionkey-v2-proc.h" #define SC_SESSION_KEY "300" #define SS_SESSION_KEY "session key" #define SC_ALREADY_HAS_KEY "301" #define SS_ALREADY_HAS_KEY "already has your session key" #define SC_NO_ENCRYPT "303" #define SS_NO_ENCRYPT "Donot encrypt channel" #define SC_BAD_KEY "400" #define SS_BAD_KEY "bad session key" enum { INIT = 0, REQUEST_SENT, SESSION_KEY_SENT, }; typedef struct { char key[40]; int state; } CcnetSendskey2ProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SENDSKEY2_PROC, CcnetSendskey2ProcPriv)) #define USE_PRIV \ CcnetSendskey2ProcPriv *priv = GET_PRIV(processor); G_DEFINE_TYPE (CcnetSendskey2Proc, ccnet_sendskey2_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { CCNET_PROCESSOR_CLASS (ccnet_sendskey2_proc_parent_class)->release_resource (processor); } static void ccnet_sendskey2_proc_class_init (CcnetSendskey2ProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "send-skey2"; proc_class->start = start; proc_class->handle_response = handle_response; proc_class->release_resource = release_resource; g_type_class_add_private (klass, sizeof (CcnetSendskey2ProcPriv)); } static void ccnet_sendskey2_proc_init (CcnetSendskey2Proc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { USE_PRIV; if (argc != 0) { ccnet_processor_done (processor, FALSE); return -1; } gboolean encrypt_channel = ccnet_session_should_encrypt_channel ( processor->session); if (encrypt_channel) ccnet_processor_send_request (processor, "receive-skey2 --enc-channel"); else ccnet_processor_send_request (processor, "receive-skey2"); priv->state = REQUEST_SENT; return 0; } /* random bytes -> sha1 -> pubkey_encrypt -> transmit to peer */ static unsigned char * generate_session_key (CcnetProcessor *processor, int *len_p) { USE_PRIV; CcnetPeer *peer = processor->peer; unsigned char sha1[20]; unsigned char *enc_out = NULL; unsigned char random_buf[40]; SHA_CTX s; RAND_pseudo_bytes (random_buf, sizeof(random_buf)); SHA1_Init (&s); SHA1_Update (&s, random_buf, sizeof(random_buf)); SHA1_Final (sha1, &s); rawdata_to_hex (sha1, priv->key, 20); enc_out = public_key_encrypt (peer->pubkey, (unsigned char *)priv->key, 40, len_p); if (*len_p <= 0) { g_free (enc_out); return NULL; } return enc_out; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { USE_PRIV; if (strcmp(code, SC_SESSION_KEY) == 0 && priv->state == REQUEST_SENT) { unsigned char *enc_out = NULL; int len = 0; enc_out = generate_session_key(processor, &len); if (enc_out) { ccnet_processor_send_update (processor, SC_SESSION_KEY, SS_SESSION_KEY, (char *)enc_out, len); g_free (enc_out); priv->state = SESSION_KEY_SENT; } else { ccnet_warning ("failed to generate session key for peer %.10s\n", processor->peer->id); ccnet_processor_done (processor, FALSE); } } else if (strcmp(code, SC_OK) == 0 && priv->state == SESSION_KEY_SENT) { processor->peer->session_key = g_strndup(priv->key, 40); if (ccnet_session_should_encrypt_channel (processor->session)) ccnet_peer_prepare_channel_encryption (processor->peer); ccnet_peer_manager_on_peer_session_key_sent (processor->peer->manager, processor->peer); ccnet_processor_done (processor, TRUE); } else if (strcmp(code, SC_ALREADY_HAS_KEY) == 0) { /* already has session key, skip */ ccnet_processor_done (processor, TRUE); } else if (strcmp(code, SC_NO_ENCRYPT) == 0) { processor->peer->session_key = g_strndup(priv->key, 40); ccnet_peer_manager_on_peer_session_key_sent (processor->peer->manager, processor->peer); ccnet_processor_done (processor, TRUE); } else { ccnet_warning ("[send session key] bad response %s:%s\n", code, code_msg); ccnet_processor_done (processor, FALSE); } } ccnet-6.1.5/net/common/processors/sendsessionkey-v2-proc.h000066400000000000000000000022751317035602700236160ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SENDSKEY2_PROC_H #define CCNET_SENDSKEY2_PROC_H #include #define CCNET_TYPE_SENDSKEY2_PROC (ccnet_sendskey2_proc_get_type ()) #define CCNET_SENDSKEY2_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SENDSKEY2_PROC, CcnetSendskey2Proc)) #define CCNET_IS_SENDSKEY2_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SENDSKEY2_PROC)) #define CCNET_SENDSKEY2_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SENDSKEY2_PROC, CcnetSendskey2ProcClass)) #define IS_CCNET_SENDSKEY2_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SENDSKEY2_PROC)) #define CCNET_SENDSKEY2_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SENDSKEY2_PROC, CcnetSendskey2ProcClass)) typedef struct _CcnetSendskey2Proc CcnetSendskey2Proc; typedef struct _CcnetSendskey2ProcClass CcnetSendskey2ProcClass; struct _CcnetSendskey2Proc { CcnetProcessor parent_instance; }; struct _CcnetSendskey2ProcClass { CcnetProcessorClass parent_class; }; GType ccnet_sendskey2_proc_get_type (); #endif ccnet-6.1.5/net/common/processors/service-proxy-proc.c000066400000000000000000000134421317035602700230330ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "session.h" #include "peer.h" #include "peer-mgr.h" #include "proc-factory.h" #include "service-proxy-proc.h" #include "service-stub-proc.h" #define DEBUG_FLAG CCNET_DEBUG_PROCESSOR #include "log.h" #define SC_BAD_CMD_FMT "400" #define SS_BAD_CMD_FMT "Bad command format" typedef struct { CcnetServiceStubProc *stub_proc; char *name; } ServiceProxyPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SERVICE_PROXY_PROC, ServiceProxyPriv)) static int service_proxy_start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); /* called by stub processor */ static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetServiceProxyProc, ccnet_service_proxy_proc, CCNET_TYPE_PROCESSOR) static void release_resource(CcnetProcessor *processor) { ServiceProxyPriv *priv = GET_PRIV(processor); if (priv->name) { g_free (priv->name); priv->name = NULL; } /* should always chain up */ CCNET_PROCESSOR_CLASS(ccnet_service_proxy_proc_parent_class)->release_resource (processor); } static void ccnet_service_proxy_proc_class_init (CcnetServiceProxyProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); /* GObjectClass *object_class = G_OBJECT_CLASS (klass); */ proc_class->name = "service-proxy-proc"; proc_class->start = service_proxy_start; proc_class->handle_update = handle_update; proc_class->handle_response = handle_response; proc_class->release_resource = release_resource; g_type_class_add_private (klass, sizeof (ServiceProxyPriv)); } static void ccnet_service_proxy_proc_init (CcnetServiceProxyProc *processor) { ServiceProxyPriv *priv = GET_PRIV(processor); priv->name = NULL; } static int service_proxy_start (CcnetProcessor *processor, int argc, char **argv) { return 0; } static char* proc_name_strjoin_n (const char *seperator, int argc, char **argv) { GString *buf; int i; char *str; buf = g_string_new (argv[0]); for (i = 1; i < argc; ++i) { g_string_append (buf, seperator); g_string_append (buf, argv[i]); } str = buf->str; g_string_free (buf, FALSE); return str; } void ccnet_service_proxy_invoke_remote (CcnetProcessor *processor, CcnetPeer *remote, int argc, char **argv) { CcnetServiceStubProc *stub_proc; ServiceProxyPriv *priv = GET_PRIV(processor); if (argc < 1) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); ccnet_processor_done (processor, FALSE); return; } priv->name = proc_name_strjoin_n(" ", argc, argv); stub_proc = CCNET_SERVICE_STUB_PROC ( ccnet_proc_factory_create_master_processor ( processor->session->proc_factory, "service-stub", remote) ); priv->stub_proc = stub_proc; ccnet_service_stub_proc_set_proxy_proc (stub_proc, processor); /* Start can fail if the remote end is not connected. */ if (ccnet_processor_start (CCNET_PROCESSOR(stub_proc), argc, argv) < 0) { ccnet_processor_send_response (processor, SC_PROC_DEAD, SS_PROC_DEAD, NULL, 0); ccnet_processor_done (processor, FALSE); } } /* TODO: the same as above, can use one function instead */ void ccnet_service_proxy_invoke_local (CcnetProcessor *processor, CcnetPeer *local, int argc, char **argv) { CcnetServiceStubProc *stub_proc; ServiceProxyPriv *priv = GET_PRIV(processor); if (argc < 1) { ccnet_processor_send_response (processor, SC_BAD_CMD_FMT, SS_BAD_CMD_FMT, NULL, 0); ccnet_processor_done (processor, FALSE); return; } priv->name = proc_name_strjoin_n(" ", argc, argv); stub_proc = CCNET_SERVICE_STUB_PROC ( ccnet_proc_factory_create_master_processor ( processor->session->proc_factory, "service-stub", local) ); priv->stub_proc = stub_proc; ccnet_service_stub_proc_set_proxy_proc (stub_proc, processor); ccnet_processor_start (CCNET_PROCESSOR(stub_proc), argc, argv); } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { ServiceProxyPriv *priv = GET_PRIV (processor); if(!priv->stub_proc || !((CcnetProcessor *)priv->stub_proc)->peer->is_local) ccnet_debug ("[Svc Proxy] %s:%d [%s] handle update: %s %s\n", GET_PNAME(processor), PRINT_ID(processor->id), priv->name, code, code_msg); ccnet_processor_handle_update ((CcnetProcessor *)priv->stub_proc, code, code_msg, content, clen); } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { ServiceProxyPriv *priv = GET_PRIV (processor); if(!priv->stub_proc || !((CcnetProcessor *)priv->stub_proc)->peer->is_local) ccnet_debug ("[Svc Proxy] %s:%d [%s] handle response: %s %s\n", GET_PNAME(processor), PRINT_ID(processor->id), priv->name, code, code_msg); /* relay this response */ ccnet_processor_send_response (processor, code, code_msg, content, clen); } ccnet-6.1.5/net/common/processors/service-proxy-proc.h000066400000000000000000000032441317035602700230370ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SERVICE_PROXY_PROC_H #define CCNET_SERVICE_PROXY_PROC_H #include #include "processor.h" #define CCNET_TYPE_SERVICE_PROXY_PROC (ccnet_service_proxy_proc_get_type ()) #define CCNET_SERVICE_PROXY_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SERVICE_PROXY_PROC, CcnetServiceProxyProc)) #define CCNET_IS_SERVICE_PROXY_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SERVICE_PROXY_PROC)) #define CCNET_SERVICE_PROXY_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SERVICE_PROXY_PROC, CcnetServiceProxyProcClass)) #define CCNET_IS_SERVICE_PROXY_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SERVICE_PROXY_PROC)) #define CCNET_SERVICE_PROXY_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SERVICE_PROXY_PROC, CcnetServiceProxyProcClass)) typedef struct _CcnetServiceProxyProc CcnetServiceProxyProc; typedef struct _CcnetServiceProxyProcClass CcnetServiceProxyProcClass; struct _CcnetServiceProxyProc { CcnetProcessor parent_instance; }; struct _CcnetServiceProxyProcClass { CcnetProcessorClass parent_class; }; GType ccnet_service_proxy_proc_get_type (); void ccnet_service_proxy_invoke_remote (CcnetProcessor *processor, CcnetPeer *remote, int argc, char **argv); void ccnet_service_proxy_invoke_local (CcnetProcessor *processor, CcnetPeer *local, int argc, char **argv); #endif ccnet-6.1.5/net/common/processors/service-stub-proc.c000066400000000000000000000066351317035602700226350ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "peer.h" #include "service-stub-proc.h" #include "service-proxy-proc.h" #define DEBUG_FLAG CCNET_DEBUG_OTHER #include "log.h" typedef struct { CcnetServiceProxyProc *proxy_proc; } ServiceStubPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_SERVICE_STUB_PROC, ServiceStubPriv)) static int service_stub_start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); G_DEFINE_TYPE (CcnetServiceStubProc, ccnet_service_stub_proc, CCNET_TYPE_PROCESSOR) static void ccnet_service_stub_proc_class_init (CcnetServiceStubProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); /* GObjectClass *object_class = G_OBJECT_CLASS (klass); */ proc_class->name = "service-stub-proc"; proc_class->start = service_stub_start; proc_class->handle_update = handle_update; proc_class->handle_response = handle_response; g_type_class_add_private (klass, sizeof (ServiceStubPriv)); } static void ccnet_service_stub_proc_init (CcnetServiceStubProc *processor) { } static void strnjoin (int n, char **strs, GString *buf) { int i; if (n == 0) return; g_string_append (buf, strs[0]); for (i = 1; i < n; i++) { g_string_append (buf, " "); g_string_append (buf, strs[i]); } } static int service_stub_start (CcnetProcessor *processor, int argc, char **argv) { GString *buf; ServiceStubPriv *priv = GET_PRIV (processor); g_return_val_if_fail (priv->proxy_proc != NULL, -1); buf = g_string_new (NULL); CcnetProcessor *pproc = (CcnetProcessor *)priv->proxy_proc; if (!pproc->peer->is_local) { /* remote? (this may be wrong) */ g_string_append (buf, "remote "); g_string_append (buf, pproc->peer->id); g_string_append (buf, " "); } strnjoin (argc, argv, buf); ccnet_processor_send_request (processor, buf->str); g_string_free (buf, TRUE); return 0; } void ccnet_service_stub_proc_set_proxy_proc (CcnetServiceStubProc *proc, CcnetProcessor *proxy_proc) { ServiceStubPriv *priv = GET_PRIV (proc); priv->proxy_proc = (CcnetServiceProxyProc *)proxy_proc; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { ServiceStubPriv *priv = GET_PRIV (processor); /* ccnet_debug ("[Svc Stub] %d handle response: %s %s\n", */ /* PRINT_ID(processor->id), code, code_msg); */ ccnet_processor_handle_response ((CcnetProcessor *)priv->proxy_proc, code, code_msg, content, clen); } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { /* ccnet_debug ("[Svc Stub] %d handle update: %s %s\n", */ /* PRINT_ID(processor->id), code, code_msg); */ ccnet_processor_send_update (processor, code, code_msg, content, clen); } ccnet-6.1.5/net/common/processors/service-stub-proc.h000066400000000000000000000031711317035602700226320ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SERVICE_STUB_PROC_H #define CCNET_SERVICE_STUB_PROC_H #include #include "processor.h" #define CCNET_TYPE_SERVICE_STUB_PROC (ccnet_service_stub_proc_get_type ()) #define CCNET_SERVICE_STUB_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SERVICE_STUB_PROC, CcnetServiceStubProc)) #define CCNET_IS_SERVICE_STUB_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SERVICE_STUB_PROC)) #define CCNET_SERVICE_STUB_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SERVICE_STUB_PROC, CcnetServiceStubProcClass)) #define CCNET_IS_SERVICE_STUB_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SERVICE_STUB_PROC)) #define CCNET_SERVICE_STUB_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SERVICE_STUB_PROC, CcnetServiceStubProcClass)) typedef struct _CcnetServiceStubProc CcnetServiceStubProc; typedef struct _CcnetServiceStubProcClass CcnetServiceStubProcClass; struct _CcnetServiceStubProc { CcnetProcessor parent_instance; }; struct _CcnetServiceStubProcClass { CcnetProcessorClass parent_class; }; GType ccnet_service_stub_proc_get_type (); void ccnet_service_stub_proc_set_proxy_proc (CcnetServiceStubProc *proc, CcnetProcessor *processor); void ccnet_service_stub_proc_send_update (CcnetServiceStubProc *proc, char *code, char *code_msg, char *content, int clen); #endif ccnet-6.1.5/net/common/processors/threaded-rpcserver-proc.c000066400000000000000000000114341317035602700240040ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "include.h" #include "server-session.h" #include "threaded-rpcserver-proc.h" #include "searpc-server.h" #include "rpc-common.h" #include "job-mgr.h" typedef struct { char *call_buf; gsize call_len; char *buf; gsize len; int off; char *error_message; } CcnetThreadedRpcserverProcPriv; #define GET_PRIV(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_THREADED_RPCSERVER_PROC, CcnetThreadedRpcserverProcPriv)) G_DEFINE_TYPE (CcnetThreadedRpcserverProc, ccnet_threaded_rpcserver_proc, CCNET_TYPE_PROCESSOR) static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { CcnetThreadedRpcserverProcPriv *priv = GET_PRIV (processor); g_free (priv->buf); CCNET_PROCESSOR_CLASS (ccnet_threaded_rpcserver_proc_parent_class)->release_resource (processor); } static void ccnet_threaded_rpcserver_proc_class_init (CcnetThreadedRpcserverProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->start = start; proc_class->handle_update = handle_update; proc_class->release_resource = release_resource; proc_class->name = "threaded-rpcserver-proc"; g_type_class_add_private (klass, sizeof(CcnetThreadedRpcserverProcPriv)); } static void ccnet_threaded_rpcserver_proc_init (CcnetThreadedRpcserverProc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { ccnet_processor_send_response (processor, SC_OK, SS_OK, NULL, 0); return 0; } static void * call_function_job (void *vprocessor) { CcnetProcessor *processor = vprocessor; CcnetThreadedRpcserverProcPriv *priv = GET_PRIV(processor); char *svc_name = processor->name; priv->buf = searpc_server_call_function (svc_name, priv->call_buf, priv->call_len, &priv->len); g_free (priv->call_buf); return vprocessor; } static void call_function_done (void *vprocessor) { CcnetProcessor *processor = vprocessor; CcnetThreadedRpcserverProcPriv *priv = GET_PRIV(processor); if (priv->buf) { if (priv->len < MAX_TRANSFER_LENGTH) { ccnet_processor_send_response (processor, SC_SERVER_RET, SS_SERVER_RET, priv->buf, priv->len); g_free (priv->buf); priv->buf = NULL; /* ccnet_processor_done (processor, TRUE); */ return; } /* we need to split data into multiple segments */ ccnet_processor_send_response (processor, SC_SERVER_MORE, SS_SERVER_MORE, priv->buf, MAX_TRANSFER_LENGTH); priv->off = MAX_TRANSFER_LENGTH; } else { char *message = priv->error_message ? priv->error_message : ""; ccnet_processor_send_response (processor, SC_SERVER_ERR, message, NULL, 0); g_free (priv->error_message); ccnet_processor_done (processor, FALSE); } } static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { CcnetThreadedRpcserverProcPriv *priv = GET_PRIV (processor); if (memcmp (code, SC_CLIENT_CALL, 3) == 0) { priv->call_buf = g_memdup (content, clen); priv->call_len = (gsize)clen; ccnet_processor_thread_create (processor, NULL, call_function_job, call_function_done, processor); return; } if (memcmp (code, SC_CLIENT_MORE, 3) == 0) { if (priv->off + MAX_TRANSFER_LENGTH < priv->len) { ccnet_processor_send_response ( processor, SC_SERVER_MORE, SS_SERVER_MORE, priv->buf + priv->off, MAX_TRANSFER_LENGTH); priv->off += MAX_TRANSFER_LENGTH; } else { ccnet_processor_send_response ( processor, SC_SERVER_RET, SS_SERVER_RET, priv->buf + priv->off, priv->len - priv->off); g_free (priv->buf); priv->buf = NULL; /* ccnet_processor_done (processor, TRUE); */ } return; } ccnet_processor_send_response (processor, SC_BAD_UPDATE_CODE, SS_BAD_UPDATE_CODE, NULL, 0); g_warning ("[rpc-server] Bad update: %s %s.\n", code, code_msg); ccnet_processor_done (processor, FALSE); } ccnet-6.1.5/net/common/processors/threaded-rpcserver-proc.h000066400000000000000000000026421317035602700240120ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_THREADED_RPCSERVER_PROC_H #define CCNET_THREADED_RPCSERVER_PROC_H #include #include "processor.h" #define CCNET_TYPE_THREADED_RPCSERVER_PROC (ccnet_threaded_rpcserver_proc_get_type ()) #define CCNET_THREADED_RPCSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_THREADED_RPCSERVER_PROC, CcnetThreadedRpcserverProc)) #define CCNET_IS_THREADED_RPCSERVER_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_THREADED_RPCSERVER_PROC)) #define CCNET_THREADED_RPCSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_THREADED_RPCSERVER_PROC, CcnetThreadedRpcserverProcClass)) #define IS_CCNET_THREADED_RPCSERVER_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_THREADED_RPCSERVER_PROC)) #define CCNET_THREADED_RPCSERVER_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_THREADED_RPCSERVER_PROC, CcnetThreadedRpcserverProcClass)) typedef struct _CcnetThreadedRpcserverProc CcnetThreadedRpcserverProc; typedef struct _CcnetThreadedRpcserverProcClass CcnetThreadedRpcserverProcClass; struct _CcnetThreadedRpcserverProc { CcnetProcessor parent_instance; }; struct _CcnetThreadedRpcserverProcClass { CcnetProcessorClass parent_class; }; GType ccnet_threaded_rpcserver_proc_get_type (); #endif ccnet-6.1.5/net/common/rpc-service.c000066400000000000000000001444121317035602700172750ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include "peer.h" #include "session.h" #include "peer-mgr.h" #include "proc-factory.h" #include "rpc-service.h" #include "ccnet-object.h" #include "processors/rpcserver-proc.h" #ifdef CCNET_SERVER #include "processors/threaded-rpcserver-proc.h" #endif #include "searpc-server.h" #include "ccnet-config.h" #ifdef CCNET_SERVER #include "server-session.h" #endif #define DEBUG_FLAG CCNET_DEBUG_OTHER #include "log.h" #include "rsa.h" #define CCNET_ERR_INTERNAL 500 extern CcnetSession *session; #include #include "searpc-signature.h" #include "searpc-marshal.h" void ccnet_start_rpc(CcnetSession *session) { searpc_server_init (register_marshals); searpc_create_service ("ccnet-rpcserver"); ccnet_proc_factory_register_processor (session->proc_factory, "ccnet-rpcserver", CCNET_TYPE_RPCSERVER_PROC); #ifdef CCNET_SERVER searpc_create_service ("ccnet-threaded-rpcserver"); ccnet_proc_factory_register_processor (session->proc_factory, "ccnet-threaded-rpcserver", CCNET_TYPE_THREADED_RPCSERVER_PROC); #endif searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_list_peers, "list_peers", searpc_signature_string__void()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_list_resolving_peers, "list_resolving_peers", searpc_signature_objlist__void()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_get_peers_by_role, "get_peers_by_role", searpc_signature_objlist__string()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_get_peer, "get_peer", searpc_signature_object__string()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_get_peer_by_idname, "get_peer_by_idname", searpc_signature_object__string()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_update_peer_address, "update_peer_address", searpc_signature_int__string_string_int()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_get_session_info, "get_session_info", searpc_signature_object__void()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_add_client, "add_client", searpc_signature_int__string()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_add_role, "add_role", searpc_signature_int__string_string()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_remove_role, "remove_role", searpc_signature_int__string_string()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_get_config, "get_config", searpc_signature_string__string()); searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_set_config, "set_config", searpc_signature_int__string_string()); /* RSA encrypt a message with peer's public key. */ searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_pubkey_encrypt, "pubkey_encrypt", searpc_signature_string__string_string()); /* RSA decrypt a message with my private key. */ searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_privkey_decrypt, "privkey_decrypt", searpc_signature_string__string()); #ifdef CCNET_SERVER searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_list_peer_stat, "list_peer_stat", searpc_signature_objlist__void()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_add_emailuser, "add_emailuser", searpc_signature_int__string_string_int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_remove_emailuser, "remove_emailuser", searpc_signature_int__string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_validate_emailuser, "validate_emailuser", searpc_signature_int__string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_emailuser, "get_emailuser", searpc_signature_object__string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_emailuser_with_import, "get_emailuser_with_import", searpc_signature_object__string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_emailuser_by_id, "get_emailuser_by_id", searpc_signature_object__int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_emailusers, "get_emailusers", searpc_signature_objlist__string_int_int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_search_emailusers, "search_emailusers", searpc_signature_objlist__string_string_int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_search_ldapusers, "search_ldapusers", searpc_signature_objlist__string_int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_count_emailusers, "count_emailusers", searpc_signature_int64__string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_count_inactive_emailusers, "count_inactive_emailusers", searpc_signature_int64__string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_update_emailuser, "update_emailuser", searpc_signature_int__string_int_string_int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_update_role_emailuser, "update_role_emailuser", searpc_signature_int__string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_superusers, "get_superusers", searpc_signature_objlist__void()); /* RSA sign a message with my private key. */ searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_sign_message, "sign_message", searpc_signature_string__string()); /* Verify a message with a peer's public key */ searpc_server_register_function ("ccnet-rpcserver", ccnet_rpc_verify_message, "verify_message", searpc_signature_int__string_string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_create_group, "create_group", searpc_signature_int__string_string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_create_org_group, "create_org_group", searpc_signature_int__int_string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_remove_group, "remove_group", searpc_signature_int__int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_group_add_member, "group_add_member", searpc_signature_int__int_string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_group_remove_member, "group_remove_member", searpc_signature_int__int_string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_group_set_admin, "group_set_admin", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_group_unset_admin, "group_unset_admin", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_set_group_name, "set_group_name", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_quit_group, "quit_group", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_groups, "get_groups", searpc_signature_objlist__string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_all_groups, "get_all_groups", searpc_signature_objlist__int_int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_group, "get_group", searpc_signature_object__int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_group_members, "get_group_members", searpc_signature_objlist__int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_check_group_staff, "check_group_staff", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_remove_group_user, "remove_group_user", searpc_signature_int__string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_is_group_user, "is_group_user", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_set_group_creator, "set_group_creator", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_create_org, "create_org", searpc_signature_int__string_string_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_remove_org, "remove_org", searpc_signature_int__int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_all_orgs, "get_all_orgs", searpc_signature_objlist__int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_count_orgs, "count_orgs", searpc_signature_int64__void()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_org_by_url_prefix, "get_org_by_url_prefix", searpc_signature_object__string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_org_by_id, "get_org_by_id", searpc_signature_object__int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_add_org_user, "add_org_user", searpc_signature_int__int_string_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_remove_org_user, "remove_org_user", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_orgs_by_user, "get_orgs_by_user", searpc_signature_objlist__string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_org_emailusers, "get_org_emailusers", searpc_signature_objlist__string_int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_add_org_group, "add_org_group", searpc_signature_int__int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_remove_org_group, "remove_org_group", searpc_signature_int__int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_is_org_group, "is_org_group", searpc_signature_int__int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_org_id_by_group, "get_org_id_by_group", searpc_signature_int__int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_get_org_groups, "get_org_groups", searpc_signature_objlist__int_int_int()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_org_user_exists, "org_user_exists", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_is_org_staff, "is_org_staff", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_set_org_staff, "set_org_staff", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_unset_org_staff, "unset_org_staff", searpc_signature_int__int_string()); searpc_server_register_function ("ccnet-threaded-rpcserver", ccnet_rpc_set_org_name, "set_org_name", searpc_signature_int__int_string()); #endif /* CCNET_SERVER */ } char * ccnet_rpc_list_peers(GError **error) { CcnetPeerManager *peer_mgr = session->peer_mgr; GList *peer_list, *ptr; GString *result; CcnetPeer *peer; peer_list = ccnet_peer_manager_get_peer_list(peer_mgr); if (peer_list == NULL) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Failed to get peer list"); return NULL; } result = g_string_new(""); ptr = peer_list; while (ptr) { peer = ptr->data; g_string_append_printf(result, "%s\n", peer->id); ptr = ptr->next; } g_list_free(peer_list); return g_string_free(result, FALSE); } GList * ccnet_rpc_list_resolving_peers (GError **error) { CcnetPeerManager *peer_mgr = session->peer_mgr; return ccnet_peer_manager_get_resolve_peers(peer_mgr); } GList * ccnet_rpc_get_peers_by_role(const char *role, GError **error) { CcnetPeerManager *peer_mgr = session->peer_mgr; return ccnet_peer_manager_get_peers_with_role (peer_mgr, role); } GObject * ccnet_rpc_get_peer(const char *peer_id, GError **error) { if (!peer_id) return NULL; CcnetPeerManager *peer_mgr = session->peer_mgr; CcnetPeer *peer = ccnet_peer_manager_get_peer(peer_mgr, peer_id); return (GObject*)peer; } int ccnet_rpc_update_peer_address (const char *peer_id, const char *addr, int port, GError **error) { if (!peer_id || !addr || port <= 0 || port > 65536) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Invalid arguments"); return -1; } CcnetPeer *peer = ccnet_peer_manager_get_peer (session->peer_mgr, peer_id); if (!peer) { return -1; } ccnet_peer_manager_set_peer_public_addr (session->peer_mgr, peer, addr, port); g_object_unref (peer); return 0; } GObject * ccnet_rpc_get_peer_by_idname(const char *idname, GError **error) { if (!idname) return NULL; CcnetPeerManager *peer_mgr = session->peer_mgr; CcnetPeer *peer = ccnet_peer_manager_get_peer(peer_mgr, idname); if (!peer) peer = ccnet_peer_manager_get_peer_by_name (peer_mgr, idname); if (peer) { return (GObject*)peer; } return NULL; } GObject * ccnet_rpc_get_session_info(GError **error) { g_object_ref (session); return (GObject*)session; } int ccnet_rpc_add_client(const char *peer_id, GError **error) { CcnetPeerManager *mgr = session->peer_mgr; CcnetPeer *peer; if (strlen(peer_id) != 40) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Peer ID must be of length 40"); return -1; } peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (mgr, peer); } ccnet_peer_manager_add_role (mgr, peer, "MyClient"); g_object_unref (peer); return 0; } int ccnet_rpc_add_role(const char *peer_id, const char *role, GError **error) { CcnetPeerManager *mgr = session->peer_mgr; CcnetPeer *peer; if (!peer_id || strlen(peer_id) != 40) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Peer ID must be of length 40"); return -1; } if (!role || strlen(role) <= 2) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Invalid role"); return -1; } peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "No such peer"); return -1; } ccnet_peer_manager_add_role (mgr, peer, role); g_object_unref (peer); return 0; } int ccnet_rpc_remove_role(const char *peer_id, const char *role, GError **error) { CcnetPeerManager *mgr = session->peer_mgr; CcnetPeer *peer; if (!peer_id || strlen(peer_id) != 40) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Peer ID must be of length 40"); return -1; } if (!role || strlen(role) <= 2) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Invalid role"); return -1; } peer = ccnet_peer_manager_get_peer (mgr, peer_id); if (!peer) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "No such peer"); return -1; } ccnet_peer_manager_remove_role (mgr, peer, role); g_object_unref (peer); return 0; } char * ccnet_rpc_get_config (const char *key, GError **error) { return ccnet_session_config_get_string (session, key); } int ccnet_rpc_set_config (const char *key, const char *value, GError **error) { return ccnet_session_config_set_string (session, key, value); } char * ccnet_rpc_pubkey_encrypt (const char *msg_base64, const char *peer_id, GError **error) { unsigned char *msg; gsize msg_len; CcnetPeer *peer; unsigned char *enc_msg; int enc_msg_len; char *ret; peer = ccnet_peer_manager_get_peer (session->peer_mgr, peer_id); if (!peer) { g_warning ("Cannot find peer %s.\n", peer_id); return NULL; } msg = g_base64_decode (msg_base64, &msg_len); enc_msg = public_key_encrypt (peer->pubkey, msg, (int)msg_len, &enc_msg_len); ret = g_base64_encode (enc_msg, enc_msg_len); g_free (msg); g_free (enc_msg); g_object_unref (peer); return ret; } char * ccnet_rpc_privkey_decrypt (const char *msg_base64, GError **error) { unsigned char *msg; gsize msg_len; unsigned char *dec_msg; int dec_msg_len; char *ret; msg = g_base64_decode (msg_base64, &msg_len); dec_msg = private_key_decrypt (session->privkey, msg, (int)msg_len, &dec_msg_len); if (dec_msg_len < 0) { g_warning ("Failed to decrypt message with RSA priv key.\n"); g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Failed to decrypt"); g_free (msg); return NULL; } ret = g_base64_encode (dec_msg, dec_msg_len); g_free (msg); g_free (dec_msg); return ret; } #ifdef CCNET_SERVER #include "user-mgr.h" #include "group-mgr.h" #include "org-mgr.h" GList * ccnet_rpc_list_peer_stat (GError **error) { GList *res = NULL; GList *ptr, *peer_list; CcnetPeer *peer; CcnetPeerManager *peer_mgr = session->peer_mgr; peer_list = ccnet_peer_manager_get_peer_list(peer_mgr); if (peer_list == NULL) { g_set_error(error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Failed to get peer list"); return NULL; } ptr = peer_list; while (ptr) { peer = ptr->data; if (peer->is_self) { ptr = ptr->next; continue; } guint proc_num = g_hash_table_size (peer->processors); CcnetPeerStat* stat = ccnet_peer_stat_new (); g_object_set (stat, "id", peer->id, "name", peer->name, "ip", peer->addr_str, "encrypt", peer->encrypt_channel, "last_up", (gint64) peer->last_up, "proc_num", (int)proc_num, NULL); res = g_list_prepend (res, stat); ptr = ptr->next; } g_list_free(peer_list); return g_list_reverse (res); } int ccnet_rpc_add_emailuser (const char *email, const char *passwd, int is_staff, int is_active, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; int ret; if (!email || !passwd) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Email and passwd can not be NULL"); return -1; } ret = ccnet_user_manager_add_emailuser (user_mgr, email, passwd, is_staff, is_active); return ret; } int ccnet_rpc_remove_emailuser (const char *source, const char *email, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; int ret; if (!email) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Email can not be NULL"); return -1; } ret = ccnet_user_manager_remove_emailuser (user_mgr, source, email); return ret; } int ccnet_rpc_validate_emailuser (const char *email, const char *passwd, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; int ret; if (!email || !passwd) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Email and passwd can not be NULL"); return -1; } if (passwd[0] == 0) return -1; ret = ccnet_user_manager_validate_emailuser (user_mgr, email, passwd); return ret; } GObject* ccnet_rpc_get_emailuser (const char *email, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; CcnetEmailUser *emailuser = NULL; emailuser = ccnet_user_manager_get_emailuser (user_mgr, email); return (GObject *)emailuser; } GObject* ccnet_rpc_get_emailuser_with_import (const char *email, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; CcnetEmailUser *emailuser = NULL; emailuser = ccnet_user_manager_get_emailuser_with_import (user_mgr, email); return (GObject *)emailuser; } GObject* ccnet_rpc_get_emailuser_by_id (int id, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; CcnetEmailUser *emailuser = NULL; emailuser = ccnet_user_manager_get_emailuser_by_id (user_mgr, id); return (GObject *)emailuser; } GList* ccnet_rpc_get_emailusers (const char *source, int start, int limit, const char *status, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; GList *emailusers = NULL; emailusers = ccnet_user_manager_get_emailusers (user_mgr, source, start, limit, status); return emailusers; } GList* ccnet_rpc_search_emailusers (const char *source, const char *email_patt, int start, int limit, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; GList *emailusers = NULL; emailusers = ccnet_user_manager_search_emailusers (user_mgr, source, email_patt, start, limit); return emailusers; } GList* ccnet_rpc_search_ldapusers (const char *keyword, int start, int limit, GError **error) { GList *ldapusers = NULL; CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; ldapusers = ccnet_user_manager_search_ldapusers (user_mgr, keyword, start, limit); return ldapusers; } gint64 ccnet_rpc_count_emailusers (const char *source, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; return ccnet_user_manager_count_emailusers (user_mgr, source); } gint64 ccnet_rpc_count_inactive_emailusers (const char *source, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; return ccnet_user_manager_count_inactive_emailusers (user_mgr, source); } #if 0 GList* ccnet_rpc_filter_emailusers_by_emails (const char *emails, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; if (!emails || g_strcmp0 (emails, "") == 0) return NULL; return ccnet_user_manager_filter_emailusers_by_emails (user_mgr, emails); } #endif int ccnet_rpc_update_emailuser (const char *source, int id, const char* passwd, int is_staff, int is_active, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; return ccnet_user_manager_update_emailuser(user_mgr, source, id, passwd, is_staff, is_active); } int ccnet_rpc_update_role_emailuser (const char* email, const char* role, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; return ccnet_user_manager_update_role_emailuser(user_mgr, email, role); } GList* ccnet_rpc_get_superusers (GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; return ccnet_user_manager_get_superusers(user_mgr); } char * ccnet_rpc_sign_message (const char *message, GError **error) { unsigned char *sig; unsigned int sig_len; char *sigret; sig = g_new0(unsigned char, RSA_size(session->privkey)); if (!RSA_sign (NID_sha1, (const unsigned char *)message, strlen(message), sig, &sig_len, session->privkey)) { g_warning ("Failed to sign message: %lu.\n", ERR_get_error()); return NULL; } sigret = g_base64_encode (sig, sig_len); g_free (sig); return sigret; } int ccnet_rpc_verify_message (const char *message, const char *sig_base64, const char *peer_id, GError **error) { unsigned char *sig; gsize sig_len; CcnetPeer *peer; sig = g_base64_decode (sig_base64, &sig_len); peer = ccnet_peer_manager_get_peer (session->peer_mgr, peer_id); if (!peer) { g_warning ("Cannot find peer %s.\n", peer_id); return -1; } if (!RSA_verify (NID_sha1, (const unsigned char *)message, strlen(message), sig, (guint)sig_len, peer->pubkey)) { g_object_unref (peer); return -1; } g_object_unref (peer); return 0; } int ccnet_rpc_create_group (const char *group_name, const char *user_name, const char *type, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (!group_name || !user_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Group name and user name can not be NULL"); return -1; } ret = ccnet_group_manager_create_group (group_mgr, group_name, user_name, error); return ret; } int ccnet_rpc_create_org_group (int org_id, const char *group_name, const char *user_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (org_id < 0 || !group_name || !user_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad args"); return -1; } ret = ccnet_group_manager_create_org_group (group_mgr, org_id, group_name, user_name, error); return ret; } int ccnet_rpc_remove_group (int group_id, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (group_id <= 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Invalid group_id parameter"); return -1; } ret = ccnet_group_manager_remove_group (group_mgr, group_id, error); return ret; } int ccnet_rpc_group_add_member (int group_id, const char *user_name, const char *member_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (group_id <= 0 || !user_name || !member_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Group id and user name and member name can not be NULL"); return -1; } ret = ccnet_group_manager_add_member (group_mgr, group_id, user_name, member_name, error); return ret; } int ccnet_rpc_group_remove_member (int group_id, const char *user_name, const char *member_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (!user_name || !member_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "User name and member name can not be NULL"); return -1; } ret = ccnet_group_manager_remove_member (group_mgr, group_id, user_name, member_name, error); return ret; } int ccnet_rpc_group_set_admin (int group_id, const char *member_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (group_id <= 0 || !member_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } ret = ccnet_group_manager_set_admin (group_mgr, group_id, member_name, error); return ret; } int ccnet_rpc_group_unset_admin (int group_id, const char *member_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (group_id <= 0 || !member_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } ret = ccnet_group_manager_unset_admin (group_mgr, group_id, member_name, error); return ret; } int ccnet_rpc_set_group_name (int group_id, const char *group_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (group_id <= 0 || !group_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } ret = ccnet_group_manager_set_group_name (group_mgr, group_id, group_name, error); return ret; } int ccnet_rpc_quit_group (int group_id, const char *user_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; int ret; if (group_id <= 0 || !user_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Group id and user name can not be NULL"); return -1; } ret = ccnet_group_manager_quit_group (group_mgr, group_id, user_name, error); return ret; } static GList * convert_group_list (CcnetGroupManager *mgr, GList *group_ids) { GList *ret = NULL, *ptr; for (ptr = group_ids; ptr; ptr = ptr->next) { int group_id = (int)(long)ptr->data; CcnetGroup *group = ccnet_group_manager_get_group (mgr, group_id, NULL); if (group != NULL) { ret = g_list_prepend (ret, group); } } return g_list_reverse (ret); } GList * ccnet_rpc_get_groups (const char *username, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; GList *group_ids = NULL; GList *ret = NULL; if (!username) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "User name can not be NULL"); return NULL; } group_ids = ccnet_group_manager_get_groupids_by_user (group_mgr, username, error); if (group_ids == NULL) { return NULL; } ret = convert_group_list (group_mgr, group_ids); g_list_free (group_ids); return ret; } GList * ccnet_rpc_get_all_groups (int start, int limit, const char *source, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; GList *ret = NULL; ret = ccnet_group_manager_get_all_groups (group_mgr, start, limit, error); return ret; } GObject * ccnet_rpc_get_group (int group_id, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; CcnetGroup *group = NULL; group = ccnet_group_manager_get_group (group_mgr, group_id, error); if (!group) { return NULL; } /* g_object_ref (group); */ return (GObject *)group; } GList * ccnet_rpc_get_group_members (int group_id, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; GList *ret = NULL; ret = ccnet_group_manager_get_group_members (group_mgr, group_id, error); if (ret == NULL) return NULL; return g_list_reverse (ret); } int ccnet_rpc_check_group_staff (int group_id, const char *user_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; if (group_id <= 0 || !user_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_group_manager_check_group_staff (group_mgr, group_id, user_name); } int ccnet_rpc_remove_group_user (const char *user, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; if (!user) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_group_manager_remove_group_user (group_mgr, user); } int ccnet_rpc_is_group_user (int group_id, const char *user, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; if (!user || group_id < 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return 0; } return ccnet_group_manager_is_group_user (group_mgr, group_id, user); } int ccnet_rpc_set_group_creator (int group_id, const char *user_name, GError **error) { CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; if (!user_name || group_id < 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_group_manager_set_group_creator (group_mgr, group_id, user_name); } int ccnet_rpc_create_org (const char *org_name, const char *url_prefix, const char *creator, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (!org_name || !url_prefix || !creator) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_create_org (org_mgr, org_name, url_prefix, creator, error); } int ccnet_rpc_remove_org (int org_id, GError **error) { GList *group_ids = NULL, *email_list=NULL, *ptr; const char *url_prefix = NULL; CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; if (org_id < 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } url_prefix = ccnet_org_manager_get_url_prefix_by_org_id (org_mgr, org_id, error); email_list = ccnet_org_manager_get_org_emailusers (org_mgr, url_prefix, 0, INT_MAX); ptr = email_list; while (ptr) { ccnet_user_manager_remove_emailuser (user_mgr, "DB", (gchar *)ptr->data); ptr = ptr->next; } string_list_free (email_list); group_ids = ccnet_org_manager_get_org_groups (org_mgr, org_id, 0, INT_MAX); ptr = group_ids; while (ptr) { ccnet_group_manager_remove_group (group_mgr, (int)(long)ptr->data, error); ptr = ptr->next; } g_list_free (group_ids); return ccnet_org_manager_remove_org (org_mgr, org_id, error); } GList * ccnet_rpc_get_all_orgs (int start, int limit, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; GList *ret = NULL; ret = ccnet_org_manager_get_all_orgs (org_mgr, start, limit); return ret; } gint64 ccnet_rpc_count_orgs (GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; return ccnet_org_manager_count_orgs(org_mgr); } GObject * ccnet_rpc_get_org_by_url_prefix (const char *url_prefix, GError **error) { CcnetOrganization *org = NULL; CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (!url_prefix) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return NULL; } org = ccnet_org_manager_get_org_by_url_prefix (org_mgr, url_prefix, error); if (!org) return NULL; return (GObject *)org; } GObject * ccnet_rpc_get_org_by_id (int org_id, GError **error) { CcnetOrganization *org = NULL; CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id <= 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return NULL; } org = ccnet_org_manager_get_org_by_id (org_mgr, org_id, error); if (!org) return NULL; return (GObject *)org; } int ccnet_rpc_add_org_user (int org_id, const char *email, int is_staff, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || !email) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_add_org_user (org_mgr, org_id, email, is_staff, error); } int ccnet_rpc_remove_org_user (int org_id, const char *email, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || !email) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_remove_org_user (org_mgr, org_id, email, error); } GList * ccnet_rpc_get_orgs_by_user (const char *email, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; GList *org_list = NULL; org_list = ccnet_org_manager_get_orgs_by_user (org_mgr, email, error); return org_list; } GList * ccnet_rpc_get_org_emailusers (const char *url_prefix, int start , int limit, GError **error) { CcnetUserManager *user_mgr = ((CcnetServerSession *)session)->user_mgr; CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; GList *email_list = NULL, *ptr; GList *ret = NULL; if (!url_prefix) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return NULL; } email_list = ccnet_org_manager_get_org_emailusers (org_mgr, url_prefix, start, limit); if (email_list == NULL) { return NULL; } ptr = email_list; while (ptr) { char *email = ptr->data; CcnetEmailUser *emailuser = ccnet_user_manager_get_emailuser (user_mgr, email); if (emailuser != NULL) { ret = g_list_prepend (ret, emailuser); } ptr = ptr->next; } string_list_free (email_list); return g_list_reverse (ret); } int ccnet_rpc_add_org_group (int org_id, int group_id, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || group_id < 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_add_org_group (org_mgr, org_id, group_id, error); } int ccnet_rpc_remove_org_group (int org_id, int group_id, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || group_id < 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_remove_org_group (org_mgr, org_id, group_id, error); } int ccnet_rpc_is_org_group (int group_id, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (group_id <= 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_is_org_group (org_mgr, group_id, error); } int ccnet_rpc_get_org_id_by_group (int group_id, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (group_id <= 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_get_org_id_by_group (org_mgr, group_id, error); } GList * ccnet_rpc_get_org_groups (int org_id, int start, int limit, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; CcnetGroupManager *group_mgr = ((CcnetServerSession *)session)->group_mgr; GList *group_ids = NULL; GList *ret = NULL; if (org_id < 0) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return NULL; } /* correct parameter */ if (start < 0 ) { start = 0; } group_ids = ccnet_org_manager_get_org_groups (org_mgr, org_id, start, limit); if (group_ids == NULL) return NULL; ret = convert_group_list (group_mgr, group_ids); g_list_free (group_ids); return ret; } int ccnet_rpc_org_user_exists (int org_id, const char *email, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || !email) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_org_user_exists (org_mgr, org_id, email, error); } int ccnet_rpc_is_org_staff (int org_id, const char *email, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || !email) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_is_org_staff (org_mgr, org_id, email, error); } int ccnet_rpc_set_org_staff (int org_id, const char *email, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || !email) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_set_org_staff (org_mgr, org_id, email, error); } int ccnet_rpc_unset_org_staff (int org_id, const char *email, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || !email) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_unset_org_staff (org_mgr, org_id, email, error); } int ccnet_rpc_set_org_name (int org_id, const char *org_name, GError **error) { CcnetOrgManager *org_mgr = ((CcnetServerSession *)session)->org_mgr; if (org_id < 0 || !org_name) { g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments"); return -1; } return ccnet_org_manager_set_org_name (org_mgr, org_id, org_name, error); } #endif /* CCNET_SERVER */ ccnet-6.1.5/net/common/rpc-service.h000066400000000000000000000202321317035602700172730ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef RPC_SERVICE_H #define RPC_SERVICE_H struct CcnetSession; void ccnet_start_rpc(CcnetSession *session); char *ccnet_rpc_list_peers(GError **error); GList *ccnet_rpc_list_resolving_peers (GError **error); GList* ccnet_rpc_get_peers_by_role(const char *role, GError **error); GObject *ccnet_rpc_get_peer(const char *peerid, GError **error); int ccnet_rpc_update_peer_address(const char *peer_id, const char *addr, int port, GError **error); GObject *ccnet_rpc_get_peer_by_idname(const char *idname, GError **error); char * ccnet_rpc_list_users(GError **error); GObject * ccnet_rpc_get_user(const char *userid, GError **error); GObject * ccnet_rpc_get_user_of_peer(const char *peerid, GError **error); GObject *ccnet_rpc_get_session_info(GError **error); int ccnet_rpc_add_client(const char *user_id, GError **error); int ccnet_rpc_add_role(const char *user_id, const char *role, GError **error); int ccnet_rpc_remove_role(const char *user_id, const char *role, GError **error); GList *ccnet_rpc_get_events(int offset, int limit, GError **error); int ccnet_rpc_count_event (GError **error); /** * ccnet_get_config: * * Return the config value with key @key */ char * ccnet_rpc_get_config (const char *key, GError **error); /** * ccnet_rpc_set_config: * * Set the value of config item with key @key to @value */ int ccnet_rpc_set_config (const char *key, const char *value, GError **error); /** * ccnet_rpc_upload_profile: * * Upload profile to the relay who is @relay_id */ int ccnet_rpc_upload_profile (const char *relay_id, GError **error); char * ccnet_rpc_pubkey_encrypt (const char *msg_base64, const char *peer_id, GError **error); char * ccnet_rpc_privkey_decrypt (const char *msg_base64, GError **error); #ifdef CCNET_SERVER GList * ccnet_rpc_list_peer_stat (GError **error); int ccnet_rpc_add_emailuser (const char *email, const char *passwd, int is_staff, int is_active, GError **error); int ccnet_rpc_remove_emailuser (const char *source, const char *email, GError **error); int ccnet_rpc_validate_emailuser (const char *email, const char *passwd, GError **error); GObject* ccnet_rpc_get_emailuser (const char *email, GError **error); GObject* ccnet_rpc_get_emailuser_with_import (const char *email, GError **error); GObject* ccnet_rpc_get_emailuser_by_id (int id, GError **error); GList* ccnet_rpc_get_emailusers (const char *source, int start, int limit, const char *status, GError **error); GList* ccnet_rpc_search_emailusers (const char *source, const char *email_patt, int start, int limit, GError **error); GList* ccnet_rpc_search_ldapusers (const char *keyword, int start, int limit, GError **error); /* Get total counts of email users. */ gint64 ccnet_rpc_count_emailusers (const char *source, GError **error); gint64 ccnet_rpc_count_inactive_emailusers (const char *source, GError **error); /** * Select multiple users according to the given emails. * * @emails: emails seperated by ",", e.g., "foo@foo.com, bar@bar.com" */ GList* ccnet_rpc_filter_emailusers_by_emails (const char *emails, GError **error); int ccnet_rpc_update_emailuser (const char *source, int id, const char* passwd, int is_staff, int is_active, GError **error); int ccnet_rpc_update_role_emailuser (const char* email, const char* role, GError **error); GList* ccnet_rpc_get_superusers (GError **error); int ccnet_rpc_add_binding (const char *email, const char *peer_id, GError **error); char * ccnet_rpc_get_binding_email (const char *peer_id, GError **error); char * ccnet_rpc_get_binding_peerids (const char *email, GError **error); int ccnet_rpc_remove_binding (const char *email, GError **error); int ccnet_rpc_remove_one_binding (const char *email, const char *peer_id, GError **error); GList * ccnet_rpc_get_peers_by_email (const char *email, GError **error); char * ccnet_rpc_sign_message (const char *message, GError **error); int ccnet_rpc_verify_message (const char *message, const char *sig_base64, const char *peer_id, GError **error); int ccnet_rpc_create_group (const char *group_name, const char *user_name, const char *type, GError **error); int ccnet_rpc_create_org_group (int org_id, const char *group_name, const char *user_name, GError **error); int ccnet_rpc_remove_group (int group_id, GError **error); int ccnet_rpc_group_add_member (int group_id, const char *user_name, const char *member_name, GError **error); int ccnet_rpc_group_remove_member (int group_id, const char *user_name, const char *member_name, GError **error); int ccnet_rpc_group_set_admin (int group_id, const char *member_name, GError **error); int ccnet_rpc_group_unset_admin (int group_id, const char *member_name, GError **error); int ccnet_rpc_set_group_name (int group_id, const char *group_name, GError **error); int ccnet_rpc_quit_group (int group_id, const char *user_name, GError **error); GList * ccnet_rpc_get_groups (const char *username, GError **error); GList * ccnet_rpc_get_all_groups (int start, int limit, const char *source, GError **error); GObject * ccnet_rpc_get_group (int group_id, GError **error); GList * ccnet_rpc_get_group_members (int group_id, GError **error); int ccnet_rpc_check_group_staff (int group_id, const char *user_name, GError **error); int ccnet_rpc_remove_group_user (const char *user, GError **error); int ccnet_rpc_is_group_user (int group_id, const char *user, GError **error); int ccnet_rpc_set_group_creator (int group_id, const char *user_name, GError **error); int ccnet_rpc_create_org (const char *org_name, const char *url_prefix, const char *creator, GError **error); int ccnet_rpc_remove_org (int org_id, GError **error); GList * ccnet_rpc_get_all_orgs (int start, int limit, GError **error); gint64 ccnet_rpc_count_orgs (GError **error); GObject * ccnet_rpc_get_org_by_url_prefix (const char *url_prefix, GError **error); GObject * ccnet_rpc_get_org_by_id (int org_id, GError **error); int ccnet_rpc_add_org_user (int org_id, const char *email, int is_staff, GError **error); int ccnet_rpc_remove_org_user (int org_id, const char *email, GError **error); GList * ccnet_rpc_get_orgs_by_user (const char *email, GError **error); GList * ccnet_rpc_get_org_emailusers (const char *url_prefix, int start , int limit, GError **error); int ccnet_rpc_add_org_group (int org_id, int group_id, GError **error); int ccnet_rpc_remove_org_group (int org_id, int group_id, GError **error); int ccnet_rpc_is_org_group (int group_id, GError **error); int ccnet_rpc_get_org_id_by_group (int group_id, GError **error); GList * ccnet_rpc_get_org_groups (int org_id, int start, int limit, GError **error); int ccnet_rpc_org_user_exists (int org_id, const char *email, GError **error); int ccnet_rpc_is_org_staff (int org_id, const char *email, GError **error); int ccnet_rpc_set_org_staff (int org_id, const char *email, GError **error); int ccnet_rpc_unset_org_staff (int org_id, const char *email, GError **error); int ccnet_rpc_set_org_name (int org_id, const char *org_name, GError **error); #endif /* CCNET_SERVER */ /** * ccnet_rpc_login_to_relay: * * send email/passwd info to relay("after registration"), to get a "MyClient" role on relay */ int ccnet_rpc_login_relay (const char *relay_id, const char *email, const char *passwd, GError **error); /** * ccnet_rpc_logout_to_relay: * * ask the relay to delete i) 'MyClient' info, ii) previous binding to an email */ int ccnet_rpc_logout_relay (const char *relay_id, GError **error); #endif /* RPC_SERVICE_H */ ccnet-6.1.5/net/common/session.c000066400000000000000000000414371317035602700165410ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include #include #include "getgateway.h" #include "utils.h" #include "net.h" #include "rsa.h" #include "ccnet-config.h" #include "session.h" #include "peer.h" #include "peer-mgr.h" #include "perm-mgr.h" #include "packet-io.h" #include "connect-mgr.h" #include "message.h" #include "message-manager.h" #include "algorithms.h" #include "proc-factory.h" #define DEBUG_FLAG CCNET_DEBUG_OTHER #include "log.h" #define THREAD_POOL_SIZE 50 static void ccnet_service_free (CcnetService *service); G_DEFINE_TYPE (CcnetSession, ccnet_session, CCNET_TYPE_SESSION_BASE); static void on_peer_auth_done (CcnetPeerManager *manager, CcnetPeer *peer, gpointer user_data); static void ccnet_session_class_init (CcnetSessionClass *klass) { /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ } static void ccnet_session_init (CcnetSession *session) { /* note, the order is important. */ session->service_hash = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify)ccnet_service_free); session->proc_factory = ccnet_proc_factory_new (session); session->peer_mgr = ccnet_peer_manager_new (session); session->connMgr = ccnet_conn_manager_new (session); session->msg_mgr = ccnet_message_manager_new (session); session->perm_mgr = ccnet_perm_manager_new (session); session->job_mgr = ccnet_job_manager_new (THREAD_POOL_SIZE); } static int load_rsakey(CcnetSession *session) { char *path; FILE *fp; RSA *key; path = g_build_filename(session->config_dir, PEER_KEYFILE, NULL); if (!g_file_test(path, G_FILE_TEST_EXISTS)) ccnet_error ("Can't load rsa private key from %s\n", path); if ((fp = g_fopen(path, "rb")) == NULL) ccnet_error ("Can't open private key file %s: %s\n", path, strerror(errno)); if ((key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL) ccnet_error ("Can't open load key file %s: format error\n", path); fclose(fp); session->privkey = key; session->pubkey = private_key_to_pub(key); g_free(path); return 0; } static void listen_on_localhost (CcnetSession *session); static void listen_on_pipe (CcnetSession *session); static void save_pubinfo (CcnetSession *session); CcnetSession * ccnet_session_new () { return g_object_new (CCNET_TYPE_SESSION, NULL); } int ccnet_session_load_config (CcnetSession *session, const char *central_config_dir_r, const char *config_dir_r) { int ret = 0; char *config_file = NULL, *config_dir = NULL, *central_config_dir = NULL; char *id = NULL, *name = NULL, *port_str = NULL, *lport_str = NULL, *un_path = NULL, *user_name = NULL; #ifdef CCNET_SERVER char *service_url; #endif int port, local_port = 0; unsigned char sha1[20]; GKeyFile *key_file; config_dir = ccnet_expand_path (config_dir_r); if (checkdir(config_dir) < 0) { ccnet_error ("Config dir %s does not exist or is not " "a directory.\n", config_dir); return -1; } #ifdef CCNET_SERVER if (central_config_dir_r) { central_config_dir = ccnet_expand_path (central_config_dir_r); if (checkdir(central_config_dir) < 0) { ccnet_error ("Server Config dir %s does not exist or is not " "a directory.\n", central_config_dir); return -1; } } #endif config_file = g_build_filename (central_config_dir ? central_config_dir : config_dir, SESSION_CONFIG_FILENAME, NULL); ccnet_message ("using config file %s\n", config_file); key_file = g_key_file_new (); g_key_file_set_list_separator (key_file, ','); if (!g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) { ccnet_warning ("Can't load config file %s.\n", config_file); return -1; } id = ccnet_key_file_get_string (key_file, "General", "ID"); user_name = ccnet_key_file_get_string (key_file, "General", "USER_NAME"); name = ccnet_key_file_get_string (key_file, "General", "NAME"); #ifdef CCNET_SERVER service_url = ccnet_key_file_get_string (key_file, "General", "SERVICE_URL"); #endif port_str = ccnet_key_file_get_string (key_file, "Network", "PORT"); lport_str = ccnet_key_file_get_string (key_file, "Client", "PORT"); un_path = ccnet_key_file_get_string (key_file, "Client", "UNIX_SOCKET"); if (port_str == NULL) { port = 0; } else { port = atoi (port_str); if (port <= 0 || port > 65535) { port = DEFAULT_PORT; } } if ( (id == NULL) || (strlen (id) != SESSION_ID_LENGTH) || (hex_to_sha1 (id, sha1) < 0) ) { ccnet_error ("Wrong ID\n"); ret = -1; goto onerror; } if (lport_str) local_port = atoi (lport_str); memcpy (session->base.id, id, 40); session->base.id[40] = '\0'; session->base.name = g_strdup(name); session->base.user_name = g_strdup(user_name); session->base.public_port = port; #ifdef CCNET_SERVER session->base.service_url = g_strdup(service_url); #endif session->config_file = config_file; session->config_dir = config_dir; session->central_config_dir = central_config_dir; session->un_path = un_path; session->local_port = local_port; session->keyf = key_file; load_rsakey(session); ret = 0; onerror: g_free (id); g_free (name); g_free (user_name); g_free (port_str); g_free (lport_str); #ifdef CCNET_SERVER g_free (service_url); #endif return ret; } void ccnet_session_free (CcnetSession *session) { ccnet_peer_manager_free (session->peer_mgr); g_object_unref (session); } int ccnet_session_prepare (CcnetSession *session, const char *central_config_dir, const char *config_dir_r, gboolean test_config) { char *misc_path; int ret; if (ccnet_session_load_config (session, central_config_dir, config_dir_r) < 0) return -1; misc_path = g_build_filename (session->config_dir, "misc", NULL); if (checkdir_with_mkdir (misc_path) < 0) { ccnet_error ("mkdir %s error", misc_path); return -1; } /* config db */ session->config_db = ccnet_session_config_open_db (misc_path); if (!session->config_db) { ccnet_warning ("Failed to open config db.\n"); return -1; } /* call subclass prepare */ ret = CCNET_SESSION_GET_CLASS (session)->prepare(session); if (ret < 0) return ret; /* peer */ ccnet_peer_manager_prepare(session->peer_mgr); g_signal_connect (session->peer_mgr, "peer-auth-done", G_CALLBACK(on_peer_auth_done), session); /* permission manager */ ccnet_perm_manager_prepare (session->perm_mgr); g_free (misc_path); if (test_config) { return 0; } else { /* Open localhost, if failed, then the program will exists. This is used * to prevent two instance of ccnet on the same port. */ #ifdef WIN32 listen_on_localhost (session); #else listen_on_pipe (session); #endif /* refresh pubinfo on every startup */ save_pubinfo (session); } return 0; } static void save_peerinfo (CcnetSession *session) { FILE *fp; char *path; char filename[64]; sprintf(filename, "%s%s", session->base.id, ".peer"); path = g_build_filename (session->config_dir, "misc", filename, NULL); if ((fp = g_fopen(path, "wb")) == NULL) { ccnet_warning ("Open public info file %s error: %s\n", path, strerror(errno)); g_free (path); return; } g_free (path); ccnet_message ("Update pubinfo file\n"); session->myself->public_port = session->base.public_port; GString *str = ccnet_peer_to_string (session->myself); fputs (str->str, fp); fclose (fp); g_string_free (str, TRUE); } static void save_pubinfo (CcnetSession *session) { save_peerinfo(session); } void ccnet_session_save_config (CcnetSession *session) { GError *error = NULL; char *str; FILE *fp; ccnet_message ("[Session] Saving configure file\n"); if (session->saving_pub) { /* only update timestamp when pubinfo changes */ save_pubinfo (session); session->saving_pub = 0; } g_key_file_set_string (session->keyf, "General", "NAME", session->base.name); g_key_file_set_string (session->keyf, "General", "ID", session->base.id); g_key_file_set_string (session->keyf, "General", "USER_NAME", session->base.user_name); #ifdef CCNET_SERVER g_key_file_set_string (session->keyf, "General", "SERVICE_URL", session->base.service_url?session->base.service_url:""); #endif g_key_file_set_integer (session->keyf, "Network", "PORT", session->base.public_port); g_key_file_set_integer (session->keyf, "Client", "PORT", session->local_port); str = g_key_file_to_data (session->keyf, NULL, &error); if (error) { ccnet_warning ("Can't save unauth peer info: %s\n", error->message); return; } if ((fp = g_fopen (session->config_file, "wb")) == NULL) { ccnet_warning ("Can't save session conf: %s\n", strerror(errno)); g_free (str); return; } fputs (str, fp); fclose (fp); g_free (str); return; } void ccnet_session_save (CcnetSession *session) { /* ccnet_req_manager_backup_requirements (session->reqMgr); */ } void ccnet_session_on_exit (CcnetSession *session) { time_t t; ccnet_peer_manager_on_exit (session->peer_mgr); ccnet_session_save (session); t = time(NULL); ccnet_message ("Exit at %s\n", ctime(&t)); ccnet_session_free (session); } static const char *net_status_string (int status) { switch (status) { case NET_STATUS_DOWN: return "Down"; case NET_STATUS_INNAT: return "In nat"; case NET_STATUS_FULL: return "Full"; default: return "Unknown"; } } static void accept_local_client (evutil_socket_t fd, short event, void *vsession) { CcnetSession *session = vsession; CcnetPacketIO *io; int connfd; CcnetPeer *peer; static int local_id = 0; connfd = accept (fd, NULL, 0); ccnet_message ("Accepted a local client\n"); io = ccnet_packet_io_new_incoming (session, NULL, connfd); peer = ccnet_peer_new (session->base.id); peer->name = g_strdup_printf("local-%d", local_id++); peer->is_local = TRUE; ccnet_peer_set_io (peer, io); ccnet_peer_set_net_state (peer, PEER_CONNECTED); ccnet_peer_manager_add_local_peer (session->peer_mgr, peer); g_object_unref (peer); } static void listen_on_localhost (CcnetSession *session) { int sockfd; if ( (sockfd = ccnet_net_bind_v4 ("127.0.0.1", &session->local_port)) < 0) { printf ("listen on localhost failed\n"); exit (1); } ccnet_message ("Listen on 127.0.0.1 %d\n", session->local_port); listen (sockfd, 5); event_set (&session->local_event, sockfd, EV_READ | EV_PERSIST, accept_local_client, session); event_add (&session->local_event, NULL); } #ifndef WIN32 static void listen_on_pipe (CcnetSession *session) { int pipe_fd = socket (AF_UNIX, SOCK_STREAM, 0); char *un_path = NULL; if (pipe_fd < 0) { ccnet_warning ("Failed to create unix socket fd : %s\n", strerror(errno)); goto failed; } struct sockaddr_un saddr; saddr.sun_family = AF_UNIX; if (!session->un_path) un_path = g_build_filename (session->config_dir, CCNET_PIPE_NAME, NULL); else un_path = g_strdup(session->un_path); if (strlen(un_path) > sizeof(saddr.sun_path)-1) { ccnet_warning ("Unix socket path %s is too long." "Please set or modify UNIX_SOCKET option in ccnet.conf.\n", un_path); g_free (un_path); goto failed; } if (g_file_test (un_path, G_FILE_TEST_EXISTS)) { ccnet_warning ("socket file exists, delete it anyway\n"); if (g_unlink (un_path) < 0) { ccnet_warning ("delete socket file failed : %s\n", strerror(errno)); goto failed; } } g_strlcpy (saddr.sun_path, un_path, sizeof(saddr.sun_path)); if (bind(pipe_fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { ccnet_warning ("failed to bind unix socket fd to %s : %s\n", un_path, strerror(errno)); goto failed; } if (listen(pipe_fd, 3) < 0) { ccnet_warning ("failed to listen to unix socket: %s\n", strerror(errno)); goto failed; } if (chmod(un_path, 0700) < 0) { ccnet_warning ("failed to set permisson for unix socket %s: %s\n", un_path, strerror(errno)); goto failed; } event_set (&session->local_pipe_event, pipe_fd, EV_READ | EV_PERSIST, accept_local_client, session); event_add (&session->local_pipe_event, NULL); ccnet_message ("Listen on %s for local clients\n", un_path); g_free (un_path); return; failed: ccnet_warning ("listen on unix socket failed\n"); exit (1); } #endif // WIN32 void ccnet_session_start_network (CcnetSession *session) { session->base.net_status = NET_STATUS_FULL; ccnet_conn_manager_start (session->connMgr); session->myself->addr_str = NULL; } void ccnet_session_shutdown_network (CcnetSession *session) { GList *peers, *ptr; peers = ccnet_peer_manager_get_peer_list(session->peer_mgr); for (ptr = peers; ptr; ptr = ptr->next) ccnet_peer_shutdown ((CcnetPeer *)ptr->data); g_list_free (peers); ccnet_conn_manager_stop (session->connMgr); } static int restart_network (CcnetSession *session) { ccnet_session_start_network (session); if (session->base.net_status != NET_STATUS_DOWN) { session->start_failure = 0; return FALSE; } if (++session->start_failure > 3) return FALSE; return TRUE; } void ccnet_session_start (CcnetSession *session) { ccnet_proc_factory_start (session->proc_factory); ccnet_message_manager_start (session->msg_mgr); if (session->base.public_port == 0) { return; } ccnet_session_start_network (session); if (session->base.net_status == NET_STATUS_DOWN) { ccnet_timer_new ((TimerCB)restart_network, session, 10000); } ccnet_peer_manager_start (session->peer_mgr); } static void ccnet_service_free (CcnetService *service) { g_free (service->svc_name); g_free (service); } int ccnet_session_register_service (CcnetSession *session, const char *svc_name, const char *group, CcnetPeer *peer) { CcnetService *service = g_new0 (CcnetService, 1); if (g_hash_table_lookup (session->service_hash, svc_name)) { ccnet_debug ("[Service] Service %s has already been registered\n", svc_name); return -1; } ccnet_debug ("[Service] Service %s registered\n", svc_name); ccnet_perm_manager_register_service (session->perm_mgr, svc_name, group, peer); service->svc_name = g_strdup(svc_name); service->provider = peer; g_hash_table_insert (session->service_hash, g_strdup(svc_name), service); return 0; } CcnetService* ccnet_session_get_service (CcnetSession *session, const char *svc_name) { return g_hash_table_lookup (session->service_hash, svc_name); } gboolean remove_service_cmp (gpointer key, gpointer value, gpointer user_data) { CcnetService *service = value; if (service->provider == user_data) { ccnet_debug ("[Service] Service %s un-registered\n", (char *)key); return TRUE; } return FALSE; } void ccnet_session_unregister_service (CcnetSession *session, CcnetPeer *peer) { g_hash_table_foreach_remove (session->service_hash, remove_service_cmp, peer); } static void on_peer_auth_done (CcnetPeerManager *manager, CcnetPeer *peer, gpointer user_data) { CcnetSession *session = (CcnetSession *)user_data; CCNET_SESSION_GET_CLASS (session)->on_peer_auth_done(session, peer); } gboolean ccnet_session_should_encrypt_channel (CcnetSession *session) { return session->encrypt_channel; } ccnet-6.1.5/net/common/session.h000066400000000000000000000102741317035602700165410ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SESSION_H #define CCNET_SESSION_H #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #else #include #endif #include #include #include "ccnet-session-base.h" #include "processor.h" #include "ccnet-db.h" #include "job-mgr.h" #include "ccnet-object.h" #define SESSION_CONFIG_FILENAME "ccnet.conf" #define SESSION_PEERDB_NAME "peer-db" #define SESSION_ID_LENGTH 40 #define CCNET_TYPE_SESSION (ccnet_session_get_type ()) #define CCNET_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SESSION, CcnetSession)) #define CCNET_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SESSION)) #define CCNET_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SESSION, CcnetSessionClass)) #define CCNET_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SESSION)) #define CCNET_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SESSION, CcnetSessionClass)) typedef struct CcnetSession CcnetSession; typedef struct _CcnetSessionClass CcnetSessionClass; struct _CcnetPeer; typedef struct _CcnetService { char *svc_name; struct _CcnetPeer *provider; } CcnetService; #include struct CcnetSession { CcnetSessionBase base; struct _CcnetPeer *myself; /* path to the central config dir for ccnet/seafile/seahub/seafdav etc. */ const char *central_config_dir; /* path to ccnet specific config dir */ const char *config_dir; const char *config_file; GKeyFile *keyf; RSA *privkey; RSA *pubkey; struct _CcnetPeerManager *peer_mgr; struct CcnetConnManager *connMgr; struct _CcnetMessageManager *msg_mgr; struct _CcnetProcFactory *proc_factory; struct _CcnetPermManager *perm_mgr; struct _CcnetJobManager *job_mgr; GHashTable *service_hash; unsigned int saving : 1; unsigned int saving_pub : 1; unsigned int encrypt_channel : 1; int local_port; char *un_path; struct event local_event; struct event local_pipe_event; int start_failure; /* how many times failed to start the network */ sqlite3 *config_db; CcnetDB *db; }; struct _CcnetSessionClass { CcnetSessionBaseClass parent_class; int (*prepare) (CcnetSession *session); void (*start) (CcnetSession *session); void (*on_peer_auth_done) (CcnetSession *session, struct _CcnetPeer *peer); }; GType ccnet_session_get_type (); CcnetSession *ccnet_session_new (); void ccnet_session_start (CcnetSession *session); void ccnet_session_on_exit (CcnetSession *session); void ccnet_session_save (CcnetSession *session); int ccnet_session_prepare (CcnetSession *session, const char *central_config_dir_r, const char *config_dir_r, gboolean test_config); void ccnet_session_save_config (CcnetSession *session); void ccnet_session_start_network (CcnetSession *session); void ccnet_session_shutdown_network (CcnetSession *session); int ccnet_session_register_service (CcnetSession *session, const char *svc_name, const char *group, struct _CcnetPeer *peer); CcnetService* ccnet_session_get_service (CcnetSession *session, const char *service); void ccnet_session_unregister_service (CcnetSession *session, struct _CcnetPeer *peer); gboolean ccnet_session_should_encrypt_channel (CcnetSession *session); #endif ccnet-6.1.5/net/daemon/000077500000000000000000000000001317035602700146545ustar00rootroot00000000000000ccnet-6.1.5/net/daemon/Makefile.am000066400000000000000000000061171317035602700167150ustar00rootroot00000000000000 AM_CPPFLAGS = @GLIB2_CFLAGS@ @GOBJECT_CFLAGS@ \ -DCCNET_DAEMON \ -I$(top_srcdir)/net/common \ -I$(top_srcdir)/include -I$(top_srcdir)/include/ccnet \ -I$(top_srcdir)/lib \ -I$(top_builddir)/include \ -I$(top_builddir)/lib \ @SEARPC_CFLAGS@ \ -Wall bin_PROGRAMS = ccnet PROC_HEADER_FILES = $(addprefix ../common/processors/, \ rcvmsg-proc.h \ sendmsg-proc.h \ rcvcmd-proc.h \ getpubinfo-proc.h putpubinfo-proc.h \ keepalive2-proc.h \ mqserver-proc.h \ service-proxy-proc.h service-stub-proc.h \ rpcserver-proc.h \ echo-proc.h \ sendsessionkey-proc.h \ recvsessionkey-proc.h \ sendsessionkey-v2-proc.h \ recvsessionkey-v2-proc.h ) # sync-kvitem-proc.h sync-kvitem-slave-proc.h # getmsg-proc.h putmsg-proc.h \ # rcvevent-proc.h \ # get-userpeer-proc.h \ # update-user-proc.h \ # update-pubinfo-proc.h \ # getgroupinfo-proc.h putgroupinfo-proc.h \ # sendgroupinfo-proc.h recvgroupinfo-proc.h \ # getaddrinfo-proc.h putaddrinfo-proc.h \ # sync-relay-proc.h sync-relay-slave-proc.h \ # sync-role-proc.h \ # kvserver-proc.h \ # sample-master-proc.h sample-slave-proc.h \ # send-profile-proc.h common_headers = ../common/algorithms.h \ ../common/proc-factory.h ../common/session.h \ ../common/common.h ../common/handshake.h ../common/perm-mgr.h \ ../common/peer.h ../common/connect-mgr.h \ ../common/packet-io.h ../common/ccnet-config.h \ ../common/log.h ../common/peer-mgr.h \ ../common/message.h \ ../common/getgateway.h ../common/message-manager.h \ ../common/processor.h \ ../common/peermgr-message.h \ ../common/rpc-service.h \ ../common/ccnet-db.h # ../common/group.h # ../common/group-mgr.h \ # ../common/groupmgr-message.h # ../common/info-syncher.h noinst_HEADERS = $(common_headers) \ daemon-session.h \ $(PROC_HEADER_FILES) common_srcs = ../common/session.c ../common/peer-mgr.c ../common/packet-io.c \ ../common/message.c ../common/perm-mgr.c \ ../common/log.c ../common/peer.c ../common/algorithms.c \ ../common/handshake.c ../common/processor.c \ ../common/getgateway.c ../common/connect-mgr.c \ ../common/message-manager.c \ ../common/proc-factory.c \ ../common/ccnet-config.c \ ../common/rpc-service.c \ ../common/peermgr-message.c \ ../common/processors/sendmsg-proc.c ../common/processors/rcvmsg-proc.c \ ../common/processors/rcvcmd-proc.c \ ../common/processors/getpubinfo-proc.c \ ../common/processors/putpubinfo-proc.c \ ../common/processors/keepalive2-proc.c \ ../common/processors/mqserver-proc.c \ ../common/processors/service-proxy-proc.c \ ../common/processors/service-stub-proc.c \ ../common/processors/rpcserver-proc.c \ ../common/processors/echo-proc.c \ ../common/processors/sendsessionkey-proc.c \ ../common/processors/recvsessionkey-proc.c \ ../common/processors/sendsessionkey-v2-proc.c \ ../common/processors/recvsessionkey-v2-proc.c ccnet_SOURCES = ccnet-daemon.c \ daemon-session.c \ $(common_srcs) ccnet_LDADD = @LIBEVENT_LIBS@ $(top_builddir)/lib/libccnetd.la \ @GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 \ @LIB_WS32@ @LIB_INTL@ @LIB_IPHLPAPI@ @SEARPC_LIBS@ ccnet_LDFLAGS = @CONSOLE@ -no-undefined ccnet-6.1.5/net/daemon/ccnet-daemon.c000066400000000000000000000125231317035602700173600ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include #else #include #endif #include "daemon-session.h" #include "rpc-service.h" #include "log.h" #ifndef SEAFILE_CLIENT_VERSION #define SEAFILE_CLIENT_VERSION PACKAGE_VERSION #endif CcnetSession *session; #ifndef WIN32 struct event sigint; struct event sigterm; struct event sigusr1; static void sigintHandler (int fd, short event, void *user_data) { ccnet_session_on_exit (session); exit (1); } static void setSigHandlers () { signal (SIGPIPE, SIG_IGN); event_set(&sigint, SIGINT, EV_SIGNAL, sigintHandler, NULL); event_add(&sigint, NULL); /* same as sigint */ event_set(&sigterm, SIGTERM, EV_SIGNAL, sigintHandler, NULL); event_add(&sigterm, NULL); /* same as sigint */ event_set(&sigusr1, SIGUSR1, EV_SIGNAL, sigintHandler, NULL); event_add(&sigusr1, NULL); } #endif static const char *short_options = "hvdp:c:D:f:M"; static struct option long_options[] = { { "help", no_argument, NULL, 'h', }, { "version", no_argument, NULL, 'v', }, { "port", required_argument, NULL, 'p', }, { "config-dir", required_argument, NULL, 'c' }, { "logfile", required_argument, NULL, 'f' }, { "debug", required_argument, NULL, 'D' }, { "daemon", no_argument, NULL, 'd' }, { NULL, 0, NULL, 0, }, }; static void usage() { fputs( "usage: ccnet [OPTIONS]\n\n" "Supported OPTIONS are:\n" " -c CONFDIR\n" " Specify the ccnet configuration directory. Default is ~/.ccnet\n" " -d\n" " Run ccnet as a daemon\n" " -D FLAGS\n" " Specify debug flags for logging, for example\n" " Peer,Group,Processor\n" " supported flags are\n" " Peer,Group,Processor,Requirement,Routing,Netio,\n" " Message,Connection,File,Other\n" " or ALL to enable all debug flags\n" " -f LOG_FILE\n" " Log file path\n", stdout); } int main (int argc, char **argv) { int c; char *config_dir; char *log_file = 0; const char *debug_str = 0; int daemon_mode = 0; const char *log_level_str = "debug"; config_dir = DEFAULT_CONFIG_DIR; #ifdef WIN32 argv = get_argv_utf8 (&argc); #endif while ((c = getopt_long (argc, argv, short_options, long_options, NULL)) != EOF) { switch (c) { case 'h': usage(); exit(0); break; case 'v': exit (1); break; case 'c': config_dir = optarg; break; case 'f': log_file = optarg; break; case 'D': debug_str = optarg; break; case 'd': daemon_mode = 1; break; default: usage(); exit (1); } } argc -= optind; argv += optind; if (config_dir == NULL) { fprintf (stderr, "Missing config dir\n"); exit (1); } #ifndef WIN32 if (daemon_mode) { #ifndef __APPLE__ daemon (1, 0); #else /* __APPLE */ /* daemon is deprecated under APPLE * use fork() instead * */ switch (fork ()) { case -1: ccnet_warning ("Failed to daemonize"); exit (-1); break; case 0: /* all good*/ break; default: /* kill origin process */ exit (0); } #endif /* __APPLE */ } #else /* WIN32 */ WSADATA wsadata; WSAStartup(0x0101, &wsadata); #endif #if !GLIB_CHECK_VERSION(2, 36, 0) g_type_init (); #endif /* log */ if (!debug_str) debug_str = g_getenv("CCNET_DEBUG"); ccnet_debug_set_flags_string (debug_str); config_dir = ccnet_expand_path (config_dir); if (!log_file) { char *logdir = g_build_filename (config_dir, "logs", NULL); checkdir_with_mkdir (logdir); g_free (logdir); log_file = g_build_filename (config_dir, "logs", "ccnet.log", NULL); } if (ccnet_log_init (log_file, log_level_str) < 0) { fprintf (stderr, "ccnet_log_init error: %s, %s\n", strerror(errno), log_file); exit (1); } ccnet_message ("starting ccnet client "SEAFILE_CLIENT_VERSION"\n"); #if defined(CCNET_SOURCE_COMMIT_ID) ccnet_message ("ccnet source code version "CCNET_SOURCE_COMMIT_ID"\n"); #endif srand (time(NULL)); session = (CcnetSession *)ccnet_daemon_session_new (); if (!session) { fputs ("Error: failed to start ccnet session, " "see log file for the detail.\n", stderr); return -1; } event_init (); evdns_init (); if (ccnet_session_prepare(session, NULL, config_dir, FALSE) < 0) { fputs ("Error: failed to start ccnet session, " "see log file for the detail.\n", stderr); return -1; } #ifndef WIN32 setSigHandlers(); #endif ccnet_session_start (session); ccnet_start_rpc(session); /* actually enter the event loop */ /* event_set_log_callback (logFunc); */ event_dispatch (); return 0; } ccnet-6.1.5/net/daemon/ccnet-test.c000066400000000000000000000103451317035602700170740ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #include "utils.h" #include "session.h" #include "peer.h" #include "peer-mgr.h" #include "perm-mgr.h" #include "daemon-session.h" #include "log.h" CcnetSession *session; CcnetGroup *group; const char *rendezvous = "eed994152b231c673eeb5f586c06cd20cf9d10e8"; #if 0 static void test_kv_mgr() { CcnetKVItem *item, *item2; char *uuid = gen_uuid(); /* test item new and unref */ item = ccnet_kvitem_new ("fileshare", group->id, uuid, "hello", 0); ccnet_kvitem_unref (item); /* build the item again */ item = ccnet_kvitem_new ("fileshare", group->id, uuid, "hello world", 0); /* receive the item twice */ ccnet_kvitem_manager_receive_item_local (session->kv_mgr, item); ccnet_kvitem_manager_receive_item_local (session->kv_mgr, item); item2 = ccnet_kvitem_manager_get_item (session->kv_mgr, uuid); g_assert (item2); g_assert (item2->ref == 3); ccnet_kvitem_unref (item2); ccnet_kvitem_unref (item); /* receive new item */ item = ccnet_kvitem_new ("fileshare", group->id, uuid, "hello world2", 0); ccnet_kvitem_manager_receive_item (session->kv_mgr, item); item2 = ccnet_kvitem_manager_get_item (session->kv_mgr, uuid); g_assert (strcmp(item2->value, "hello world2") == 0); g_assert (item == item2); /* test fetch list api */ GList *items; items = ccnet_kvitem_manager_get_items_by_group (session->kv_mgr, group->id); g_assert (g_list_length(items) == 1); ccnet_kvitem_list_free (items); items = ccnet_kvitem_manager_get_items_by_category (session->kv_mgr, "fileshare"); ccnet_kvitem_list_free (items); items = ccnet_kvitem_manager_get_item_timestamps ( session->kv_mgr, "fileshare", group->id); ccnet_kvitem_list_free (items); g_assert (g_list_length(items) == 1); g_free (uuid); } #endif void test_perm_manager() { CcnetPeer *peer; peer = ccnet_peer_manager_get_peer (session->peer_mgr, rendezvous); if (!peer) { fprintf (stderr, "Can't get peer. You should call setup first.\n"); exit (1); } char *argv[10]; argv[0] = "put-pubinfo"; argv[1] = NULL; g_assert (ccnet_perm_manager_check_permission ( session->perm_mgr, peer, "put-pubinfo", 0, 1, argv) == PERM_CHECK_OK); g_assert (ccnet_perm_manager_check_permission ( session->perm_mgr, peer, "ccnet-rpcserver", 0, 1, argv) == PERM_CHECK_ERROR); g_assert (ccnet_perm_manager_check_role_permission ( session->perm_mgr, "MyClient", "seafserv") == PERM_CHECK_OK); g_object_unref (peer); } static void test() { /* group = ccnet_group_manager_create_group ( */ /* session->groupMgr, "sample-group", rendezvous); */ /* test_kv_mgr(); */ test_perm_manager(); } int main (int argc, char **argv) { char *config_dir; char *log_file = 0; const char *debug_str = 0; int relay_mode = 0; g_setenv ("G_SLICE", "always-malloc", 0); config_dir = "../../tests/basic/conf1"; #if !GLIB_CHECK_VERSION(2, 36, 0) g_type_init (); #endif /* log */ if (!debug_str) debug_str = g_getenv("CCNET_DEBUG"); ccnet_debug_set_flags_string (debug_str); if (!log_file) log_file = "-"; if (ccnet_log_init (log_file, "info") < 0) { fprintf (stderr, "ccnet_log_init error: %s, %s\n", strerror(errno), log_file); exit (1); } srand (time(NULL)); session = (CcnetSession *)ccnet_daemon_session_new (); if (!session) { fputs ("Error: failed to start ccnet session, " "see log file for the detail.\n", stderr); return -1; } event_init (); evdns_init (); if (ccnet_session_prepare(session, NULL, config_dir, TRUE) < 0) { fprintf (stderr, "session prepare error\n"); return -1; } test(); fprintf (stderr, "success\n"); return 0; } ccnet-6.1.5/net/daemon/daemon-session.c000066400000000000000000000042321317035602700177450ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include #include #include #include #include "getgateway.h" #include "utils.h" #include "daemon-session.h" #include "peer.h" #include "peer-mgr.h" #include "perm-mgr.h" #include "packet-io.h" #include "connect-mgr.h" #include "message.h" #include "message-manager.h" #include "algorithms.h" #include "net.h" #include "rsa.h" #include "ccnet-config.h" #include "proc-factory.h" G_DEFINE_TYPE (CcnetDaemonSession, ccnet_daemon_session, CCNET_TYPE_SESSION); static int daemon_session_prepare (CcnetSession *session); static void daemon_session_start (CcnetSession *session); static void on_peer_auth_done (CcnetSession *session, CcnetPeer *peer); static void ccnet_daemon_session_class_init (CcnetDaemonSessionClass *klass) { CcnetSessionClass *session_class = CCNET_SESSION_CLASS (klass); session_class->prepare = daemon_session_prepare; session_class->start = daemon_session_start; session_class->on_peer_auth_done = on_peer_auth_done; } static void ccnet_daemon_session_init (CcnetDaemonSession *session) { } CcnetDaemonSession * ccnet_daemon_session_new () { return g_object_new (CCNET_TYPE_DAEMON_SESSION, NULL); } int daemon_session_prepare (CcnetSession *session) { /* CcnetDaemonSession *daemon_session = (CcnetDaemonSession *)session; */ /* setting of encrypt_channel */ char *encrypt_channel; /* Default to encrypt channel */ encrypt_channel = ccnet_session_config_get_string (session, "encrypt_channel"); if (!encrypt_channel) { session->encrypt_channel = 1; ccnet_session_config_set_string (session, "encrypt_channel", "on"); } else if (g_strcmp0(encrypt_channel, "off") == 0) session->encrypt_channel = 0; else session->encrypt_channel = 1; g_free (encrypt_channel); return 0; } void daemon_session_start (CcnetSession *session) { } static void on_peer_auth_done (CcnetSession *session, CcnetPeer *peer) { ccnet_peer_manager_send_ready_message (session->peer_mgr, peer); } ccnet-6.1.5/net/daemon/daemon-session.h000066400000000000000000000027001317035602700177500ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_DAEMON_SESSION_H #define CCNET_DAEMON_SESSION_H #include "session.h" #define CCNET_TYPE_DAEMON_SESSION (ccnet_daemon_session_get_type ()) #define CCNET_DAEMON_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_DAEMON_SESSION, CcnetDaemonSession)) #define CCNET_IS_DAEMON_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_DAEMON_SESSION)) #define CCNET_DAEMON_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_DAEMON_SESSION, CcnetDaemonSessionClass)) #define CCNET_IS_DAEMON_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_DAEMON_SESSION)) #define CCNET_DAEMON_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_DAEMON_SESSION, CcnetDaemonSessionClass)) typedef struct CcnetDaemonSession CcnetDaemonSession; typedef struct CcnetDaemonSessionClass CcnetDaemonSessionClass; struct CcnetDaemonSession { CcnetSession common_session; struct _CcnetPeer *default_relay; }; struct CcnetDaemonSessionClass { CcnetSessionClass parent_class; }; CcnetDaemonSession *ccnet_daemon_session_new (); void ccnet_daemon_session_set_relay (CcnetDaemonSession *session, struct _CcnetPeer *peer); void ccnet_daemon_session_unset_relay (CcnetDaemonSession *session); #endif ccnet-6.1.5/net/daemon/processors/000077500000000000000000000000001317035602700170565ustar00rootroot00000000000000ccnet-6.1.5/net/daemon/processors/sendlogin-proc.c000066400000000000000000000064541317035602700221560ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "common.h" #include "processor.h" #include "sendlogin-proc.h" #include "peer.h" #include "log.h" G_DEFINE_TYPE (CcnetSendloginProc, ccnet_sendlogin_proc, CCNET_TYPE_PROCESSOR) /* [request] "recvlogin " client -------------------------------------> relay [response] SC_OK OK 301 wrong email/passwd 302 relay internal error 303 already login, do not relogin <--------------------------------- */ static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { /* FILL IT */ CCNET_PROCESSOR_CLASS (ccnet_sendlogin_proc_parent_class)->release_resource (processor); } static void ccnet_sendlogin_proc_class_init (CcnetSendloginProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "sendlogin-proc"; proc_class->start = start; proc_class->handle_response = handle_response; proc_class->release_resource = release_resource; } static void ccnet_sendlogin_proc_init (CcnetSendloginProc *processor) { } static int start (CcnetProcessor *processor, int argc, char **argv) { if (argc != 2 || !argv[0] || !argv[1]) { ccnet_processor_error (processor, SC_BAD_ARGS, SS_BAD_ARGS); return -1; } GString *buf = g_string_new (NULL); char *email = argv[0]; char *passwd = argv[1]; g_string_append_printf (buf, "recvlogin %s %s", email, passwd); /* ccnet_message ("[Send Login] send login to relay %.10s: email(%s), passwd(%s)\n", */ /* processor->peer->id, email, passwd); */ ccnet_processor_send_request (processor, buf->str); g_string_free (buf, TRUE); CcnetPeer *relay = processor->peer; relay->login_started = TRUE; if (relay->login_error) g_free(relay->login_error); relay->login_error = NULL; return 0; } static void set_login_relay_status (CcnetProcessor *processor, gboolean success, const char *err_msg) { if (!err_msg) err_msg = "Unknown Error"; CcnetPeer *relay = processor->peer; if (relay->login_error) { g_free (relay->login_error); relay->login_error = NULL; } if (!success) { relay->login_error = g_strdup(err_msg); } else { relay->login_error = NULL; } relay->login_started = FALSE; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (g_strcmp0(code, SC_OK) == 0) { ccnet_message ("[Send Login] Successfully send login to relay %.10s\n", processor->peer->id); set_login_relay_status (processor, TRUE, NULL); ccnet_processor_done (processor, TRUE); } else { ccnet_warning ("[Send Login] Error: get repsonse: %s, %s.\n", code, code_msg); set_login_relay_status(processor, FALSE, code_msg); ccnet_processor_done (processor, FALSE); } } ccnet-6.1.5/net/daemon/processors/sendlogin-proc.h000066400000000000000000000022751317035602700221600ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SENDLOGIN_PROC_H #define CCNET_SENDLOGIN_PROC_H #include #define CCNET_TYPE_SENDLOGIN_PROC (ccnet_sendlogin_proc_get_type ()) #define CCNET_SENDLOGIN_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SENDLOGIN_PROC, CcnetSendloginProc)) #define CCNET_IS_SENDLOGIN_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SENDLOGIN_PROC)) #define CCNET_SENDLOGIN_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SENDLOGIN_PROC, CcnetSendloginProcClass)) #define IS_CCNET_SENDLOGIN_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SENDLOGIN_PROC)) #define CCNET_SENDLOGIN_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SENDLOGIN_PROC, CcnetSendloginProcClass)) typedef struct _CcnetSendloginProc CcnetSendloginProc; typedef struct _CcnetSendloginProcClass CcnetSendloginProcClass; struct _CcnetSendloginProc { CcnetProcessor parent_instance; }; struct _CcnetSendloginProcClass { CcnetProcessorClass parent_class; }; GType ccnet_sendlogin_proc_get_type (); #endif ccnet-6.1.5/net/daemon/processors/sendlogout-proc.c000066400000000000000000000051461317035602700223540ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include "sendlogout-proc.h" #include "session.h" #include "processor.h" #include "peer.h" #include "log.h" G_DEFINE_TYPE (CcnetSendlogoutProc, ccnet_sendlogout_proc, CCNET_TYPE_PROCESSOR) /* [request] "recvlogout" client -------------------------------------> relay [response] SC_OK OK 301 error <--------------------------------- */ static int start (CcnetProcessor *processor, int argc, char **argv); static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen); static void release_resource(CcnetProcessor *processor) { /* FILL IT */ CCNET_PROCESSOR_CLASS (ccnet_sendlogout_proc_parent_class)->release_resource (processor); } static void ccnet_sendlogout_proc_class_init (CcnetSendlogoutProcClass *klass) { CcnetProcessorClass *proc_class = CCNET_PROCESSOR_CLASS (klass); proc_class->name = "sendlogout-proc"; proc_class->start = start; proc_class->handle_response = handle_response; proc_class->release_resource = release_resource; } static void ccnet_sendlogout_proc_init (CcnetSendlogoutProc *processor) { } static void logout_done_cb (CcnetProcessor *processor, gboolean success, void *data) { CcnetPeer *peer = data; peer->logout_started = FALSE; g_signal_handlers_disconnect_by_func (processor, logout_done_cb, data); } static int start (CcnetProcessor *processor, int argc, char **argv) { if (argc != 0) { ccnet_processor_error (processor, SC_BAD_ARGS, SS_BAD_ARGS); return -1; } ccnet_processor_send_request (processor, "recvlogout"); g_signal_connect (processor, "done", (GCallback)logout_done_cb, processor->peer); processor->peer->logout_started = TRUE; return 0; } static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (g_strcmp0(code, SC_OK) == 0) { ccnet_message ("[Send Logout] Successfully send logout to relay %.10s\n", processor->peer->id); processor->peer->logout_started = FALSE; /* processor->peer->bind_status = BIND_NO; */ ccnet_processor_done (processor, TRUE); } else { ccnet_warning ("[Send Logout] Error: get repsonse: %s, %s.\n", code, code_msg); processor->peer->logout_started = FALSE; /* processor->peer->bind_status = BIND_YES; */ ccnet_processor_done (processor, FALSE); } } ccnet-6.1.5/net/daemon/processors/sendlogout-proc.h000066400000000000000000000023541317035602700223570ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef CCNET_SENDLOGOUT_PROC_H #define CCNET_SENDLOGOUT_PROC_H #include #include #define CCNET_TYPE_SENDLOGOUT_PROC (ccnet_sendlogout_proc_get_type ()) #define CCNET_SENDLOGOUT_PROC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CCNET_TYPE_SENDLOGOUT_PROC, CcnetSendlogoutProc)) #define CCNET_IS_SENDLOGOUT_PROC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CCNET_TYPE_SENDLOGOUT_PROC)) #define CCNET_SENDLOGOUT_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CCNET_TYPE_SENDLOGOUT_PROC, CcnetSendlogoutProcClass)) #define IS_CCNET_SENDLOGOUT_PROC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CCNET_TYPE_SENDLOGOUT_PROC)) #define CCNET_SENDLOGOUT_PROC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CCNET_TYPE_SENDLOGOUT_PROC, CcnetSendlogoutProcClass)) typedef struct _CcnetSendlogoutProc CcnetSendlogoutProc; typedef struct _CcnetSendlogoutProcClass CcnetSendlogoutProcClass; struct _CcnetSendlogoutProc { CcnetProcessor parent_instance; }; struct _CcnetSendlogoutProcClass { CcnetProcessorClass parent_class; }; GType ccnet_sendlogout_proc_get_type (); #endif ccnet-6.1.5/python/000077500000000000000000000000001317035602700141445ustar00rootroot00000000000000ccnet-6.1.5/python/Makefile.am000066400000000000000000000000171317035602700161760ustar00rootroot00000000000000SUBDIRS = ccnetccnet-6.1.5/python/ccnet/000077500000000000000000000000001317035602700152405ustar00rootroot00000000000000ccnet-6.1.5/python/ccnet/Makefile.am000066400000000000000000000005571317035602700173030ustar00rootroot00000000000000ccnetdir=${pyexecdir}/ccnet ccnet_PYTHON = __init__.py errors.py status_code.py utils.py \ packet.py message.py \ client.py sync_client.py \ pool.py rpc.py ccnet_asyncdir = ${ccnetdir}/async ccnet_async_PYTHON = async/__init__.py \ async/async_client.py async/processor.py \ async/rpcserverproc.py async/sendcmdproc.py \ async/mqclientproc.py async/timer.py ccnet-6.1.5/python/ccnet/__init__.py000066400000000000000000000003401317035602700173460ustar00rootroot00000000000000from ccnet.errors import NetworkError from ccnet.sync_client import SyncClient from ccnet.pool import ClientPool from ccnet.rpc import RpcClientBase, CcnetRpcClient, CcnetThreadedRpcClient from ccnet.message import Messageccnet-6.1.5/python/ccnet/async/000077500000000000000000000000001317035602700163555ustar00rootroot00000000000000ccnet-6.1.5/python/ccnet/async/__init__.py000066400000000000000000000005371317035602700204730ustar00rootroot00000000000000''' @module: ccnet.async @description: The async client of ccnet depends on python-libevent, so we move it to a standalone package. ''' from .async_client import AsyncClient from .processor import Processor from .rpcserverproc import RpcServerProc from .sendcmdproc import SendCmdProc from .mqclientproc import MqClientProc from .timer import Timerccnet-6.1.5/python/ccnet/async/async_client.py000066400000000000000000000201521317035602700214020ustar00rootroot00000000000000import logging import libevent from ccnet.client import Client, parse_update, parse_response from ccnet.packet import response_to_packet, parse_header, Packet from ccnet.packet import to_response_id, to_master_id, to_slave_id, to_packet_id from ccnet.packet import CCNET_MSG_REQUEST, CCNET_MSG_UPDATE, CCNET_MSG_RESPONSE, \ CCNET_HEADER_LENGTH, CCNET_MAX_PACKET_LENGTH from ccnet.status_code import SC_PROC_DONE, SC_PROC_DEAD, SS_PROC_DEAD, \ SC_UNKNOWN_SERVICE, SC_PROC_KEEPALIVE, SS_PROC_KEEPALIVE, SC_PERM_ERR from ccnet.status_code import PROC_NO_SERVICE, PROC_PERM_ERR, \ PROC_BAD_RESP, PROC_REMOTE_DEAD from ccnet.errors import NetworkError from .processor import Processor from .sendcmdproc import SendCmdProc from .mqclientproc import MqClientProc __all__ = [ 'AsyncClient', ] def debug_print(msg): print msg class AsyncClient(Client): '''Async mode client''' def __init__(self, config_dir, event_base, central_config_dir=None): Client.__init__(self, config_dir, central_config_dir) self.proc_types = {} self.procs = {} self.register_processors() self._bev = None self._evbase = event_base def get_event_base(self): return self._evbase def add_processor(self, proc): self.procs[proc.id] = proc def remove_processor(self, proc): if proc.id in self.procs: del self.procs[proc.id] def get_proc(self, id): return self.procs.get(id, None) def write_packet(self, pkt): outbuf = self._bev.output outbuf.add(pkt.header.to_string()) outbuf.add(pkt.body) def send_response(self, id, code, code_msg, content=''): id = to_response_id(id) pkt = response_to_packet(id, code, code_msg, content) self.write_packet(pkt) def handle_packet(self, pkt): ptype = pkt.header.ptype if ptype == CCNET_MSG_REQUEST: self.handle_request(pkt.header.id, pkt.body) elif ptype == CCNET_MSG_UPDATE: code, code_msg, content = parse_update(pkt.body) self.handle_update(pkt.header.id, code, code_msg, content) elif ptype == CCNET_MSG_RESPONSE: code, code_msg, content = parse_response(pkt.body) self.handle_response(pkt.header.id, code, code_msg, content) else: logging.warning("unknown packet type %d", ptype) def handle_request(self, id, req): commands = req.split() self.create_slave_processor(to_slave_id(id), commands) def create_slave_processor(self, id, commands): peer_id = self.peer_id if commands[0] == 'remote': if len(commands) < 3: logging.warning("invalid request %s", commands) return peer_id = commands[1] commands = commands[2:] proc_name = commands[0] if not proc_name in self.proc_types: logging.warning("unknown processor type %s", proc_name) return cls = self.proc_types[proc_name] proc = cls(proc_name, id, peer_id, self) self.add_processor(proc) proc.start(*commands[1:]) def create_master_processor(self, proc_name): id = self.get_request_id() cls = self.proc_types.get(proc_name, None) if cls == None: logging.error('unknown processor type %s', proc_name) return None proc = cls(proc_name, id, self.peer_id, self) self.add_processor(proc) return proc def handle_update(self, id, code, code_msg, content): proc = self.get_proc(to_slave_id(id)) if proc == None: if code != SC_PROC_DEAD: self.send_response(id, SC_PROC_DEAD, SS_PROC_DEAD) return if code[0] == '5': logging.info('shutdown processor %s(%d): %s %s\n', proc.name, to_packet_id(proc.id), code, code_msg) if code == SC_UNKNOWN_SERVICE: proc.shutdown(PROC_NO_SERVICE) elif code == SC_PERM_ERR: proc.shutdown(PROC_PERM_ERR) else: proc.shutdown(PROC_BAD_RESP) elif code == SC_PROC_KEEPALIVE: proc.send_response(SC_PROC_KEEPALIVE, SS_PROC_KEEPALIVE) elif code == SC_PROC_DEAD: logging.info('shutdown processor %s(%d): when peer(%.8s) processor is dead\n', proc.name, to_packet_id(proc.id), proc.peer_id) proc.shutdown(PROC_REMOTE_DEAD) elif code == SC_PROC_DONE: proc.done(True) else: proc.handle_update(code, code_msg, content) def handle_response(self, id, code, code_msg, content): proc = self.get_proc(to_master_id(id)) if proc == None: if code != SC_PROC_DEAD: self.send_update(id, SC_PROC_DEAD, SS_PROC_DEAD) return if code[0] == '5': logging.info('shutdown processor %s(%d): %s %s\n', proc.name, to_packet_id(proc.id), code, code_msg) if code == SC_UNKNOWN_SERVICE: proc.shutdown(PROC_NO_SERVICE) elif code == SC_PERM_ERR: proc.shutdown(PROC_PERM_ERR) else: proc.shutdown(PROC_BAD_RESP) elif code == SC_PROC_KEEPALIVE: proc.send_update(id, SC_PROC_KEEPALIVE, SS_PROC_KEEPALIVE) elif code == SC_PROC_DEAD: logging.info('shutdown processor %s(%d): when peer(%.8s) processor is dead\n', proc.name, to_packet_id(proc.id), proc.peer_id) proc.shutdown(PROC_REMOTE_DEAD) else: proc.handle_response(code, code_msg, content) def register_processor(self, proc_name, proc_type): assert Processor in proc_type.mro() self.proc_types[proc_name] = proc_type def register_processors(self): self.register_processor("send-cmd", SendCmdProc) self.register_processor("mq-client", MqClientProc) def register_service(self, service, group, proc_type, callback=None): self.register_processor(service, proc_type) cmd = 'register-service %s %s' % (service, group) self.send_cmd(cmd, callback) def send_cmd(self, cmd, callback=None): proc = self.create_master_processor("send-cmd") if callback: proc.set_callback(callback) proc.start() proc.send_cmd(cmd) def _read_cb(self, bev, cb_data): dummy = bev, cb_data inbuf = self._bev.input while (True): raw = inbuf.copyout(CCNET_HEADER_LENGTH) header = parse_header(raw) if len(inbuf) < CCNET_HEADER_LENGTH + header.length: break inbuf.drain(CCNET_HEADER_LENGTH) data = inbuf.copyout(header.length) pkt = Packet(header, data) self.handle_packet(pkt) inbuf.drain(header.length) if len(inbuf) < CCNET_HEADER_LENGTH: break def _event_cb(self, bev, what, cb_data): dummy = bev, cb_data logging.warning('libevent error: what = %s' % what) if what & libevent.BEV_EVENT_EOF or \ what & libevent.BEV_EVENT_ERROR or \ what & libevent.BEV_EVENT_READING or \ what & libevent.BEV_EVENT_WRITING: if self._bev is not None: self._bev = None raise NetworkError('libevent error: what = %s' % what) def base_loop(self): '''Create an event base -> register socket events -> loop''' self._bev = libevent.BufferEvent(self._evbase, self._connfd.fileno()) self._bev.set_watermark(libevent.EV_READ, CCNET_HEADER_LENGTH, # low wartermark CCNET_MAX_PACKET_LENGTH * 2) # highmark self._bev.set_callbacks(self._read_cb, # read callback None, # write callback self._event_cb) # event callback self._bev.enable(libevent.EV_READ | libevent.EV_WRITE) self._evbase.loop() def main_loop(self): self.base_loop() ccnet-6.1.5/python/ccnet/async/mqclientproc.py000066400000000000000000000026021317035602700214270ustar00rootroot00000000000000import logging from .processor import Processor from ccnet.message import message_from_string, message_to_string INIT = 0 REQUEST_SENT = 1 READY = 2 SC_MSG = '300' SC_UNSUBSCRIBE = '301' class MqClientProc(Processor): def __init__(self, *args, **kwargs): Processor.__init__(self, *args, **kwargs) self.state = INIT self.callback = None def start(self, *argv): req = 'mq-server ' + ' '.join(argv) self.send_request(req) self.state = REQUEST_SENT def set_callback(self, cb): self.callback = cb def handle_response(self, code, code_msg, content): if self.state == REQUEST_SENT: if code[0] != '2': logging.warning('bad response: %s %s\n', code, code_msg) self.done(False) self.state = READY elif self.state == READY: if code[0] != '2' and code[0] != '3': logging.warning('bad response: %s %s\n', code, code_msg) return if code[0] == '3' and code[2] == '0': msg = message_from_string(content[:-1]) if self.callback: self.callback(msg) def put_message(self, msg): buf = message_to_string(msg) self.send_update(SC_MSG, '', buf + '\000') def unsubscribe(self): self.send_update(SC_UNSUBSCRIBE, '') self.done(True)ccnet-6.1.5/python/ccnet/async/processor.py000066400000000000000000000032331317035602700207470ustar00rootroot00000000000000import logging from ccnet.packet import SLAVE_BIT_MASK, to_print_id from ccnet.status_code import SC_PROC_DONE, SS_PROC_DONE, PROC_DONE class Processor(object): """Base processor class""" name = "Processor" def __init__(self, name, id, peer_id, client): self.name = name self.id = id self.peer_id = peer_id self.client = client def start(self, *args, **kwargs): raise NotImplementedError def handle_request(self, *args, **kwargs): raise NotImplementedError def handle_update(self, *args, **kwargs): raise NotImplementedError def handle_response(self, *args, **kwargs): raise NotImplementedError def __str__(self): return "" % (self.name, to_print_id(self.id)) def is_master(self): return not (self.id & SLAVE_BIT_MASK) def send_request(self, buf): assert self.is_master() return self.client.send_request(self.id, buf) def send_response(self, code, code_msg, content=''): assert not self.is_master() return self.client.send_response(self.id, code, code_msg, content) def send_update(self, code, code_msg, content=''): assert self.is_master() return self.client.send_update(self.id, code, code_msg, content) def done(self, success): if self.is_master() and success: self.send_update(SC_PROC_DONE, SS_PROC_DONE, '') self.client.remove_processor(self) def shutdown(self, reason): if reason > PROC_DONE: logging.debug('shut down %s: %s', self, reason) self.client.remove_processor(self)ccnet-6.1.5/python/ccnet/async/rpcserverproc.py000066400000000000000000000026161317035602700216330ustar00rootroot00000000000000from pysearpc import searpc_server from ccnet.status_code import SC_OK, SS_OK from ccnet.status_code import SC_SERVER_RET, SS_SERVER_RET, SC_SERVER_MORE, SS_SERVER_MORE, \ SC_CLIENT_CALL, SC_CLIENT_MORE, SC_CLIENT_CALL_MORE from .processor import Processor class RpcServerProc(Processor): name = 'rpcserver-proc' max_transfer_length = 65535 - 128 def __init__(self, *args, **kwargs): Processor.__init__(self, *args, **kwargs) self.fretstr = '' self.fcallstr = '' def start(self, *argv): self.send_response(SC_OK, SS_OK, '') def send_fret(self): maxlen = self.max_transfer_length l = len(self.fretstr) if l < maxlen: self.send_response(SC_SERVER_RET, SS_SERVER_RET, self.fretstr) self.fretstr = '' else: buf = self.fretstr[:maxlen] self.send_response(SC_SERVER_MORE, SS_SERVER_MORE, buf) self.fretstr = self.fretstr[maxlen:] def handle_update(self, code, code_msg, content): if code == SC_CLIENT_CALL_MORE: self.fcallstr += content return elif code == SC_CLIENT_CALL: self.fcallstr += content self.fretstr = searpc_server.call_function(self.name, self.fcallstr) self.fcallstr = '' self.send_fret() elif code == SC_CLIENT_MORE: self.send_fret()ccnet-6.1.5/python/ccnet/async/sendcmdproc.py000066400000000000000000000015761317035602700212410ustar00rootroot00000000000000import logging from .processor import Processor INIT = 0 REQUET_SENT = 1 CONNECTED = 2 class SendCmdProc(Processor): name = "send-cmd" def __init__(self, *args, **kwargs): Processor.__init__(self, *args, **kwargs) self.callback = None self.state = INIT def start(self, *argv): self.send_request('receive-cmd') self.state = REQUET_SENT def set_callback(self, cb): self.callback = cb def send_cmd(self, cmd): self.send_update('200', '', cmd + '\000') def handle_response(self, code, code_msg, content): if code[0] != '2': logging.warning("Received bad response %s %s", code, code_msg) if self.state == REQUET_SENT: self.state = CONNECTED elif self.state == CONNECTED: if self.callback: self.callback(code, code_msg, content)ccnet-6.1.5/python/ccnet/async/timer.py000066400000000000000000000011101317035602700200400ustar00rootroot00000000000000import libevent import logging class Timer(object): '''Wraps aroud a libevent timeout event''' def __init__(self, ev_base, timeout): self._timeout = timeout self._evtimer = libevent.Timer(ev_base, self._callback, None) self._evtimer.add(timeout) # pylint: disable=E1101 def _callback(self, evtimer, user_data): dummy = user_data try: self.callback() except: logging.exception('error in timer callback:') evtimer.add(self._timeout) def callback(self): raise NotImplementedErrorccnet-6.1.5/python/ccnet/client.py000066400000000000000000000107461317035602700171000ustar00rootroot00000000000000#coding: UTF-8 import os import socket import ConfigParser import logging from ccnet.packet import to_request_id, to_update_id from ccnet.packet import request_to_packet, update_to_packet from ccnet.packet import write_packet from ccnet.errors import NetworkError from .utils import is_win32, make_socket_closeonexec CCNET_PIPE_NAME = 'ccnet.sock' def parse_response(body): '''Parse the content of the response The struct of response data: - first 3 bytes is the - from the 4th byte to the first occurrence of '\n' is the . If the 4th byte is '\n', then there is no - from the first occurrence of '\n' to the end is the ''' code = body[:3] if body[3] == '\n': code_msg = '' content = body[4:] else: pos = body.index('\n') code_msg = body[4:pos] content = body[pos + 1:] return code, code_msg, content def parse_update(body): '''The structure of an update is the same with a response''' code = body[:3] if body[3] == '\n': code_msg = '' content = body[4:] else: pos = body.index('\n') code_msg = body[4:pos] content = body[pos + 1:] return code, code_msg, content class Client(object): '''Base ccnet client class''' def __init__(self, config_dir, central_config_dir=None): if not isinstance(config_dir, unicode): config_dir = config_dir.decode('UTF-8') if central_config_dir: central_config_dir = os.path.expanduser(central_config_dir) if not os.path.exists(central_config_dir): raise RuntimeError(u'%s does not exits' % central_config_dir) config_dir = os.path.expanduser(config_dir) config_file = os.path.join(central_config_dir if central_config_dir else config_dir, u'ccnet.conf') logging.debug('using config file %s', config_file) if not os.path.exists(config_file): raise RuntimeError(u'%s does not exits' % config_file) self.central_config_dir = central_config_dir self.config_dir = config_dir self.config_file = config_file self.config = None self.port = None self.peer_id = None self.peer_name = None self.parse_config() self._connfd = None self._req_id = 1000 def __del__(self): '''Destructor of the client class. We close the socket here, if connetced to daemon ''' if self.is_connected(): try: self._connfd.close() except: pass def parse_config(self): self.config = ConfigParser.ConfigParser() self.config.read(self.config_file) self.port = self.config.getint('Client', 'PORT') self.un_path = '' if self.config.has_option('Client', 'UNIX_SOCKET'): self.un_path = self.config.get('Client', 'UNIX_SOCKET') self.peer_id = self.config.get('General', 'ID') self.peer_name = self.config.get('General', 'NAME') def connect_daemon_with_pipe(self): self._connfd = socket.socket(socket.AF_UNIX) if not self.un_path: pipe_name = os.path.join(self.config_dir, CCNET_PIPE_NAME) else: pipe_name = self.un_path try: self._connfd.connect(pipe_name) except: raise NetworkError("Can't connect to daemon") make_socket_closeonexec(self._connfd.fileno()) def connect_daemon_with_socket(self): self._connfd = socket.socket() self._connfd.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) try: self._connfd.connect(('127.0.0.1', self.port)) except: raise NetworkError("Can't connect to daemon") make_socket_closeonexec(self._connfd.fileno()) def connect_daemon(self): if is_win32(): return self.connect_daemon_with_socket() else: return self.connect_daemon_with_pipe() def is_connected(self): return self._connfd is not None def send_request(self, id, req): id = to_request_id(id) pkt = request_to_packet(id, req) write_packet(self._connfd, pkt) def send_update(self, id, code, code_msg, content=''): id = to_update_id(id) pkt = update_to_packet(id, code, code_msg, content) write_packet(self._connfd, pkt) def get_request_id(self): self._req_id += 1 return self._req_id ccnet-6.1.5/python/ccnet/errors.py000066400000000000000000000002441317035602700171260ustar00rootroot00000000000000class NetworkError(Exception): def __init__(self, msg): Exception.__init__(self) self.msg = msg def __str__(self): return self.msg ccnet-6.1.5/python/ccnet/message.py000066400000000000000000000026721317035602700172450ustar00rootroot00000000000000#coding: UTF-8 '''Message is the carrier of a simple Pub/Sub system on top of ccnet''' import datetime import re import uuid import time MESSAGE_PATTERN = re.compile(r'(?P[\d]+) (?P[^ ]+) (?P[^ ]+) (?P[^ ]+) (?P[^ ]+) (?P[^ ]+) (?P[^ ]+) (?P.*)') class Message(object): def __init__(self, d): self.flags = int(d['flags']) self.from_ = d['from'] self.to = d['to'] self.id = d['id'] self.ctime = float(d['ctime']) self.rtime = float(d['rtime']) self.app = d['app'] self.body = d['body'] def message_from_string(s): results = MESSAGE_PATTERN.match(s) if results is None: raise RuntimeError('Bad message: %s' % s) d = results.groupdict() return Message(d) def gen_inner_message_string(self_id, app, content): result = "%d %s %s %s %d %d %s %s\000" % (0, self_id, self_id, str(uuid.uuid1()), int(time.time()), 0, app, content) return result def message_to_string(msg): f = '%(flags)s %(from_)s %(to)s %(id)s %(ctime)s %(rtime)s %(app)s %(body)s' return f % dict(flags=msg.flags, from_=msg.from_, to=msg.to, id=msg.id, ctime=msg.ctime, rtime=msg.rtime, app=msg.app, body=msg.body) ccnet-6.1.5/python/ccnet/packet.py000066400000000000000000000066731317035602700170750ustar00rootroot00000000000000#coding: UTF-8 """ Packet level protocol of ccnet. About various types of id: - A slave processor's id has its highest bit set; a master processor has its highest bit clear - The field of a ccnet packet always has its highest bit clear. The field of the packet determines what type of the packet is (a request, a response, or an update) """ import logging import struct from ccnet.utils import recvall, sendall, NetworkError REQUEST_ID_MASK = 0x7fffffff SLAVE_BIT_MASK = 0x80000000 CCNET_MSG_OK = 0 CCNET_MSG_HANDSHAKE = 1 CCNET_MSG_REQUEST = 2 CCNET_MSG_RESPONSE = 3 CCNET_MSG_UPDATE = 4 CCNET_MSG_RELAY = 5 def to_request_id(id): return id & REQUEST_ID_MASK to_response_id = to_request_id to_update_id = to_request_id to_master_id = to_request_id to_packet_id = to_request_id def to_slave_id(id): return id | SLAVE_BIT_MASK def to_print_id(id): if id & SLAVE_BIT_MASK: return -to_request_id(id) else: return id # the byte sequence of ccnet packet header CCNET_HEADER_FORMAT = '>BBHI' # Number of bytes for the header CCNET_HEADER_LENGTH = struct.calcsize(CCNET_HEADER_FORMAT) CCNET_MAX_PACKET_LENGTH = 65535 class PacketHeader(object): def __init__(self, ver, ptype, length, id): self.ver = ver self.ptype = ptype self.length = length self.id = id def to_string(self): return struct.pack(CCNET_HEADER_FORMAT, self.ver, self.ptype, self.length, self.id) def __str__(self): return "" % (self.ptype, self.length, self.id) class Packet(object): version = 1 def __init__(self, header, body): self.header = header self.body = body def parse_header(buf): try: ver, ptype, length, id = struct.unpack(CCNET_HEADER_FORMAT, buf) except struct.error, e: raise NetworkError('error when unpack packet header: %s' % e) return PacketHeader(ver, ptype, length, id) def format_response(code, code_msg, content): body = code if code_msg: body += " " + code_msg body += "\n" if content: body += content return body format_update = format_response def request_to_packet(id, buf): hdr = PacketHeader(1, CCNET_MSG_REQUEST, len(buf), to_request_id(id)) return Packet(hdr, buf) def response_to_packet(id, code, code_msg, content): body = format_response(code, code_msg, content) hdr = PacketHeader(1, CCNET_MSG_RESPONSE, len(body), to_response_id(id)) return Packet(hdr, body) def update_to_packet(id, code, code_msg, content): body = format_update(code, code_msg, content) hdr = PacketHeader(1, CCNET_MSG_UPDATE, len(body), to_update_id(id)) return Packet(hdr, body) def read_packet(fd): hdr = recvall(fd, CCNET_HEADER_LENGTH) if len(hdr) == 0: logging.warning('connection to daemon is lost') raise NetworkError('Connection to daemon is lost') elif len(hdr) < CCNET_HEADER_LENGTH: raise NetworkError('Only read %d bytes header, expected 8' % len(hdr)) header = parse_header(hdr) if header.length == 0: body = '' else: body = recvall(fd, header.length) if len(body) < header.length: raise NetworkError('Only read %d bytes body, expected %d' % (len(body), header.length)) return Packet(header, body) def write_packet(fd, packet): hdr = packet.header.to_string() sendall(fd, hdr) sendall(fd, packet.body)ccnet-6.1.5/python/ccnet/pool.py000066400000000000000000000020241317035602700165610ustar00rootroot00000000000000from ccnet.sync_client import SyncClient import Queue class ClientPool(object): """ccnet client pool.""" def __init__(self, conf_dir, pool_size=5, central_config_dir=None): """ :param central_config_dir: path to the central config dir for ccnet/seafile/seahub/seafdav etc. :param conf_dir: the ccnet configuration directory :param pool_size: """ self.central_config_dir = central_config_dir self.conf_dir = conf_dir self.pool_size = pool_size self._pool = Queue.Queue(pool_size) def _create_client(self): client = SyncClient(self.conf_dir, self.central_config_dir) client.req_ids = {} client.connect_daemon() return client def get_client(self): try: client = self._pool.get(False) except: client = self._create_client() return client def return_client(self, client): try: self._pool.put(client, False) except Queue.Full: pass ccnet-6.1.5/python/ccnet/rpc.py000066400000000000000000000274661317035602700164150ustar00rootroot00000000000000from pysearpc import SearpcClient, searpc_func, SearpcError from ccnet.status_code import SC_CLIENT_CALL, SS_CLIENT_CALL, \ SC_CLIENT_MORE, SS_CLIENT_MORE, SC_SERVER_RET, \ SC_SERVER_MORE, SC_PROC_DEAD from ccnet.errors import NetworkError class DeadProcError(Exception): def __str__(self): return "Processor is dead" class RpcClientBase(SearpcClient): def __init__(self, ccnet_client_pool, service_name, retry_num=1, is_remote=False, remote_peer_id='', req_pool=False): SearpcClient.__init__(self) self.pool = ccnet_client_pool self.service_name = service_name self.retry_num = retry_num self.is_remote = is_remote self.remote_peer_id = remote_peer_id self.req_pool = req_pool if self.is_remote and len(self.remote_peer_id) != 40: raise ValueError("Invalid remote peer id") def _start_service(self, client): req_id = client.get_request_id() req_str = self.service_name if self.is_remote: req_str = "remote " + self.remote_peer_id + " " + self.service_name client.send_request(req_id, req_str) rsp = client.read_response() if rsp.code != "200": raise SearpcError("Error received: %s %s (In _start_service)" % (rsp.code, rsp.code_msg)) return req_id def _real_call(self, client, req_id, fcall_str): client.send_update(req_id, SC_CLIENT_CALL, SS_CLIENT_CALL, fcall_str) rsp = client.read_response() if rsp.code == SC_SERVER_RET: return rsp.content elif rsp.code == SC_SERVER_MORE: buf = rsp.content while True: client.send_update(req_id, SC_CLIENT_MORE, SS_CLIENT_MORE, '') rsp = client.read_response() if rsp.code == SC_SERVER_MORE: buf += rsp.content elif rsp.code == SC_SERVER_RET: buf += rsp.content break else: raise SearpcError("Error received: %s %s (In Read More)" % (rsp.code, rsp.code_msg)) return buf elif rsp.code == SC_PROC_DEAD: raise DeadProcError() else: raise SearpcError("Error received: %s %s" % (rsp.code, rsp.code_msg)) def call_remote_func_sync(self, fcall_str): """Call remote function `fcall_str` and wait response.""" retried = 0 while True: try: client = self.pool.get_client() if self.req_pool: req_id = client.req_ids.get(self.service_name, -1) if req_id == -1: req_id = self._start_service(client) client.req_ids[self.service_name] = req_id try: ret = self._real_call(client, req_id, fcall_str) except DeadProcError: client.req_ids[self.service_name] = -1 self.pool.return_client(client) if retried < self.retry_num: retried = retried + 1 continue else: raise self.pool.return_client(client) return ret else: # no req pool req_id = self._start_service(client) ret = self._real_call(client, req_id, fcall_str) client.send_update(req_id, "103", "service is done", "") self.pool.return_client(client) return ret except (NetworkError, SearpcError): # the client is not returned to the pool and is freed automatically if retried < self.retry_num: retried = retried + 1 continue else: raise class CcnetRpcClient(RpcClientBase): def __init__(self, ccnet_client_pool, retry_num=1, *args, **kwargs): RpcClientBase.__init__(self, ccnet_client_pool, "ccnet-rpcserver", *args, **kwargs) @searpc_func("string", []) def list_peers(self): pass @searpc_func("objlist", []) def list_resolving_peers(self): pass @searpc_func("objlist", ["string"]) def get_peers_by_role(self): pass @searpc_func("object", ["string"]) def get_peer(self): pass @searpc_func("object", []) def get_session_info(self): pass @searpc_func("int", ["string"]) def add_client(self): pass @searpc_func("int", ["string", "string"]) def add_role(self, peer_id, role): pass @searpc_func("int", ["string", "string"]) def remove_role(self, peer_id, role): pass @searpc_func("objlist", ["int", "int"]) def get_procs_alive(self, offset, limit): pass @searpc_func("int", []) def count_procs_alive(self): pass @searpc_func("objlist", ["int", "int"]) def get_procs_dead(self, offset, limit): pass @searpc_func("int", []) def count_procs_dead(self): pass @searpc_func("string", ["string"]) def get_config(self, key): pass @searpc_func("int", ["string", "string"]) def set_config(self, key, value): pass @searpc_func("objlist", []) def list_peer_stat(self, key, value): pass class CcnetThreadedRpcClient(RpcClientBase): def __init__(self, ccnet_client_pool, retry_num=1, *args, **kwargs): RpcClientBase.__init__(self, ccnet_client_pool, "ccnet-threaded-rpcserver", *args, **kwargs) @searpc_func("int", ["string", "string", "int", "int"]) def add_emailuser(self, email, passwd, is_staff, is_active): pass @searpc_func("int", ["string", "string"]) def remove_emailuser(self, source, email): pass @searpc_func("int", ["string", "string"]) def validate_emailuser(self, email, passwd): pass @searpc_func("object", ["string"]) def get_emailuser(self, email): pass @searpc_func("object", ["string"]) def get_emailuser_with_import(self, email): pass @searpc_func("object", ["int"]) def get_emailuser_by_id(self, user_id): pass @searpc_func("objlist", ["string", "int", "int", "string"]) def get_emailusers(self, source, start, limit, status): pass @searpc_func("objlist", ["string", "string", "int", "int"]) def search_emailusers(self, source, email_patt, start, limit): pass @searpc_func("objlist", ["string", "int", "int"]) def search_ldapusers(self, keyword, start, limit): pass @searpc_func("int64", ["string"]) def count_emailusers(self, source): pass @searpc_func("int64", ["string"]) def count_inactive_emailusers(self, source): pass @searpc_func("objlist", ["string"]) def filter_emailusers_by_emails(self): pass @searpc_func("int", ["string", "int", "string", "int", "int"]) def update_emailuser(self, source, user_id, password, is_staff, is_active): pass @searpc_func("int", ["string", "string"]) def update_role_emailuser(self, email, role): pass @searpc_func("objlist", []) def get_superusers(self): pass @searpc_func("int", ["string", "string"]) def add_binding(self, email, peer_id): pass @searpc_func("string", ["string"]) def get_binding_email(self, peer_id): pass @searpc_func("string", ["string"]) def get_binding_peerids(self, email): pass @searpc_func("int", ["string"]) def remove_binding(self, email): pass @searpc_func("int", ["string", "string"]) def remove_one_binding(self, email, peer_id): pass @searpc_func("objlist", ["string"]) def get_peers_by_email(self, email): pass @searpc_func("int", ["string", "string", "string"]) def create_group(self, group_name, user_name, gtype): pass @searpc_func("int", ["int", "string", "string"]) def create_org_group(self, org_id, group_name, user_name): pass @searpc_func("int", ["int"]) def remove_group(self, group_id): pass @searpc_func("int", ["int", "string", "string"]) def group_add_member(self, group_id, user_name, member_name): pass @searpc_func("int", ["int", "string", "string"]) def group_remove_member(self, group_id, user_name, member_name): pass @searpc_func("int", ["int", "string"]) def group_set_admin(self, group_id, member_name): pass @searpc_func("int", ["int", "string"]) def group_unset_admin(self, group_id, member_name): pass @searpc_func("int", ["int", "string"]) def set_group_name(self, group_id, group_name): pass @searpc_func("int", ["int", "string"]) def quit_group(self, group_id, user_name): pass @searpc_func("objlist", ["string"]) def get_groups(self, user_name): pass @searpc_func("objlist", ["int", "int", "string"]) def get_all_groups(self, start, limit, source): pass @searpc_func("object", ["int"]) def get_group(self, group_id): pass @searpc_func("objlist", ["int"]) def get_group_members(self, group_id): pass @searpc_func("int", ["int", "string"]) def check_group_staff(self, group_id, username): pass @searpc_func("int", ["string"]) def remove_group_user(self, username): pass @searpc_func("int", ["int", "string"]) def is_group_user(self, group_id, user): pass @searpc_func("int", ["int", "string"]) def set_group_creator(self, group_id, user_name): pass @searpc_func("int", ["string", "string", "string"]) def create_org(self, org_name, url_prefix, creator): pass @searpc_func("int", ["int"]) def remove_org(self, org_id): pass @searpc_func("objlist", ["int", "int"]) def get_all_orgs(self, start, limit): pass @searpc_func("int64", []) def count_orgs(self): pass @searpc_func("object", ["string"]) def get_org_by_url_prefix(self, url_prefix): pass @searpc_func("object", ["string"]) def get_org_by_id(self, org_id): pass @searpc_func("int", ["int", "string", "int"]) def add_org_user(self, org_id, email, is_staff): pass @searpc_func("int", ["int", "string"]) def remove_org_user(self, org_id, email): pass @searpc_func("objlist", ["string"]) def get_orgs_by_user(self, email): pass @searpc_func("objlist", ["string", "int", "int"]) def get_org_emailusers(self, url_prefix, start, limit): pass @searpc_func("int", ["int", "int"]) def add_org_group(self, org_id, group_id): pass @searpc_func("int", ["int", "int"]) def remove_org_group(self, org_id, group_id): pass @searpc_func("int", ["int"]) def is_org_group(self, group_id): pass @searpc_func("int", ["int"]) def get_org_id_by_group(self, group_id): pass @searpc_func("objlist", ["int", "int", "int"]) def get_org_groups(self, org_id, start, limit): pass @searpc_func("int", ["int", "string"]) def org_user_exists(self, org_id, email): pass @searpc_func("int", ["int", "string"]) def is_org_staff(self, org_id, user): pass @searpc_func("int", ["int", "string"]) def set_org_staff(self, org_id, user): pass @searpc_func("int", ["int", "string"]) def unset_org_staff(self, org_id, user): pass @searpc_func("int", ["int", "string"]) def set_org_name(self, org_id, org_name): pass ccnet-6.1.5/python/ccnet/status_code.py000066400000000000000000000036061317035602700201340ustar00rootroot00000000000000#coding: UTF-8 '''Status code and status messages used in ccnet. Should be treated as constants''' EC_NETWORK_ERR = 1 ES_NETWORK_ERR = 'Network Error' SC_PROC_KEEPALIVE = '100' SS_PROC_KEEPALIVE = 'processor keep alive' SC_PROC_ALIVE = '101' SS_PROC_ALIVE = 'processor is alive' SC_PROC_DEAD = '102' SS_PROC_DEAD = 'processor is dead' SC_PROC_DONE = '103' SS_PROC_DONE = 'service is done' SC_OK = '200' SS_OK = 'OK' SC_SERV_EXISTED = '210' SS_SERV_EXISTED = 'The service existed' SC_PERM_CHECKING = '250' SS_PERM_CHECKING = 'Permission Checking' SC_SHUTDOWN = '500' SS_SHUTDOWN = 'Shutdown' SC_CREATE_PROC_ERR = '501' SS_CREATE_PROC_ERR = 'Create Processor Error' SC_BAD_PEER = '502' SS_BAD_PEER = 'Bad peer id' SC_BAD_USER = '502' SS_BAD_USER = 'Bad user id' SC_BAD_ARGS = '503' SS_BAD_ARGS = 'Bad arguments' SC_PERM_ERR = '504' SS_PERM_ERR = 'Permission Error' SC_BAD_UPDATE_CODE = '506' SS_BAD_UPDATE_CODE = 'Bad update code' SC_BAD_RESPONSE_CODE = '507' SS_BAD_RESPONSE_CODE = 'Bad response code' SC_VERSION_MISMATCH = '508' SS_VERSION_MISMATCH = 'Version Mismatch' SC_UNKNOWN_PEER = '510' SS_UNKNOWN_PEER = 'Unknown peer' SC_UNKNOWN_SERVICE = '511' SS_UNKNOWN_SERVICE = 'Unknown service' SC_PEER_UNREACHABLE = '512' SS_PEER_UNREACHABLE = 'Peer Unreachable' SC_CON_TIMEOUT = '513' SS_CON_TIMEOUT = 'connection timeout' SC_KEEPALIVE_TIMEOUT = '514' SS_KEEPALIVE_TIMEOUT = 'keepalive timeout' SC_NETDOWN = '515' SS_NETDOWN = 'peer down' PROC_NOTSET = 0 PROC_DONE = 1 PROC_REMOTE_DEAD = 2 PROC_NO_SERVICE = 3 PROC_PERM_ERR = 4 PROC_BAD_RESP = 5 SC_CLIENT_CALL = '301' SS_CLIENT_CALL = 'CLIENT CALL' SC_CLIENT_MORE = '302' SS_CLIENT_MORE = 'MORE' SC_CLIENT_CALL_MORE = '303' SS_CLIENT_CALL_MORE = 'CLIENT HAS MORE' SC_SERVER_RET = '311' SS_SERVER_RET = 'SERVER RET' SC_SERVER_MORE = '312' SS_SERVER_MORE = 'HAS MORE' SC_SERVER_ERR = '411' SS_SERVER_ERR = 'Fail to invoke the function, check the function'ccnet-6.1.5/python/ccnet/sync_client.py000066400000000000000000000063151317035602700201310ustar00rootroot00000000000000from ccnet.client import Client, parse_response from ccnet.packet import read_packet, CCNET_MSG_RESPONSE from ccnet.status_code import SC_PROC_DONE, SS_PROC_DONE from ccnet.message import message_from_string, gen_inner_message_string _REQ_ID_START = 1000 class Response(object): def __init__(self, code, code_msg, content): self.code = code self.code_msg = code_msg self.content = content class SyncClient(Client): '''sync mode client''' def __init__(self, config_dir, central_config_dir=None): Client.__init__(self, config_dir, central_config_dir) self._req_id = _REQ_ID_START self.mq_req_id = -1 def disconnect_daemon(self): if self.is_connected(): try: self._connfd.close() except: pass def read_response(self): packet = read_packet(self._connfd) if packet.header.ptype != CCNET_MSG_RESPONSE: raise RuntimeError('Invalid Response') code, code_msg, content = parse_response(packet.body) return Response(code, code_msg, content) def send_cmd(self, cmd): req_id = self.get_request_id() self.send_request(req_id, 'receive-cmd') resp = self.read_response() if resp.code != '200': raise RuntimeError('Failed to send-cmd: %s %s' % (resp.code, resp.code_msg)) cmd += '\000' self.send_update(req_id, '200', '', cmd) resp = self.read_response() if resp.code != '200': raise RuntimeError('Failed to send-cmd: %s %s' % (resp.code, resp.code_msg)) self.send_update(req_id, SC_PROC_DONE, SS_PROC_DONE, '') def prepare_recv_message(self, msg_type): request = 'mq-server %s' % msg_type req_id = self.get_request_id() self.send_request(req_id, request) resp = self.read_response() if resp.code != '200': raise RuntimeError('bad response: %s %s' % (resp.code, resp.code_msg)) def receive_message(self): resp = self.read_response() # the message from ccnet daemon has the trailing null byte included msg = message_from_string(resp.content[:-1]) return msg def prepare_send_message(self): request = 'mq-server' mq_req_id = self.get_request_id() self.send_request(mq_req_id, request) resp = self.read_response() if resp.code != '200': raise RuntimeError('bad response: %s %s' % (resp.code, resp.code_msg)) self.mq_req_id = mq_req_id def send_message(self, msg_type, content): if self.mq_req_id == -1: self.prepare_send_message() msg = gen_inner_message_string(self.peer_id, msg_type, content) self.send_update(self.mq_req_id, "300", '', msg) resp = self.read_response() if resp.code != '200': self.mq_req_id = -1 raise RuntimeError('bad response: %s %s' % (resp.code, resp.code_msg)) def register_service_sync(self, service, group): '''Mainly used by a program to register a dummy service to ensure only single instance of that program is running ''' cmd = 'register-service %s %s' % (service, group) self.send_cmd(cmd) ccnet-6.1.5/python/ccnet/test-client.py000066400000000000000000000025301317035602700200450ustar00rootroot00000000000000import sys import os from ccnet import ClientPool, RpcClientBase from pysearpc import searpc_func import threading import logging RPC_SERVICE_NAME = 'test-rpcserver' CCNET_CONF_DIR = os.path.expanduser('~/.ccnet') class TestRpcClient(RpcClientBase): def __init__(self, client_pool, *args, **kwargs): RpcClientBase.__init__(self, client_pool, RPC_SERVICE_NAME, *args, **kwargs) @searpc_func('string', ['string', 'int']) def str_mul(self, s, n): pass class Worker(threading.Thread): def __init__(self, rpc): threading.Thread.__init__(self) self.rpc = rpc def run(self): s = 'abcdef' n = 100 assert self.rpc.str_mul(s, n) == s * n def test(n): rpcclient = TestRpcClient(ClientPool(CCNET_CONF_DIR, CCNET_CONF_DIR)) workers = [] for i in xrange(n): t = Worker(rpcclient) t.start() workers.append(t) for t in workers: t.join() def setup_logging(): kw = { 'format': '[%(asctime)s][%(module)s]: %(message)s', 'datefmt': '%m/%d/%Y %H:%M:%S', 'level': logging.DEBUG, 'stream': sys.stdout, } logging.basicConfig(**kw) def main(): setup_logging() if len(sys.argv) > 1: test(int(sys.argv[1])) else: test(100) print 'test passed' if __name__ == '__main__': main() ccnet-6.1.5/python/ccnet/test-server.py000066400000000000000000000020601317035602700200730ustar00rootroot00000000000000import os import logging import libevent from pysearpc import searpc_server from ccnet.async import AsyncClient, RpcServerProc RPC_SERVICE_NAME = 'test-rpcserver' CCNET_CONF_DIR = os.path.expanduser('~/.ccnet') def init_logging(): """Configure logging module""" level = logging.DEBUG kw = { 'format': '[%(asctime)s] %(message)s', 'datefmt': '%m/%d/%Y %H:%M:%S', 'level': level, } logging.basicConfig(**kw) i = 0 def register_rpc_functions(session): def str_mul(a, b): global i i = i + 1 print '[%s] a = %s, b = %s' % (i, a, b) return a * b searpc_server.create_service(RPC_SERVICE_NAME) searpc_server.register_function(RPC_SERVICE_NAME, str_mul) session.register_service(RPC_SERVICE_NAME, 'basic', RpcServerProc) def main(): init_logging() evbase = libevent.Base() session = AsyncClient(CCNET_CONF_DIR, evbase, CCNET_CONF_DIR) session.connect_daemon() register_rpc_functions(session) session.main_loop() if __name__ == '__main__': main() ccnet-6.1.5/python/ccnet/utils.py000066400000000000000000000020631317035602700167530ustar00rootroot00000000000000import os import socket from ccnet.errors import NetworkError def recvall(fd, total): remain = total data = '' while remain > 0: try: new = fd.recv(remain) except socket.error as e: raise NetworkError('Failed to read from socket: %s' % e) n = len(new) if n <= 0: raise NetworkError("Failed to read from socket") else: data += new remain -= n return data def sendall(fd, data): total = len(data) offset = 0 while offset < total: try: n = fd.send(data[offset:]) except socket.error as e: raise NetworkError('Failed to write to socket: %s' % e) if n <= 0: raise NetworkError('Failed to write to socket') else: offset += n def is_win32(): return os.name == 'nt' def make_socket_closeonexec(fd): if not is_win32(): import fcntl old_flags = fcntl.fcntl(fd, fcntl.F_GETFD) fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC) ccnet-6.1.5/tools/000077500000000000000000000000001317035602700137635ustar00rootroot00000000000000ccnet-6.1.5/tools/Makefile.am000066400000000000000000000003461317035602700160220ustar00rootroot00000000000000 AM_CPPFLAGS = -I$(top_srcdir)/include @GLIB2_CFLAGS@ -I$(top_srcdir)/lib bin_PROGRAMS = ccnet-init ccnet_init_SOURCES = ccnet-init.c ccnet_init_LDADD = @SSL_LIBS@ @LIB_RESOLV@ @GLIB2_LIBS@ \ $(top_builddir)/lib/libccnetd.la ccnet-6.1.5/tools/ccnet-init.c000066400000000000000000000142531317035602700161710ustar00rootroot00000000000000 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsa.h" #include "utils.h" enum { ERR_NAME_NULL = 1, ERR_NAME_INVALID, ERR_PERMISSION, ERR_CONF_FILE, }; /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ #define DEFAULT_BITS 2048 static guint32 bits = 0; static int quiet = 0; static char *identity_file_peer = NULL; static RSA *peer_privkey = NULL; static RSA *peer_pubkey = NULL; static char *user_name = NULL; static char *peer_name = NULL; static char *peer_id = NULL; static char *host_str = NULL; static char *port_str = NULL; /* argv0 */ static char *program_name = NULL; static void make_configure_file (const char *config_file); void save_privkey (RSA *key, const char *file) { FILE *f; f = g_fopen (file, "wb"); PEM_write_RSAPrivateKey(f, key, NULL, NULL, 0, NULL, NULL); fclose (f); } static void create_peerkey () { peer_privkey = generate_private_key (bits); peer_pubkey = private_key_to_pub (peer_privkey); } static const char *short_opts = "hc:n:H:P:F:"; static const struct option long_opts[] = { { "help", no_argument, NULL, 'h' }, { "config-dir", required_argument, NULL, 'c' }, { "central-config-dir", required_argument, NULL, 'F' }, { "name", required_argument, NULL, 'n' }, { "host", required_argument, NULL, 'H' }, { "port", required_argument, NULL, 'P' }, { 0, 0, 0, 0 }, }; void usage (int exit_status) { printf ("Usage: %s [OPTION]...\n", program_name); fputs ("Init ccnet configuration directory.\n\n", stdout); fputs ("Mandatory arguments to long options are mandatory " "for short options too.\n", stdout); fputs ("" " -c, --config-dir=DIR use DIR as the output ccnet configuration\n" " directory. Default is ~/.ccnet\n" , stdout); fputs ("" " -n, --name=NAME your public name\n" , stdout); fputs ("" " -H, --host= Public addr. Only useful for server.\n" , stdout); fputs ("" " -P, --port=port Public port. Only useful for server.\n" " Default 10001.\n" , stdout); exit (exit_status); } static int is_valid_username (const char *name) { const char *p = name; while (*p) { if (!isalnum(*p) && *p != '_' && *p != '-') return 0; ++p; } return 1; } int main(int argc, char **argv) { char *config_dir; char *central_config_dir = NULL; char *config_file; int c; char *name = NULL; program_name = argv[0]; config_dir = DEFAULT_CONFIG_DIR; while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != EOF) { switch (c) { case 'h': usage (1); break; case 'F': central_config_dir = strdup(optarg); break; case 'c': config_dir = strdup(optarg); break; case 'n': name = strdup (optarg); break; case 'H': host_str = strdup (optarg); break; case 'P': port_str = strdup (optarg); break; default: usage(1); } } config_dir = ccnet_expand_path (config_dir); /* printf("[conf_dir=%s\n]", config_dir); */ OpenSSL_add_all_algorithms(); if (RAND_status() != 1) { /* it should be seeded automatically */ fprintf(stderr, "PRNG is not seeded\n"); exit (1); } if (bits == 0) bits = DEFAULT_BITS; /* create peer key */ if (!name) { usage(-ERR_NAME_NULL); } if (strlen(name) < 2 || strlen (name) > 16 || !is_valid_username(name)) { fprintf (stderr, "The user name should be more than 2 bytes and less than 16 bytes, only digits, alphabetes and '-', '_' are allowed"); exit(-ERR_NAME_INVALID); } user_name = name; peer_name = g_strdup (name); create_peerkey (); peer_id = id_from_pubkey (peer_pubkey); identity_file_peer = g_build_filename (config_dir, PEER_KEYFILE, NULL); /* create dir */ if (ccnet_mkdir(config_dir, 0700) < 0) { fprintf (stderr, "Make dir %s error: %s\n", config_dir, strerror(errno)); exit(-ERR_PERMISSION); } struct stat st; if (central_config_dir && g_stat(central_config_dir, &st) < 0 && ccnet_mkdir(central_config_dir, 0700) < 0) { fprintf(stderr, "Make dir %s error: %s\n", central_config_dir, strerror(errno)); exit(-ERR_PERMISSION); } /* save key */ save_privkey (peer_privkey, identity_file_peer); /* make configure file */ config_file = g_build_filename (central_config_dir ? central_config_dir : config_dir, CONFIG_FILE_NAME, NULL); make_configure_file (config_file); printf ("Successly create configuration dir %s.\n", config_dir); exit(0); } static void make_configure_file (const char *config_file) { FILE *fp; if ((fp = g_fopen(config_file, "wb")) == NULL) { fprintf (stderr, "Open config file %s error: %s\n", config_file, strerror(errno)); exit(-ERR_CONF_FILE); } fprintf (fp, "[General]\n"); fprintf (fp, "USER_NAME = %s\n", user_name); fprintf (fp, "ID = %s\n", peer_id); fprintf (fp, "NAME = %s\n", peer_name); if (host_str) fprintf (fp, "SERVICE_URL = http://%s:8000\n", host_str); if (port_str) { fprintf (fp, "\n"); fprintf (fp, "[Network]\n"); fprintf (fp, "PORT = %s\n", port_str); } fprintf (fp, "\n"); fprintf (fp, "[Client]\n"); /* Use differnet ports for ccnet-daemon and ccnet-server */ if (port_str != NULL) { /* ccnet-server */ fprintf (fp, "PORT = 13418\n"); } else { /* ccnet-daemon */ fprintf (fp, "PORT = 13419\n"); } fclose (fp); fprintf (stdout, "done\n"); }