<div dir="ltr"><div><div><div><div><div><div>Hi Anders,<br><br></div>Thanks for your explanation. Setting additional options in diameter:add_transport and retrieving them with diameter:service_info from the peer_up callback work well. And the descriptions about the peer states according to RFC3539 and 6733 make a lot of sense.<br>
<br></div>The case I am trying to resolve is:<br></div>Start multiple processes on one pc, each process tries to connect to one same server (obviously I will get already_connected warning, but it can keep going), in each process, then I try to send a diameter message to the server, I used to insert a certain amount of sleep time before I send the message after connecting to the server and it works ok. But I wanted to use the peer up callback to behave like a handshaking procedure among the client and the server, so the server is supposed to be ready when the client process sends the message.<br>
<br></div>Now, the fact is that only one peer up callback is invoked for multiple processes. Then I tried to notify all the processes in the peer up callback when invoked and the processes send out the diameter messages. However, the processes don't receive any responses. Or sometimes only part of the processes get responses. Why inserting an amount of sleep time always works. <br>
<br>This is a little bit confusing me, how peer up should be used properly to get the notification done right for multiple processes.<br></div><br></div><div>Thanks for any suggestions!<br><br></div><div>Samuel<br><br><br>
</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Apr 25, 2013 at 5:40 AM, Anders Svensson <span dir="ltr"><<a href="mailto:anders.otp@gmail.com" target="_blank">anders.otp@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On Wed, Apr 24, 2013 at 5:23 PM, S X <<a href="mailto:erlangprogram@gmail.com">erlangprogram@gmail.com</a>> wrote:<br>
> Thanks a lot for your comments.<br>
><br>
> The diameter:call function allows to send extra arguments. It works fine<br>
> after changing the callback function signatures accordingly. This is very<br>
> useful when I want to notify the other process to do the next thing.<br>
><br>
> Before sending a diameter message, we call diameter:add_transport to connect<br>
> to a peer and peform CER/CEA capability information exchange. On the caller<br>
> side, let's say the client callback module, the peer_up will be invoked when<br>
> CER/CEA is completed. Why it doesn't have the similar mechanism like<br>
> diameter:call to allow insert additional arguments so we can utilize them,<br>
> for example, notify the others to send diameter messages?<br>
<br>
</div>No particular reason aside from history and that the need hasn't come<br>
up. As it is, you can pass arbitrary options to<br>
diameter:add_transport/2 (history again) and retrieve these in a<br>
callback with diameter:service_info(PeerRef), so that can be used a<br>
substitute for extra arguments in this case.<br>
<div class="im"><br>
> diameter:add_transport is a sync call, but it doesn't mean you can send<br>
<br>
</div>add_transport *doesn't* wait for the config it's passed to result in a<br>
connection before returning. (It might never happen for one.)<br>
<div class="im"><br>
> diameter messages successfully when the function returns, i.e. it usually<br>
> gets {error, no_connection} or { error, timeout }(this might because of the<br>
> server side) if you call diameter:call right after diameter:add_transport.<br>
<br>
</div>This is because the peer won't be ready to respond to requests until<br>
capabilities exchange has completed (at least). If you call before the<br>
relevant peer_up callback then the result is {error, no_connection}.<br>
After peer_up the result will be {error, timeout} if the peer doesn't<br>
answer. One case in which this is expected is after a connection has<br>
been reestablished following an exchange of 3 x DWR/DWA. (ie. RFC 3539<br>
DOWN -> REOPEN -> OKAY.) Since both ends of the connection do this,<br>
the client can consider the connection to be reestablished before the<br>
server. If the client sends a request before the server is done with<br>
it's exchange (ie. reached OKAY) then RFC 6733 says it should discard<br>
the request, resulting in a timeout on the client end.<br>
<div class="im"><br>
> So is there any reason why not allowing to add additional arguments and use<br>
> them in peer_up callback function? Since it means capability exchange is<br>
> done and the peer is ready, at this point it should be safe to send diameter<br>
> messages to the peer.<br>
<br>
</div>See above.<br>
<span class="HOEnZb"><font color="#888888"><br>
Anders<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
><br>
> Any suggestions?<br>
><br>
> Thanks!<br>
><br>
> Samuel<br>
><br>
><br>
> On Tue, Apr 16, 2013 at 7:22 AM, Anders Svensson <<a href="mailto:anders.otp@gmail.com">anders.otp@gmail.com</a>><br>
> wrote:<br>
>><br>
>> On Sun, Apr 14, 2013 at 7:01 PM, S X <<a href="mailto:erlangprogram@gmail.com">erlangprogram@gmail.com</a>> wrote:<br>
>> > Hello,<br>
>> ><br>
>> > Based on the erlang diameter library and the sample code, I want to<br>
>> > start<br>
>> > multiple diameter client processes in one erlang node(one client IP),<br>
>> > and<br>
>> > the client needs to define a diameter_app callback module for certain<br>
>> > application, for example:<br>
>> ><br>
>> > -define(SERVICE(Name), [{'Origin-Host', ?L(Name) ++ ".<a href="http://example.com" target="_blank">example.com</a>"},<br>
>> > {'Origin-Realm', "<a href="http://example.com" target="_blank">example.com</a>"},<br>
>> > {'Vendor-Id', 193},<br>
>> > {'Product-Name', "Client"},<br>
>> > {'Auth-Application-Id',<br>
>> > [?DIAMETER_APP_ID_COMMON,<br>
>> > ?DIAMETER_APP_ID_CCRA]},<br>
>> > {application, [{alias, ?APP_CCR_ALIAS},<br>
>> > {dictionary,<br>
>> > ?DIAMETER_DICT_CCRA},<br>
>> > {module, client_cb_ccra}]}]).<br>
>> ><br>
>> ><br>
>> > First question:<br>
>> > how the diameter library handles this situation? Will all diameter<br>
>> > client<br>
>> > processes share one single diameter_app callback module "client_cb_ccra"<br>
>> > or<br>
>> > it will automatically attach different instance of the callback module<br>
>> > (process) to the different client process by using spawn_monitor? So<br>
>> > from<br>
>> > the callback handle_answer in "client_cb_ccra" I can notify the proper<br>
>> > client proce by just calling client:notify() something.<br>
>><br>
>> diameter doesn't know anything about your client process. If you want<br>
>> a callback to be able to contact the client process associated with<br>
>> the service in question (ie. the service whose name the callback gets<br>
>> as an argument) then you need to give the callback the means to do so.<br>
>> One way would be to map the service name to your process (eg. it's the<br>
>> registered name of your client process), another would be to pass some<br>
>> identification as extra arguments to the callbacks. (Eg. {module,<br>
>> [client_cb_ccra, X]} in the config above.)<br>
>><br>
>> > Second question:<br>
>> > Notice that diameter:call allows to set extra arguments, so I was<br>
>> > wondering<br>
>> > I could set some data like:<br>
>> > diameter:call(Name, ?APP_CCR_ALIAS, CCR, [{extra, [self()]}]).<br>
>> > which sets the client process ID and I hope to deliver to the callback<br>
>> > module "client_cb_ccra" and when the callback module knows which client<br>
>> > process sends request and response accordingly, for example using the<br>
>> > client<br>
>> > process ID in the callback function handle_answer.<br>
>><br>
>> You can do that, but what is it you're trying to accomplish? if it's<br>
>> handle_answer that's supposed to communicate something then it already<br>
>> does: the return value of handle_answer is returned by diameter:call.<br>
>><br>
>> > However, I don't want pack the extra arguments into the diameter packet<br>
>> > since the diameter server doesn't know what they are and the extra ones<br>
>> > are<br>
>> > not part of standard diameter packet.<br>
>><br>
>> Not sure what you mean here. There's no way for your client to send<br>
>> the server anything other than a Diameter message.<br>
>><br>
>> > Now I changed the pick_peer callback signatures to allow extra<br>
>> > arguments,<br>
>> > pick_peer([Peer | _], _, _SvcName, _State, A)<br>
>> ><br>
>> > But I got encoding error in the callback prepare_request<br>
>> ><br>
>> > =ERROR REPORT==== 14-Apr-2013::11:40:41 ===<br>
>> > Error in process <0.175.0> with exit value:<br>
>> > {undef,[{client_cb_ccra,prepare_request,[{diameter_packet,<br>
>><br>
>> The arity of your callback probably doesn't agree with the number of<br>
>> extra arguments you've specified: prepare_request will also get your<br>
>> extra arguments.<br>
>><br>
>><br>
>> > >{diameter_header,1,undefined,undefined,undefined,3958849953,3958849953,undefined,undefined,undefined,undefined},undefined,{diameter_rfc4006_cc_CCR,["who",";","142745567...<br>
>> ><br>
>> > {error,encode}<br>
>> ><br>
>> > In overall, I read the online documents, which have limited information<br>
>> > on<br>
>> > how to use the extra arguments in the library and don't quite get how<br>
>> > to<br>
>> > utilize the extra arguments to do something tricky,<br>
>> ><br>
>> > Are there any suggestions on how to deal with multiple client processes?<br>
>><br>
>> Not sure I understand what problem it is you're trying to solve.<br>
>> Multiple processes invoking diameter:call is nothing strange. You<br>
>> typically just return something useful (eg. the answer message from<br>
>> the peer) from handle_answer, which diameter:call then returns for the<br>
>> caller to deal with.<br>
>><br>
>> Anders<br>
>><br>
>><br>
>> > Thanks a lot!<br>
>> ><br>
>> > Samuel<br>
>> ><br>
><br>
><br>
</div></div></blockquote></div><br></div>