/* Real-time Charging System for Telecom & ISP environments Copyright (C) 2012-2015 ITsysCOM GmbH This program is free software: you can Storagetribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITH*out 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, see */ package engine import ( "bytes" "fmt" "io" "log" "net" "net/http" "net/rpc" "net/rpc/jsonrpc" "github.com/cgrates/cgrates/utils" "golang.org/x/net/websocket" ) type Server struct { rpcEnabled bool httpEnabled bool } func (s *Server) RpcRegister(rcvr interface{}) { rpc.Register(rcvr) s.rpcEnabled = true } func (s *Server) RpcRegisterName(name string, rcvr interface{}) { rpc.RegisterName(name, rcvr) s.rpcEnabled = true } func (s *Server) RegisterHttpFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) { http.HandleFunc(pattern, handler) s.httpEnabled = true } func (s *Server) ServeJSON(addr string) { if !s.rpcEnabled { return } lJSON, e := net.Listen("tcp", addr) if e != nil { log.Fatal("listen error:", e) } utils.Logger.Info(fmt.Sprintf("Starting CGRateS JSON server at %s.", addr)) for { conn, err := lJSON.Accept() if err != nil { utils.Logger.Err(fmt.Sprintf(" Accept error: %v", conn)) continue } //utils.Logger.Info(fmt.Sprintf(" New incoming connection: %v", conn.RemoteAddr())) go jsonrpc.ServeConn(conn) } } func (s *Server) ServeGOB(addr string) { if !s.rpcEnabled { return } lGOB, e := net.Listen("tcp", addr) if e != nil { log.Fatal("listen error:", e) } utils.Logger.Info(fmt.Sprintf("Starting CGRateS GOB server at %s.", addr)) for { conn, err := lGOB.Accept() if err != nil { utils.Logger.Err(fmt.Sprintf(" Accept error: %v", conn)) continue } //utils.Logger.Info(fmt.Sprintf(" New incoming connection: %v", conn.RemoteAddr())) go rpc.ServeConn(conn) } } func (s *Server) ServeHTTP(addr string) { if s.rpcEnabled { http.HandleFunc("/jsonrpc", func(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() w.Header().Set("Content-Type", "application/json") res := NewRPCRequest(req.Body).Call() io.Copy(w, res) }) http.Handle("/ws", websocket.Handler(func(ws *websocket.Conn) { jsonrpc.ServeConn(ws) })) s.httpEnabled = true } if !s.httpEnabled { return } utils.Logger.Info(fmt.Sprintf("Starting CGRateS HTTP server at %s.", addr)) http.ListenAndServe(addr, nil) } // rpcRequest represents a RPC request. // rpcRequest implements the io.ReadWriteCloser interface. type rpcRequest struct { r io.Reader // holds the JSON formated RPC request rw io.ReadWriter // holds the JSON formated RPC response done chan bool // signals then end of the RPC request } // NewRPCRequest returns a new rpcRequest. func NewRPCRequest(r io.Reader) *rpcRequest { var buf bytes.Buffer done := make(chan bool) return &rpcRequest{r, &buf, done} } func (r *rpcRequest) Read(p []byte) (n int, err error) { return r.r.Read(p) } func (r *rpcRequest) Write(p []byte) (n int, err error) { n, err = r.rw.Write(p) r.done <- true return } func (r *rpcRequest) Close() error { //r.done <- true // seem to be called sometimes before the write command finishes! return nil } // Call invokes the RPC request, waits for it to complete, and returns the results. func (r *rpcRequest) Call() io.Reader { go jsonrpc.ServeConn(r) <-r.done return r.rw }