github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/synchronization/compression/handshake.go (about) 1 package compression 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 ) 8 9 // errAlgorithmUnsupported indicates that the algorithm requested by the client 10 // is unsupported by the server. 11 var errAlgorithmUnsupported = errors.New("algorithm unsupported") 12 13 // ClientHandshake performs a client-side compression handshake on the stream. 14 // It transmits the desired compression algorithm and verifies that this 15 // algorithm is supported by the server. 16 func ClientHandshake(stream io.ReadWriter, algorithm Algorithm) error { 17 // Verify that the algorithm can be encoded into a single byte. 18 if algorithm < 0 || algorithm > 255 { 19 return errors.New("invalid algorithm value") 20 } 21 22 // Convert the algorithm specification. 23 data := [1]byte{byte(algorithm)} 24 25 // Transmit the data. 26 if _, err := stream.Write(data[:]); err != nil { 27 return fmt.Errorf("unable to transmit algorithm specification: %w", err) 28 } 29 30 // Receive the response. 31 if _, err := io.ReadFull(stream, data[:]); err != nil { 32 return fmt.Errorf("unable to receive response: %w", err) 33 } 34 35 // Handle the response. 36 switch data[0] { 37 case 0: 38 return errAlgorithmUnsupported 39 case 1: 40 return nil 41 default: 42 return errors.New("invalid response from server") 43 } 44 } 45 46 // ServerHandshake performs a server-side compression handshake on the stream. 47 // It receives the desired compression algorithm from the client, verifies that 48 // this algorithm is supported, and transmits a response to the client. 49 func ServerHandshake(stream io.ReadWriter) (Algorithm, error) { 50 // Receive the algorithm specification. 51 var data [1]byte 52 if _, err := io.ReadFull(stream, data[:]); err != nil { 53 return Algorithm_AlgorithmDefault, fmt.Errorf("unable to receive algorithm specification: %w", err) 54 } 55 56 // Convert the algorithm specification and ensure that it's supported. 57 algorithm := Algorithm(data[0]) 58 supported := algorithm.SupportStatus() == AlgorithmSupportStatusSupported 59 60 // Format and transmit the response. 61 if supported { 62 data[0] = 1 63 } else { 64 data[0] = 0 65 } 66 if _, err := stream.Write(data[:]); err != nil { 67 return Algorithm_AlgorithmDefault, fmt.Errorf("unable to transmit response: %w", err) 68 } 69 70 // Handle unsupported algorithms. 71 if !supported { 72 return Algorithm_AlgorithmDefault, errAlgorithmUnsupported 73 } 74 75 // Success. 76 return algorithm, nil 77 }