github.com/rbisecke/kafka-go@v0.4.27/protocol/response.go (about) 1 package protocol 2 3 import ( 4 "fmt" 5 "io" 6 ) 7 8 func ReadResponse(r io.Reader, apiKey ApiKey, apiVersion int16) (correlationID int32, msg Message, err error) { 9 if i := int(apiKey); i < 0 || i >= len(apiTypes) { 10 err = fmt.Errorf("unsupported api key: %d", i) 11 return 12 } 13 14 t := &apiTypes[apiKey] 15 if t == nil { 16 err = fmt.Errorf("unsupported api: %s", apiNames[apiKey]) 17 return 18 } 19 20 minVersion := t.minVersion() 21 maxVersion := t.maxVersion() 22 23 if apiVersion < minVersion || apiVersion > maxVersion { 24 err = fmt.Errorf("unsupported %s version: v%d not in range v%d-v%d", apiKey, apiVersion, minVersion, maxVersion) 25 return 26 } 27 28 d := &decoder{reader: r, remain: 4} 29 size := d.readInt32() 30 31 if err = d.err; err != nil { 32 err = dontExpectEOF(err) 33 return 34 } 35 36 d.remain = int(size) 37 correlationID = d.readInt32() 38 39 res := &t.responses[apiVersion-minVersion] 40 41 if res.flexible { 42 // In the flexible case, there's a tag buffer at the end of the response header 43 taggedCount := int(d.readUnsignedVarInt()) 44 for i := 0; i < taggedCount; i++ { 45 d.readUnsignedVarInt() // tagID 46 size := d.readUnsignedVarInt() 47 48 // Just throw away the values for now 49 d.read(int(size)) 50 } 51 } 52 53 msg = res.new() 54 res.decode(d, valueOf(msg)) 55 d.discardAll() 56 57 if err = d.err; err != nil { 58 err = dontExpectEOF(err) 59 } 60 61 return 62 } 63 64 func WriteResponse(w io.Writer, apiVersion int16, correlationID int32, msg Message) error { 65 apiKey := msg.ApiKey() 66 67 if i := int(apiKey); i < 0 || i >= len(apiTypes) { 68 return fmt.Errorf("unsupported api key: %d", i) 69 } 70 71 t := &apiTypes[apiKey] 72 if t == nil { 73 return fmt.Errorf("unsupported api: %s", apiNames[apiKey]) 74 } 75 76 minVersion := t.minVersion() 77 maxVersion := t.maxVersion() 78 79 if apiVersion < minVersion || apiVersion > maxVersion { 80 return fmt.Errorf("unsupported %s version: v%d not in range v%d-v%d", apiKey, apiVersion, minVersion, maxVersion) 81 } 82 83 r := &t.responses[apiVersion-minVersion] 84 v := valueOf(msg) 85 b := newPageBuffer() 86 defer b.unref() 87 88 e := &encoder{writer: b} 89 e.writeInt32(0) // placeholder for the response size 90 e.writeInt32(correlationID) 91 if r.flexible { 92 // Flexible messages use extra space for a tag buffer, 93 // which begins with a size value. Since we're not writing any fields into the 94 // latter, we can just write zero for now. 95 // 96 // See 97 // https://cwiki.apache.org/confluence/display/KAFKA/KIP-482%3A+The+Kafka+Protocol+should+Support+Optional+Tagged+Fields 98 // for details. 99 e.writeUnsignedVarInt(0) 100 } 101 r.encode(e, v) 102 err := e.err 103 104 if err == nil { 105 size := packUint32(uint32(b.Size()) - 4) 106 b.WriteAt(size[:], 0) 107 _, err = b.WriteTo(w) 108 } 109 110 return err 111 }