protocols/udp/udp.go (56 lines of code) (raw):

/* Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. */ package udp import ( "errors" "fmt" "net" "strconv" "time" "github.com/facebookincubator/fbender/log" "github.com/pinterest/bender" ) // MaxResponseSize is the max response size for UDP test. const MaxResponseSize = 2048 // Datagram represents a udp datagram to be sent. type Datagram struct { Port int Data []byte } // ErrInvalidType is raised when object type mismatch. var ErrInvalidType = errors.New("invalid type") // ResponseValidator validates a udp response. type ResponseValidator func(request *Datagram, response []byte) error // CreateExecutor creates a new UDP RequestExecutor. func CreateExecutor(timeout time.Duration, validator ResponseValidator, hosts ...string) bender.RequestExecutor { var i int return func(_ int64, request interface{}) (interface{}, error) { datagram, ok := request.(*Datagram) if !ok { return nil, fmt.Errorf("%w, want: *Datagram, got: %T", ErrInvalidType, request) } addr := net.JoinHostPort(hosts[i], strconv.Itoa(datagram.Port)) i = (i + 1) % len(hosts) // Setup connection conn, err := net.Dial("udp", addr) if err != nil { //nolint:wrapcheck return nil, err } defer func() { if err = conn.Close(); err != nil { log.Errorf("Error closing connection: %v\n", err) } }() if err = conn.SetWriteDeadline(time.Now().Add(timeout)); err != nil { //nolint:wrapcheck return nil, err } _, err = conn.Write(datagram.Data) if err != nil { //nolint:wrapcheck return nil, err } buffer := make([]byte, MaxResponseSize) if err = conn.SetReadDeadline(time.Now().Add(timeout)); err != nil { //nolint:wrapcheck return nil, err } n, err := conn.Read(buffer) if err != nil { //nolint:wrapcheck return nil, err } if err = validator(datagram, buffer[:n]); err != nil { return nil, err } return buffer[:n], nil } }