コード例 #1
0
ファイル: HttpUtils.go プロジェクト: alekseyfadeev86/Tutorial
func (parser *BigRequestsParser) Parse() (res []*HttpBigRequest) {

	if (parser.body_writer != nil) && (len(parser.unworked_data) != 0) {
		panic(errors.New("(parser.body_writer != nil) && (len(parser.unworked_data) != 0)"))
	}

	req_identifier := []byte(http_version + endline_str) // Признак запроса (версия HTTP + символы конца строки)
	endl := []byte(endline_str)

	for len(parser.unworked_data) > 0 {
		if parser.unfinished_req == nil {
			// Обрабатываем накопленные данные как начало нового запроса
			p_req_id := bytes.Index(parser.unworked_data, req_identifier)
			p_endl := -1
			if p_req_id >= 0 {
				p_endl = bytes.LastIndex(parser.unworked_data[:p_req_id], endl)
			} else {
				p_endl = bytes.LastIndex(parser.unworked_data, endl)
			}

			if p_req_id < 0 {
				// Признак запроса не был обнаружен
				if p_endl > 0 {
					// ...но был обнаружен переход на новую строку - ошибка
					parser.unworked_data = parser.unworked_data[p_endl+len(endline_str):]
					if len(parser.unworked_data) == 0 {
						parser.unworked_data = nil
					}

					res = append(res, nil)
				}

				return
			} else {
				p_req_id += len(req_identifier)
			}

			if p_endl < 0 {
				p_endl = 0
			} else {
				// Обнаружен переход на новую строку перед признаком запроса
				res = append(res, nil)
				p_endl += len(endline_str)
			}

			// Найден признак запроса
			req_head_line := string(parser.unworked_data[p_endl:p_req_id])
			parser.unworked_data = parser.unworked_data[p_req_id:]
			if len(parser.unworked_data) == 0 {
				parser.unworked_data = nil
			}

			params := strings.Split(req_head_line, " ")
			if len(params) == 3 {
				// Нашли заголовок запроса
				parser.unfinished_req = &HttpBigRequest{Type: params[0], Host: params[1]}
			} else {
				// Неверный заголовок
				res = append(res, nil)
				continue
			}
		} // if parser.unfinished_req == nil

		// Формируем параметры заголовка
		param_error := false
		pos := bytes.Index(parser.unworked_data, endl)
		for ; pos >= 0; pos = bytes.Index(parser.unworked_data, endl) {
			// Формируем строку с параметром (без символа перехода на следующую строку)
			// и отрезаем обработанный кусок данных от необработанных данных (вместе с символом перехода)
			one_param_str := string(parser.unworked_data[:pos])
			parser.unworked_data = parser.unworked_data[pos+len(endl):]
			if len(parser.unworked_data) == 0 {
				parser.unworked_data = nil
			}

			if pos == 0 {
				// Дошли до конца заголовка
				break
			}

			// Обрабатываем параметр заголовка
			param, success := param_parser(one_param_str)
			if success {
				// Обработали один параметр - добавляем его е запросу
				parser.unfinished_req.HeaderParams = append(parser.unfinished_req.HeaderParams, param)
			} else {
				// Ошибка разбора параметра заголовка
				parser.unfinished_req = nil
				res = append(res, nil)
				param_error = true
				break
			}
		} // for ; pos >= 0; pos = bytes.Index(parser.unworked_data, endl)

		if param_error {
			// При разборке параметров заголовка произошла ошибка
			continue
		} else if pos < 0 {
			// Символ перехода на следующую строку не найден - больше обрабатывать нечего
			return
		}

		// Если попали сюда - параметры заголовка считаны полностью,
		// дальше идёт тело и/или следующий запрос
		var body_len int = len(parser.unworked_data)
		for _, param := range parser.unfinished_req.HeaderParams {
			if param.Name == BodySizeParamName {
				// Обнаружили параметр длины тела
				var e error
				body_len, e = strconv.Atoi(param.Value)
				if e != nil {
					// Некорректное значение параметра длины
					parser.unfinished_req = nil
					res = append(res, nil)
					param_error = true
				}

				break
			} // if param.Name == BodySizeParamName
		} // for _, param := range parser.unfinished_req.HeaderParams

		if param_error {
			continue
		}

		if body_len <= len(parser.unworked_data) {
			// В необработанных данных уже содержится всё тело запроса
			parser.unfinished_req.Body = bytes.NewReader(parser.unworked_data[:body_len])
			parser.unworked_data = parser.unworked_data[body_len:]
			if len(parser.unworked_data) == 0 {
				parser.unworked_data = nil
			}
		} else if body_len != 0 {
			// Всё тело ещё не считали
			var one_piece_max_sz int = body_len
			var chan_sz uint16 = 2

			if one_piece_max_sz > 10240 {
				one_piece_max_sz = 10240
				chan_sz = 10
			}

			reader, writer := IoUtils.NonBlockingPipe(one_piece_max_sz, chan_sz)
			parser.body_writer = IoUtils.LimitWriteCloser(writer, int64(body_len))
			parser.unfinished_req.Body = io.LimitReader(reader, int64(body_len))

			if parser.unworked_data != nil {
				sz, e := parser.body_writer.Write(parser.unworked_data)
				if (sz < len(parser.unworked_data)) || (e != nil) {
					// Были записаны не все данные
					panic(errors.New("Ошибка записи тела запроса")) // Возможно, стоит убрать
				}

				parser.unworked_data = nil
			}
		}

		res = append(res, parser.unfinished_req)
		parser.unfinished_req = nil
	} // for len(parser.unworked_data) > 0

	return res
} // func (p *BigRequestsParser) Parse() []*HttpBigRequest
コード例 #2
0
// Разбор полученных данных
func (p *BigFrameParser) Parse() (res []BigFrame) {
	for len(p.unworked_data) > 0 {
		if p.data_writer != nil {
			panic(errors.New("Не закончили запись данных предыдущего пакета, а уже есть данные для нового"))
		}

		// Начинаем формировать новый пакет
		head_len := 2 // Длина заголовка (минимум 2 байта)
		data_len := len(p.unworked_data)

		if data_len < head_len {
			// Недостаточно данных даже для формирования заголовка
			return
		}

		if (0x80 & p.unworked_data[1]) != 0 {
			// В заголовке присутствует маска - +4 байта к заголовку
			head_len += 4
		}

		if ln_param := 0x7F & p.unworked_data[1]; ln_param == 126 {
			// Поле длины пакета занимает лишние 2 байта
			head_len += 2
		} else if ln_param == 127 {
			// Поле длины пакета занимает лишние 8 байт
			head_len += 8
		}

		if data_len < head_len {
			// Недостаточно данных даже для формироваиня заголовка
			return
		}

		// Формируем заголовок пакета
		new_frame := BigFrame{}
		new_frame.Fin = (0x80 & p.unworked_data[0]) != 0
		for t := byte(0); t < 3; t++ {
			new_frame.Rsvs[t] = (p.unworked_data[0] & (byte(0x40) >> t)) != 0
		}

		new_frame.Type = 0xF & p.unworked_data[0]
		new_frame.Mask = (0x80 & p.unworked_data[1]) != 0
		if new_frame.Mask {
			for i := 0; i < 4; i++ {
				new_frame.MaskKey[i] = p.unworked_data[head_len-4+i]
			}
		}

		data_sz := uint64(0x7F & p.unworked_data[1])
		if data_sz == 126 {
			data_sz = 0
			for _, v := range p.unworked_data[2:4] {
				data_sz <<= 8
				data_sz |= uint64(v)
			}
		} else if data_sz > 126 {
			data_sz = 0
			for _, v := range p.unworked_data[2:10] {
				data_sz <<= 8
				data_sz |= uint64(v)
			}
		}

		p.unworked_data = p.unworked_data[head_len:]
		if len(p.unworked_data) == 0 {
			p.unworked_data = nil
		}

		// Формируем данные пакета
		if data_sz <= uint64(len(p.unworked_data)) {
			// Считано достаточно данных для форрмирования тела
			frame_data := p.unworked_data[:data_sz]
			p.unworked_data = p.unworked_data[data_sz:]
			if len(p.unworked_data) == 0 {
				p.unworked_data = nil
			}

			if new_frame.Mask {
				// Задана маска - расшифровываем данные
				for i := range frame_data {
					frame_data[i] = frame_data[i] ^ new_frame.MaskKey[i%4]
				}
			}

			new_frame.Data = bytes.NewReader(frame_data)
		} else {
			// Всё тело ещё не считали
			var one_piece_max_sz int = int(data_sz)
			var chan_sz uint16 = 2

			if one_piece_max_sz > 10240 {
				one_piece_max_sz = 10240
				chan_sz = 10
			}

			reader, writer := IoUtils.NonBlockingPipe(one_piece_max_sz, chan_sz)
			p.data_writer = IoUtils.LimitWriteCloser(writer, int64(data_sz))
			var conv IoUtils.Converter
			if new_frame.Mask {
				conv = &frame_data_converter{mask_key: new_frame.MaskKey}
			}
			new_frame.Data = IoUtils.Serialize(nil, io.LimitReader(reader, int64(data_sz)), conv, nil)

			if p.unworked_data != nil {
				sz, e := p.data_writer.Write(p.unworked_data)
				if (sz < len(p.unworked_data)) || (e != nil) {
					// Были записаны не все данные
					panic(errors.New("Ошибка записи тела запроса")) // Возможно, стоит убрать
				}

				p.unworked_data = nil
			}
		}

		// Пакет сформирован
		res = append(res, new_frame)
	} // for len(r.unworked_data) > 0

	return
} // func (p *BigFrameParser) Parse() (res []BigFrame)