package rpc import "lux/proto" // FSM to handle TCP-window split XML packets const LUX_XML_REQUEST_BEGIN = "= tagLen { return string(slice[:tagLen]) == tag } return false } // will return true if data is complete func (def *LuxRpcDefrag) Feed(data []byte) bool { // try find tag opening at beginning if def.state == defragStateOff { for i := 0; i < len(data); i++ { slice := data[i:] if matchTag(slice, LUX_XML_REQUEST_BEGIN) { def.state = defragStateReadingRequest def.beginOff = i + len(LUX_XML_REQUEST_BEGIN) break } else if matchTag(slice, LUX_XML_RESPONSE_BEGIN) { def.state = defragStateReadingResponse def.beginOff = i + len(LUX_XML_RESPONSE_BEGIN) break } else if matchTag(slice, LUX_XML_ERROR_BEGIN) { def.state = defragStateReadingError def.beginOff = i + len(LUX_XML_ERROR_BEGIN) break } } } // now check if slice has ending tag, if so - complete data if def.state >= defragStateReading { for i := def.beginOff; i < len(data); i++ { slice := data[i:] if matchTag(slice, LUX_XML_REQUEST_END) { def.state = defragStateHasRequest def.endOff = i + len(LUX_XML_REQUEST_END) break } else if matchTag(slice, LUX_XML_RESPONSE_END) { def.state = defragStateHasResponse def.endOff = i + len(LUX_XML_RESPONSE_END) break } else if matchTag(slice, LUX_XML_ERROR_END) { def.state = defragStateHasError def.endOff = i + len(LUX_XML_ERROR_END) break } } // got end tag? push exact 0:endOff slice if def.state >= defragStateHasData { def.buffer.WriteBytes(data[:def.endOff]) return true // we got complete data! } else { // if there is no end tag, then reset beginOff so it wont // confuse next Feed call def.beginOff = 0 } } // push whatever data is def.buffer.WriteBytes(data) return false } func (def *LuxRpcDefrag) GetAndForget() []byte { data := def.buffer.AllBytes() // reset state def.buffer = proto.NewLuxBuffer() def.state = defragStateOff def.beginOff = 0 def.endOff = 0 return data }