func (this *Pinger) marshalMessage(m *icmp.Message, p []byte) ([]byte, error) {
	if m.Type.Protocol() == ProtocolIPv6ICMP {
		return nil, fmt.Errorf("ping/marshalMessage: IPv6 not yet supported")
	}

	var mtype, proto int
	switch typ := m.Type.(type) {
	case ipv4.ICMPType:
		mtype = int(typ)
		proto = ProtocolICMP
	case ipv6.ICMPType:
		mtype = int(typ)
		proto = ProtocolIPv6ICMP
	default:
		return nil, syscall.EINVAL
	}

	// http://en.wikipedia.org/wiki/Ping_(networking_utility)
	// 1 byte Type
	// 1 byte Code
	// 2 bytes checksum
	total := 4 + m.Body.Len(proto)
	if cap(p) < total {
		p = make([]byte, total)
	}
	p = p[0:total]

	// p[0] is the Type
	// p[1] is the Code
	// p[2,3] is the checksum, which is not set yet
	p[0], p[1], p[2], p[3] = byte(mtype), byte(m.Code), 0, 0

	// Copy the echo message
	if m.Body != nil && m.Body.Len(proto) != 0 {
		er, ok := m.Body.(*icmp.Echo)
		if !ok {
			return nil, fmt.Errorf("ping/marshalMessage: Error type requireing m.Body to *icmp.Echo")
		}

		p[4], p[5] = byte(er.ID>>8), byte(er.ID)
		p[6], p[7] = byte(er.Seq>>8), byte(er.Seq)
		copy(p[8:], er.Data)
	}

	csumcv := len(p) - 1 // checksum coverage
	s := uint32(0)

	for i := 0; i < csumcv; i += 2 {
		s += uint32(p[i+1])<<8 | uint32(p[i])
	}

	if csumcv&1 == 0 {
		s += uint32(p[csumcv])
	}

	s = s>>16 + s&0xffff
	s = s + s>>16

	// Place checksum back in header; using ^= avoids the
	// assumption the checksum bytes are zero.
	p[2] ^= byte(^s)
	p[3] ^= byte(^s >> 8)

	return p, nil
}
// marshalMessage encodes an icmp.Message into the supplied buffer p. If p has enough
// capacity, then it will be used. If p does not have enough capacity, then a new
// buffer will be allocated. The updated buffer, p or the new one, will be returned
// and the length will be set to the length of the echo message.
marshalMessage encodes an icmp.Message into the supplied buffer p. If p has enough
capacity, then it will be used. If p does not have enough capacity, then a new
buffer will be allocated. The updated buffer, p or the new one, will be returned
and the length will be set to the length of the echo message.
// marshalMessage encodes an icmp . Message into the supplied buffer p . If p has enough // capacity then it will be used . If p does not have enough capacity then a new // buffer will be allocated . The updated buffer p or the new one will be returned // and the length will be set to the length of the echo message .
func (this *Pinger) marshalMessage(m *icmp.Message, p []byte) ([]byte, error) {
	if m.Type.Protocol() == ProtocolIPv6ICMP {
		return nil, fmt.Errorf("ping/marshalMessage: IPv6 not yet supported")
	}
	var mtype, proto int
	switch typ := m.Type.(type) {
	case ipv4.ICMPType:
		mtype = int(typ)
		proto = ProtocolICMP
	case ipv6.ICMPType:
		mtype = int(typ)
		proto = ProtocolIPv6ICMP
	default:
		return nil, syscall.EINVAL
	}
	total := 4 + m.Body.Len(proto)
	if cap(p) < total {
		p = make([]byte, total)
	}
	p = p[0:total]
	p[0], p[1], p[2], p[3] = byte(mtype), byte(m.Code), 0, 0
	if m.Body != nil && m.Body.Len(proto) != 0 {
		er, ok := m.Body.(*icmp.Echo)
		if !ok {
			return nil, fmt.Errorf("ping/marshalMessage: Error type requireing m.Body to *icmp.Echo")
		}
		p[4], p[5] = byte(er.ID>>8), byte(er.ID)
		p[6], p[7] = byte(er.Seq>>8), byte(er.Seq)
		copy(p[8:], er.Data)
	}
	csumcv := len(p) - 1 
	s := uint32(0)
	for i := 0; i < csumcv; i += 2 {
		s += uint32(p[i+1])<<8 | uint32(p[i])
	}
	if csumcv&1 == 0 {
		s += uint32(p[csumcv])
	}
	s = s>>16 + s&0xffff
	s = s + s>>16
	p[2] ^= byte(^s)
	p[3] ^= byte(^s >> 8)
	return p, nil
}
func ( this * Pinger ) marshalMessage ( m * icmp . Message , p [ ] byte ) ( [ ] byte , error ) { if m . Type . Protocol ( ) == ProtocolIPv6ICMP { return nil , fmt . Errorf ( " " ) } var mtype , proto int switch typ := m . Type . ( type ) { case ipv4 . ICMPType : mtype = int ( typ ) proto = ProtocolICMP case ipv6 . ICMPType : mtype = int ( typ ) proto = ProtocolIPv6ICMP default : return nil , syscall . EINVAL } total := 4 + m . Body . Len ( proto ) if cap ( p ) < total { p = make ( [ ] byte , total ) } p = p [ 0 : total ] p [ 0 ] , p [ 1 ] , p [ 2 ] , p [ 3 ] = byte ( mtype ) , byte ( m . Code ) , 0 , 0 if m . Body != nil && m . Body . Len ( proto ) != 0 { er , ok := m . Body . ( * icmp . Echo ) if ! ok { return nil , fmt . Errorf ( " " ) } p [ 4 ] , p [ 5 ] = byte ( er . ID >> 8 ) , byte ( er . ID ) p [ 6 ] , p [ 7 ] = byte ( er . Seq >> 8 ) , byte ( er . Seq ) copy ( p [ 8 : ] , er . Data ) } csumcv := len ( p ) - 1 s := uint32 ( 0 ) for i := 0 ; i < csumcv ; i += 2 { s += uint32 ( p [ i + 1 ] ) << 8 | uint32 ( p [ i ] ) } if csumcv & 1 == 0 { s += uint32 ( p [ csumcv ] ) } s = s >> 16 + s & 0xffff s = s + s >> 16 p [ 2 ] ^= byte ( ^ s ) p [ 3 ] ^= byte ( ^ s >> 8 ) return p , nil }
marshalMessage encodes an icmp.Message into the supplied buffer p. If p has enough
capacity, then it will be used.
marshalMessage encodes an icmp . Message into the supplied buffer p . If p has enough capacity then it will be used .
// http://en.wikipedia.org/wiki/Ping_(networking_utility) // 1 byte Type // 1 byte Code // 2 bytes checksum // p[0] is the Type // p[1] is the Code // p[2,3] is the checksum, which is not set yet // Copy the echo message // checksum coverage // Place checksum back in header; using ^= avoids the // assumption the checksum bytes are zero.