func Start(m *PluginMeta, c Plugin, requestString string) (error, int) {
	s, sErr, retCode := NewSessionState(requestString, c, m)
	if sErr != nil {
		return sErr, retCode
	}
	var (
		r        *Response
		exitCode int = 0
	)
	switch m.Type {
	case CollectorPluginType:
		proxy := &collectorPluginProxy{
			Plugin:  c.(CollectorPlugin),
			Session: s,
		}
		rpc.RegisterName("Collector", proxy)
		r = &Response{
			Type:  CollectorPluginType,
			State: PluginSuccess,
			Meta:  *m,
		}
		if !m.Unsecure {
			r.PublicKey = &s.privateKey.PublicKey
		}
	case PublisherPluginType:
		r = &Response{
			Type:  PublisherPluginType,
			State: PluginSuccess,
			Meta:  *m,
		}
		if !m.Unsecure {
			r.PublicKey = &s.privateKey.PublicKey
		}
		proxy := &publisherPluginProxy{
			Plugin:  c.(PublisherPlugin),
			Session: s,
		}
		rpc.RegisterName("Publisher", proxy)
	case ProcessorPluginType:
		r = &Response{
			Type:  ProcessorPluginType,
			State: PluginSuccess,
			Meta:  *m,
		}
		if !m.Unsecure {
			r.PublicKey = &s.privateKey.PublicKey
		}
		proxy := &processorPluginProxy{
			Plugin:  c.(ProcessorPlugin),
			Session: s,
		}
		rpc.RegisterName("Processor", proxy)
	}
	e := rpc.Register(s)
	if e != nil {
		if e.Error() != "rpc: service already defined: SessionState" {
			s.Logger().Error(e.Error())
			return e, 2
		}
	}
	l, err := net.Listen("tcp", "127.0.0.1:"+s.ListenPort())
	if err != nil {
		s.Logger().Error(err.Error())
		panic(err)
	}
	s.SetListenAddress(l.Addr().String())
	s.Logger().Debugf("Listening %s\n", l.Addr())
	s.Logger().Debugf("Session token %s\n", s.Token())
	switch r.Meta.RPCType {
	case NativeRPC:
		go func() {
			for {
				conn, err := l.Accept()
				if err != nil {
					panic(err)
				}
				go rpc.ServeConn(conn)
			}
		}()
	default:
		panic("Unsupported RPC type")
	}
	resp := s.generateResponse(r)
	fmt.Println(string(resp))
	s.Logger().Println(string(resp))
	go s.heartbeatWatch(s.KillChan())
	if s.isDaemon() {
		exitCode = <-s.KillChan()  
	}
	return nil, exitCode
}
Start starts a plugin where:
PluginMeta - base information about plugin
Plugin - CollectorPlugin, ProcessorPlugin or PublisherPlugin
requestString - plugins arguments (marshaled json of control/plugin Arg struct)
returns an error and exitCode (exitCode from SessionState initialization or plugin termination code)
package plugin
import (
	"fmt"
	"net"
	"net/rpc"
	"regexp"
	"runtime"
	"time"
	log "github.com/sirupsen/logrus"
)
var (
	PingTimeoutLimit = 3
)
type metaOp func(m *PluginMeta)
func ConcurrencyCount(cc int) metaOp {
	return func(m *PluginMeta) {
		m.ConcurrencyCount = cc
	}
}
func Exclusive(e bool) metaOp {
	return func(m *PluginMeta) {
		m.Exclusive = e
	}
}
func Unsecure(e bool) metaOp {
	return func(m *PluginMeta) {
		m.Unsecure = e
	}
}
func RoutingStrategy(r RoutingStrategyType) metaOp {
	return func(m *PluginMeta) {
		m.RoutingStrategy = r
	}
}
func CacheTTL(t time.Duration) metaOp {
	return func(m *PluginMeta) {
		m.CacheTTL = t
	}
}
func NewPluginMeta(name string, version int, pluginType PluginType, acceptContentTypes, returnContentTypes []string, opts ...metaOp) *PluginMeta {
	if len(acceptContentTypes) == 0 {
		acceptContentTypes = append(acceptContentTypes, "snap.*")
	}
	for _, s := range acceptContentTypes {
		b, e := regexp.MatchString(`^[a-z0-9*]+\.[a-z0-9*]+$`, s)
		if e != nil {
			panic(e)
		}
		if !b {
			panic(fmt.Sprintf("Bad accept content type [%s] for [%d] [%s]", name, version, s))
		}
	}
	for _, s := range returnContentTypes {
		b, e := regexp.MatchString(`^[a-z0-9*]+\.[a-z0-9*]+$`, s)
		if e != nil {
			panic(e)
		}
		if !b {
			panic(fmt.Sprintf("Bad return content type [%s] for [%d] [%s]", name, version, s))
		}
	}
	p := &PluginMeta{
		Name:                 name,
		Version:              version,
		Type:                 pluginType,
		AcceptedContentTypes: acceptContentTypes,
		ReturnedContentTypes: returnContentTypes,
		ConcurrencyCount: 1,
	}
	for _, opt := range opts {
		opt(p)
	}
	return p
}