github.com/criyle/go-sandbox@v0.10.3/container/socket_linux.go (about)

     1  package container
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/gob"
     6  	"fmt"
     7  
     8  	"github.com/criyle/go-sandbox/pkg/unixsocket"
     9  )
    10  
    11  // 16k buffer size
    12  const bufferSize = 16 << 10
    13  
    14  type socket struct {
    15  	*unixsocket.Socket
    16  
    17  	buff []byte
    18  
    19  	decoder  *gob.Decoder
    20  	recvBuff bufferRotator
    21  
    22  	encoder  *gob.Encoder
    23  	sendBuff bytes.Buffer
    24  }
    25  
    26  // bufferRotator replace the underlying Buffers to avoid allocation
    27  type bufferRotator struct {
    28  	*bytes.Buffer
    29  }
    30  
    31  func (b *bufferRotator) Rotate(buffer *bytes.Buffer) {
    32  	b.Buffer = buffer
    33  }
    34  
    35  func newSocket(s *unixsocket.Socket) *socket {
    36  	soc := socket{
    37  		Socket: s,
    38  	}
    39  	soc.buff = make([]byte, bufferSize)
    40  	soc.decoder = gob.NewDecoder(&soc.recvBuff)
    41  	soc.encoder = gob.NewEncoder(&soc.sendBuff)
    42  
    43  	return &soc
    44  }
    45  
    46  func (s *socket) RecvMsg(e interface{}) (msg unixsocket.Msg, err error) {
    47  	n, msg, err := s.Socket.RecvMsg(s.buff)
    48  	if err != nil {
    49  		return msg, fmt.Errorf("RecvMsg: %v", err)
    50  	}
    51  	s.recvBuff.Rotate(bytes.NewBuffer(s.buff[:n]))
    52  
    53  	if err := s.decoder.Decode(e); err != nil {
    54  		return msg, fmt.Errorf("RecvMsg: failed to decode %v", err)
    55  	}
    56  	return msg, nil
    57  }
    58  
    59  func (s *socket) SendMsg(e interface{}, msg unixsocket.Msg) error {
    60  	s.sendBuff.Reset()
    61  	if err := s.encoder.Encode(e); err != nil {
    62  		return fmt.Errorf("SendMsg: failed to encode %v", err)
    63  	}
    64  
    65  	if err := s.Socket.SendMsg(s.sendBuff.Bytes(), msg); err != nil {
    66  		return fmt.Errorf("SendMsg: failed to SendMsg %v", err)
    67  	}
    68  	return nil
    69  }