package ipv4
import (
"net"
"golang.org/x/net/internal/socket"
)
type packetHandler struct {
*net .IPConn
*socket .Conn
rawOpt
}
func (c *packetHandler ) ok () bool { return c != nil && c .IPConn != nil && c .Conn != nil }
func (c *packetHandler ) ReadFrom (b []byte ) (h *Header , p []byte , cm *ControlMessage , err error ) {
if !c .ok () {
return nil , nil , nil , errInvalidConn
}
c .rawOpt .RLock ()
m := socket .Message {
Buffers : [][]byte {b },
OOB : NewControlMessage (c .rawOpt .cflags ),
}
c .rawOpt .RUnlock ()
if err := c .RecvMsg (&m , 0 ); err != nil {
return nil , nil , nil , &net .OpError {Op : "read" , Net : c .IPConn .LocalAddr ().Network (), Source : c .IPConn .LocalAddr (), Err : err }
}
var hs []byte
if hs , p , err = slicePacket (b [:m .N ]); err != nil {
return nil , nil , nil , &net .OpError {Op : "read" , Net : c .IPConn .LocalAddr ().Network (), Source : c .IPConn .LocalAddr (), Err : err }
}
if h , err = ParseHeader (hs ); err != nil {
return nil , nil , nil , &net .OpError {Op : "read" , Net : c .IPConn .LocalAddr ().Network (), Source : c .IPConn .LocalAddr (), Err : err }
}
if m .NN > 0 {
if compatFreeBSD32 {
adjustFreeBSD32 (&m )
}
cm = new (ControlMessage )
if err := cm .Parse (m .OOB [:m .NN ]); err != nil {
return nil , nil , nil , &net .OpError {Op : "read" , Net : c .IPConn .LocalAddr ().Network (), Source : c .IPConn .LocalAddr (), Err : err }
}
}
if src , ok := m .Addr .(*net .IPAddr ); ok && cm != nil {
cm .Src = src .IP
}
return
}
func slicePacket(b []byte ) (h , p []byte , err error ) {
if len (b ) < HeaderLen {
return nil , nil , errHeaderTooShort
}
hdrlen := int (b [0 ]&0x0f ) << 2
return b [:hdrlen ], b [hdrlen :], nil
}
func (c *packetHandler ) WriteTo (h *Header , p []byte , cm *ControlMessage ) error {
if !c .ok () {
return errInvalidConn
}
m := socket .Message {
OOB : cm .Marshal (),
}
wh , err := h .Marshal ()
if err != nil {
return err
}
m .Buffers = [][]byte {wh , p }
dst := new (net .IPAddr )
if cm != nil {
if ip := cm .Dst .To4 (); ip != nil {
dst .IP = ip
}
}
if dst .IP == nil {
dst .IP = h .Dst
}
m .Addr = dst
if err := c .SendMsg (&m , 0 ); err != nil {
return &net .OpError {Op : "write" , Net : c .IPConn .LocalAddr ().Network (), Source : c .IPConn .LocalAddr (), Addr : opAddr (dst ), Err : err }
}
return nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .