defmodule CWMP.Protocol.Parser.Envelope do
use CWMP.Protocol.ParserHelpers
defmodule Header do
use Elixir.CWMP.Protocol.ParserHelpers
alias CWMP.Protocol.Messages.Header
def initial_acc do
%Header{}
end
@known_header_fields ['ID', 'HoldRequests', 'SessionTimeout', 'NoMoreRequests']
def start_element(state, [field], attribs, _uri) do
mustUnderstand = not((for {:attribute, 'mustUnderstand', _, _, '1'} <- attribs, do: true) |> Enum.empty?)
if mustUnderstand && !Enum.member?(@known_header_fields, field) do
raise "Field '#{field}' must be understood, but we don't"
end
state
end
def end_element(state, ['ID']) do
update_acc(state, fn cur -> %Header{cur | id: state.last_text} end)
end
def end_element(state, ['SessionTimeout']) do
update_acc(state, fn cur -> %Header{cur | session_timeout: integerValue(state.last_text, fn(x) -> x > 0 end)} end)
end
def end_element(state, ['HoldRequests']) do
update_acc(state, fn cur -> %Header{cur | hold_requests: integerValue(state.last_text, fn(x) -> x in 0..1 end)} end)
end
def end_element(state, ['NoMoreRequests']) do
update_acc(state, fn cur -> %Header{cur | no_more_requests: boolValue(state.last_text)} end)
end
end
def initial_acc do
%{cwmp_version: nil,
header: nil,
entries: []}
end
@message_types %{
'Fault' => CWMP.Protocol.Parser.Messages.Fault,
'Inform' => CWMP.Protocol.Parser.Messages.Inform,
'InformResponse' => CWMP.Protocol.Parser.Messages.InformResponse,
'TransferComplete' => CWMP.Protocol.Parser.Messages.TransferComplete,
'TransferCompleteResponse' => CWMP.Protocol.Parser.Messages.TransferCompleteResponse,
'AutonomousTransferComplete' => CWMP.Protocol.Parser.Messages.AutonomousTransferComplete,
'AutonomousTransferCompleteResponse' => CWMP.Protocol.Parser.Messages.AutonomousTransferCompleteResponse,
'GetRPCMethodsResponse' => CWMP.Protocol.Parser.Messages.GetRPCMethodsResponse,
'GetRPCMethods' => CWMP.Protocol.Parser.Messages.GetRPCMethods,
'GetParameterValues' => CWMP.Protocol.Parser.Messages.GetParameterValues,
'GetParameterValuesResponse' => CWMP.Protocol.Parser.Messages.GetParameterValuesResponse,
'GetParameterNames' => CWMP.Protocol.Parser.Messages.GetParameterNames,
'GetParameterNamesResponse' => CWMP.Protocol.Parser.Messages.GetParameterNamesResponse,
'SetParameterValues' => CWMP.Protocol.Parser.Messages.SetParameterValues,
'SetParameterValuesResponse' => CWMP.Protocol.Parser.Messages.SetParameterValuesResponse,
'SetParameterAttributesResponse' => CWMP.Protocol.Parser.Messages.SetParameterAttributesResponse,
'GetParameterAttributes' => CWMP.Protocol.Parser.Messages.GetParameterAttributes,
'GetParameterAttributesResponse' => CWMP.Protocol.Parser.Messages.GetParameterAttributesResponse,
'SetParameterAttributes' => CWMP.Protocol.Parser.Messages.SetParameterAttributes,
'AddObject' => CWMP.Protocol.Parser.Messages.AddObject,
'AddObjectResponse' => CWMP.Protocol.Parser.Messages.AddObjectResponse,
'DeleteObject' => CWMP.Protocol.Parser.Messages.DeleteObject,
'DeleteObjectResponse' => CWMP.Protocol.Parser.Messages.DeleteObjectResponse,
'Download' => CWMP.Protocol.Parser.Messages.Download,
'DownloadResponse' => CWMP.Protocol.Parser.Messages.DownloadResponse,
'Reboot' => CWMP.Protocol.Parser.Messages.Reboot,
'RebootResponse' => CWMP.Protocol.Parser.Messages.RebootResponse,
'GetQueuedTransfers' => CWMP.Protocol.Parser.Messages.GetQueuedTransfers,
'GetQueuedTransfersResponse' => CWMP.Protocol.Parser.Messages.GetQueuedTransfersResponse,
'ScheduleInform' => CWMP.Protocol.Parser.Messages.ScheduleInform,
'ScheduleInformResponse' => CWMP.Protocol.Parser.Messages.ScheduleInformResponse,
'SetVouchers' => CWMP.Protocol.Parser.Messages.SetVouchers,
'SetVouchersResponse' => CWMP.Protocol.Parser.Messages.SetVouchersResponse,
'GetOptions' => CWMP.Protocol.Parser.Messages.GetOptions,
'GetOptionsResponse' => CWMP.Protocol.Parser.Messages.GetOptionsResponse,
'Upload' => CWMP.Protocol.Parser.Messages.Upload,
'UploadResponse' => CWMP.Protocol.Parser.Messages.UploadResponse,
'FactoryReset' => CWMP.Protocol.Parser.Messages.FactoryReset,
'FactoryResetResponse' => CWMP.Protocol.Parser.Messages.FactoryResetResponse,
'GetAllQueuedTransfers' => CWMP.Protocol.Parser.Messages.GetAllQueuedTransfers,
'GetAllQueuedTransfersResponse' => CWMP.Protocol.Parser.Messages.GetAllQueuedTransfersResponse,
'ScheduleDownload' => CWMP.Protocol.Parser.Messages.ScheduleDownload,
'ScheduleDownloadResponse' => CWMP.Protocol.Parser.Messages.ScheduleDownloadResponse,
'CancelTransfer' => CWMP.Protocol.Parser.Messages.CancelTransfer,
'CancelTransferResponse' => CWMP.Protocol.Parser.Messages.CancelTransferResponse,
'ChangeDUState' => CWMP.Protocol.Parser.Messages.ChangeDUState,
'ChangeDUStateResponse' => CWMP.Protocol.Parser.Messages.ChangeDUStateResponse,
'Kicked' => CWMP.Protocol.Parser.Messages.Kicked,
'KickedResponse' => CWMP.Protocol.Parser.Messages.KickedResponse,
'RequestDownload' => CWMP.Protocol.Parser.Messages.RequestDownload,
'RequestDownloadResponse' => CWMP.Protocol.Parser.Messages.RequestDownloadResponse,
'DUStateChangeComplete' => CWMP.Protocol.Parser.Messages.DUStateChangeComplete,
'DUStateChangeCompleteResponse' => CWMP.Protocol.Parser.Messages.DUStateChangeCompleteResponse,
'AutonomousDUStateChangeComplete' => CWMP.Protocol.Parser.Messages.AutonomousDUStateChangeComplete,
'AutonomousDUStateChangeCompleteResponse' => CWMP.Protocol.Parser.Messages.AutonomousDUStateChangeCompleteResponse
}
def start_element(state, ['Header', 'Envelope'], _attribs, _uri) do
push_handler(state, Header)
end
def start_element(state, [msgtype, 'Body', 'Envelope'], _attribs, uri) do
case Map.get(@message_types, msgtype) do
nil -> raise "Message type '#{msgtype}' is not known"
handler -> case parse_cwmp_version(uri) do
ver when not is_nil(ver) -> update_acc(state, fn cur -> %{cur | cwmp_version: ver} end) |> push_handler(handler)
nil -> push_handler(state,handler)
end
end
end
def end_element(state, ['Header', 'Envelope']) do
update_acc(state, fn cur -> %{cur | header: state.last_acc} end)
end
def end_element(state, [_, 'Body', 'Envelope']) do
update_acc(state, fn cur -> %{cur | entries: cur.entries ++ [state.last_acc]} end)
end
end