Permalink
Browse files

initial import

  • Loading branch information...
0 parents commit f230594a67f4e096bb4fb6cb2d6ec02d6bee267b Ralf Weinbrecher committed Oct 26, 2009
Showing with 1,146 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +23 −0 LICENSE
  3. +22 −0 Makefile
  4. +25 −0 README
  5. +60 −0 example_serv.erl
  6. +38 −0 log.hrl
  7. +156 −0 tcp_serv.erl
  8. +186 −0 xmlrpc.erl
  9. +38 −0 xmlrpc.hrl
  10. +209 −0 xmlrpc_decode.erl
  11. +145 −0 xmlrpc_encode.erl
  12. +206 −0 xmlrpc_http.erl
  13. +37 −0 xmlrpc_util.erl
@@ -0,0 +1 @@
+.DS_Store
23 LICENSE
@@ -0,0 +1,23 @@
+Copyright (C) 2003 Joakim Greben� <jocke@gleipnir.com>.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,22 @@
+# Update the XMERL_PATH to point at your xmerl installation.
+XMERL_PATH=../../xmerl
+
+# Do not change anything below this line.
+ifeq ($(DEBUG),true)
+DEBUG_FLAGS = -DDEBUG
+else
+DEBUG_FLAGS =
+endif
+
+ERLC=erlc
+ERLC_FLAGS=-W $(DEBUG_FLAGS) -I $(XMERL_PATH)/inc -o ../ebin
+MODULES=xmlrpc xmlrpc_decode xmlrpc_encode xmlrpc_http xmlrpc_util tcp_serv
+EBIN_FILES=$(MODULES:%=../ebin/%.beam)
+
+all: $(EBIN_FILES)
+
+../ebin/%.beam: %.erl log.hrl
+ $(ERLC) $(ERLC_FLAGS) $<
+
+clean:
+ rm -f $(EBIN_FILES)
25 README
@@ -0,0 +1,25 @@
+This is an HTTP 1.1 compliant XML-RPC library for Erlang. It is
+designed to make it easy to write XML-RPC Erlang clients and/or
+servers. The library is compliant with the XML-RPC specification
+published by http://www.xmlrpc.org/.
+
+Prior to using this library you need a recent installation of
+Erlang. Get it at http://www.erlang.org/. You furthermore need to
+install the xmerl package, version 0.18 or better. Get it at
+http://sourceforge.net/projects/sowap/.
+
+In order compile the library you need to update the XMERL_PATH
+variable in src/Makefile to point at your xmerl installation.
+
+After this go to the src/ directory and run make to compile.
+
+You are now ready to try the client and server examples in the
+examples/ directory.
+
+Do not forget to read doc/xmlrpc.3 (or xmlrpc.txt, xmlrpc.ps,
+xmlrpc.pdf) for a detailed API description.
+
+Get the latest version of this library at
+http://www.gleipnir.com/xmlrpc/.
+
+Send questions and/or suggestions to jocke@gleipnir.com.
@@ -0,0 +1,60 @@
+-module(example_serv).
+-author('jocke@gleipnir.com').
+-export([start_link/2]).
+-export([foo/1, bar/3]).
+-export([init/2]).
+
+-record(state, {}).
+
+%%
+%% API
+%%
+
+%% Exported: start_link/2
+
+start_link(Args, Timeout) ->
+ Pid = spawn_link(?MODULE, init, [self(), Args]),
+ receive
+ {Pid, started} -> {ok, Pid};
+ {Pid, Reason} -> Reason
+ after Timeout -> {error, timeout}
+ end.
+
+%% Exported: foo/1
+
+foo(Pid) -> foo ! Pid.
+
+%% Exported: bar/3
+
+bar(Pid, Timeout, Message) ->
+ Pid !!
+
+
+ {bar, Message, self()} ! Pid,
+ receive
+ {Pid, Result} -> Result
+ after Timeout -> {error, timeout}
+ end.
+
+%%
+%% Server
+%%
+
+%% Exported: init/2
+
+init(Parent, Args) ->
+ Parent ! {self(), started},
+ loop(#state{}).
+
+loop(State) ->
+ receive
+ stop ->
+ stop;
+
+ {bar, Message, From} ->
+ {self(), Message},
+ loop(State);
+ UnknownMessage ->
+ io:format("Unknown message: ~p~n", [UnknownMessage]),
+ loop(State)
+ end.
38 log.hrl
@@ -0,0 +1,38 @@
+%% Copyright (C) 2003 Joakim Grebenö <jocke@gleipnir.com>.
+%% All rights reserved.
+%%
+%% Redistribution and use in source and binary forms, with or without
+%% modification, are permitted provided that the following conditions
+%% are met:
+%%
+%% 1. Redistributions of source code must retain the above copyright
+%% notice, this list of conditions and the following disclaimer.
+%% 2. Redistributions in binary form must reproduce the above
+%% copyright notice, this list of conditions and the following
+%% disclaimer in the documentation and/or other materials provided
+%% with the distribution.
+%%
+%% THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+%% OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+%% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+%% ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+%% DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+%% DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+%% GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+%% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+%% WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+%% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-define(INFO_LOG(Reason),
+ error_logger:info_report({?MODULE, ?LINE, Reason})).
+
+-define(ERROR_LOG(Reason),
+ error_logger:error_report({?MODULE, ?LINE, Reason})).
+
+-ifdef(DEBUG).
+-define(DEBUG_LOG(Reason),
+ error_logger:info_report({debug, ?MODULE, ?LINE, Reason})).
+-else.
+-define(DEBUG_LOG(Reason), ok).
+-endif.
@@ -0,0 +1,156 @@
+%% Copyright (C) 2003 Joakim Grebenö <jocke@gleipnir.com>.
+%% All rights reserved.
+%%
+%% Redistribution and use in source and binary forms, with or without
+%% modification, are permitted provided that the following conditions
+%% are met:
+%%
+%% 1. Redistributions of source code must retain the above copyright
+%% notice, this list of conditions and the following disclaimer.
+%% 2. Redistributions in binary form must reproduce the above
+%% copyright notice, this list of conditions and the following
+%% disclaimer in the documentation and/or other materials provided
+%% with the distribution.
+%%
+%% THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+%% OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+%% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+%% ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+%% DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+%% DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+%% GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+%% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+%% WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+%% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-module(tcp_serv).
+-vsn("1.13").
+-author('jocke@gleipnir.com').
+-export([start_link/1, start_link/2, stop/1, stop/2]).
+-export([init/2, start_session/3]).
+-export([system_continue/3, system_terminate/4]).
+
+-include("log.hrl").
+
+-record(state, {
+ %% int()
+ max_sessions,
+ %% {M, F, A}
+ %% M = F = atom()
+ %% A = [term()]
+ session_handler,
+ %% [pid()]
+ session_list,
+ %% socket()
+ listen_socket,
+ %% pid()
+ parent,
+ %% term()
+ debug_info
+ }).
+
+%% Exported: start_link/{1,2}
+
+start_link(Args) -> start_link(Args, 60000).
+
+start_link(Args, Timeout) ->
+ Pid = proc_lib:spawn_link(?MODULE, init, [self(), Args]),
+ receive
+ {Pid, started} -> {ok, Pid};
+ {Pid, Reason} -> {error, Reason}
+ after Timeout -> {error, timeout}
+ end.
+
+%% Exported: stop/{1,2}
+
+stop(Pid) -> stop(Pid, 15000).
+
+stop(Pid, Timeout) ->
+ Pid ! {self(), stop},
+ receive
+ {Pid, Reply} -> Reply
+ after
+ Timeout -> {error, timeout}
+ end.
+
+%% Exported: init/2
+
+init(Parent, [Port, MaxSessions, OptionList, SessionHandler]) ->
+ process_flag(trap_exit, true),
+ case gen_tcp:listen(Port, OptionList) of
+ {ok, ListenSocket} ->
+ self() ! start_session,
+ Parent ! {self(), started},
+ loop(#state{max_sessions = MaxSessions,
+ session_handler = SessionHandler,
+ session_list = [],
+ listen_socket = ListenSocket,
+ parent = Parent});
+ Reason -> Parent ! {self(), {not_started, Reason}}
+ end.
+
+loop(#state{session_list = SessionList, listen_socket = ListenSocket,
+ parent = Parent} = State) ->
+ receive
+ {From, stop} ->
+ cleanup(State),
+ From ! {self(), ok};
+ start_session when length(SessionList) > State#state.max_sessions ->
+ timer:sleep(5000),
+ self() ! start_session,
+ loop(State);
+ start_session ->
+ A = [self(), State#state.session_handler, ListenSocket],
+ Pid = proc_lib:spawn_link(?MODULE, start_session, A),
+ loop(State#state{session_list = [Pid|SessionList]});
+ {'EXIT', Parent, Reason} ->
+ cleanup(State),
+ exit(Reason);
+ {'EXIT', Pid, Reason} ->
+ case lists:member(Pid, SessionList) of
+ true ->
+ PurgedSessionList = lists:delete(Pid, SessionList),
+ loop(State#state{session_list = PurgedSessionList});
+ false ->
+ ?ERROR_LOG({ignoring, {'EXIT', Pid, Reason}}),
+ loop(State)
+ end;
+ {system, From, Request} ->
+ sys:handle_system_msg(Request, From, Parent, ?MODULE,
+ State#state.debug_info, State);
+ UnknownMessage ->
+ ?ERROR_LOG({unknown_message, UnknownMessage}),
+ loop(State)
+ end.
+
+cleanup(State) -> gen_tcp:close(State#state.listen_socket).
+
+%% Exported: start_seesion/3
+
+start_session(Parent, {M, F, A}, ListenSocket) ->
+ case gen_tcp:accept(ListenSocket) of
+ {ok, Socket} ->
+ Parent ! start_session,
+ case apply(M, F, [Socket|A]) of
+ ok -> gen_tcp:close(Socket);
+ {error, closed} -> ok;
+ {error, Reason} ->
+ ?ERROR_LOG({M, F, Reason}),
+ gen_tcp:close(Socket)
+ end;
+ {error, Reason} ->
+ timer:sleep(5000),
+ Parent ! start_session
+ end.
+
+%% Exported: system_continue/3
+
+system_continue(Parent, DebugInfo, State) ->
+ loop(State#state{parent = Parent, debug_info = DebugInfo}).
+
+%% Exported: system_terminate/3
+
+system_terminate(Reason, Parent, DebugInfo, State) ->
+ cleanup(State),
+ exit(Reason).
Oops, something went wrong.

0 comments on commit f230594

Please sign in to comment.