First import
authorNeutron Soutmun <neo.neutron@gmail.com>
Tue, 19 Aug 2008 15:49:00 +0000 (22:49 +0700)
committerNeutron Soutmun <neo.neutron@gmail.com>
Sun, 2 Nov 2008 19:42:54 +0000 (02:42 +0700)
2008-08-19  Neutron Soutmun <neo.neutron@gmail.com>

* === First import the project ===

29 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
config.h.in [new file with mode: 0644]
configure.ac [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/Makefile.in [new file with mode: 0644]
src/ipset-control.c [new file with mode: 0644]
src/ipset-control.h [new file with mode: 0644]
src/rahunasd.c [new file with mode: 0644]
src/rahunasd.h [new file with mode: 0644]
src/rh-ipset.c [new file with mode: 0644]
src/rh-ipset.h [new file with mode: 0644]
src/rh-xmlrpc-server.c [new file with mode: 0644]
src/rh-xmlrpc-server.h [new file with mode: 0644]
xmlrpc/Makefile.am [new file with mode: 0644]
xmlrpc/Makefile.in [new file with mode: 0644]
xmlrpc/README [new file with mode: 0644]
xmlrpc/test-xmlrpc-client-php.c [new file with mode: 0644]
xmlrpc/test-xmlrpc-client.c [new file with mode: 0644]
xmlrpc/test-xmlrpc-server.c [new file with mode: 0644]
xmlrpc/xmlrpc-client.c [new file with mode: 0644]
xmlrpc/xmlrpc-server.c [new file with mode: 0644]
xmlrpc/xmlrpc.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..b51df76
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Neutron Soutmun <neo.neutron@gmail.com>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    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.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..ae2eb6f
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,3 @@
+2008-08-19  Neutron Soutmun <neo.neutron@gmail.com>
+
+       * === First import the project ===
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..4935283
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = xmlrpc src
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..790d8a6
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+aclocal
+automake --add-missing
+autoconf
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..ccfd3dd
--- /dev/null
@@ -0,0 +1,111 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the `dup2' function. */
+#undef HAVE_DUP2
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+   and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..ee7db99
--- /dev/null
@@ -0,0 +1,47 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT([RahuNAS],[0.1],[neo.neutron@gmail.com] )
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AM_MAINTAINER_MODE
+AC_CONFIG_SRCDIR([src/rahunasd.h])
+AC_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+
+# Checks for libraries.
+dnl Check for GNet 2.x
+GNET_REQ=2.0.8
+PKG_CHECK_MODULES(LIBGNET, [ gnet-2.0 >= $GNET_REQ ], , [ AC_MSG_ERROR([GNet is required]) ])
+
+AC_SUBST(LIBGNET_CFLAGS)
+AC_SUBST(LIBGNET_LIBS)
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([fcntl.h stdlib.h string.h syslog.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_PID_T
+AC_STRUCT_TM
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_TYPE_SIGNAL
+AC_FUNC_STRFTIME
+AC_CHECK_FUNCS([dup2])
+AC_CONFIG_FILES([
+       Makefile
+       xmlrpc/Makefile
+       src/Makefile
+])
+
+AC_OUTPUT
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..1be8d2a
--- /dev/null
@@ -0,0 +1,8 @@
+bin_PROGRAMS = rahunasd
+
+AM_CFLAGS = $(LIBGNET_CFLAGS)
+
+rahunasd_SOURCES = rahunasd.c rh-xmlrpc-server.c ipset-control.c
+rahunasd_LDADD =  \
+       $(top_builddir)/xmlrpc/libgnetxmlrpc.a \
+       $(LIBGNET_LIBS)
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644 (file)
index 0000000..88975cc
--- /dev/null
@@ -0,0 +1,421 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+bin_PROGRAMS = rahunasd$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_rahunasd_OBJECTS = rahunasd.$(OBJEXT) rh-xmlrpc-server.$(OBJEXT) \
+       ipset-control.$(OBJEXT)
+rahunasd_OBJECTS = $(am_rahunasd_OBJECTS)
+am__DEPENDENCIES_1 =
+rahunasd_DEPENDENCIES = $(top_builddir)/xmlrpc/libgnetxmlrpc.a \
+       $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(rahunasd_SOURCES)
+DIST_SOURCES = $(rahunasd_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBGNET_CFLAGS = @LIBGNET_CFLAGS@
+LIBGNET_LIBS = @LIBGNET_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = $(LIBGNET_CFLAGS)
+rahunasd_SOURCES = rahunasd.c rh-xmlrpc-server.c ipset-control.c
+rahunasd_LDADD = \
+       $(top_builddir)/xmlrpc/libgnetxmlrpc.a \
+       $(LIBGNET_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+         ; then \
+           f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+          $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+         rm -f "$(DESTDIR)$(bindir)/$$f"; \
+       done
+
+clean-binPROGRAMS:
+       -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+rahunasd$(EXEEXT): $(rahunasd_OBJECTS) $(rahunasd_DEPENDENCIES) 
+       @rm -f rahunasd$(EXEEXT)
+       $(LINK) $(rahunasd_OBJECTS) $(rahunasd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipset-control.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rahunasd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rh-xmlrpc-server.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+       for dir in "$(DESTDIR)$(bindir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+       clean-generic ctags distclean distclean-compile \
+       distclean-generic distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-binPROGRAMS \
+       install-data install-data-am install-dvi install-dvi-am \
+       install-exec install-exec-am install-html install-html-am \
+       install-info install-info-am install-man install-pdf \
+       install-pdf-am install-ps install-ps-am install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+       uninstall-am uninstall-binPROGRAMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/ipset-control.c b/src/ipset-control.c
new file mode 100644 (file)
index 0000000..96e5274
--- /dev/null
@@ -0,0 +1,139 @@
+/**
+ * ipset control implementation
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-08-07
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <syslog.h>
+
+#include "ipset-control.h"
+
+int _issue_ipset_cmd(unsigned short cmd_type, const char *ip)
+{
+       char *cmd = NULL; 
+       int   idx  = 0;
+       char  line[256];
+       int   pipefd[2];
+  int   status;
+       char  buf;
+       pid_t cpid;
+       
+       if (cmd_type == RH_IPSET_CMD_ADD)
+         cmd = strdup("-A");
+       else if (cmd_type == RH_IPSET_CMD_DEL)
+         cmd = strdup("-D");
+       else if (cmd_type == RH_IPSET_CMD_FLS)
+    cmd = strdup("-F");
+       else
+         return (-1);
+
+  if (pipe(pipefd) == (-1)) {
+    syslog(LOG_ERR, "Could not create pipe");
+               return (-1);
+       }
+
+       cpid = fork();
+       if (cpid == 0) {
+    close(pipefd[0]);
+               dup2(pipefd[1], STDOUT_FILENO);
+    
+    if (ip == NULL)
+                 logmsg(RH_LOG_DEBUG, "ipset %s %s", cmd, SET_NAME);
+    else
+                 logmsg(RH_LOG_DEBUG, "ipset %s %s %s", cmd, SET_NAME, ip);
+
+               execlp("ipset", "ipset", cmd, SET_NAME, ip, NULL);
+               close(pipefd[1]);
+               return (-1);
+       }
+
+  cpid = wait(&status);
+
+  close(pipefd[1]);
+       while (getline(pipefd[0], line, sizeof line) > 0) {
+    logmsg(RH_LOG_DEBUG, line);
+       }
+       close(pipefd[0]);
+
+       if (cmd)
+         free(cmd);
+
+  if (WIFEXITED(status) && (WEXITSTATUS(status) == 0))
+    return 0;
+  else
+         return (-1);
+}
+
+int ctrl_add_to_set(struct rahunas_map *map, uint32_t id)
+{
+       struct rahunas_member *members = NULL;
+  struct in_addr sess_addr;
+       int ret;
+
+       if (!map)
+         return (-1);
+
+  if (!map->members)
+    return (-1);
+
+  members = map->members;
+
+       if (id > ((map->size) - 1) || id < 0)
+         return (-1);
+
+       if (members[id].flags)
+         return 0;
+               
+  ret = _issue_ipset_cmd(RH_IPSET_CMD_ADD, idtoip(map, id));
+
+       chk_set(map);
+
+       if (ret == 0 && members[id].flags)
+    return 0;
+       else
+         return (-1);
+}
+
+int ctrl_del_from_set(struct rahunas_map *map, uint32_t id)
+{
+       struct rahunas_member *members = NULL;
+  struct in_addr sess_addr;
+       int ret;
+
+       if (!map)
+         return (-1);
+
+  if (!map->members)
+    return (-1);
+
+  members = map->members;
+
+       if (id > ((map->size) - 1) || id < 0)
+         return (-1);
+
+       if (!members[id].flags)
+         return 0;
+       
+  ret = _issue_ipset_cmd(RH_IPSET_CMD_DEL, idtoip(map, id));
+
+       if (ret == 0)
+         members[id].flags = 0;
+       
+       return ret;
+}
+
+int ctrl_flush()
+{
+  return _issue_ipset_cmd(RH_IPSET_CMD_FLS, NULL);
+}
diff --git a/src/ipset-control.h b/src/ipset-control.h
new file mode 100644 (file)
index 0000000..4199851
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * ipset control header 
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-08-07
+ */
+
+#ifndef __IPSET_CONTROL_H
+#define __IPSET_CONTROL_H
+
+#include "rahunasd.h"
+
+#define        RH_IPSET_CMD_ADD  1
+#define RH_IPSET_CMD_DEL  2
+#define RH_IPSET_CMD_FLS  3
+
+int ctrl_add_to_set(struct rahunas_map *map, uint32_t id);
+
+int ctrl_del_from_set(struct rahunas_map *map, uint32_t id);
+
+int ctrl_flush();
+
+#endif //__IPSET_CONTROL_H
+
diff --git a/src/rahunasd.c b/src/rahunasd.c
new file mode 100644 (file)
index 0000000..e8b37f9
--- /dev/null
@@ -0,0 +1,701 @@
+/**
+ * RahuNASd
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-08-07
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+#include <syslog.h>
+
+#include "rahunasd.h"
+#include "rh-xmlrpc-server.h"
+#include "ipset-control.h"
+
+/* Abstract functions */
+int getline(int fd, char *buf, size_t size);
+int finish();
+int ipset_flush();
+int chk_set(struct rahunas_map *map);
+int update_set(struct rahunas_map *map);
+
+struct rahunas_map* rh_init_map();
+int rh_init_members(struct rahunas_map *map);
+
+int parse_set_header(const char *in, struct rahunas_map *map);
+int parse_set_list(const char *in, struct rahunas_map *map);
+
+int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id);
+
+/* Declaration */
+struct rahunas_map *map = NULL;
+int fd_log;
+int fd_debug;
+
+uint32_t iptoid(struct rahunas_map *map, const char *ip) {
+  uint32_t ret;
+  struct in_addr req_ip;
+
+  if (!map || !ip)
+         return (-1);
+
+  if (!(inet_aton(ip, &req_ip))) {
+    logmsg(RH_LOG_DEBUG, "Could not convert IP: %s", ip);
+    return (-1);  
+  }
+
+  //logmsg(RH_LOG_DEBUG, "Request IP: %s", ip);
+       
+  ret = ntohl(req_ip.s_addr) - ntohl(map->first_ip);
+       if (ret < 0 || ret > (map->size - 1))
+         ret = (-1);
+
+  //logmsg(RH_LOG_DEBUG, "Request Index: %lu", ret);
+  return ret; 
+}
+
+char *idtoip(struct rahunas_map *map, uint32_t id) {
+  struct in_addr sess_addr;
+
+  if (!map)
+         return NULL;
+
+  sess_addr.s_addr = htonl((ntohl(map->first_ip) + id));
+
+  return inet_ntoa(sess_addr);
+}
+
+void *rh_malloc(size_t size)
+{
+  void *p;
+  
+  if (size == 0)
+    return NULL;
+
+  if ((p = malloc(size)) == NULL) {
+    syslog(LOG_ERR, "RahuNASd: not enough memory");
+    exit(EXIT_FAILURE);
+  } 
+
+  return p;
+}
+
+void rh_free(void **data)
+{
+  if (*data == NULL)
+    return;
+
+  free(*data);
+  *data = NULL;
+}
+
+int rh_openlog(const char *filename)
+{
+  fd_log = open(filename, O_WRONLY | O_APPEND);
+       if (fd_log == (-1))
+         return 0;
+  else 
+         return 1;
+}
+
+int rh_closelog(int fd)
+{
+  if (close(fd) == 0)
+         return 1;
+       else
+         return 0;
+}
+
+int logmsg(int priority, const char *msg, ...) 
+{
+  int n, size = 256;
+  char time_msg[20];
+  time_t t;
+       va_list ap;
+       char *time_fmt = "%b %e %T";
+       char *p = NULL;
+  char *np = NULL;
+  struct tm *ltime = NULL;
+
+       if (priority < RH_LOG_LEVEL)
+         return 0;
+
+       if ((p = rh_malloc(size)) == NULL) {
+               return (-1);
+       }
+
+       while (1) {
+    va_start(ap, msg);
+               n = vsnprintf(p, size, msg, ap);
+               va_end(ap);
+
+               if (n > -1 && n < size)
+                 break;
+    if (n > -1)
+                 size = n+1;
+               else
+                 size *= 2;
+
+               if ((np = realloc(p, size)) == NULL) {
+      free(p);
+      p = NULL;
+                       break;
+               } else {
+      p = np;
+               }
+       }
+
+       if (!p)
+         return (-1);
+
+       t = time(NULL);
+       ltime = localtime(&t);
+       if (ltime == NULL) {
+               return (-1);
+       }
+
+       if ((np = rh_malloc(size+20)) == NULL) {
+               rh_free(p);
+               return (-1);
+       }
+
+       strftime(time_msg, sizeof time_msg, time_fmt, ltime);
+
+       fprintf(stderr, "%s : %s\n", time_msg, p);
+
+       rh_free(&p);
+       rh_free(&np);
+}
+
+void rh_shutdown(int sig)
+{
+  ipset_flush();
+  finish();
+  rh_closelog(DEFAULT_LOG);
+}
+
+int ipset_flush()
+{
+  logmsg(RH_LOG_NORMAL, "Flushing IPSET...");
+  return ctrl_flush();
+}
+
+int finish()
+{
+  char *exitmsg = "Exit Gracefully";
+       struct rahunas_member *members = NULL;
+       int i;
+  int end;
+
+  if (map) {
+    if (map->members) {
+      members = map->members;
+      end = map->size;
+    } else {
+      end = 0;
+    }  
+
+         for (i=0; i < end; i++) {
+                         rh_free(&(members[i].username));
+                         rh_free(&(members[i].session_id));
+               }
+
+               rh_free(&(map->members));
+               rh_free(&map);
+       }
+
+  logmsg(RH_LOG_NORMAL, exitmsg);
+       syslog(LOG_INFO, exitmsg);
+  return 0;
+}
+
+int getline(int fd, char *buf, size_t size)
+{
+  char cbuf;
+       char *current;
+
+  if (!buf || fd < 0)
+    return 0;
+
+       current = buf;
+
+  while (read(fd, &cbuf, 1) > 0) {
+         *current = cbuf;
+         if (cbuf == '\n') {
+                 *current = '\0';
+                 break;
+               } else if ((current - buf) < (size - 1)) {
+                 current++;
+         }
+       }
+
+       return (current - buf);
+}
+
+
+int parse_set_header(const char *in, struct rahunas_map *map)
+{
+       in_addr_t first_ip;
+       in_addr_t last_ip;
+       char *ip_from_start = NULL;
+  char *ip_from_end = NULL;
+       char *ip_to_start = NULL;
+  char *ip_to_end = NULL;
+       char *ip_from = NULL;
+  char *ip_to = NULL;
+
+       if (!map || !in)
+         return (-1);
+
+  ip_from_start = strstr(in, "from:");
+       if (ip_from_start == NULL)
+         return (-1);
+
+       ip_to_start = strstr(in, "to:");
+       if (ip_to_start == NULL)
+         return (-1);
+
+  ip_from_start += 6;
+       ip_from_end = ip_to_start - 1;
+       ip_to_start += 4;
+       ip_to_end = in + strlen(in);
+
+       ip_from = strndup(ip_from_start, ip_from_end - ip_from_start);
+       ip_to   = strndup(ip_to_start, ip_to_end - ip_to_start);
+       logmsg(RH_LOG_NORMAL, "First IP: %s", ip_from);
+       logmsg(RH_LOG_NORMAL, "Last IP: %s", ip_to);
+
+       first_ip = inet_addr(ip_from);
+  memcpy(&map->first_ip, &first_ip, sizeof(in_addr_t));
+
+       last_ip = inet_addr(ip_to);
+  memcpy(&map->last_ip, &last_ip, sizeof(in_addr_t));
+
+       map->size = ntohl(map->last_ip) - ntohl(map->first_ip) + 1;
+
+       logmsg(RH_LOG_NORMAL, "Set Size: %lu", map->size);
+       free(ip_from);
+       free(ip_to);
+
+       return 0;
+}
+
+int parse_set_list(const char *in, struct rahunas_map *map)
+{
+       char *sep = NULL;
+  char *sess_ip = NULL;
+       char *sess_idle_time = NULL;
+       uint32_t  id;
+
+       struct rahunas_member *members;
+
+       if (!map || !in)
+         return (-1);
+
+  if (!map->members)
+    return (-1);
+       
+       members = map->members;
+
+  // Found members
+  //logmsg(RH_LOG_DEBUG, in);
+       sep = strstr(in, ":");
+       sess_ip = strndup(in, sep - in);
+  if (sess_ip == NULL)
+    return (-1);
+       id = iptoid(map, sess_ip);
+       sess_idle_time = strndup(sep + 1, strstr(in, "seconds") - sep - 1);
+  if (sess_idle_time == NULL)
+    return (-1);
+
+  members[id].flags = 1;
+  members[id].expired = atoi(sess_idle_time) < IDLE_THRESHOLD ? 0 : 1;
+
+  free(sess_ip);
+  free(sess_idle_time);
+       return id;
+}
+
+int chk_set(struct rahunas_map *map) 
+{
+  struct rahunas_member *members = NULL;
+       unsigned short set_start = 0;
+       char  line[256];
+  int   pipefd[2];
+       pid_t cpid;
+       uint32_t  id;
+
+       members = map->members;
+
+       if (pipe(pipefd) == -1) {
+    syslog(LOG_ERR, "Could not create pipe");
+               return -1;
+       }
+
+       cpid = fork();
+       if (cpid == 0) {
+         close(pipefd[0]);
+               dup2(pipefd[1], STDOUT_FILENO);
+               execlp("ipset", "ipset", "-nL", SET_NAME, NULL);
+               return (-1);
+               close(pipefd[1]);
+       }
+
+  wait(NULL);
+
+  close(pipefd[1]);
+
+       while (getline(pipefd[0], line, sizeof line) > 0) {
+
+    if (strstr(line, "Bindings:") != NULL)
+                 set_start = 0;
+
+               if (set_start)
+                 parse_set_list(line, map);
+
+               // Capture header
+    if (strstr(line, "Header:") != NULL)
+                 if (map != NULL && map->size == 0) {
+        parse_set_header(line, map);
+                               break;
+                       }
+
+               if (strstr(line, "Members:") != NULL)
+                 set_start = 1;
+       }
+       close(pipefd[0]); 
+
+       return 0;
+}
+
+
+int update_set(struct rahunas_map *map) 
+{
+  struct rahunas_member *members = NULL;
+  unsigned int i;
+  unsigned short no_detail = 0;
+  if (!map)
+         return (-1);
+       
+       members = map->members;
+
+       for (i=0; i < map->size; i++) {
+    no_detail = 0;
+    if (members[i].flags) {
+      if (!members[i].username || !members[i].session_id)
+        no_detail = 1;
+    
+
+                 if (members[i].expired) {
+         if (!no_detail) {
+                   logmsg(RH_LOG_DEBUG, "IP %s, Client: Username %s, "
+                                        "Session-ID %s, Session-Start %d, "
+                                 "Expired %d",
+                                 idtoip(map, i),
+                                                                                                members[i].username, 
+                                                                                                members[i].session_id,
+                                                                                                members[i].session_start,
+                                 members[i].expired);
+
+                             send_xmlrpc_stopacct(map, i);
+          }
+
+        if (ctrl_del_from_set(map, i) == 0) {
+          if (!no_detail) {
+            logmsg(RH_LOG_NORMAL, "Session Stop, User: %s, IP: %s, "
+                            "Session ID: %s",
+                            members[i].username, 
+                            idtoip(map, i), 
+                            members[i].session_id); 
+          }
+
+            rh_free(&(members[i].username));
+            rh_free(&(members[i].session_id));
+
+                           memset(&members[i], 0, sizeof(struct rahunas_member));
+                           logmsg(RH_LOG_NORMAL, "Client IP %s was removed!", idtoip(map,i));
+                         }
+                       }
+               }
+       }
+  return 0;
+}
+
+int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id) {
+  struct rahunas_member *members = NULL;
+  GNetXmlRpcClient *client = NULL;
+  gchar *reply  = NULL;
+       gchar *params = NULL;
+
+       if (!map)
+         return (-1);
+
+  if (!map->members)
+    return (-1);
+
+  if (id < 0 || id > (map->size - 1))
+    return (-1);
+       
+       members = map->members;
+
+  client = gnet_xmlrpc_client_new(XMLSERVICE_HOST, XMLSERVICE_URL, 
+                                       XMLSERVICE_PORT);
+
+  if (!client) {
+    logmsg(RH_LOG_ERROR, "Could not connect to XML-RPC service");
+    return (-1);
+  }
+       
+       params = g_strdup_printf("%s|%s|%d", 
+                                members[id].username,
+                                                                                                        members[id].session_id,
+                                                                                                        members[id].session_start);
+
+  if (params == NULL)
+    return (-1);
+  
+  if (gnet_xmlrpc_client_call(client, "stopacct", params, &reply) == 0)
+    {
+      logmsg(RH_LOG_DEBUG, "stopacct reply = %s", reply);
+      g_free(reply);
+    }
+  else
+    logmsg(RH_LOG_DEBUG, "Failed executing stopacct!");
+       
+       g_free(params);
+
+  return 0;
+}
+
+
+struct rahunas_map* rh_init_map() {
+  struct rahunas_map *map = NULL;
+
+       map = (struct rahunas_map*)(rh_malloc(sizeof(struct rahunas_map)));
+
+  map->members = NULL;
+       map->size = 0;
+
+       return map;
+}
+
+int rh_init_members (struct rahunas_map* map)
+{
+       struct rahunas_member *members = NULL;
+       int size;
+
+  if (!map)
+         return (-1);
+       
+       size = map->size == 0 ? MAX_MEMBERS : map->size;
+
+       members = 
+    (struct rahunas_member*)(rh_malloc(sizeof(struct rahunas_member)*size));
+
+       memset(members, 0, sizeof(struct rahunas_member)*size);
+
+       map->members = members;
+
+       return 0;
+}
+
+gboolean polling(gpointer data) {
+  struct rahunas_map *map = (struct rahunas_map *)data;
+       logmsg(RH_LOG_DEBUG, "Start polling!");
+       chk_set (map);
+       update_set (map);
+  return TRUE;
+}
+
+static void
+watch_child(char *argv[])
+{
+  char *prog = NULL;
+       int failcount = 0;
+       time_t start;
+       time_t stop;
+       int status;
+
+       int nullfd;
+
+  pid_t pid, sid;
+
+       if (*(argv[0]) == '(')
+         return;
+
+  signal(SIGINT, rh_shutdown);
+  signal(SIGTERM, rh_shutdown);
+  signal(SIGKILL, rh_shutdown);
+
+  pid = fork();        
+       if (pid < 0) {
+         syslog(LOG_ALERT, "fork failed");
+               exit(EXIT_FAILURE);
+       } else if (pid > 0) {
+         /* parent */
+         exit(EXIT_SUCCESS);
+       }
+
+  /* Change the file mode mask */
+  umask(0);
+
+  /* Open log file */
+       if (!rh_openlog(DEFAULT_LOG)) {
+    syslog(LOG_ERR, "Could not open log file %s", DEFAULT_LOG);
+    exit(EXIT_FAILURE);
+  }
+
+       if ((sid = setsid()) < 0)
+         syslog(LOG_ALERT, "setsid failed");
+
+       if ((chdir("/")) < 0) {
+    exit(EXIT_FAILURE);
+  }
+    
+  /* Close out the standard file descriptors */
+       close(STDIN_FILENO);
+       close(STDOUT_FILENO);
+       close(STDERR_FILENO);
+
+  while(1) {
+
+         if ((pid = fork()) == 0) {
+      /* child */
+      prog = strdup(argv[0]);
+           argv[0] = strdup("(rahunasd)");
+                 execvp(prog, argv);
+                 syslog(LOG_ALERT, "execvp failed");
+               }
+  
+    syslog(LOG_NOTICE, "RahuNASd Parent: child process %d started", pid);   
+
+    time(&start);
+         /* parent */
+       pid = wait3(&status, 0, NULL);
+       time(&stop);
+  
+       if (WIFEXITED(status)) {
+         syslog(LOG_NOTICE,
+                        "RahuNASd Parent: child process %d exited with status %d",
+                                                pid, WEXITSTATUS(status));
+       } else if (WIFSIGNALED(status)) {
+      syslog(LOG_NOTICE,
+                        "RahuNASd Parent: child process %d exited due to signal %d",
+                                                pid, WTERMSIG(status));
+       } else {
+      syslog(LOG_NOTICE, "RahuNASd Parent: child process %d exited", pid);
+       }
+  
+               if (stop - start < 10)
+                 failcount++;
+               else
+                 failcount = 0;
+  
+               if (failcount == 5) {
+                 syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
+                       exit(EXIT_FAILURE);
+               }
+  
+  
+       if (WIFEXITED(status))
+         if (WEXITSTATUS(status) == 0)
+                 exit(EXIT_SUCCESS);
+       
+       if (WIFSIGNALED(status)) {
+      switch (WTERMSIG(status)) {
+                 case SIGKILL:
+                         exit(0);
+                               break;
+                       
+                       case SIGINT:
+                       case SIGTERM:
+                         syslog(LOG_ALERT, "Exiting due to unexpected forced shutdown");
+                               exit(EXIT_FAILURE);
+                               break;
+                       
+                       default:
+                         break;
+               }
+       }
+       
+       sleep(3);
+  }
+}
+
+int main(int argc, char **argv) 
+{
+       gchar* addr = "localhost";
+       int port    = 8123;
+
+       char line[256];
+       char version[256];
+
+       GNetXmlRpcServer *server = NULL;
+       GMainLoop* main_loop     = NULL;
+
+       watch_child(argv);
+  
+  gnet_init();
+  main_loop = g_main_loop_new (NULL, FALSE);
+
+  sprintf(version, "Starting %s - Version %s", PROGRAM, VERSION);
+
+  /* Test open log file */
+       if (!rh_openlog()) {
+    syslog(LOG_ERR, "Could not open log file %s", DEFAULT_LOG);
+    exit(EXIT_FAILURE);
+  }
+
+       logmsg(RH_LOG_NORMAL, version);
+  syslog(LOG_INFO, version);
+
+  map = rh_init_map();
+  chk_set(map);
+  rh_init_members(map);
+
+  /* XML RPC Server */
+       server = gnet_xmlrpc_server_new (addr, port);
+
+       if (!server) {
+    syslog(LOG_ERR, "Could not start XML-RPC server!");
+    ipset_flush();
+    finish(); 
+         exit (EXIT_FAILURE);
+       }
+
+       gnet_xmlrpc_server_register_command (server, 
+                                            "startsession", 
+                                                                                                                                          do_startsession, 
+                                                                                                                                                map);
+
+       gnet_xmlrpc_server_register_command (server, 
+                                            "stopsession", 
+                                                                                                                                          do_stopsession, 
+                                                                                                                                                map);
+
+  gnet_xmlrpc_server_register_command (server, 
+                                            "getsessioninfo", 
+                                                                                                                                          do_getsessioninfo, 
+                                                                                                                                                map);
+
+  g_timeout_add_seconds (POLLING, polling, map);
+
+       g_main_loop_run(main_loop);
+
+       exit(EXIT_SUCCESS);
+       return 0;
+}
diff --git a/src/rahunasd.h b/src/rahunasd.h
new file mode 100644 (file)
index 0000000..b193662
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * RahuNASd header 
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-08-07
+ */
+
+#ifndef __RAHUNASD_H
+#define __RAHUNASD_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <time.h>
+
+#define PROGRAM "RuhuNASd"
+#define VERSION "0.1"
+#define MAX_MEMBERS 65536
+
+/* Configuration */
+#define DEFAULT_LOG "/var/log/rahunas/rahunas.log"
+#define IDLE_THRESHOLD 30
+#define POLLING 30 
+#define SET_NAME "rahunas_set"
+#define XMLSERVICE_HOST        "localhost"
+#define XMLSERVICE_PORT        8888
+#define XMLSERVICE_URL "/xmlrpc_service.php"
+
+enum RH_LOG {
+  RH_LOG_DEBUG,
+       RH_LOG_NORMAL,
+       RH_LOG_ERROR
+};
+
+#ifdef RH_LOG_LEVEL
+#else
+#  ifdef LOG_DEBUG
+#    define RH_LOG_LEVEL RH_LOG_DEBUG
+#  else
+#    ifdef LOG_NORMAL
+#      define RH_LOG_LEVEL RH_LOG_NORMAL
+#    else
+#      define RH_LOG_LEVEL RH_LOG_ERROR
+#    endif
+#  endif
+#endif
+
+#ifdef RH_DEBUG
+#define DP(priority, format, args...) \
+  do {  \
+    if (priority > RH_LOG_LEVEL) { \
+      fprintf(stderr, "%s: %s (DBG): ", __FILE__, __FUNCTION__); \
+      fprintf(stderr, format "\n", ## args);
+    } \
+  } while (0)
+#else
+#define DP(priority, format, args...)
+#endif
+
+struct rahunas_map {
+  struct rahunas_member *members;
+       in_addr_t first_ip;
+       in_addr_t last_ip;
+       unsigned int size;
+};
+
+struct rahunas_member {
+  unsigned short flags; 
+  unsigned short expired;
+       time_t session_start;
+       char *username;
+  char *session_id;
+};
+
+uint32_t iptoid(struct rahunas_map *map, const char *ip);
+char *idtoip(struct rahunas_map *map, uint32_t id);
+
+void *rh_malloc(size_t size);
+void rh_free(void **data);
+
+#endif // __RAHUNASD_H
diff --git a/src/rh-ipset.c b/src/rh-ipset.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/rh-ipset.h b/src/rh-ipset.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/rh-xmlrpc-server.c b/src/rh-xmlrpc-server.c
new file mode 100644 (file)
index 0000000..25bc05a
--- /dev/null
@@ -0,0 +1,217 @@
+/**
+ * RahuNAS XML-RPC Server implementation
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-08-07
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "rahunasd.h"
+#include "rh-xmlrpc-server.h"
+#include "ipset-control.h"
+
+int do_startsession(GNetXmlRpcServer *server,
+                    const gchar *command,
+                                                                               const gchar *param,
+                                                                               gpointer user_data,
+                                                                               gchar **reply_string) 
+{
+  struct rahunas_map *map = (struct rahunas_map *)user_data;
+       struct rahunas_member *members = NULL;
+       gchar *ip = NULL;
+       gchar *username = NULL;
+       gchar *session_id = NULL;
+       gchar *pStart = NULL;
+       gchar *pEnd = NULL;
+       uint32_t id;
+
+       if (!map)
+         goto out;
+
+  if (!map->members)
+    goto out;
+
+  if (param == NULL)
+    goto out;
+
+       members = map->members;
+
+  pStart = param;
+       pEnd = g_strstr_len(pStart, strlen(pStart), "|");
+       if (pEnd == NULL) {
+         goto out;
+       }
+
+       ip = g_strndup(pStart, pEnd - pStart);
+  if (ip == NULL)
+    goto out;
+
+       pStart = pEnd + 1;
+       pEnd = g_strstr_len(pStart, strlen(pStart), "|");
+       if (pEnd == NULL) {
+    goto out;
+       }
+       username = g_strndup(pStart, pEnd - pStart);
+       pStart = pEnd + 1;
+  session_id = g_strndup(pStart, strlen(pStart));
+
+       id = iptoid(map, ip);
+
+       if (id < 0) {
+    *reply_string = g_strdup("Invalid IP Address");
+               return 0;
+       }
+
+       if (members[id].flags) {
+    *reply_string = g_strdup("Client already login");
+               return 0;
+       }
+
+  if (ctrl_add_to_set(map, id) == 0) {
+         if (!members[id].username)
+                 free(members[id].username);
+               members[id].username = username;
+    
+               if (!members[id].session_id)
+                 free(members[id].session_id);
+               members[id].session_id = session_id;
+
+               time(&(members[id].session_start));
+
+    logmsg(RH_LOG_NORMAL, "Session Start, User: %s, IP: %s, "
+                          "Session ID: %s",
+                          members[id].username, 
+                          idtoip(map, id), 
+                          members[id].session_id); 
+       }
+
+  *reply_string = g_strdup_printf("Greeting! Got: IP %s, User %s, ID %s", 
+                                        ip, members[id].username, 
+                                                                                                                                        members[id].session_id);
+  g_free(ip);
+       return 0;
+
+out:
+    *reply_string = g_strdup("Invalid input parameters");
+    g_free(ip);
+               return 0;
+}
+
+int do_stopsession(GNetXmlRpcServer *server,
+                   const gchar *command,
+                                                                        const gchar *param,
+                                                                        gpointer user_data,
+                                                                        gchar **reply_string)
+{
+  struct rahunas_map *map = (struct rahunas_map *)user_data;
+       struct rahunas_member *members;
+       gchar *ip;
+       uint32_t   id;
+
+       if (!map)
+         goto out;
+
+  if (!map->members)
+    goto out;
+
+       members = map->members;
+
+       if (param == NULL)
+         goto out;
+
+  ip = param;
+       id = iptoid(map, ip);
+
+       if (id < 0) {
+    *reply_string = g_strdup("Invalid IP Address");
+               return 0;
+       }
+
+       if (members[id].flags) {
+         if (ctrl_del_from_set(map, id) == 0) {
+
+    logmsg(RH_LOG_NORMAL, "Session Stop, User: %s, IP: %s, "
+                          "Session ID: %s",
+                          members[id].username, 
+                          idtoip(map, id), 
+                          members[id].session_id); 
+
+      if (members[id].username)
+        free(members[id].username);
+         
+      if (members[id].session_id)
+        free(members[id].session_id);
+
+           memset(&members[id], 0, sizeof(struct rahunas_member));
+                       *reply_string = g_strdup_printf("Client IP %s was removed!", 
+                                                       idtoip(map, id));
+                       return 0;
+               } else {
+      *reply_string = g_strdup_printf("Client IP %s remove error", ip);
+                 return 0;
+               }
+       }
+
+  *reply_string = g_strdup_printf("%s", ip);
+       return 0;
+
+out:
+    *reply_string = g_strdup("Invalid input parameters");
+               return 0;
+}
+
+int do_getsessioninfo(GNetXmlRpcServer *server,
+                      const gchar *command,
+                                                                           const gchar *param,
+                                                                           gpointer user_data,
+                                                                           gchar **reply_string)
+{
+  struct rahunas_map *map = (struct rahunas_map *)user_data;
+       struct rahunas_member *members = NULL;
+       gchar *ip = NULL;
+       uint32_t   id;
+
+       if (!map)
+         goto out;
+
+  if (!map->members)
+    goto out;
+
+       members = map->members;
+
+       if (param == NULL)
+         goto out;
+
+  ip = param;
+       id = iptoid(map, ip);
+
+       if (id < 0) {
+    *reply_string = g_strdup("Invalid IP Address");
+               return 0;
+       }
+
+       if (members[id].flags) {
+    if (!members[id].username) {
+      *reply_string = g_strdup("Invalid Username");
+      return 0;
+    }
+
+    if (!members[id].session_id) {
+      *reply_string = g_strdup("Invalid Session ID");
+      return 0;
+    }
+    
+    *reply_string = g_strdup_printf("%s|%s|%s|%d", ip, 
+                                                              members[id].username,
+                                                                                                                                                                                                  members[id].session_id,
+                                                                                                                                                                                                  members[id].session_start);
+               return 0;
+       }
+
+  *reply_string = g_strdup_printf("%s", ip);
+       return 0;
+
+out:
+    *reply_string = g_strdup("Invalid input parameters");
+               return 0;
+}
diff --git a/src/rh-xmlrpc-server.h b/src/rh-xmlrpc-server.h
new file mode 100644 (file)
index 0000000..77cc3fc
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * RahuNAS XML-RPC Server implementation header
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-08-07
+ */
+#ifndef __RH_XMLRPC_SERVER_H
+#define __RH_XMLRPC_SERVER_H
+
+#include "../xmlrpc/xmlrpc.h"
+
+int do_startsession(GNetXmlRpcServer *server,
+                    const gchar *command,
+                                                                               const gchar *param,
+                                                                               gpointer user_data,
+                                                                               gchar **reply_string);
+
+int do_stopsession(GNetXmlRpcServer *server,
+                   const gchar *command,
+                                                                        const gchar *param,
+                                                                        gpointer user_data,
+                                                                        gchar **reply_string);
+
+int do_getsessioninfo(GNetXmlRpcServer *server,
+                      const gchar *command,
+                                                                           const gchar *param,
+                                                                           gpointer user_data,
+                                                                           gchar **reply_string);
+
+#endif // __RH_XMLRPC_SERVER_H
diff --git a/xmlrpc/Makefile.am b/xmlrpc/Makefile.am
new file mode 100644 (file)
index 0000000..33b8089
--- /dev/null
@@ -0,0 +1,29 @@
+## Process this file with automake to produce Makefile.in
+
+@SET_MAKE@
+
+noinst_LIBRARIES = libgnetxmlrpc.a
+
+noinst_PROGRAMS = \
+       test-xmlrpc-client \
+       test-xmlrpc-client-php \
+       test-xmlrpc-server
+
+AM_CFLAGS = $(LIBGNET_CFLAGS)
+
+libgnetxmlrpc_a_SOURCES = xmlrpc-client.c xmlrpc-server.c xmlrpc.h
+
+test_xmlrpc_client_SOURCES = test-xmlrpc-client.c xmlrpc.h
+test_xmlrpc_client_LDADD = \
+       libgnetxmlrpc.a \
+       $(LIBGNET_LIBS)
+
+test_xmlrpc_client_php_SOURCES = test-xmlrpc-client-php.c xmlrpc.h
+test_xmlrpc_client_php_LDADD = \
+       libgnetxmlrpc.a \
+       $(LIBGNET_LIBS)
+
+test_xmlrpc_server_SOURCES = test-xmlrpc-server.c xmlrpc.h
+test_xmlrpc_server_LDADD = \
+       libgnetxmlrpc.a \
+       $(LIBGNET_LIBS)
diff --git a/xmlrpc/Makefile.in b/xmlrpc/Makefile.in
new file mode 100644 (file)
index 0000000..6888339
--- /dev/null
@@ -0,0 +1,448 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+noinst_PROGRAMS = test-xmlrpc-client$(EXEEXT) \
+       test-xmlrpc-client-php$(EXEEXT) test-xmlrpc-server$(EXEEXT)
+subdir = xmlrpc
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libgnetxmlrpc_a_AR = $(AR) $(ARFLAGS)
+libgnetxmlrpc_a_LIBADD =
+am_libgnetxmlrpc_a_OBJECTS = xmlrpc-client.$(OBJEXT) \
+       xmlrpc-server.$(OBJEXT)
+libgnetxmlrpc_a_OBJECTS = $(am_libgnetxmlrpc_a_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am_test_xmlrpc_client_OBJECTS = test-xmlrpc-client.$(OBJEXT)
+test_xmlrpc_client_OBJECTS = $(am_test_xmlrpc_client_OBJECTS)
+am__DEPENDENCIES_1 =
+test_xmlrpc_client_DEPENDENCIES = libgnetxmlrpc.a \
+       $(am__DEPENDENCIES_1)
+am_test_xmlrpc_client_php_OBJECTS = test-xmlrpc-client-php.$(OBJEXT)
+test_xmlrpc_client_php_OBJECTS = $(am_test_xmlrpc_client_php_OBJECTS)
+test_xmlrpc_client_php_DEPENDENCIES = libgnetxmlrpc.a \
+       $(am__DEPENDENCIES_1)
+am_test_xmlrpc_server_OBJECTS = test-xmlrpc-server.$(OBJEXT)
+test_xmlrpc_server_OBJECTS = $(am_test_xmlrpc_server_OBJECTS)
+test_xmlrpc_server_DEPENDENCIES = libgnetxmlrpc.a \
+       $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libgnetxmlrpc_a_SOURCES) $(test_xmlrpc_client_SOURCES) \
+       $(test_xmlrpc_client_php_SOURCES) \
+       $(test_xmlrpc_server_SOURCES)
+DIST_SOURCES = $(libgnetxmlrpc_a_SOURCES) \
+       $(test_xmlrpc_client_SOURCES) \
+       $(test_xmlrpc_client_php_SOURCES) \
+       $(test_xmlrpc_server_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBGNET_CFLAGS = @LIBGNET_CFLAGS@
+LIBGNET_LIBS = @LIBGNET_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = libgnetxmlrpc.a
+AM_CFLAGS = $(LIBGNET_CFLAGS)
+libgnetxmlrpc_a_SOURCES = xmlrpc-client.c xmlrpc-server.c xmlrpc.h
+test_xmlrpc_client_SOURCES = test-xmlrpc-client.c xmlrpc.h
+test_xmlrpc_client_LDADD = \
+       libgnetxmlrpc.a \
+       $(LIBGNET_LIBS)
+
+test_xmlrpc_client_php_SOURCES = test-xmlrpc-client-php.c xmlrpc.h
+test_xmlrpc_client_php_LDADD = \
+       libgnetxmlrpc.a \
+       $(LIBGNET_LIBS)
+
+test_xmlrpc_server_SOURCES = test-xmlrpc-server.c xmlrpc.h
+test_xmlrpc_server_LDADD = \
+       libgnetxmlrpc.a \
+       $(LIBGNET_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  xmlrpc/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  xmlrpc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLIBRARIES:
+       -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libgnetxmlrpc.a: $(libgnetxmlrpc_a_OBJECTS) $(libgnetxmlrpc_a_DEPENDENCIES) 
+       -rm -f libgnetxmlrpc.a
+       $(libgnetxmlrpc_a_AR) libgnetxmlrpc.a $(libgnetxmlrpc_a_OBJECTS) $(libgnetxmlrpc_a_LIBADD)
+       $(RANLIB) libgnetxmlrpc.a
+
+clean-noinstPROGRAMS:
+       -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+test-xmlrpc-client$(EXEEXT): $(test_xmlrpc_client_OBJECTS) $(test_xmlrpc_client_DEPENDENCIES) 
+       @rm -f test-xmlrpc-client$(EXEEXT)
+       $(LINK) $(test_xmlrpc_client_OBJECTS) $(test_xmlrpc_client_LDADD) $(LIBS)
+test-xmlrpc-client-php$(EXEEXT): $(test_xmlrpc_client_php_OBJECTS) $(test_xmlrpc_client_php_DEPENDENCIES) 
+       @rm -f test-xmlrpc-client-php$(EXEEXT)
+       $(LINK) $(test_xmlrpc_client_php_OBJECTS) $(test_xmlrpc_client_php_LDADD) $(LIBS)
+test-xmlrpc-server$(EXEEXT): $(test_xmlrpc_server_OBJECTS) $(test_xmlrpc_server_DEPENDENCIES) 
+       @rm -f test-xmlrpc-server$(EXEEXT)
+       $(LINK) $(test_xmlrpc_server_OBJECTS) $(test_xmlrpc_server_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-xmlrpc-client-php.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-xmlrpc-client.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-xmlrpc-server.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-client.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-server.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-noinstLIBRARIES clean-noinstPROGRAMS ctags distclean \
+       distclean-compile distclean-generic distclean-tags distdir dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-data install-data-am install-dvi install-dvi-am \
+       install-exec install-exec-am install-html install-html-am \
+       install-info install-info-am install-man install-pdf \
+       install-pdf-am install-ps install-ps-am install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+       uninstall-am
+
+
+@SET_MAKE@
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/xmlrpc/README b/xmlrpc/README
new file mode 100644 (file)
index 0000000..f001362
--- /dev/null
@@ -0,0 +1,63 @@
+
+  ===========================================================================
+
+                     GNetXmlRpc server and client
+                  XMLRPC functionality using GLib/GNet
+              Written by Dov Grobgeld <dov.grobgeld@gmail.com>
+                           Version 0.0.3
+
+  ===========================================================================
+
+   BACKGROUND
+
+   I built this library for a scientific gtk display application in which
+   I am generating date in one process, and would like to display it in
+   another process. Through this library, whenever the data is ready for
+   display, I can easily send it to the display program.
+
+   For this application it was enough to support one string in and one
+   string out subset of the full XMLRPC application. If someone is
+   interested it would be easy to add a parallell callback functionality
+   for the full XML data. I doubt that I will get around to doing it though.
+
+   See the two example programs test-xml-server and test-xml-client for
+   examples how to use this library.
+
+  ===========================================================================
+
+   TODO
+
+   - Ideally, GnetXmlRpcClient would be built on top of GConnHttp and
+     GnetXMLRcpServer would be built on top of a still-to-write GServerHttp
+     (= provide asynchronous client functionality, HTTP authentication would
+     then be handled by GServerHttp)
+
+   - XML escaping/unescaping should be done using GLib's g_markup_*
+     family of functions.
+
+   - XML parsing should be done using GMarkupParser (any non-UTF8 input would
+     need to be converted to UTF8 first).
+
+   - Support other types than just strings / add full xml parameter support
+
+   - By default block connections from servers other than localhost (IP filter)
+
+   - Add option to accept connections from a wild card of servers.
+
+   - When registering commands, check if they already exist and free
+     the corresponding resources.
+
+   - When destroying a server, destroy the command table hash.
+
+   - Better error handling.
+
+   - Make it part of GNet? (needs all of the above fixed + a decent API)
+
+  ===========================================================================
+
+   FURTHER INFORMATION
+
+   http://www.xmlrpc.com/
+   http://www.gnetlibrary.org/
+
+  ===========================================================================
diff --git a/xmlrpc/test-xmlrpc-client-php.c b/xmlrpc/test-xmlrpc-client-php.c
new file mode 100644 (file)
index 0000000..f170c95
--- /dev/null
@@ -0,0 +1,60 @@
+/* Example program for a client using the gnet_xmlrpc library.
+ *
+ * Copyright (c) 2006 Dov Grobgeld <dov.grobgeld@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "xmlrpc.h"
+
+int
+main(int argc, char *argv[])
+{
+  GNetXmlRpcClient *client;
+  gchar *reply;
+  gint port = 80;
+       gchar *url = "/rahu-login/xmlrpc2.php";
+
+  if (argc > 1)
+    port = atoi(argv[1]);
+
+  gnet_init ();
+
+  client = gnet_xmlrpc_client_new("localhost", url, port);
+
+  if (!client)
+    {
+      printf("Failed connecting to localhost!\n");
+      exit(-1);
+    }
+  
+  if (gnet_xmlrpc_client_call(client,
+                             "uptime",
+                             "",
+                             /* output  */
+                             &reply) == 0)
+    {
+      printf("Reply = %s\n", reply);
+      g_free(reply);
+    }
+  else
+    printf("Failed executing echo!\n");
+
+  return 0;
+}
diff --git a/xmlrpc/test-xmlrpc-client.c b/xmlrpc/test-xmlrpc-client.c
new file mode 100644 (file)
index 0000000..a251e7e
--- /dev/null
@@ -0,0 +1,71 @@
+/* Example program for a client using the gnet_xmlrpc library.
+ *
+ * Copyright (c) 2006 Dov Grobgeld <dov.grobgeld@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "xmlrpc.h"
+
+int
+main(int argc, char *argv[])
+{
+  GNetXmlRpcClient *client;
+  gchar *reply;
+  gint port = 8123;
+
+  if (argc > 1)
+    port = atoi(argv[1]);
+
+  gnet_init ();
+
+  client = gnet_xmlrpc_client_new("localhost", "/RPC2", port);
+
+  if (!client)
+    {
+      printf("Failed connecting to localhost!\n");
+      exit(-1);
+    }
+  
+  if (gnet_xmlrpc_client_call(client,
+                             "echo",
+                             "Hello world",
+                             /* output  */
+                             &reply) == 0)
+    {
+      printf("echo reply = %s\n", reply);
+      g_free(reply);
+    }
+  else
+    printf("Failed executing echo!\n");
+
+  if (gnet_xmlrpc_client_call(client,
+                             "async",
+                             "",
+                             // output
+                             &reply) == 0)
+    {
+      printf("async reply = %s\n", reply);
+      g_free(reply);
+    }
+  else
+    printf("Failed executing echo!\n");
+
+  return 0;
+}
diff --git a/xmlrpc/test-xmlrpc-server.c b/xmlrpc/test-xmlrpc-server.c
new file mode 100644 (file)
index 0000000..be7513a
--- /dev/null
@@ -0,0 +1,132 @@
+/* Example program for the gnet_xmlrpc server functionality.
+ *
+ * Copyright (c) 2006 Dov Grobgeld <dov.grobgeld@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "xmlrpc.h"
+int do_foo(GNetXmlRpcServer *server,
+          const gchar *command,
+          const gchar *param,
+          gpointer user_data,
+          /* output */
+          gchar **reply_string);
+int do_echo(GNetXmlRpcServer *server,
+           const gchar *command,
+           const gchar *param,
+           gpointer user_data,
+           /* output */
+           gchar **reply_string);
+
+int do_async(GNetXmlRpcServer *server,
+             GConn *conn,
+             const gchar *command,
+             const gchar *param,
+             gpointer user_data);
+
+gboolean say_hello(gpointer user_data);
+
+int
+main(int argc, char** argv)
+{
+  int port = 8123;
+       gchar* addr = "localhost";
+  GNetXmlRpcServer *server;
+  GMainLoop* main_loop;
+
+  gnet_init ();
+
+  if (argc > 1)
+      port = atoi(argv[1]);
+
+  /* Create the main loop */
+  main_loop = g_main_loop_new (NULL,
+                               FALSE);
+
+  server = gnet_xmlrpc_server_new(addr, port);
+
+  if (!server)
+    {
+      fprintf (stderr, "Error: Could not start server\n");
+      exit (EXIT_FAILURE);
+    }
+
+  gnet_xmlrpc_server_register_command(server,
+                                     "foo",
+                                     do_foo,
+                                     NULL);
+
+  gnet_xmlrpc_server_register_command(server,
+                                     "echo",
+                                     do_echo,
+                                     NULL);
+  
+  gnet_xmlrpc_server_register_async_command(server,
+                                     "async",
+                                     do_async,
+                                     NULL);
+
+  /* Start the main loop */
+  g_main_loop_run(main_loop);
+
+  exit (EXIT_SUCCESS);
+  return 0;
+}
+
+int do_foo(GNetXmlRpcServer *server,
+          const gchar *command,
+          const gchar *param,
+          gpointer user_data,
+          // output
+          gchar **reply_string)
+{
+    *reply_string = g_strdup("BAR!");
+    return 0;
+}
+
+int do_echo(GNetXmlRpcServer *server,
+           const gchar *command,
+           const gchar *param,
+           gpointer user_data,
+           // output
+           gchar **reply_string)
+{
+    *reply_string = g_strdup_printf("You said: \"%s\"", param);
+
+    return 0;
+}
+
+int do_async(GNetXmlRpcServer *server,
+             GConn *conn,
+             const gchar *command,
+             const gchar *param,
+             gpointer user_data)
+{
+  g_timeout_add(2000,
+                say_hello,
+                conn);
+  return 0;
+}
+
+gboolean say_hello(gpointer user_data)
+{
+  GConn *conn = (GConn*)user_data;
+  gnet_xmlrpc_async_client_response(conn, "hi!!");
+  return FALSE;
+}
diff --git a/xmlrpc/xmlrpc-client.c b/xmlrpc/xmlrpc-client.c
new file mode 100644 (file)
index 0000000..8e43657
--- /dev/null
@@ -0,0 +1,279 @@
+/* An XMLRPC client and server library for GNet
+ *
+ * Copyright (c) 2006 Dov Grobgeld <dov.grobgeld@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "xmlrpc.h"
+
+typedef struct  {
+  GNetXmlRpcClient client;
+       GString *url;
+  GTcpSocket* socket;
+  GString *xmlrpc_string;
+  gboolean in_header;
+  gint header_lineno;
+  gint message_size;
+  gint error;
+} GNetXmlRpcClientPrivate;
+
+static gchar *build_xmlrpc_message(GNetXmlRpcClient *_client,
+                                   const gchar *method,
+                                   const gchar *param);
+
+GNetXmlRpcClient *gnet_xmlrpc_client_new(const gchar *hostname,
+                                         const gchar *url,
+                                         int port)
+{
+  GNetXmlRpcClientPrivate *client = g_new0(GNetXmlRpcClientPrivate, 1);
+  GInetAddr* addr;
+
+  addr = gnet_inetaddr_new (hostname, port);
+  if (!addr)
+    {
+      fprintf (stderr, "Error: Name lookup for %s failed\n", hostname);
+      return NULL;
+    }
+
+  /* Create the socket */
+  client->socket = gnet_tcp_socket_new (addr);
+  gnet_inetaddr_delete (addr);
+  if (!client->socket)
+    {
+      fprintf (stderr, "Error: Could not connect to %s:%d\n", hostname, port);
+      return NULL;
+    }
+  
+  client->client.gnet_channel = gnet_tcp_socket_get_io_channel (client->socket);
+  g_assert (client->client.gnet_channel != NULL);
+
+       client->url = g_string_new("");
+       g_string_append_len (client->url, url, strlen (url));
+
+  client->xmlrpc_string = g_string_new("");
+  client->in_header = TRUE;
+  client->header_lineno = 0;
+  client->message_size = 0;
+  client->error = 0;
+
+  return (GNetXmlRpcClient*)client;
+}
+
+void gnet_xmlrpc_client_delete(GNetXmlRpcClient *_client)
+{
+  GNetXmlRpcClientPrivate *client = (GNetXmlRpcClientPrivate*)_client;
+
+  g_string_free(client->xmlrpc_string, TRUE);
+       g_string_free(client->url, TRUE);
+  gnet_tcp_socket_delete (client->socket);
+  g_free(client);
+}
+
+int gnet_xmlrpc_client_call(GNetXmlRpcClient *_client,
+                            const gchar *method,
+                            const gchar *param,
+                            // output
+                            gchar **reply)
+{
+  GNetXmlRpcClientPrivate *client = (GNetXmlRpcClientPrivate*)_client;
+  gchar *xmlrpc_message = build_xmlrpc_message((GNetXmlRpcClient*)client, 
+                                                     method, param);
+  gchar *msg_start, *msg_end;
+  gchar *p;
+  GString *xmlrpc_string = g_string_new("");
+  GString *reply_string = g_string_new("");
+  gsize n;
+  gchar buffer[1024];
+  gint error;
+  
+  n = strlen(xmlrpc_message);
+  //  printf("Writing...\n"); fflush(stdout);
+  error = gnet_io_channel_writen (client->client.gnet_channel,
+                                  xmlrpc_message, n, &n);
+  // printf("error = %d\n", error); fflush(stdout);
+  if (error != G_IO_ERROR_NONE)
+      return -1;
+
+  // fprintf(stderr, "entering while loop\n");
+  while (gnet_io_channel_readline (client->client.gnet_channel, buffer, sizeof(buffer), &n) == G_IO_ERROR_NONE)
+    {
+      if (client->in_header)
+        {
+          // Check for a valid response
+          if (client->header_lineno == 0)
+            {
+              // If we don't have HTTP we've got a problem
+              if (g_strstr_len(buffer, 5, "HTTP") == NULL)
+                {
+                  return -1;
+                }
+            }
+          else if (n < 5) // Assume that empty line the line less than 5 chars
+            {
+              client->in_header = FALSE;
+            }
+          else
+            {
+              // Look for the content-length string case independant.
+              char *p;
+
+              // Lower case buf
+              p = buffer;
+              while(*p)
+                {
+                  *p = g_ascii_tolower(*p);
+                  p++;
+                }
+              
+              // Search for string
+              if ((p = g_strstr_len(buffer, n-1,
+                                    "content-length:")) != NULL)
+                {
+                  p += strlen("Content-length:");
+                  client->message_size = atoi(p);
+                }
+            }
+          client->header_lineno++;
+        }
+      // If we are not in the header then append the line to the xmlrpc string.
+      else
+        {
+          g_string_append_len(xmlrpc_string, buffer, n-1);
+          g_string_append_c(xmlrpc_string, '\n');
+        }
+
+      // Check if we are finished
+      if (xmlrpc_string->len
+          && xmlrpc_string->len >= client->message_size)
+        {
+          // Quit and reset parsing for next message
+          client->in_header = 1;
+          client->header_lineno = 0;
+          break;
+        }
+    }
+
+  // Extract the response. Should be exchanged to some more robust
+  // XML parsing.
+  msg_start = g_strstr_len(xmlrpc_string->str,
+                           xmlrpc_string->len,
+                           "<string>");
+  if (msg_start == NULL)
+    return -1;
+  
+  msg_start += strlen("<string>");
+  msg_end = g_strrstr(msg_start, "</string>");
+
+  // Decode the response
+  p = msg_start;
+  while(*p != '<')
+    {
+      gchar c = *p++;
+
+      if (c == '&')
+        {
+          if (g_strstr_len(p, 4, "amp;") == p)
+            {
+              g_string_append_c(reply_string, '&');
+              p+= 4;
+            }
+          else if (g_strstr_len(p, 3, "lt;") == p)
+            {
+              g_string_append_c(reply_string, '<');
+              p+= 3;
+            }
+          else if (g_strstr_len(p, 3, "gt;") == p)
+            {
+              g_string_append_c(reply_string, '>');
+              p+= 3;
+            }
+          else
+            {
+              // Don't know what to do. Just add the ampersand..
+              g_string_append_c(reply_string, '&');
+            }
+        }
+      else
+        g_string_append_c(reply_string, c);
+    }
+  *reply = reply_string->str;
+  g_string_free(reply_string, FALSE);
+  g_string_free(xmlrpc_string, TRUE);
+
+  return 0;
+}
+  
+static gchar *build_xmlrpc_message(GNetXmlRpcClient *_client,
+                                   const gchar *method,
+                                   const gchar *param)
+{
+  GNetXmlRpcClientPrivate *client = (GNetXmlRpcClientPrivate*)_client;
+  GString *xmlrpc_msg = g_string_new("");
+  GString *req_string = g_string_new("");
+  const gchar *p;
+  gchar *ret;
+  
+  g_string_append_printf(xmlrpc_msg,
+                         "<?xml version=\"1.0\"?>\n"
+                         "<methodCall>\n"
+                         "<methodName>%s</methodName>\n"
+                         "<params>\n"
+                         "<param><value><string>",
+                         method);
+
+  // Encode the param string
+  p = param;
+  while(*p)
+    {
+      gchar c = *p++;
+      switch (c)
+        {
+        case '&' : g_string_append(xmlrpc_msg, "&amp;"); break;
+        case '<': g_string_append(xmlrpc_msg, "&lt;"); break;
+        case '>': g_string_append(xmlrpc_msg, "&gt;"); break;
+        default:
+          g_string_append_c(xmlrpc_msg, c);
+        }
+    }
+  
+  g_string_append(xmlrpc_msg,
+                  "</string></value></param>\n"
+                  "</params>\n"
+                  "</methodCall>\n");
+  
+  g_string_append_printf(req_string,
+                         "POST %s HTTP/1.0\n"
+                         "User-Agent: RahuNASd/0.1\n"
+                         "Host: localhost\n"
+                         "Content-Type: text/xml\n"
+                         "Content-length: %u\n\n",
+                                                                                                client->url->str,
+                         (guint) xmlrpc_msg->len);
+  g_string_append_len(req_string,
+                      xmlrpc_msg->str,
+                      xmlrpc_msg->len);
+  g_string_free(xmlrpc_msg, TRUE);
+
+  ret = req_string->str;
+  g_string_free(req_string, FALSE);
+
+  return ret;
+}
diff --git a/xmlrpc/xmlrpc-server.c b/xmlrpc/xmlrpc-server.c
new file mode 100644 (file)
index 0000000..ca1999b
--- /dev/null
@@ -0,0 +1,411 @@
+/* An XMLRPC client and server library for GNet
+ *
+ * Copyright (c) 2006 Dov Grobgeld <dov.grobgeld@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <gnet.h>
+#include "xmlrpc.h"
+
+typedef struct {
+  GNetXmlRpcServer server; 
+  GHashTable *command_hash;
+} GNetXmlRpcServerPrivate;
+
+typedef struct {
+  GNetXmlRpcCommandCallback *callback;
+  GNetXmlRpcCommandAsyncCallback *async_callback;
+  gpointer user_data;
+} command_hash_value_t;
+
+typedef struct {
+  GNetXmlRpcServerPrivate *xmlrpc_server;
+  GString *connection_string;
+} connection_state_t;
+
+static void ob_server_func (GServer* server, GConn* conn, gpointer user_data);
+static void ob_client_func (GConn* conn, GConnEvent* event, 
+                            gpointer user_data);
+gchar *create_response_string(const gchar *reply);
+static GServer* ob_server = NULL;
+
+int extract_xmlrpc_request(const gchar *str,
+                           /* output */
+                           gchar **command_name,
+                           gchar **parameter
+                           );
+
+GNetXmlRpcServer *gnet_xmlrpc_server_new(const gchar* hostname, int port)
+{
+  GNetXmlRpcServerPrivate *xmlrpc_server = g_new0(GNetXmlRpcServerPrivate, 1);
+  
+  /* Create the server */
+       GInetAddr* addr = gnet_inetaddr_new (hostname, port);
+  GServer *gnet_server = gnet_server_new (addr, port, ob_server_func, xmlrpc_server);
+       gnet_inetaddr_delete (addr);
+  if (!gnet_server)
+    {
+      fprintf (stderr, "Error: Could not start server\n");
+      return NULL;
+    }
+  xmlrpc_server->server.gnet_server = gnet_server;
+  xmlrpc_server->command_hash = g_hash_table_new(g_str_hash,
+                                                 g_str_equal);
+
+  return (GNetXmlRpcServer*)xmlrpc_server;
+}
+
+void gnet_xmlrpc_server_delete(GNetXmlRpcServer *server)
+{
+  gnet_server_delete (ob_server);
+}
+
+static void
+ob_server_func (GServer* server, GConn* conn, gpointer user_data)
+{
+  if (conn)
+    {
+      connection_state_t *conn_state = g_new0(connection_state_t, 1);
+      conn_state->xmlrpc_server = (GNetXmlRpcServerPrivate*)user_data;
+      conn_state->connection_string = g_string_new("");
+      
+      gnet_conn_set_callback (conn, ob_client_func, conn_state);
+      gnet_conn_set_watch_error (conn, TRUE);
+      gnet_conn_readline (conn);
+    }
+  else  /* Error */
+    {
+      gnet_server_delete (server);
+      exit (EXIT_FAILURE);
+    }
+}
+
+
+static void
+ob_client_func (GConn* conn, GConnEvent* event, gpointer user_data)
+{
+  connection_state_t *conn_state = (connection_state_t*)user_data;
+  GNetXmlRpcServerPrivate *xmlrpc_server = conn_state->xmlrpc_server;
+  GString *req_string = conn_state->connection_string;
+
+  switch (event->type)
+    {
+    case GNET_CONN_READ:
+      {
+        event->buffer[event->length-1] = '\n';
+        g_string_append_len(req_string, event->buffer, event->length);
+
+        /* Check if we have the whole request */
+        if (g_strstr_len(req_string->str,
+                         req_string->len,
+                         "</methodCall>") != NULL)
+          {
+            /* Extract command name */
+            gchar *command_name=NULL, *parameter=NULL;
+            gchar *response=NULL;
+            command_hash_value_t *command_val;
+            
+            extract_xmlrpc_request(req_string->str,
+                                   /* output */
+                                   &command_name,
+                                   &parameter
+                                   );
+
+            /* Call the callback */
+            command_val = g_hash_table_lookup(xmlrpc_server->command_hash,
+                                              command_name);
+            if (!command_val)
+              response = create_response_string("No such method!");
+            else if (command_val->async_callback)
+              {
+                (*command_val->async_callback)((GNetXmlRpcServer*)xmlrpc_server,
+                                               conn,
+                                               command_name,
+                                               parameter,
+                                               command_val->user_data);
+              }
+            else
+              {
+                gchar *reply;
+                (*command_val->callback)((GNetXmlRpcServer*)xmlrpc_server,
+                                         command_name,
+                                         parameter,
+                                         command_val->user_data,
+                                         /* output */
+                                         &reply);
+                response = create_response_string(reply);
+                g_free(reply);
+              }
+
+            if (response)
+              {
+                /* Send reply */
+                gnet_conn_write (conn, response, strlen(response));
+                g_free(response);
+              }
+            
+            /* printf("rs = ((%s)) len=%d\n", req_string->str, event->length); */
+            g_string_assign(conn_state->connection_string, "");
+
+            g_free(command_name);
+            if (parameter)
+                g_free(parameter);
+          }
+
+        gnet_conn_readline (conn);
+        break;
+      }
+
+    case GNET_CONN_WRITE:
+      {
+        ; /* Do nothing */
+        break;
+      }
+
+    case GNET_CONN_CLOSE:
+    case GNET_CONN_TIMEOUT:
+    case GNET_CONN_ERROR:
+      {
+        g_string_free(conn_state->connection_string, TRUE);
+        g_free(conn_state);
+        gnet_conn_delete (conn);
+        break;
+      }
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static int
+gnet_xmlrpc_server_register_command_full(GNetXmlRpcServer *_xmlrpc_server,
+                                         const gchar *command,
+                                         GNetXmlRpcCommandCallback *callback,
+                                         GNetXmlRpcCommandAsyncCallback *async_callback,
+                                         gpointer user_data)
+{
+  GNetXmlRpcServerPrivate *xmlrpc_server = (GNetXmlRpcServerPrivate*)_xmlrpc_server;
+  /* TBD - Check if command exist and override it */
+  command_hash_value_t *val = g_new0(command_hash_value_t, 1);
+  val->callback = callback;
+  val->async_callback = async_callback;
+  val->user_data = user_data;
+  g_hash_table_insert(xmlrpc_server->command_hash,
+                      g_strdup(command),
+                      val);
+
+  return 0;
+}
+
+int gnet_xmlrpc_server_register_command(GNetXmlRpcServer *_xmlrpc_server,
+                                        const gchar *command,
+                                        GNetXmlRpcCommandCallback *callback,
+                                        gpointer user_data)
+{
+  gnet_xmlrpc_server_register_command_full(_xmlrpc_server,
+                                           command,
+                                           callback,
+                                           NULL, /* async */
+                                           user_data);
+
+  return 0;
+}
+
+int gnet_xmlrpc_server_register_async_command(GNetXmlRpcServer *_xmlrpc_server,
+                                              const gchar *command,
+                                              GNetXmlRpcCommandAsyncCallback *async_callback,
+                                              gpointer user_data)
+{
+  gnet_xmlrpc_server_register_command_full(_xmlrpc_server,
+                                           command,
+                                           NULL,
+                                           async_callback, /* async */
+                                           user_data);
+  return 0;
+}
+
+/** 
+ * Reply to an async request
+ * 
+ * @param gnet_client 
+ * @param reply_string 
+ * 
+ * @return 
+ */
+int gnet_xmlrpc_async_client_response(GConn *conn,
+                                      const gchar *reply)
+{
+  gchar *response = create_response_string(reply);
+  /* Send reply */
+  gnet_conn_write (conn, response, strlen(response));
+  g_free(response);
+
+  return 0;
+}
+
+/**
+ * Extract the xmlrpc request. This is done by simple reg exp matching.
+ * This should be changed to xml decoding
+ */
+int extract_xmlrpc_request(const gchar *str,
+                           /* output */
+                           gchar **command_name,
+                           gchar **parameter
+                           )
+{
+  int len = strlen(str);
+  gchar *method_name_start, *method_name_end;
+  gchar *param_name_start, *param_name_end;
+  GString *param_string = g_string_new("");
+  const gchar *p;
+  
+  method_name_start = g_strstr_len(str,
+                                   len,
+                                   "<methodName>");
+  if (method_name_start == NULL)
+    return -1;
+  method_name_start += strlen("<methodName>");
+
+  method_name_end = g_strstr_len(method_name_start,
+                                 strlen(method_name_start),
+                                 "</methodName>");
+  if (method_name_end == NULL)
+    return -1;
+
+  *command_name = g_strndup(method_name_start,
+                            method_name_end - method_name_start);
+       
+       param_name_start = g_strstr_len(str,
+                                       len,
+                                                                                                                                       "<string>");
+       if (param_name_start == NULL) {
+    *parameter = NULL;
+               return 0;
+       }
+  
+       param_name_start += strlen("<string>");
+       param_name_end = g_strstr_len(param_name_start,
+                                     strlen(param_name_start),
+                                                                                                                               "</string>");
+
+       if (param_name_end == NULL) {
+    return -1;
+       }
+
+  /* Decode and build parameter */
+  if (param_name_start) {
+      p = param_name_start;
+      while (*p)
+        {
+          gchar c = *p++;
+          if (p > param_name_end)
+            break;
+    
+          if (c == '&')
+            {
+              if (g_strstr_len(p, 4, "amp;") == p)
+                {
+                  g_string_append_c(param_string, '&');
+                  p+= 4;
+                }
+              if (g_strstr_len(p, 5, "quot;") == p)
+                {
+                  g_string_append_c(param_string, '"');
+                  p+= 5;
+                }
+              else if (g_strstr_len(p, 3, "lt;") == p)
+                {
+                  g_string_append_c(param_string, '<');
+                  p+= 3;
+                }
+              else if (g_strstr_len(p, 3, "gt;") == p)
+                {
+                  g_string_append_c(param_string, '>');
+                  p+= 3;
+                }
+              else
+                {
+                  /* Don't know what to do. Just add the ampersand.. */
+                  g_string_append_c(param_string, '&');
+                }
+            }
+          else
+            g_string_append_c(param_string, c);
+        }
+      *parameter = param_string->str;
+      g_string_free(param_string, FALSE);
+  }
+  else
+      *parameter = NULL;
+    
+  return 0;
+                                   
+}
+
+gchar *create_response_string(const gchar *reply)
+{
+  GString *response_string = g_string_new("");
+  GString *content_string = g_string_new("");
+  gchar *res;
+  const gchar *p;
+
+  g_string_append(content_string,
+                  "<?xml version=\"1.0\"?> <methodResponse> <params> <param> <value><string>");
+
+  /* Encode and add the reply */
+  p=reply;
+  while(*p) {
+      gchar c = *p++;
+      switch (c)
+        {
+        case '&' : g_string_append(content_string, "&amp;"); break;
+        case '<': g_string_append(content_string, "&lt;"); break;
+        case '>': g_string_append(content_string, "&gt;"); break;
+        default:
+          g_string_append_c(content_string, c);
+        }
+  }
+
+  g_string_append(content_string,
+                  "</string></value> </param> </params> </methodResponse>\n");
+
+
+  g_string_append_printf(response_string,
+                         "HTTP/1.1 200 OK\n"
+                         "Connection: close\n"
+                         "Content-Length: %" G_GSIZE_FORMAT "\n"
+                         "Content-Type: text/xml\n"
+                         "Server: RahuNASd XMLRPC server\n"
+                         "\n"
+                         "%s",
+                         content_string->len,
+                         content_string->str
+                         );
+
+  g_string_free(content_string, TRUE);
+
+  res = response_string->str;
+
+  g_string_free(response_string, FALSE);
+
+  return res;
+}
+
diff --git a/xmlrpc/xmlrpc.h b/xmlrpc/xmlrpc.h
new file mode 100644 (file)
index 0000000..46d4510
--- /dev/null
@@ -0,0 +1,85 @@
+/* An XMLRPC client and server library for GNet
+ *
+ * Copyright (c) 2006 Dov Grobgeld <dov.grobgeld@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef GNET_XMLRPC_H
+#define GNET_XMLRPC_H
+
+#include <gnet.h>
+
+G_BEGIN_DECLS
+
+/* GNetXmlRpcServer API */
+
+typedef struct {
+  /*< private >*/
+  GServer *gnet_server;
+} GNetXmlRpcServer; 
+
+typedef gint (GNetXmlRpcCommandCallback) (GNetXmlRpcServer * server,
+                                          const gchar      * command,
+                                          const gchar      * param,
+                                          gpointer           user_data,
+                                          gchar           ** reply_string);
+
+typedef int (GNetXmlRpcCommandAsyncCallback)(GNetXmlRpcServer *server,
+                                             GConn *gnet_client,
+                                             const gchar *command,
+                                             const gchar *param,
+                                             gpointer user_data);
+
+GNetXmlRpcServer * gnet_xmlrpc_server_new    (const gchar *hostname, gint port);
+
+void               gnet_xmlrpc_server_delete (GNetXmlRpcServer * server);
+
+gint               gnet_xmlrpc_server_register_command (GNetXmlRpcServer          * server,
+                                                        const gchar               * command,
+                                                        GNetXmlRpcCommandCallback * callback,
+                                                        gpointer                    user_data);
+gint               gnet_xmlrpc_server_register_async_command (GNetXmlRpcServer               * server,
+                                                              const gchar                    * command,
+                                                              GNetXmlRpcCommandAsyncCallback * async_callback,
+                                                              gpointer                         user_data);
+
+/* GNetXmlRpcClient API */
+
+typedef struct {
+  /*< private >*/
+  GIOChannel *gnet_channel;
+} GNetXmlRpcClient;
+
+GNetXmlRpcClient * gnet_xmlrpc_client_new    (const gchar      * hostname,
+                                              const gchar      * url,
+                                              gint               port);
+
+void               gnet_xmlrpc_client_delete (GNetXmlRpcClient * client);
+
+gint               gnet_xmlrpc_client_call   (GNetXmlRpcClient * client,
+                                              const gchar      * method,
+                                              const gchar      * param,
+                                              gchar           ** reply);  /* output */
+
+int                gnet_xmlrpc_async_client_response(GConn *gnet_client,
+                                                     const gchar *reply);
+
+
+G_END_DECLS
+
+#endif /* GNET_XMLRPC */