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