func randomSettingID() http2.SettingID { return http2.SettingID(rand.Intn(6)) }
func main() { filename := "" hostname := "" if len(os.Args) > 2 { filename = os.Args[1] hostname = os.Args[2] } else { fmt.Println("Usage: replay [JSON file] [host:port]\nExiting...") os.Exit(1) } file, err := ioutil.ReadFile(filename) if err != nil { panic(err) } var lines []string lines = strings.Split(string(file), "\n") for _, frameJSON := range lines { if len(frameJSON) < 1 { break } frame := util.FromJSON([]byte(frameJSON)) c := fuzzer.NewConnection(hostname, true, true, true) switch frame["FrameMethod"] { case "RawFrame": fmt.Println(frame) frameType := http2.FrameType(uint8(frame["FrameType"].(float64))) flags := http2.Flags(uint8(frame["Flags"].(float64))) streamID := uint32(frame["StreamID"].(float64)) payload := util.FromBase64(frame["Payload"].(string)) c.Framer.WriteRawFrame(frameType, flags, streamID, payload) case "PingFrame": fmt.Println(frame) data := [8]byte{byte(frame["Byte1"].(float64)), byte(frame["Byte2"].(float64)), byte(frame["Byte3"].(float64)), byte(frame["Byte4"].(float64)), byte(frame["Byte5"].(float64)), byte(frame["Byte6"].(float64)), byte(frame["Byte7"].(float64)), byte(frame["Byte8"].(float64))} fmt.Println("SENDING DATA ", data) c.Framer.WritePing(false, data) case "SettingsFrame": fmt.Println(frame) num_settings := uint32(frame["NumberSettings"].(float64)) settings := []http2.Setting{} for s := uint32(1); s < num_settings; s++ { setting_id := fmt.Sprintf("SettingID_%d", s) setting_val := fmt.Sprintf("SettingVal_%d", s) setting := http2.Setting{ ID: http2.SettingID(frame[setting_id].(float64)), Val: uint32(frame[setting_val].(float64)), } settings = append(settings, setting) } fmt.Println("Settings: ", settings) c.Framer.WriteSettings(settings...) case "PushPromise": fmt.Println(frame) promise := http2.PushPromiseParam{ StreamID: uint32(frame["StreamID"].(float64)), PromiseID: uint32(frame["PromiseID"].(float64)), BlockFragment: util.FromBase64(frame["BlockFragment"].(string)), EndHeaders: bool(frame["EndHeaders"].(bool)), PadLength: uint8(frame["PadLength"].(float64)), } fmt.Println("Push Promise: ", promise) c.Framer.WritePushPromise(promise) case "HeaderFrame": header_frame := http2.HeadersFrameParam{ StreamID: uint32(frame["StreamID"].(float64)), BlockFragment: util.FromBase64(frame["BlockFragment"].(string)), EndStream: bool(frame["EndStream"].(bool)), EndHeaders: bool(frame["EndHeaders"].(bool)), } fmt.Println("Headers: ", header_frame) c.Framer.WriteHeaders(header_frame) case "RawTCPFrame": payload := frame["Payload"].(string) fmt.Println("RawTCP: ", payload) io.WriteString(c.Raw, string(payload)) case "PriorityFrame": priority := http2.PriorityParam{ StreamDep: uint32(frame["StreamDep"].(float64)), Exclusive: bool(frame["Exclusive"].(bool)), Weight: uint8(frame["Weight"].(float64)), } streamID := uint32(frame["StreamID"].(float64)) fmt.Println("PriorityFrame") c.Framer.WritePriority(streamID, priority) case "ContinuationFrame": streamID := uint32(frame["StreamID"].(float64)) endStream := bool(frame["EndStream"].(bool)) payload := util.FromBase64(frame["Payload"].(string)) c.Framer.WriteContinuation(streamID, endStream, payload) case "DataFrame": streamID := uint32(frame["StreamID"].(float64)) endStream := bool(frame["EndStream"].(bool)) payload := util.FromBase64(frame["Payload"].(string)) c.Framer.WriteData(streamID, endStream, payload) case "WindowUpdate": streamID := uint32(frame["StreamID"].(float64)) incr := uint32(frame["Increment"].(float64)) c.Framer.WriteWindowUpdate(streamID, incr) case "ResetFrame": streamID := uint32(frame["StreamID"].(float64)) errorCode := http2.ErrCode(frame["ErrorCode"].(float64)) c.Framer.WriteRSTStream(streamID, errorCode) } } }
func RunReplay(c *Connection, filename string) { file, err := os.Open(filename) if err != nil { log.Fatal(err) } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { frameJSON := scanner.Text() frame := util.FromJSON([]byte(frameJSON)) if c.Err != nil { fmt.Println("Connection Error", c.Err, "restarting connection") c = NewConnection(c.Host, c.IsTLS, c.IsPreface, c.IsSendSettings) } switch frame["FrameMethod"] { case "RawFrame": frameType := uint8(frame["FrameType"].(float64)) flags := uint8(frame["Flags"].(float64)) streamID := uint32(frame["StreamID"].(float64)) payload := util.FromBase64(frame["Payload"].(string)) c.WriteRawFrame(frameType, flags, streamID, payload) case "Ping": pingData := frame["Data"].([]interface{}) var pingDataArray [8]byte for i := 0; i < len(pingData); i++ { pingDataArray[i] = uint8(pingData[i].(float64)) } c.SendPing(pingDataArray) case "SettingsFrame": arrSettings := frame["Settings"].([]interface{}) settings := make([]http2.Setting, len(arrSettings)) for i := 0; i < len(arrSettings); i++ { singleSettingsInterface := arrSettings[i].(map[string]interface{}) http2Setting := http2.Setting{http2.SettingID(singleSettingsInterface["ID"].(float64)), uint32(singleSettingsInterface["Val"].(float64))} settings[i] = http2Setting } c.WriteSettingsFrame(settings) case "DataFrame": streamID := uint32(frame["StreamID"].(float64)) endStream := bool(frame["EndStream"].(bool)) data := util.FromBase64(frame["Data"].(string)) c.WriteDataFrame(streamID, endStream, data) case "PushPromiseFrame": streamID := uint32(frame["StreamID"].(float64)) promiseID := uint32(frame["PromiseID"].(float64)) blockFragment := util.FromBase64(frame["BlockFragment"].(string)) endHeaders := frame["EndHeaders"].(bool) padLength := uint8(frame["PadLength"].(float64)) promise := http2.PushPromiseParam{streamID, promiseID, blockFragment, endHeaders, padLength} c.WritePushPromiseFrame(promise) case "HeadersFrame": headers := frame["Headers"].(map[string]interface{}) headers_map := make(map[string]string) for key, value := range headers { switch value := value.(type) { case string: headers_map[key] = value } } c.cmdHeaders(headers_map) case "ContinuationFrame": streamID := uint32(frame["StreamID"].(float64)) endStream := frame["EndStream"].(bool) data := util.FromBase64(frame["Data"].(string)) c.WriteContinuationFrame(streamID, endStream, data) case "PriorityFrame": streamID := uint32(frame["StreamID"].(float64)) streamDep := uint32(frame["StreamDep"].(float64)) weight := uint8(frame["Weight"].(float64)) exclusive := frame["Exclusive"].(bool) c.WritePriorityFrame(streamID, streamDep, weight, exclusive) case "ResetFrame": streamID := uint32(frame["StreamID"].(float64)) errorCode := uint32(frame["ErrorCode"].(float64)) c.WriteResetFrame(streamID, errorCode) c = NewConnection(c.Host, c.IsTLS, c.IsPreface, c.IsSendSettings) case "WindowUpdateFrame": streamID := uint32(frame["StreamID"].(float64)) incr := uint32(frame["Incr"].(float64)) c.WriteWindowUpdateFrame(streamID, incr) } } fmt.Println("ALL DONE") }