This page hosts a formal specification of tls_client_hello using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.
import (
"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
"bytes"
)
type TlsClientHello struct {
Version *TlsClientHello_Version
Random *TlsClientHello_Random
SessionId *TlsClientHello_SessionId
CipherSuites *TlsClientHello_CipherSuites
CompressionMethods *TlsClientHello_CompressionMethods
Extensions *TlsClientHello_Extensions
_io *kaitai.Stream
_root *TlsClientHello
_parent kaitai.Struct
}
func NewTlsClientHello() *TlsClientHello {
return &TlsClientHello{
}
}
func (this TlsClientHello) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello) Read(io *kaitai.Stream, parent kaitai.Struct, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp1 := NewTlsClientHello_Version()
err = tmp1.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Version = tmp1
tmp2 := NewTlsClientHello_Random()
err = tmp2.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Random = tmp2
tmp3 := NewTlsClientHello_SessionId()
err = tmp3.Read(this._io, this, this._root)
if err != nil {
return err
}
this.SessionId = tmp3
tmp4 := NewTlsClientHello_CipherSuites()
err = tmp4.Read(this._io, this, this._root)
if err != nil {
return err
}
this.CipherSuites = tmp4
tmp5 := NewTlsClientHello_CompressionMethods()
err = tmp5.Read(this._io, this, this._root)
if err != nil {
return err
}
this.CompressionMethods = tmp5
tmp6, err := this._io.EOF()
if err != nil {
return err
}
if (tmp6 == false) {
tmp7 := NewTlsClientHello_Extensions()
err = tmp7.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Extensions = tmp7
}
return err
}
type TlsClientHello_Alpn struct {
ExtLen uint16
AlpnProtocols []*TlsClientHello_Protocol
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello_Extension
}
func NewTlsClientHello_Alpn() *TlsClientHello_Alpn {
return &TlsClientHello_Alpn{
}
}
func (this TlsClientHello_Alpn) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_Alpn) Read(io *kaitai.Stream, parent *TlsClientHello_Extension, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp8, err := this._io.ReadU2be()
if err != nil {
return err
}
this.ExtLen = uint16(tmp8)
for i := 0;; i++ {
tmp9, err := this._io.EOF()
if err != nil {
return err
}
if tmp9 {
break
}
tmp10 := NewTlsClientHello_Protocol()
err = tmp10.Read(this._io, this, this._root)
if err != nil {
return err
}
this.AlpnProtocols = append(this.AlpnProtocols, tmp10)
}
return err
}
type TlsClientHello_CipherSuites struct {
Len uint16
CipherSuites []uint16
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello
}
func NewTlsClientHello_CipherSuites() *TlsClientHello_CipherSuites {
return &TlsClientHello_CipherSuites{
}
}
func (this TlsClientHello_CipherSuites) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_CipherSuites) Read(io *kaitai.Stream, parent *TlsClientHello, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp11, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Len = uint16(tmp11)
for i := 0; i < int(this.Len / 2); i++ {
_ = i
tmp12, err := this._io.ReadU2be()
if err != nil {
return err
}
this.CipherSuites = append(this.CipherSuites, tmp12)
}
return err
}
type TlsClientHello_CompressionMethods struct {
Len uint8
CompressionMethods []byte
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello
}
func NewTlsClientHello_CompressionMethods() *TlsClientHello_CompressionMethods {
return &TlsClientHello_CompressionMethods{
}
}
func (this TlsClientHello_CompressionMethods) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_CompressionMethods) Read(io *kaitai.Stream, parent *TlsClientHello, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp13, err := this._io.ReadU1()
if err != nil {
return err
}
this.Len = tmp13
tmp14, err := this._io.ReadBytes(int(this.Len))
if err != nil {
return err
}
tmp14 = tmp14
this.CompressionMethods = tmp14
return err
}
type TlsClientHello_Extension struct {
Type uint16
Len uint16
Body interface{}
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello_Extensions
_raw_Body []byte
}
func NewTlsClientHello_Extension() *TlsClientHello_Extension {
return &TlsClientHello_Extension{
}
}
func (this TlsClientHello_Extension) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_Extension) Read(io *kaitai.Stream, parent *TlsClientHello_Extensions, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp15, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Type = uint16(tmp15)
tmp16, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Len = uint16(tmp16)
switch (this.Type) {
case 0:
tmp17, err := this._io.ReadBytes(int(this.Len))
if err != nil {
return err
}
tmp17 = tmp17
this._raw_Body = tmp17
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp18 := NewTlsClientHello_Sni()
err = tmp18.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp18
case 16:
tmp19, err := this._io.ReadBytes(int(this.Len))
if err != nil {
return err
}
tmp19 = tmp19
this._raw_Body = tmp19
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp20 := NewTlsClientHello_Alpn()
err = tmp20.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp20
default:
tmp21, err := this._io.ReadBytes(int(this.Len))
if err != nil {
return err
}
tmp21 = tmp21
this._raw_Body = tmp21
}
return err
}
type TlsClientHello_Extensions struct {
Len uint16
Extensions []*TlsClientHello_Extension
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello
}
func NewTlsClientHello_Extensions() *TlsClientHello_Extensions {
return &TlsClientHello_Extensions{
}
}
func (this TlsClientHello_Extensions) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_Extensions) Read(io *kaitai.Stream, parent *TlsClientHello, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp22, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Len = uint16(tmp22)
for i := 0;; i++ {
tmp23, err := this._io.EOF()
if err != nil {
return err
}
if tmp23 {
break
}
tmp24 := NewTlsClientHello_Extension()
err = tmp24.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Extensions = append(this.Extensions, tmp24)
}
return err
}
type TlsClientHello_Protocol struct {
Strlen uint8
Name []byte
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello_Alpn
}
func NewTlsClientHello_Protocol() *TlsClientHello_Protocol {
return &TlsClientHello_Protocol{
}
}
func (this TlsClientHello_Protocol) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_Protocol) Read(io *kaitai.Stream, parent *TlsClientHello_Alpn, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp25, err := this._io.ReadU1()
if err != nil {
return err
}
this.Strlen = tmp25
tmp26, err := this._io.ReadBytes(int(this.Strlen))
if err != nil {
return err
}
tmp26 = tmp26
this.Name = tmp26
return err
}
type TlsClientHello_Random struct {
GmtUnixTime uint32
Random []byte
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello
}
func NewTlsClientHello_Random() *TlsClientHello_Random {
return &TlsClientHello_Random{
}
}
func (this TlsClientHello_Random) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_Random) Read(io *kaitai.Stream, parent *TlsClientHello, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp27, err := this._io.ReadU4be()
if err != nil {
return err
}
this.GmtUnixTime = uint32(tmp27)
tmp28, err := this._io.ReadBytes(int(28))
if err != nil {
return err
}
tmp28 = tmp28
this.Random = tmp28
return err
}
type TlsClientHello_ServerName struct {
NameType uint8
Length uint16
HostName []byte
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello_Sni
}
func NewTlsClientHello_ServerName() *TlsClientHello_ServerName {
return &TlsClientHello_ServerName{
}
}
func (this TlsClientHello_ServerName) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_ServerName) Read(io *kaitai.Stream, parent *TlsClientHello_Sni, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp29, err := this._io.ReadU1()
if err != nil {
return err
}
this.NameType = tmp29
tmp30, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Length = uint16(tmp30)
tmp31, err := this._io.ReadBytes(int(this.Length))
if err != nil {
return err
}
tmp31 = tmp31
this.HostName = tmp31
return err
}
type TlsClientHello_SessionId struct {
Len uint8
Sid []byte
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello
}
func NewTlsClientHello_SessionId() *TlsClientHello_SessionId {
return &TlsClientHello_SessionId{
}
}
func (this TlsClientHello_SessionId) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_SessionId) Read(io *kaitai.Stream, parent *TlsClientHello, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp32, err := this._io.ReadU1()
if err != nil {
return err
}
this.Len = tmp32
tmp33, err := this._io.ReadBytes(int(this.Len))
if err != nil {
return err
}
tmp33 = tmp33
this.Sid = tmp33
return err
}
type TlsClientHello_Sni struct {
ListLength uint16
ServerNames []*TlsClientHello_ServerName
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello_Extension
}
func NewTlsClientHello_Sni() *TlsClientHello_Sni {
return &TlsClientHello_Sni{
}
}
func (this TlsClientHello_Sni) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_Sni) Read(io *kaitai.Stream, parent *TlsClientHello_Extension, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp34, err := this._io.ReadU2be()
if err != nil {
return err
}
this.ListLength = uint16(tmp34)
for i := 0;; i++ {
tmp35, err := this._io.EOF()
if err != nil {
return err
}
if tmp35 {
break
}
tmp36 := NewTlsClientHello_ServerName()
err = tmp36.Read(this._io, this, this._root)
if err != nil {
return err
}
this.ServerNames = append(this.ServerNames, tmp36)
}
return err
}
type TlsClientHello_Version struct {
Major uint8
Minor uint8
_io *kaitai.Stream
_root *TlsClientHello
_parent *TlsClientHello
}
func NewTlsClientHello_Version() *TlsClientHello_Version {
return &TlsClientHello_Version{
}
}
func (this TlsClientHello_Version) IO_() *kaitai.Stream {
return this._io
}
func (this *TlsClientHello_Version) Read(io *kaitai.Stream, parent *TlsClientHello, root *TlsClientHello) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp37, err := this._io.ReadU1()
if err != nil {
return err
}
this.Major = tmp37
tmp38, err := this._io.ReadU1()
if err != nil {
return err
}
this.Minor = tmp38
return err
}