1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2004-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%----------------------------------------------------------------------
22%% Purpose: Utility functions for the (snmp manager) user test(s).
23%%----------------------------------------------------------------------
24
25-module(snmp_manager_user_test_lib).
26
27-behaviour(snmpm_user).
28
29
30%%----------------------------------------------------------------------
31%% Include files
32%%----------------------------------------------------------------------
33-include_lib("common_test/include/ct.hrl").
34-include("snmp_test_lib.hrl").
35
36
37%%----------------------------------------------------------------------
38%% External exports
39%%----------------------------------------------------------------------
40-export([
41         start_link/0, stop/1,
42	 simulate_crash/2,
43	 register/2, register/3,
44	 register_monitor/2, register_monitor/3,
45	 unregister/1, unregister/2,
46	 register_agent/4
47        ]).
48
49%%----------------------------------------------------------------------
50%% Internal exports
51%%----------------------------------------------------------------------
52-export([
53         user/1
54        ]).
55
56-export([
57	 handle_error/3,
58         handle_agent/5,
59         handle_agent/4,   % For backwards compatibillity
60         handle_pdu/4,
61         handle_pdu/5,     % For backwards compatibillity
62         handle_trap/3,
63         handle_trap/4,    % For backwards compatibillity
64         handle_inform/3,
65         handle_inform/4,  % For backwards compatibillity
66         handle_report/3,
67         handle_report/4   % For backwards compatibillity
68	]).
69
70
71-record(state, {parent, ids = []}).
72
73
74%%----------------------------------------------------------------------
75%% The user simulation API
76%%----------------------------------------------------------------------
77
78start_link() ->
79    S = #state{parent = self()},
80    proc_lib:start_link(?MODULE, user, [S]).
81
82stop(Pid) ->
83    cast(Pid, stop).
84
85simulate_crash(Pid, Reason) ->
86    call(Pid, {simulate_crash, Reason}).
87
88%% For backwards compatibillity
89register(Pid, Id) ->
90    call(Pid, {register, Id}).
91
92register(Pid, Id, DefaultAgentConfig) ->
93    call(Pid, {register, Id, DefaultAgentConfig}).
94
95%% For backwards compatibillity
96register_monitor(Pid, Id) ->
97    call(Pid, {register_monitor, Id}).
98
99register_monitor(Pid, Id, DefaultAgentConfig) ->
100    call(Pid, {register_monitor, Id, DefaultAgentConfig}).
101
102unregister(Pid) ->
103    call(Pid, unregister).
104
105unregister(Pid, Id) ->
106    call(Pid, {unregister, Id}).
107
108register_agent(Pid, Id, TargetName, AgentConfig) ->
109    call(Pid, {register_agent, Id, TargetName, AgentConfig}).
110
111user(#state{parent = Pid} = S) ->
112    proc_lib:init_ack(Pid, {ok, self()}),
113    user_loop(S).
114
115user_loop(#state{parent = Parent} = S) ->
116    receive
117	{stop, Parent} ->
118	    exit(normal);
119
120	{{simulate_crash, Reason}, Parent, Ref} ->
121	    reply(Parent, ok, Ref),
122	    exit(Reason);
123
124	%% For backwards compatibillity
125	{{register, Id}, Parent, Ref} ->
126	    IDs = S#state.ids,
127	    case lists:member(Id, IDs) of
128		false ->
129		    Res = snmpm:register_user(Id, ?MODULE, self()),
130		    reply(Parent, Res, Ref),
131		    user_loop(S#state{ids = [Id|IDs]});
132		true ->
133		    reply(Parent, {error, already_registered}, Ref),
134		    user_loop(S)
135	    end;
136
137	{{register, Id, DefaultAgentConf}, Parent, Ref} ->
138	    IDs = S#state.ids,
139	    case lists:member(Id, IDs) of
140		false ->
141		    Res = snmpm:register_user(Id, ?MODULE, self(),
142					      DefaultAgentConf),
143		    reply(Parent, Res, Ref),
144		    user_loop(S#state{ids = [Id|IDs]});
145		true ->
146		    reply(Parent, {error, already_registered}, Ref),
147		    user_loop(S)
148	    end;
149
150	%% For backwards compatibillity
151	{{register_monitor, Id}, Parent, Ref} ->
152	    IDs = S#state.ids,
153	    case lists:member(Id, IDs) of
154		false ->
155		    Res = snmpm:register_user_monitor(Id, ?MODULE, self()),
156		    reply(Parent, Res, Ref),
157		    user_loop(S#state{ids = [Id|IDs]});
158		true ->
159		    reply(Parent, {error, already_registered}, Ref),
160		    user_loop(S)
161	    end;
162
163	{{register_monitor, Id, DefaultAgentConf}, Parent, Ref} ->
164	    IDs = S#state.ids,
165	    case lists:member(Id, IDs) of
166		false ->
167		    Res = snmpm:register_user_monitor(Id, ?MODULE, self(),
168						      DefaultAgentConf),
169		    reply(Parent, Res, Ref),
170		    user_loop(S#state{ids = [Id|IDs]});
171		true ->
172		    reply(Parent, {error, already_registered}, Ref),
173		    user_loop(S)
174	    end;
175
176	{unregister, Parent, Ref} ->
177	    Res = [snmpm:unregister_user(Id) || Id <- S#state.ids],
178	    reply(Parent, {ok, Res}, Ref),
179	    user_loop(S);
180
181	{{unregister, Id}, Parent, Ref} ->
182	    IDs = S#state.ids,
183	    IDs2 =
184		case lists:member(Id, IDs) of
185		    true ->
186			Res = snmpm:unregister_user(Id),
187			reply(Parent, Res, Ref),
188			lists:delete(Id, IDs);
189		    false ->
190			reply(Parent, {error, not_registered}, Ref),
191			IDs
192		end,
193	    user_loop(S#state{ids = IDs2});
194
195	{{register_agent, Id, TargetName, Config}, Parent, Ref} ->
196	    IDs = S#state.ids,
197	    case lists:member(Id, IDs) of
198		true ->
199		    Res = snmpm:register_agent(Id, TargetName, Config),
200		    reply(Parent, Res, Ref),
201		    user_loop(S);
202		false ->
203		    reply(Parent, {error, {unknown_user, Id}}, Ref),
204		    user_loop(S)
205	    end;
206
207
208
209	%% SNMP manager callback messages (from our callback API):
210
211	{handle_error, Pid, ReqId, Reason} ->
212	    do_handle_error(Pid, ReqId, Reason),
213	    user_loop(S);
214
215	{handle_agent, Pid, Domain, Address, Type, SnmpInfo} ->
216	    do_handle_agent(Pid, Domain, Address, Type, SnmpInfo),
217	    user_loop(S);
218
219	{handle_agent, Pid, Addr, Port, SnmpInfo} ->
220	    do_handle_agent(Pid, Addr, Port, SnmpInfo),
221	    user_loop(S);
222
223	{handle_pdu, Pid, TargetName, ReqId, SnmpResponse} ->
224	    do_handle_pdu(Pid, TargetName, ReqId, SnmpResponse),
225	    user_loop(S);
226
227	{handle_pdu, Pid, Addr, Port, ReqId, SnmpResponse} ->
228	    do_handle_pdu(Pid, Addr, Port, ReqId, SnmpResponse),
229	    user_loop(S);
230
231	{handle_trap, Pid, TargetName, SnmpTrap} ->
232	    do_handle_trap(Pid, TargetName, SnmpTrap),
233	    user_loop(S);
234
235	{handle_trap, Pid, Addr, Port, SnmpTrap} ->
236	    do_handle_trap(Pid, Addr, Port, SnmpTrap),
237	    user_loop(S);
238
239	{handle_inform, Pid, TargetName, SnmpInform} ->
240	    do_handle_inform(Pid, TargetName, SnmpInform),
241	    user_loop(S);
242
243	{handle_inform, Pid, Addr, Port, SnmpInform} ->
244	    do_handle_inform(Pid, Addr, Port, SnmpInform),
245	    user_loop(S);
246
247	{handle_report, Pid, TargetName, SnmpReport} ->
248	    do_handle_report(Pid, TargetName, SnmpReport),
249	    user_loop(S);
250
251	{handle_report, Pid, Addr, Port, SnmpReport} ->
252	    do_handle_report(Pid, Addr, Port, SnmpReport),
253	    user_loop(S);
254
255	Unknown ->
256	    info("received unknown message: ~n~p", [Unknown]),
257	    user_loop(S)
258    end.
259
260
261%% -------------
262
263do_handle_error(Pid, ReqId, Reason) ->
264    info("received error callback:"
265         "~n   ReqId:    ~p"
266         "~n   Reason:   ~p", [ReqId, Reason]),
267    Pid ! {ignore, self()},
268    ok.
269
270
271do_handle_agent(Pid, Domain, Address, Type, SnmpInfo) ->
272    info("received agent callback:"
273         "~n   Domain:   ~p"
274         "~n   Address:  ~p"
275         "~n   Type:     ~p"
276         "~n   SnmpInfo: ~p", [Domain, Address, Type, SnmpInfo]),
277    Pid ! {ignore, self()},
278    ok.
279
280
281do_handle_agent(Pid, Addr, Port, SnmpInfo) ->
282    info("received agent callback:"
283         "~n   Addr:     ~p"
284         "~n   Port:     ~p"
285         "~n   SnmpInfo: ~p", [Addr, Port, SnmpInfo]),
286    Pid ! {ignore, self()},
287    ok.
288
289
290do_handle_pdu(Pid, TargetName, ReqId, SnmpResponse) ->
291    info("received pdu callback:"
292         "~n   TargetName:   ~p"
293         "~n   ReqId:        ~p"
294         "~n   SnmpResponse: ~p", [TargetName, ReqId, SnmpResponse]),
295    Pid ! {ignore, self()},
296    ok.
297
298%% For backwards compatibillity
299do_handle_pdu(Pid, Addr, Port, ReqId, SnmpResponse) ->
300    info("received pdu callback:"
301         "~n   Addr:         ~p"
302         "~n   Port:         ~p"
303         "~n   ReqId:        ~p"
304         "~n   SnmpResponse: ~p", [Addr, Port, ReqId, SnmpResponse]),
305    Pid ! {ignore, self()},
306    ok.
307
308
309do_handle_trap(Pid, TargetName, SnmpTrap) ->
310    info("received trap callback:"
311         "~n   TargetName: ~p"
312         "~n   SnmpTrap:   ~p", [TargetName, SnmpTrap]),
313    Pid ! {ignore, self()},
314    ok.
315
316%% For backwards compatibillity
317do_handle_trap(Pid, Addr, Port, SnmpTrap) ->
318    info("received trap callback:"
319         "~n   Addr:     ~p"
320         "~n   Port:     ~p"
321         "~n   SnmpTrap: ~p", [Addr, Port, SnmpTrap]),
322    Pid ! {ignore, self()},
323    ok.
324
325
326do_handle_inform(Pid, TargetName, SnmpInform) ->
327    info("received inform callback:"
328         "~n   TargetName: ~p"
329         "~n   SnmpInform: ~p", [TargetName, SnmpInform]),
330    Pid ! {ignore, self()},
331    ok.
332
333%% For backwards compatibillity
334do_handle_inform(Pid, Addr, Port, SnmpInform) ->
335    info("received inform callback:"
336         "~n   Addr:       ~p"
337         "~n   Port:       ~p"
338         "~n   SnmpInform: ~p", [Addr, Port, SnmpInform]),
339    Pid ! {ignore, self()},
340    ok.
341
342
343do_handle_report(Pid, TargetName, SnmpReport) ->
344    info("received report callback:"
345         "~n   TargetName: ~p"
346         "~n   SnmpReport: ~p", [TargetName, SnmpReport]),
347    Pid ! {ignore, self()},
348    ok.
349
350%% For backwards compatibillity
351do_handle_report(Pid, Addr, Port, SnmpReport) ->
352    info("received report callback:"
353         "~n   Addr:       ~p"
354         "~n   Port:       ~p"
355         "~n   SnmpReport: ~p", [Addr, Port, SnmpReport]),
356    Pid ! {ignore, self()},
357    ok.
358
359
360info(F, A) ->
361    error_logger:info_msg("USER SIMULATOR " ++ F ++ "~n", A).
362
363
364%% -------------
365
366call(UserPid, Req) ->
367    call(UserPid, Req, 5000).
368
369call(UserPid, Req, To) ->
370    Ref = make_ref(),
371    UserPid ! {Req, self(), Ref},
372    receive
373	{Reply, UserPid, Ref} ->
374	    Reply
375    after To ->
376	    {error, timeout}
377    end.
378
379reply(Pid, Reply, Ref) ->
380    Pid ! {Reply, self(), Ref}.
381
382cast(UserPid, Msg) ->
383    UserPid ! {Msg, self()},
384    ok.
385
386
387%%----------------------------------------------------------------------
388%% User callback functions:
389%%----------------------------------------------------------------------
390
391handle_error(ReqId, Reason, UserPid) ->
392    UserPid ! {handle_error, self(), ReqId, Reason},
393    ignore.
394
395
396handle_agent(Domain, Address, Type, SnmpInfo, UserPid) ->
397    UserPid ! {handle_agent, self(), Domain, Address, Type, SnmpInfo},
398    ignore.
399
400
401%% For backwards compatibillity
402handle_agent(Addr, Port, SnmpInfo, UserPid) ->
403    UserPid ! {handle_agent, self(), Addr, Port, SnmpInfo},
404    ignore.
405
406
407handle_pdu(TargetName, ReqId, SnmpResponse, UserPid) ->
408    UserPid ! {handle_pdu, self(), TargetName, ReqId, SnmpResponse},
409    ignore.
410
411%% For backwards compatibillity
412handle_pdu(Addr, Port, ReqId, SnmpResponse, UserPid) ->
413    UserPid ! {handle_pdu, self(), Addr, Port, ReqId, SnmpResponse},
414    ignore.
415
416
417handle_trap(TargetName, SnmpTrap, UserPid) ->
418    UserPid ! {handle_trap, self(), TargetName, SnmpTrap},
419    ok.
420
421%% For backwards compatibillity
422handle_trap(Addr, Port, SnmpTrap, UserPid) ->
423    UserPid ! {handle_trap, self(), Addr, Port, SnmpTrap},
424    ok.
425
426
427handle_inform(TargetName, SnmpInform, UserPid) ->
428    UserPid ! {handle_inform, self(), TargetName, SnmpInform},
429    ok.
430
431%% For backwards compatibillity
432handle_inform(Addr, Port, SnmpInform, UserPid) ->
433    UserPid ! {handle_inform, self(), Addr, Port, SnmpInform},
434    ok.
435
436
437handle_report(TargetName, SnmpReport, UserPid) ->
438    UserPid ! {handle_report, self(), TargetName, SnmpReport},
439    ok.
440
441%% For backwards compatibillity
442handle_report(Addr, Port, SnmpReport, UserPid) ->
443    UserPid ! {handle_report, self(), Addr, Port, SnmpReport},
444    ok.
445