Pass in the dialogue from the lower layer to make sure to respond
to the right party (including the from/to being in the right order).
Implement the re-invite that is needed to keep a phone call alive
for more than 45 seconds on this system.
Add a testcase for testing ProxyAuthenticate and ProxyAuthorize,
extend the grammar and parser to handle the needed bits. Document
another error/failure with the dialog handling code and create a
testcase that fully connects a call.
* -> INVITE
* <- 100 Trying
* -> Cancel
* <- 200 ACK
* -> OK
* <- 100 Trying
...
* <- 463 Timeout
and we would run through the same circle again. Instead opt for
a simple work-around right now and remember if we canceled once.
We should spawn a transaction and remember the result.
To support servers behind a NAT we need to include the rport
parameter in our via. This way the server will respond to us
on the sourceport it got the message from.
We will probably need to implement the same and return the
sourceport as rport=1234 to the other end.
We must extend the grammar to add caseInsensitive to a lot of
fields as they are case-insensitive as part of the specification
this even applies to some parameter names where expires and
eXpiReS are considered to be the same. Start with the simple
case of the parameter.
Avoid infinite auth retries and remember if the last message has
been an authentication request. Ignore the 100 TRYING like messages
as they do not add much value.
This should work for all transactions carried out by the transaction
layer but the unit test is only created for INVITE. It has not been
verified against another SIP engine yet. It has not been verified for
BYE/ACK. Specially for ACK the code might still be wrong as the wrong
operation name is taken into account for the digest.
We would need to have SIPParameter as a baseclass that works without
having a dataobject. Right now this is a duck-type as it implements
the used methods.
This only implements one of the possible approaches for the digest
handling. This is a very simple test and the choiche of the same
username/password was a bit unfortunate.
Update the grammar to handle the WWW-Authenticate according to the
RFC. Add the parser to compact everything into a Dictionary. Add the
realm last to avoid being overwritten with another parameter.
These generate random strings so it is difficult to unit test. But
the invocation worked:
st> Osmo.SIPRandomHelper generateTag
'MzU0MjIxMTQ1OTIzODI1ODc3NjU_'
st> Osmo.SIPRandomHelper generateCallId
'MTk3MTU3OTAxOA__@xiaoyu'
st> Osmo.SIPUserAgent generateBranch
'z9hG4bKMzU0MjIwNDM2Myw0MjIxNg__'
* Change the category for the tests and extensions
* Rewrite usages of >>nl and >>cr
* There are still issues with the Socket code, Datagram handling
and and expands.
Use DatagramSocket>>ensureReadable as this is using async poll,
make sure the socket is still open after ensureReadable returns.
Move the RX/TX into selectors as this allows us to return from
them.
The class was called SIPSecureRandom as it used /dev/random for
random numbers. The downside of /dev/random is that a read can
block until enough data has been generated. This does occur, e.g.
on an isolated system. Start using /dev/urandom for the tags. It
is better than the Mersene twister of GST but it is no source
for key material.
* This isn't doing proper routing (e.g. the via is not modified
properly but we return it to the right address)
* An unknown BYE will be acked with a 481. The 'respondWith:...'
includes the wrong 'Allow:' but it is good enough from the
structure for now.
* Re-Order the loading of files as the SIPUserAgent is extended
the SIPRequests.
* Add the port/ip to the SIPDialog so that responding to the
request is possible.
The name session base is a bit misleading as it is not the session
that holds the initial dialog, the confirmed dialog, the UAS and then
also the session when it is setup. When the dialog gets confirmed we
will register it with the useragent and then will be called for new
requests. On hangup/cancel the dialog will be scheduled for removal.
Constructing a PetitParser is an expensive operation (Object>>becomeForward:)
we can keep the parser in the class. For the SIPTransactions we keep it as
a global, it is assumed that all SIPTransactions operate through the same
process and will not run into concurrency issues.
This is still more complicated (and wrong) then it should be,
when we CANCEL an INVITE we can either send a CANCEL or we need
to wait for a 100. Now the CANCEL could be too late (the server
already sent a 200), in that case we would get a 200 for the
INVITE and pass this to the higher levels (which we probably
should).
The code only tests this with the response but it should work for
the request as well. Depending on this one needs to switch from/to
but this needs to happen on a higher level.
The CSeq only needs to be unique within a dialog, so we can have
a global function to generate a valid CSeq start (< 2^31) and then
handle cseq's within the dialog.
Introduce a high level class that can create multiple transactions,
handles the sequence numbers, the dialogs, the opened session and
provides a nice call, hangup, cancel, terminate interface.
This is fixing a previous commit, fixes the timed out handling, attempts
to change the initial dialog -> confirmed dialog handling (but still
gets it wrong, it should compare the dialog, or just get a new dialog
from the response and check if it is compatible with the initial dialog).
Only the INVITE transaction can be canceled, when it gets
canceled we might or might not get a confirmation or we might
be too late to cancel things. With this flag we will be able
to do something sensible when we get a late final response.
The transaction now work on something called an initial dialog, e.g.
during a INVITE we go from an initial dialog to a confirmed dialog and
maybe create a session. Prepare the code to support this.
It is still not clear how callbacks, dialog confirmation and session
creation will be handled but it will somehow fit together.
Parse every generic_param (or specialized) into a SIPGenericParam,
provide a asFoldedString implementation, tell the folding code about
it, create a SIPToFromParam that holds the list of params.
Dispatch the data from thre socket in a new context. This assures
that we will not run into locking issues. One day where we will have
VMs that can use multiple cores we might have a dispatcher set in
each transaction/session. The we could establish a rule that each
transaction is dispatched in the right/same queue.