|
Hi Olivier – here you go with the code changes you asked for: For completeness, this is the spec: Added
timeout="milliseconds" as a recv (and recvCmd) option. This sets a
time limit on how long to wait for a received message. (Note that if you have
optional receives in a sequence, the timeout needs to be set on every one, not
just the last. The times may be additive.) Added
as an option to timeout for recv, recvCmd and send
(with retrans) to allow control of the flow on timeout rather than just
dropping through to the next statement. Added
optional="global" as a new option and changed the meaning of
optional="true" to be limited to a consecutive sequence of receives. And this was the further discussion on the last item: On the last I thought I had sent a separate email. I
discovered that in process_incomming() the code section headed /* Try to
find it in the old non-mandatory receptions */ looks backwards without limit.
We were working on some very long scenarios at the time with lots of optional
receives and until I looked at the code I believed that an optional receive had
to be part of the immediate receive block. So I decided to change
optional="true" to search only as far as the next non-receive and
have optional="global" incase we actually needed the original
behaviour. (Clearly you could keep optional="true" and add
optional="local" if you thought the existing code was correct.) OJ>>Hmmm. I must
have missed the email. Clearly, the current behaviour is not expected
(pessimist programmers or even testers might call this a bug :) ). I also
thought that the optional="true" was local. I think that
optional="global" (the current behavior) should not be kept. Ok, I'm
up for those changes too :) (Note originally I had
another item, but when I looked further, I discovered that the public code
already has an equivalent change.) Line numbers refer to the sipp_2006_07_11
version. The first set of changes is to scenario.hpp/cpp
to implement the new options: In scenario.hpp, add these defines after
the existing ones, say at line 53. #define
OPTIONAL_TRUE 1 #define
OPTIONAL_FALSE 0 #define
OPTIONAL_GLOBAL 2 #define
MAX_LABELS 20 Later (line 81) in the message class, change
the definition of optional to int:
int optional; In the “anyway” section (line
89), add: unsigned
int on_timeout; At the end (line 150), change the
labelArray declaration to this line: extern unsigned
int labelArray[MAX_LABELS]; Notes on the above: 1) I maybe should have
used an enum for optional. 2) I re-used the send variable retrans_delay for
receive as well – probably worth a comment. 3) I actually have MAX_LABELS
set to 100 on my system because I needed more labels. In scenario.cpp (line 56) add a line to initialize
on_timeout: > In scenario.cpp load_scenario(), in the
recv decode, replace the current optional test (lines 328-333) by this one and
add the timeout decode:
if (0 != (ptr = xp_get_value((char *)"optional"))) {
if(!strcmp(ptr, "true")) {
scenario[scenario_len] -> optional = OPTIONAL_TRUE;
++recv_opt_count;
}
if(!strcmp(ptr, "global")) {
scenario[scenario_len] -> optional = OPTIONAL_GLOBAL;
++recv_opt_count;
}
}
if (0 != (ptr = xp_get_value((char *)"timeout"))) {
scenario[scenario_len]->retrans_delay = atol(ptr);
} Later, in the generic section at the end
(line 494), add this code:
if (0 != (ptr = xp_get_value((char *)"ontimeout")) ) {
if ((::scenario[scenario_len]-> >= MAX_LABELS) {
ERROR_P1("Ontimeout label larger than max supported %d",
MAX_LABELS-1);
}
} Note with the above code “ontimeout”
will be accepted in any scenario command – it is only implemented with
send, recv and recvCmd though. Currently if you next to an undefined
label, you go to scenario line 0 – some would call that a bug. The
current code has no test that all used labels are defined, that labels are
defined only once, etc. For the purpose of keeping this change simple, I have
left my fixes for these out because they involve several changes to other
existing bits of code. There is also a bug fix that you need here,
replace line 495 (was scenario_len++;) by this test:
if (++scenario_len >= SCEN_MAX_MESSAGES) {
ERROR("Too many items in xml scenario file");
} Otherwise too long scenario files seg
fault. In call.cpp we need to implement these
things, I’ll do them by function rather than position in the file: In the retransmit code, where we detect
too many retransmissions, we need to test for “ontimeout” being set.
So between lines 1126 and 1127,
which are:
scenario[last_send_index] -> nb_timeout ++;
CStat::instance()->computeStat(CStat::E_CALL_FAILED); Insert this new code:
if (scenario[last_send_index]->on_timeout) { // action on timeout
msg_index = labelArray[scenario[last_send_index]->on_timeout];
next_retrans = 0;
WARNING_P2("Step call %ld to state %d on timeout",m_number,msg_index);
recv_timeout = 0;
if (msg_index < scenario_len) return true;
// here if asked to go to the last label – delete the call
CStat::instance()->computeStat(CStat::E_CALL_FAILED);
delete_call(id);
return false;
} Note the code I have is not exactly as
above – I just drop through for the last label case. However the public
code has the “default_behavior” logic and I think you don’t
want default behaviour if you explicitly asked to go to a label that does
nothing. In the periodic scan, we need to implement
the receive timeout code. So near the very end of run(), change line 1304 from } to:
} else if (scenario[msg_index]->M_type == MSG_TYPE_RECV #ifdef __3PCC__ ||
scenario[msg_index]->M_type == MSG_TYPE_RECVCMD #endif
)
{
if (recv_timeout) {
if(recv_timeout > clock_tick || recv_timeout > getmilliseconds()) {
return true;
}
recv_timeout = 0;
++scenario[msg_index]->nb_timeout;
if (scenario[msg_index]-> 0) {
// if you set a timeout but not a label you drop through to the next scenario
line
return next();
}
msg_index = labelArray[scenario[msg_index]->on_timeout];
recv_timeout = 0;
WARNING_P2("Step call %ld to state %d on recv timeout",m_number,msg_index);
if (msg_index < scenario_len) return true;
// special case - the label points to the end - finish the call
CStat::instance()->computeStat(CStat::E_CALL_FAILED);
delete_call();
return false;
} else if (scenario[msg_index]->retrans_delay) {
recv_timeout = getmilliseconds() + scenario[msg_index]->retrans_delay;
return true;
}
} Just to check – the next line is:
return true; Again my code is different because I use a
switch rather than an if(){ } else if () { } chain. Note the way the above
works is that on the call to run() on entering receive mode it starts the
timeout and on following scans it checks for timeout expiry. There are a few things you need to do to
add recv_timeout to the class, etc. Define it in call.hpp:
unsigned int recv_timeout; Initialize it,
recv_timeout(0), and clear it when we do a next():
recv_timeout = 0; Note it was also cleared in the transmit “ontimeout”
above. I could not find any other cases that the public code jumps about the
scenario without going through next() – if there are then they also need
to clear recv_timeout. Next we need to implement the optional=”global”
or optional=”true” stuff. The current code at call.cpp line 2355
is: /* Try to
find it in the old non-mandatory receptions */ if(!found)
{
for(search_index = msg_index - 1;
search_index >= 0;
search_index--) {
if(MATCHES_SCENARIO(search_index)) {
if ((scenario[search_index] -> optional)) {
found = true;
break; Change it to this: /* Try to
find it in the old non-mandatory receptions */ if(!found)
{
bool contig = true;
for(search_index = msg_index - 1;
search_index >= 0;
search_index--) {
if (scenario[search_index]->optional == OPTIONAL_FALSE) contig = false;
if(MATCHES_SCENARIO(search_index) &&
(contig || scenario[search_index]->optional == OPTIONAL_GLOBAL)) {
found = true;
break; I think that’s everything. Let me
know of any problems or questions. --------------- This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and delete this e-mail. Any unauthorized copying, disclosure or distribution of the contents in this e-mail is strictly forbidden. --------------- |
------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________ Sipp-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sipp-users
