Rejecting transfers to in-use parking spaces

Home » Asterisk Users » Rejecting transfers to in-use parking spaces
Asterisk Users 4 Comments

> I’m trying to emulate the functionality of our existing phone system,
> which is somewhat different than what Asterisk provides with a
> trivial parking configuration. I’d like each user to have three park
> buttons, park 1, park 2, park 3. The snom 870s I’m using have a
> “Park+Orbit” button, which best I can determine, is a shortcut to
> transfer someone to an extension. So, I defined some extensions:
> exten => _*70[123],1,NoOp(parking in ${EXTEN:1})
> same => n,Set(PARKINGEXTEN=${EXTEN:1})
> same =>
> n,GotoIf(${DEVICE_STATE(park:${PARKINGEXTEN}@parkedcalls)}=INUSE?busy)
> same => n,Park()
> same => n(busy),Busy()
> As you can see, I’m calling Busy() if someone is already parked in
> the space, but this doesn’t do what I’d like. What I’m hoping to
> accomplish is have Asterisk respond to the Sip REFER to *701 with a
> 404 or similar response; if Asterisk can do this, then the Snom will
> say “transfer failed!”. As it is, the transfer is successful, and
> the caller hears a busy tone. Is there an application that has the
> effect of “Pretend this extension doesn’t exist”, or can I somehow
> get the caller back to the person that tried to park them in this
> space that’s in use?

The dialplan device state check above is not always going to work
because another call could park in that space between the check
and the actual park. The device state check in this case is
also unnecessary because Park will continue executing dialplan if
the park fails.

You could try three parkinglots with one parking space each. Each
phone park button would transfer the call to a different parkinglot.
Then all you need to do is include the parkinglot context(s) into your
dialplan context to have access to the generated parking extensions.

Please note that for Asterisk to detect an extension as a parking
extension, the first priority of the extension must be the park
application. If the park application is not the first priority of
the extension, then the transfer is treated as a normal transfer.


4 thoughts on - Rejecting transfers to in-use parking spaces

  • Hmm. Well, I could live with that race condition. Our call volume is low enough that the odds of hitting it acceptably low.

    I’m not entirely sure what it means for Asterisk to detect an extension as a parking extension. Can you please explain how a parking transfer is different than a normal transfer?

  • The next sentence also tried to point out that the check is not even
    needed because if Park fails for whatever reason, it continues executing
    dialplan. With that dialplan, it is mainly going to fail if the parking
    space is already in use.

    If Asterisk detects the extension as a parking extension:
    exten => 700,1,Park()
    Asterisk can perform special processing dealing with parking the
    call that may be needed for the channel driver. Also note that the
    dialplan extension is *not* actually executed in this case.

    For SIP, blind transferring to parking, the parking is done as part
    of the transfer. If the park attempt fails, the transfer fails. A
    normal blind transfer would complete the transfer and then execute
    the dialplan extension on the transferred channel.

    For DTMF transfers (features.conf), attended and blind transferring
    to parking are identical. You will always hear the parking space
    assigned. If the park attempt fails, the interrupted bridge will be


  • Thanks, that was very helpful. I tweaked a bit, and ended up with this working code:

    exten => _70[123],1,NoOp(Dynamic Parking Pickup from ${BLINDTRANSFER})
    ; if this was a blind transfer, attempt to park the call. Otherwise, unpark
    ; the call.
    same => n,GoToIf($[${LEN(${BLINDTRANSFER})} > 0]?attemptpark)
    same => n,ParkedCall(${EXTEN})

    same => 100(attemptpark),NoOp(Attempt To Park)
    same => n,Set(PARKINGEXTEN=${EXTEN})
    same => n,Park(,${CONTEXT},${EXTEN},200,s) ; return priority here must be a number, not a label.
    same => n,Goto(200)

    ; send the call back to the sender. Either the park timed out, or the
    ; parking space was in use, or otherwise failed to park.
    same => 200(backtosender),Dial(${PARKRETURNTO},300)

    I’m a bit unsure if grabbing the channel name from BLINDTRANFSER, cutting off the bit after “-“, and passing that to Dial() is the Right Thing. It appears to work, though I’m quite inexperienced. I guess my concern is that the channel names might not necessarily be a dial()able thing. Of course, it would be better if I could just reject the transfer, but that doesn’t sound like it’s possible. Anyone have pointers on how to make this more robust? Is there any way I can get more information about the channel referenced by BLINDTRANSFER? Maybe I’ll also dial the front desk after dialing PARKRETURNTO, just in case.

    On the phone side, I configured three BLFs for 701-703. This does require that to park a caller, the receptionist hits “transfer”, then the BLF. However, this is more explicit, and avoids a weird case where someone else parks a call just before the receptionist hits the park button, so she ends up putting the caller on hold and unparking someone else, rather than parking the caller as she intended. I think I’ll teach users to not depend so heavily on park, and they will adapt.