// Copyright 2012 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.

package gopacket

import (
	"errors"
)

// DecodeFeedback is used by DecodingLayer layers to provide decoding metadata.
type DecodeFeedback interface {
	// SetTruncated should be called if during decoding you notice that a packet
	// is shorter than internal layer variables (HeaderLength, or the like) say it
	// should be.  It sets packet.Metadata().Truncated.
	SetTruncated()
}

type nilDecodeFeedback struct{}

func (nilDecodeFeedback) SetTruncated() {}

// NilDecodeFeedback implements DecodeFeedback by doing nothing.
var NilDecodeFeedback DecodeFeedback = nilDecodeFeedback{}

// PacketBuilder is used by layer decoders to store the layers they've decoded,
// and to defer future decoding via NextDecoder.
// Typically, the pattern for use is:
//  func (m *myDecoder) Decode(data []byte, p PacketBuilder) error {
//    if myLayer, err := myDecodingLogic(data); err != nil {
//      return err
//    } else {
//      p.AddLayer(myLayer)
//    }
//    // maybe do this, if myLayer is a LinkLayer
//    p.SetLinkLayer(myLayer)
//    return p.NextDecoder(nextDecoder)
//  }
type PacketBuilder interface {
	DecodeFeedback
	// AddLayer should be called by a decoder immediately upon successful
	// decoding of a layer.
	AddLayer(l Layer)
	// The following functions set the various specific layers in the final
	// packet.  Note that if many layers call SetX, the first call is kept and all
	// other calls are ignored.
	SetLinkLayer(LinkLayer)
	SetNetworkLayer(NetworkLayer)
	SetTransportLayer(TransportLayer)
	SetApplicationLayer(ApplicationLayer)
	SetErrorLayer(ErrorLayer)
	// NextDecoder should be called by a decoder when they're done decoding a
	// packet layer but not done with decoding the entire packet.  The next
	// decoder will be called to decode the last AddLayer's LayerPayload.
	// Because of this, NextDecoder must only be called once all other
	// PacketBuilder calls have been made.  Set*Layer and AddLayer calls after
	// NextDecoder calls will behave incorrectly.
	NextDecoder(next Decoder) error
	// DumpPacketData is used solely for decoding.  If you come across an error
	// you need to diagnose while processing a packet, call this and your packet's
	// data will be dumped to stderr so you can create a test.  This should never
	// be called from a production decoder.
	DumpPacketData()
}

// Decoder is an interface for logic to decode a packet layer.  Users may
// implement a Decoder to handle their own strange packet types, or may use one
// of the many decoders available in the 'layers' subpackage to decode things
// for them.
type Decoder interface {
	// Decode decodes the bytes of a packet, sending decoded values and other
	// information to PacketBuilder, and returning an error if unsuccessful.  See
	// the PacketBuilder documentation for more details.
	Decode([]byte, PacketBuilder) error
}

// DecodeFunc wraps a function to make it a Decoder.
type DecodeFunc func([]byte, PacketBuilder) error

func (d DecodeFunc) Decode(data []byte, p PacketBuilder) error {
	// function, call thyself.
	return d(data, p)
}

// DecodePayload is a Decoder that returns a Payload layer containing all
// remaining bytes.
var DecodePayload Decoder = DecodeFunc(decodePayload)

// DecodeUnknown is a Decoder that returns an Unknown layer containing all
// remaining bytes, useful if you run up against a layer that you're unable to
// decode yet.  This layer is considered an ErrorLayer.
var DecodeUnknown Decoder = DecodeFunc(decodeUnknown)

// DecodeFragment is a Decoder that returns a Fragment layer containing all
// remaining bytes.
var DecodeFragment Decoder = DecodeFunc(decodeFragment)

// LayerTypeZero is an invalid layer type, but can be used to determine whether
// layer type has actually been set correctly.
var LayerTypeZero LayerType = RegisterLayerType(0, LayerTypeMetadata{"Unknown", DecodeUnknown})

// LayerTypeDecodeFailure is the layer type for the default error layer.
var LayerTypeDecodeFailure LayerType = RegisterLayerType(1, LayerTypeMetadata{"DecodeFailure", DecodeUnknown})

// LayerTypePayload is the layer type for a payload that we don't try to decode
// but treat as a success, IE: an application-level payload.
var LayerTypePayload LayerType = RegisterLayerType(2, LayerTypeMetadata{"Payload", DecodePayload})

// LayerTypeFragment is the layer type for a fragment of a layer transported
// by an underlying layer that supports fragmentation.
var LayerTypeFragment LayerType = RegisterLayerType(3, LayerTypeMetadata{"Fragment", DecodeFragment})

// DecodeFailure is a packet layer created if decoding of the packet data failed
// for some reason.  It implements ErrorLayer.  LayerContents will be the entire
// set of bytes that failed to parse, and Error will return the reason parsing
// failed.
type DecodeFailure struct {
	data  []byte
	err   error
	stack []byte
}

// Error returns the error encountered during decoding.
func (d *DecodeFailure) Error() error          { return d.err }
func (d *DecodeFailure) LayerContents() []byte { return d.data }
func (d *DecodeFailure) LayerPayload() []byte  { return nil }
func (d *DecodeFailure) String() string {
	return "Packet decoding error: " + d.Error().Error()
}
func (d *DecodeFailure) Dump() (s string) {
	if d.stack != nil {
		s = string(d.stack)
	}
	return
}

// LayerType returns LayerTypeDecodeFailure
func (d *DecodeFailure) LayerType() LayerType { return LayerTypeDecodeFailure }

// decodeUnknown "decodes" unsupported data types by returning an error.
// This decoder will thus always return a DecodeFailure layer.
func decodeUnknown(data []byte, p PacketBuilder) error {
	return errors.New("Layer type not currently supported")
}
