// 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 receiver and name are publicly visible, that is, begin with an upper case letter.
		- the method has two arguments, both pointers to publicly visible types.
		- 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 pointer containing the arguments, and a pointer 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 Quotient struct {
			Quo, Rem int
		}

		type Arith int

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

		func (t *Arith) Divide(args *Args, quo *Quotient) os.Error {
			if args.B == 0 {
				return os.ErrorString("divide by zero")
			}
			quo.Quo = args.A / args.B
			quo.Rem = 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}
		var reply int
		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)

	or

		// Asynchronous call
		quotient := new(Quotient)
		divCall := client.Go("Arith.Divide", args, &quotient, 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.
}

// ClientInfo records information about an RPC client connection.
type ClientInfo struct {
	LocalAddr  string
	RemoteAddr string
}

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 s.typ.PkgPath() != "" && !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 mtype.PkgPath() != "" && !isPublic(mname) {
			continue
		}
		// Method needs three ins: receiver, *args, *reply.
		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
		}
		replyType, ok := mtype.In(2).(*reflect.PtrType)
		if !ok {
			log.Stderr(mname, "reply type not a pointer:", mtype.In(2))
			continue
		}
		if argType.Elem().PkgPath() != "" && !isPublic(argType.Elem().Name()) {
			log.Stderr(mname, "argument type not public:", argType)
			continue
		}
		if replyType.Elem().PkgPath() != "" && !isPublic(replyType.Elem().Name()) {
			log.Stderr(mname, "reply type not public:", replyType)
			continue
		}
		if mtype.NumIn() == 4 {
			t := mtype.In(3)
			if t != reflect.Typeof((*ClientInfo)(nil)) {
				log.Stderr(mname, "last argument not *ClientInfo")
				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, ".", -1)
		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))
}
