using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Tls
{
public sealed class ServerNameList
{
private readonly IList m_serverNameList;
/// an of .
public ServerNameList(IList serverNameList)
{
if (null == serverNameList)
throw new ArgumentNullException("serverNameList");
this.m_serverNameList = serverNameList;
}
/// an of .
public IList ServerNames
{
get { return m_serverNameList; }
}
/// Encode this to a .
/// the to encode to .
///
public void Encode(Stream output)
{
MemoryStream buf = new MemoryStream();
short[] nameTypesSeen = TlsUtilities.EmptyShorts;
foreach (ServerName entry in ServerNames)
{
nameTypesSeen = CheckNameType(nameTypesSeen, entry.NameType);
if (null == nameTypesSeen)
throw new TlsFatalAlert(AlertDescription.internal_error);
entry.Encode(buf);
}
int length = (int)buf.Length;
TlsUtilities.CheckUint16(length);
TlsUtilities.WriteUint16(length, output);
Streams.WriteBufTo(buf, output);
}
/// Parse a from a .
/// the to parse from.
/// a object.
///
public static ServerNameList Parse(Stream input)
{
byte[] data = TlsUtilities.ReadOpaque16(input, 1);
MemoryStream buf = new MemoryStream(data, false);
short[] nameTypesSeen = TlsUtilities.EmptyShorts;
IList server_name_list = Platform.CreateArrayList();
while (buf.Position < buf.Length)
{
ServerName entry = ServerName.Parse(buf);
nameTypesSeen = CheckNameType(nameTypesSeen, entry.NameType);
if (null == nameTypesSeen)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
server_name_list.Add(entry);
}
return new ServerNameList(server_name_list);
}
private static short[] CheckNameType(short[] nameTypesSeen, short nameType)
{
// RFC 6066 3. The ServerNameList MUST NOT contain more than one name of the same NameType.
if (Arrays.Contains(nameTypesSeen, nameType))
return null;
return Arrays.Append(nameTypesSeen, nameType);
}
}
}