func (msg *message) SetBody(body string, setContentLength bool) {
	msg.mu.Lock()
	msg.body = body
	msg.mu.Unlock()
	if setContentLength {
		hdrs := msg.GetHeaders("Content-Length")
		if len(hdrs) == 0 {
			length := ContentLength(len(body))
			msg.AppendHeader(&length)
		} else {
			length := ContentLength(len(body))
			msg.ReplaceHeaders("Content-Length", []Header{&length})
		}
	}
}
SetBody sets message body, calculates it length and add 'Content-Length' header.
package sip
import (
	"bytes"
	"strings"
	"sync"
	uuid "github.com/satori/go.uuid"
	"github.com/ghettovoice/gosip/log"
)
type RequestMethod string
type StatusCode uint16
func (method *RequestMethod) Equals(other *RequestMethod) bool {
	if method != nil && other != nil {
		return strings.EqualFold(string(*method), string(*other))
	} else {
		return method == other
	}
}
const (
	INVITE    RequestMethod = "INVITE"
	ACK       RequestMethod = "ACK"
	CANCEL    RequestMethod = "CANCEL"
	BYE       RequestMethod = "BYE"
	REGISTER  RequestMethod = "REGISTER"
	OPTIONS   RequestMethod = "OPTIONS"
	SUBSCRIBE RequestMethod = "SUBSCRIBE"
	NOTIFY    RequestMethod = "NOTIFY"
	REFER     RequestMethod = "REFER"
	INFO      RequestMethod = "INFO"
	MESSAGE   RequestMethod = "MESSAGE"
	PRACK     RequestMethod = "PRACK"
	UPDATE    RequestMethod = "UPDATE"
	PUBLISH   RequestMethod = "PUBLISH"
)
type MessageID string
func NextMessageID() MessageID {
	return MessageID(uuid.Must(uuid.NewV4()).String())
}
type Message interface {
	MessageID() MessageID
	Clone() Message
	StartLine() string
	String() string
	Short() string
	SipVersion() string
	SetSipVersion(version string)
	Headers() []Header
	GetHeaders(name string) []Header
	AppendHeader(header Header)
	PrependHeader(header Header)
	PrependHeaderAfter(header Header, afterName string)
	RemoveHeader(name string)
	ReplaceHeaders(name string, headers []Header)
	Body() string
	SetBody(body string, setContentLength bool)
	CallID() (*CallID, bool)
	Via() (ViaHeader, bool)
	ViaHop() (*ViaHop, bool)
	From() (*FromHeader, bool)
	To() (*ToHeader, bool)
	CSeq() (*CSeq, bool)
	ContentLength() (*ContentLength, bool)
	ContentType() (*ContentType, bool)
	Contact() (*ContactHeader, bool)
	Transport() string
	SetTransport(tp string)
	Source() string
	SetSource(src string)
	Destination() string
	SetDestination(dest string)
	IsCancel() bool
	IsAck() bool
	Fields() log.Fields
	WithFields(fields log.Fields) Message
}
type headers struct {
	mu sync.RWMutex
	headers map[string][]Header
	headerOrder []string
}
func newHeaders(hdrs []Header) *headers {
	hs := new(headers)
	hs.headers = make(map[string][]Header)
	hs.headerOrder = make([]string, 0)
	for _, header := range hdrs {
		hs.AppendHeader(header)
	}
	return hs
}
func (hs *headers) String() string {
	buffer := bytes.Buffer{}
	hs.mu.RLock()
	for typeIdx, name := range hs.headerOrder {
		headers := hs.headers[name]
		for idx, header := range headers {
			buffer.WriteString(header.String())
			if typeIdx < len(hs.headerOrder) || idx < len(headers) {
				buffer.WriteString("\r\n")
			}
		}
	}
	hs.mu.RUnlock()
	return buffer.String()
}
func (hs *headers) AppendHeader(header Header) {
	name := strings.ToLower(header.Name())
	hs.mu.Lock()
	if _, ok := hs.headers[name]; ok {
		hs.headers[name] = append(hs.headers[name], header)
	} else {
		hs.headers[name] = []Header{header}
		hs.headerOrder = append(hs.headerOrder, name)
	}
	hs.mu.Unlock()
}
func (hs *headers) PrependHeader(header Header) {
	name := strings.ToLower(header.Name())
	hs.mu.Lock()
	if hdrs, ok := hs.headers[name]; ok {
		hs.headers[name] = append([]Header{header}, hdrs...)
	} else {
		hs.headers[name] = []Header{header}
		newOrder := make([]string, 1, len(hs.headerOrder)+1)
		newOrder[0] = name
		hs.headerOrder = append(newOrder, hs.headerOrder...)
	}
	hs.mu.Unlock()
}
func (hs *headers) PrependHeaderAfter(header Header, afterName string) {
	headerName := strings.ToLower(header.Name())
	afterName = strings.ToLower(afterName)
	hs.mu.Lock()
	if _, ok := hs.headers[afterName]; ok {
		afterIdx := -1
		headerIdx := -1
		for i, name := range hs.headerOrder {
			if name == afterName {
				afterIdx = i
			}
			if name == headerName {
				headerIdx = i
			}
		}
		if headerIdx == -1 {
			hs.headers[headerName] = []Header{header}
			newOrder := make([]string, 0)
			newOrder = append(newOrder, hs.headerOrder[:afterIdx+1]...)
			newOrder = append(newOrder, headerName)
			newOrder = append(newOrder, hs.headerOrder[afterIdx+1:]...)
			hs.headerOrder = newOrder
		} else {
			hs.headers[headerName] = append([]Header{header}, hs.headers[headerName]...)
			newOrder := make([]string, 0)
			if afterIdx < headerIdx {
				newOrder = append(newOrder, hs.headerOrder[:afterIdx+1]...)
				newOrder = append(newOrder, headerName)
				newOrder = append(newOrder, hs.headerOrder[afterIdx+1:headerIdx]...)
				newOrder = append(newOrder, hs.headerOrder[headerIdx+1:]...)
			} else {
				newOrder = append(newOrder, hs.headerOrder[:headerIdx]...)
				newOrder = append(newOrder, hs.headerOrder[headerIdx+1:afterIdx+1]...)
				newOrder = append(newOrder, headerName)
				newOrder = append(newOrder, hs.headerOrder[afterIdx+1:]...)
			}
			hs.headerOrder = newOrder
		}
		hs.mu.Unlock()
	} else {
		hs.mu.Unlock()
		hs.PrependHeader(header)
	}
}
func (hs *headers) ReplaceHeaders(name string, headers []Header) {
	name = strings.ToLower(name)
	hs.mu.Lock()
	if _, ok := hs.headers[name]; ok {
		hs.headers[name] = headers
	}
	hs.mu.Unlock()
}
func (hs *headers) Headers() []Header {
	hdrs := make([]Header, 0)
	hs.mu.RLock()
	for _, key := range hs.headerOrder {
		hdrs = append(hdrs, hs.headers[key]...)
	}
	hs.mu.RUnlock()
	return hdrs
}
func (hs *headers) GetHeaders(name string) []Header {
	name = strings.ToLower(name)
	hs.mu.RLock()
	defer hs.mu.RUnlock()
	if hs.headers == nil {
		hs.headers = map[string][]Header{}
		hs.headerOrder = []string{}
	}
	if headers, ok := hs.headers[name]; ok {
		return headers
	}
	return []Header{}
}
func (hs *headers) RemoveHeader(name string) {
	name = strings.ToLower(name)
	hs.mu.Lock()
	delete(hs.headers, name)
	for idx, entry := range hs.headerOrder {
		if entry == name {
			hs.headerOrder = append(hs.headerOrder[:idx], hs.headerOrder[idx+1:]...)
			break
		}
	}
	hs.mu.Unlock()
}
func (hs *headers) CloneHeaders() []Header {
	return cloneHeaders(hs)
}
func cloneHeaders(msg interface{ Headers() []Header }) []Header {
	hdrs := make([]Header, 0)
	for _, header := range msg.Headers() {
		hdrs = append(hdrs, header.Clone())
	}
	return hdrs
}
func (hs *headers) CallID() (*CallID, bool) {
	hdrs := hs.GetHeaders("Call-ID")
	if len(hdrs) == 0 {
		return nil, false
	}
	callId, ok := hdrs[0].(*CallID)
	if !ok {
		return nil, false
	}
	return callId, true
}
func (hs *headers) Via() (ViaHeader, bool) {
	hdrs := hs.GetHeaders("Via")
	if len(hdrs) == 0 {
		return nil, false
	}
	via, ok := (hdrs[0]).(ViaHeader)
	if !ok {
		return nil, false
	}
	return via, true
}
func (hs *headers) ViaHop() (*ViaHop, bool) {
	via, ok := hs.Via()
	if !ok {
		return nil, false
	}
	hops := []*ViaHop(via)
	if len(hops) == 0 {
		return nil, false
	}
	return hops[0], true
}
func (hs *headers) From() (*FromHeader, bool) {
	hdrs := hs.GetHeaders("From")
	if len(hdrs) == 0 {
		return nil, false
	}
	from, ok := hdrs[0].(*FromHeader)
	if !ok {
		return nil, false
	}
	return from, true
}
func (hs *headers) To() (*ToHeader, bool) {
	hdrs := hs.GetHeaders("To")
	if len(hdrs) == 0 {
		return nil, false
	}
	to, ok := hdrs[0].(*ToHeader)
	if !ok {
		return nil, false
	}
	return to, true
}
func (hs *headers) CSeq() (*CSeq, bool) {
	hdrs := hs.GetHeaders("CSeq")
	if len(hdrs) == 0 {
		return nil, false
	}
	cseq, ok := hdrs[0].(*CSeq)
	if !ok {
		return nil, false
	}
	return cseq, true
}
func (hs *headers) ContentLength() (*ContentLength, bool) {
	hdrs := hs.GetHeaders("Content-Length")
	if len(hdrs) == 0 {
		return nil, false
	}
	contentLength, ok := hdrs[0].(*ContentLength)
	if !ok {
		return nil, false
	}
	return contentLength, true
}
func (hs *headers) ContentType() (*ContentType, bool) {
	hdrs := hs.GetHeaders("Content-Type")
	if len(hdrs) == 0 {
		return nil, false
	}
	contentType, ok := hdrs[0].(*ContentType)
	if !ok {
		return nil, false
	}
	return contentType, true
}
func (hs *headers) Contact() (*ContactHeader, bool) {
	hdrs := hs.GetHeaders("Contact")
	if len(hdrs) == 0 {
		return nil, false
	}
	contactHeader, ok := hdrs[0].(*ContactHeader)
	if !ok {
		return nil, false
	}
	return contactHeader, true
}
type message struct {
	*headers
	mu         sync.RWMutex
	messID     MessageID
	sipVersion string
	body       string
	startLine  func() string
	tp         string
	src        string
	dest       string
	fields     log.Fields
}
func (msg *message) MessageID() MessageID {
	return msg.messID
}
func (msg *message) StartLine() string {
	return msg.startLine()
}
func (msg *message) Fields() log.Fields {
	msg.mu.RLock()
	defer msg.mu.RUnlock()
	return msg.fields.WithFields(log.Fields{
		"transport":   msg.tp,
		"source":      msg.src,
		"destination": msg.dest,
	})
}
func (msg *message) String() string {
	var buffer bytes.Buffer
	buffer.WriteString(msg.StartLine() + "\r\n")
	msg.mu.RLock()
	buffer.WriteString(msg.headers.String())
	msg.mu.RUnlock()
	buffer.WriteString("\r\n" + msg.Body())
	return buffer.String()
}
func (msg *message) SipVersion() string {
	msg.mu.RLock()
	defer msg.mu.RUnlock()
	return msg.sipVersion
}
func (msg *message) SetSipVersion(version string) {
	msg.mu.Lock()
	msg.sipVersion = version
	msg.mu.Unlock()
}
func (msg *message) Body() string {
	msg.mu.RLock()
	defer msg.mu.RUnlock()
	return msg.body
}