// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
	The rpc package provides access to the public methods of an object across a
	network or other I/O connection.  A server registers an object, making it visible
	as a service with the name of the type of the object.  After registration, public
	methods of the object will be accessible remotely.  A server may register multiple
	objects (services) of different types but it is an error to register multiple
	objects of the same type.

	Only methods that satisfy these criteria will be made available for remote access;
	other methods will be ignored:

		- the method name is publicly visible, that is, begins with an upper case letter.
		- the method has two arguments, both pointers to publicly visible structs.
		- the method has return type os.Error.

	The method's first argument represents the arguments provided by the caller; the
	second argument represents the result parameters to be returned to the caller.
	The method's return value, if non-nil, is passed back as a string that the client
	sees as an os.ErrorString.

	The server may handle requests on a single connection by calling ServeConn.  More
	typically it will create a network listener and call Accept or, for an HTTP
	listener, HandleHTTP and http.Serve.

	A client wishing to use the service establishes a connection and then invokes
	NewClient on the connection.  The convenience function Dial (DialHTTP) performs
	both steps for a raw network connection (an HTTP connection).  The resulting
	Client object has two methods, Call and Go, that specify the service and method to
	call, a structure containing the arguments, and a structure to receive the result
	parameters.

	Call waits for the remote call to complete; Go launches the call asynchronously
	and returns a channel that will signal completion.

	Package "gob" is used to transport the data.

	Here is a simple example.  A server wishes to export an object of type Arith:

		package server

		type Args struct {
			A, B int
		}

		type Reply struct {
			C int
		}

		type Arith int

		func (t *Arith) Multiply(args *Args, reply *Reply) os.Error {
			reply.C = args.A * args.B
			return nil
		}

		func (t *Arith) Divide(args *Args, reply *Reply) os.Error {
			if args.B == 0 {
				return os.ErrorString("divide by zero")
			}
			reply.C = args.A / args.B
			return nil
		}

	The server calls (for HTTP service):

		arith := new(Arith)
		rpc.Register(arith)
		rpc.HandleHTTP()
		l, e := net.Listen("tcp", ":1234")
		if e != nil {
			log.Exit("listen error:", e)
		}
		go http.Serve(l, nil)

	At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
	"Arith.Divide".  To invoke one, a client first dials the server:

		client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
		if err != nil {
			log.Exit("dialing:", err)
		}

	Then it can make a remote call:

		// Synchronous call
		args := &server.Args{7,8}
		reply := new(server.Reply)
		err = client.Call("Arith.Multiply", args, reply)
		if err != nil {
			log.Exit("arith error:", err)
		}
		fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply.C)

	or

		// Asynchronous call
		divCall := client.Go("Arith.Divide", args, reply, nil)
		replyCall := <-divCall.Done	// will be equal to divCall
		// check errors, print, etc.

	A server implementation will often provide a simple, type-safe wrapper for the
	client.
*/
package rpc

import (
	"gob"
	"http"
	"log"
	"io"
	"net"
	"os"
	"reflect"
	"strings"
	"sync"
	"unicode"
	"utf8"
)

// Precompute the reflect type for os.Error.  Can't use os.Error directly
// because Typeof takes an empty interface value.  This is annoying.
var unusedError *os.Error
var typeOfOsError = reflect.Typeof(unusedError).(*reflect.PtrType).Elem()

type methodType struct {
	sync.Mutex // protects counters
	method     reflect.Method
	argType    *reflect.PtrType
	replyType  *reflect.PtrType
	numCalls   uint
}

type service struct {
	name   string                 // name of service
	rcvr   reflect.Value          // receiver of methods for the service
	typ    reflect.Type           // type of the receiver
	method map[string]*methodType // registered methods
}

// Request is a header written before every RPC call.  It is used internally
// but documented here as an aid to debugging, such as when analyzing
// network traffic.
type Request struct {
	ServiceMethod string // format: "Service.Method"
	Seq           uint64 // sequence number chosen by client
}

// Response is a header written before every RPC return.  It is used internally
// but documented here as an aid to debugging, such as when analyzing
// network traffic.
type Response struct {
	ServiceMethod string // echoes that of the Request
	Seq           uint64 // echoes that of the request
	Error         string // error, if any.
}

type serverType struct {
	sync.Mutex // protects the serviceMap
	serviceMap map[string]*service
}

// This variable is a global whose "public" methods are really private methods
// called from the global functions of this package: rpc.Register, rpc.ServeConn, etc.
// For example, rpc.Register() calls server.add().
var server = &serverType{serviceMap: make(map[string]*service)}

// Is this a publicly visible - upper case - name?
func isPublic(name string) bool {
	rune, _ := utf8.DecodeRuneInString(name)
	return unicode.IsUpper(rune)
}

func (server *serverType) register(rcvr interface{}) os.Error {
	server.Lock()
	defer server.Unlock()
	if server.serviceMap == nil {
		server.serviceMap = make(map[string]*service)
	}
	s := new(service)
	s.typ = reflect.Typeof(rcvr)
	s.rcvr = reflect.NewValue(rcvr)
	sname := reflect.Indirect(s.rcvr).Type().Name()
	if sname == "" {
		log.Exit("rpc: no service name for type", s.typ.String())
	}
	if !isPublic(sname) {
		s := "rpc Register: type " + sname + " is not public"
		log.Stderr(s)
		return os.ErrorString(s)
	}
	if _, present := server.serviceMap[sname]; present {
		return os.ErrorString("rpc: service already defined: " + sname)
	}
	s.name = sname
	s.method = make(map[string]*methodType)

	// Install the methods
	for m := 0; m < s.typ.NumMethod(); m++ {
		method := s.typ.Method(m)
		mtype := method.Type
		mname := method.Name
		if !isPublic(mname) {
			continue
		}
		// Method needs three ins: receiver, *args, *reply.
		// The args and reply must be structs until gobs are more general.
		if mtype.NumIn() != 3 {
			log.Stderr("method", mname, "has wrong number of ins:", mtype.NumIn())
			continue
		}
		argType, ok := mtype.In(1).(*reflect.PtrType)
		if !ok {
			log.Stderr(mname, "arg type not a pointer:", mtype.In(1))
			continue
		}
		if _, ok := argType.Elem().(*reflect.StructType); !ok {
			log.Stderr(mname, "arg type not a pointer to a struct:", argType)
			continue
		}
		replyType, ok := mtype.In(2).(*reflect.PtrType)
		if !ok {
			log.Stderr(mname, "reply type not a pointer:", mtype.In(2))
			continue
		}
		if _, ok := replyType.Elem().(*reflect.StructType); !ok {
			log.Stderr(mname, "reply type not a pointer to a struct:", replyType)
			continue
		}
		if !isPublic(argType.Elem().Name()) {
			log.Stderr(mname, "argument type not public:", argType)
			continue
		}
		if !isPublic(replyType.Elem().Name()) {
			log.Stderr(mname, "reply type not public:", replyType)
			continue
		}
		// Method needs one out: os.Error.
		if mtype.NumOut() != 1 {
			log.Stderr("method", mname, "has wrong number of outs:", mtype.NumOut())
			continue
		}
		if returnType := mtype.Out(0); returnType != typeOfOsError {
			log.Stderr("method", mname, "returns", returnType.String(), "not os.Error")
			continue
		}
		s.method[mname] = &methodType{method: method, argType: argType, replyType: replyType}
	}

	if len(s.method) == 0 {
		s := "rpc Register: type " + sname + " has no public methods of suitable type"
		log.Stderr(s)
		return os.ErrorString(s)
	}
	server.serviceMap[s.name] = s
	return nil
}

// A value sent as a placeholder for the response when the server receives an invalid request.
type InvalidRequest struct {
	marker int
}

var invalidRequest = InvalidRequest{1}

func _new(t *reflect.PtrType) *reflect.PtrValue {
	v := reflect.MakeZero(t).(*reflect.PtrValue)
	v.PointTo(reflect.MakeZero(t.Elem()))
	return v
}

func sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
	resp := new(Response)
	// Encode the response header
	resp.ServiceMethod = req.ServiceMethod
	if errmsg != "" {
		resp.Error = errmsg
	}
	resp.Seq = req.Seq
	sending.Lock()
	err := codec.WriteResponse(resp, reply)
	if err != nil {
		log.Stderr("rpc: writing response: ", err)
	}
	sending.Unlock()
}

func (s *service) call(sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
	mtype.Lock()
	mtype.numCalls++
	mtype.Unlock()
	function := mtype.method.Func
	// Invoke the method, providing a new value for the reply.
	returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
	// The return value for the method is an os.Error.
	errInter := returnValues[0].Interface()
	errmsg := ""
	if errInter != nil {
		errmsg = errInter.(os.Error).String()
	}
	sendResponse(sending, req, replyv.Interface(), codec, errmsg)
}

type gobServerCodec struct {
	rwc io.ReadWriteCloser
	dec *gob.Decoder
	enc *gob.Encoder
}

func (c *gobServerCodec) ReadRequestHeader(r *Request) os.Error {
	return c.dec.Decode(r)
}

func (c *gobServerCodec) ReadRequestBody(body interface{}) os.Error {
	return c.dec.Decode(body)
}

func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) os.Error {
	if err := c.enc.Encode(r); err != nil {
		return err
	}
	return c.enc.Encode(body)
}

func (c *gobServerCodec) Close() os.Error {
	return c.rwc.Close()
}

func (server *serverType) input(codec ServerCodec) {
	sending := new(sync.Mutex)
	for {
		// Grab the request header.
		req := new(Request)
		err := codec.ReadRequestHeader(req)
		if err != nil {
			if err == os.EOF || err == io.ErrUnexpectedEOF {
				if err == io.ErrUnexpectedEOF {
					log.Stderr("rpc: ", err)
				}
				break
			}
			s := "rpc: server cannot decode request: " + err.String()
			sendResponse(sending, req, invalidRequest, codec, s)
			break
		}
		serviceMethod := strings.Split(req.ServiceMethod, ".", 0)
		if len(serviceMethod) != 2 {
			s := "rpc: service/method request ill-formed: " + req.ServiceMethod
			sendResponse(sending, req, invalidRequest, codec, s)
			continue
		}
		// Look up the request.
		server.Lock()
		service, ok := server.serviceMap[serviceMethod[0]]
		server.Unlock()
		if !ok {
			s := "rpc: can't find service " + req.ServiceMethod
			sendResponse(sending, req, invalidRequest, codec, s)
			continue
		}
		mtype, ok := service.method[serviceMethod[1]]
		if !ok {
			s := "rpc: can't find method " + req.ServiceMethod
			sendResponse(sending, req, invalidRequest, codec, s)
			continue
		}
		// Decode the argument value.
		argv := _new(mtype.argType)
		replyv := _new(mtype.replyType)
		err = codec.ReadRequestBody(argv.Interface())
		if err != nil {
			log.Stderr("rpc: tearing down", serviceMethod[0], "connection:", err)
			sendResponse(sending, req, replyv.Interface(), codec, err.String())
			break
		}
		go service.call(sending, mtype, req, argv, replyv, codec)
	}
	codec.Close()
}

func (server *serverType) accept(lis net.Listener) {
	for {
		conn, err := lis.Accept()
		if err != nil {
			log.Exit("rpc.Serve: accept:", err.String()) // TODO(r): exit?
		}
		go ServeConn(conn)
	}
}

// Register publishes in the server the set of methods of the
// receiver value that satisfy the following conditions:
//	- public method
//	- two arguments, both pointers to public structs
//	- one return value of type os.Error
// It returns an error if the receiver is not public or has no
// suitable methods.
func Register(rcvr interface{}) os.Error { return server.register(rcvr) }

// A ServerCodec implements reading of RPC requests and writing of
// RPC responses for the server side of an RPC session.
// The server calls ReadRequestHeader and ReadRequestBody in pairs
// to read requests from the connection, and it calls WriteResponse to
// write a response back.  The server calls Close when finished with the
// connection.
type ServerCodec interface {
	ReadRequestHeader(*Request) os.Error
	ReadRequestBody(interface{}) os.Error
	WriteResponse(*Response, interface{}) os.Error

	Close() os.Error
}

// ServeConn runs the server on a single connection.
// ServeConn blocks, serving the connection until the client hangs up.
// The caller typically invokes ServeConn in a go statement.
// ServeConn uses the gob wire format (see package gob) on the
// connection.  To use an alternate codec, use ServeCodec.
func ServeConn(conn io.ReadWriteCloser) {
	ServeCodec(&gobServerCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(conn)})
}

// ServeCodec is like ServeConn but uses the specified codec to
// decode requests and encode responses.
func ServeCodec(codec ServerCodec) {
	server.input(codec)
}

// Accept accepts connections on the listener and serves requests
// for each incoming connection.  Accept blocks; the caller typically
// invokes it in a go statement.
func Accept(lis net.Listener) { server.accept(lis) }

// Can connect to RPC service using HTTP CONNECT to rpcPath.
var rpcPath string = "/_goRPC_"
var debugPath string = "/debug/rpc"
var connected = "200 Connected to Go RPC"

func serveHTTP(c *http.Conn, req *http.Request) {
	if req.Method != "CONNECT" {
		c.SetHeader("Content-Type", "text/plain; charset=utf-8")
		c.WriteHeader(http.StatusMethodNotAllowed)
		io.WriteString(c, "405 must CONNECT to "+rpcPath+"\n")
		return
	}
	conn, _, err := c.Hijack()
	if err != nil {
		log.Stderr("rpc hijacking ", c.RemoteAddr, ": ", err.String())
		return
	}
	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
	ServeConn(conn)
}

// HandleHTTP registers an HTTP handler for RPC messages.
// It is still necessary to invoke http.Serve(), typically in a go statement.
func HandleHTTP() {
	http.Handle(rpcPath, http.HandlerFunc(serveHTTP))
	http.Handle(debugPath, http.HandlerFunc(debugHTTP))
}
