And they said it's going to be simple.

Why?

It's kind of cool having SMS. Texts can be more then thousand words. But in the specific case we're dealing with at least 250 chars of pure message transport which may be useful.

How?

In order to enable SMS, we have to add a message context to our basic macros, which are used to configure the phones

[phone_endpoint_macro](!)
type=endpoint
transport=transport-udp
context=internalsip
disallow=all
allow=g722
allow=alaw
message_context=messages ## new line

Auth failed

The first tries ended (again) with auth failes, but as the traning of the last pjsip and asterisk experience helped to understand the product, it was simple.

2019-04-15T23:47:47.375293+02:00 asterisk asterisk[1]: NOTICE[295]: res_pjsip/pjsip_distributor.c:676 in log_failed_request: Request 'MESSAGE' from '<sip:11@asterisk.my.net>' failed for '10.11.12.89:5062' (callid: 3342885942@10.11.12.89) - No matching endpoint found
2019-04-15T23:47:47.378077+02:00 asterisk asterisk[1]: NOTICE[295]: res_pjsip/pjsip_distributor.c:676 in log_failed_request: Request 'MESSAGE' from '<sip:11@asterisk.my.net>' failed for '10.11.12.89:5062' (callid: 3342885942@10.11.12.89) - Failed to authenticate

You have to enable history. History is what makes future generation better then the current one, as the could learn from us and do not redo our faults. Yes - this is theoretically true. In this case we could learn and see how this works by issuing pjsip set history on into the asterisk console.

Looking into the history helped understanding that the Contact: header is not present in a sip MESSAGE message. I needed another way to identify the phones. The From: header appears to be a better choice.

[11_message]
type=identify
endpoint=phone_11
match_header=From:/11@/

This introduced the XY_message node to all configs, where XY is the number of the phone.

Adding identifier leads to working SMS

Complete conversation when working.

# pjsip set history on
...
# pjsip show history
No.   Timestamp  (Dir) Address                  SIP Message
===== ========== ============================== ===================================
00000 1555366967 * <== 10.11.12.211:5060      MESSAGE sip:*11@asterisk.my.net SIP/2.0
00001 1555366967 * ==> 10.11.12.211:5060      SIP/2.0 401 Unauthorized
00002 1555366967 * <== 10.11.12.211:5060      MESSAGE sip:*11@asterisk.my.net SIP/2.0
00003 1555366967 * ==> 10.11.12.211:5060      SIP/2.0 415 Unsupported Media Type
00004 1555366968 * <== 10.11.12.211:5060      MESSAGE sip:*11@asterisk.my.net SIP/2.0
00005 1555366968 * ==> 10.11.12.211:5060      SIP/2.0 401 Unauthorized
00006 1555366968 * <== 10.11.12.211:5060      MESSAGE sip:*11@asterisk.my.net SIP/2.0
00007 1555366968 * ==> 10.11.12.211:5060      SIP/2.0 202 Accepted
00008 1555366968 * ==> 10.11.12.89:5062       MESSAGE sip:11@10.11.12.89:5062 SIP/2.0
00009 1555366968 * <== 10.11.12.89:5062       SIP/2.0 200 OK
#  pjsip show history entry 1
<--- History Entry 1 Sent to 10.11.12.211:5060 at 1555366967 --->
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.11.12.211:5060;rport=5060;received=10.11.12.211;branch=z9hG4bK.Bn3J-uxme
Call-ID: zVm0LoNRCI
From: "21" <sip:21@asterisk.my.net>;tag=mcK7gvg3V
To: <sip:*11@asterisk.my.net>;tag=z9hG4bK.Bn3J-uxme
CSeq: 20 MESSAGE
WWW-Authenticate: Digest realm="asterisk.my.net",nonce="***",opaque="***",algorithm=md5,qop="auth"
Server: Asterisk PBX 15.x.y
Content-Length:  0


#  pjsip show history entry 2
<--- History Entry 2 Received from 10.11.12.211:5060 at 1555366967 --->
MESSAGE sip:*11@asterisk.my.net SIP/2.0
Via: SIP/2.0/UDP 10.11.12.211:5060;rport=5060;received=10.11.12.211;branch=z9hG4bK.et~mbbgxr
From: "21" <sip:21@asterisk.my.net>;tag=mcK7gvg3V
To: <sip:*11@asterisk.my.net>
CSeq: 21 MESSAGE
Call-ID: zVm0LoNRCI
Max-Forwards: 70
Supported: replaces, outbound
Content-Type: application/im-iscomposing+xml
Content-Length: 282
Date: Mon, 15 Apr 2019 22:22:47 GMT
User-Agent: Linphone Desktop
Authorization: Digest username="21", realm="asterisk.my.net", nonce="***", uri="sip:*11@asterisk.my.net", response="***", algorithm=md5, cnonce="***", opaque="***", qop=auth, nc=00000001
Content-Type: application/im-iscomposing+xml
Content-Length:   282

<?xml version="1.0" encoding="UTF-8"?>
<isComposing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xml:ns:im-composing iscomposing.xsd" xmlns="urn:ietf:params:xml:ns:im-iscomposing"><state>active</state><refresh>60</refresh></isComposing>

#  pjsip show history entry 3
<--- History Entry 3 Sent to 10.11.12.211:5060 at 1555366967 --->
SIP/2.0 415 Unsupported Media Type
Via: SIP/2.0/UDP 10.11.12.211:5060;rport=5060;received=10.11.12.211;branch=z9hG4bK.et~mbbgxr
Call-ID: zVm0LoNRCI
From: "21" <sip:21@asterisk.my.net>;tag=mcK7gvg3V
To: <sip:*11@asterisk.my.net>;tag=z9hG4bK.et~mbbgxr
CSeq: 21 MESSAGE
Server: Asterisk PBX 15.x.y
Content-Length:  0


#  pjsip show history entry 4
<--- History Entry 4 Received from 10.11.12.211:5060 at 1555366968 --->
MESSAGE sip:*11@asterisk.my.net SIP/2.0
Via: SIP/2.0/UDP 10.11.12.211:5060;rport=5060;received=10.11.12.211;branch=z9hG4bK.OXdrC2BlC
From: "21" <sip:21@asterisk.my.net>;tag=T2noKmvzC
To: <sip:*11@asterisk.my.net>
CSeq: 20 MESSAGE
Call-ID: i4jsoh30d8
Max-Forwards: 70
Supported: replaces, outbound
Content-Type: text/plain
Content-Length: 4
Date: Mon, 15 Apr 2019 22:22:48 GMT
User-Agent: Linphone Desktop
Content-Type: text/plain
Content-Length:     4

test
#  pjsip show history entry 5
<--- History Entry 5 Sent to 10.11.12.211:5060 at 1555366968 --->
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.11.12.211:5060;rport=5060;received=10.11.12.211;branch=z9hG4bK.OXdrC2BlC
Call-ID: i4jsoh30d8
From: "21" <sip:21@asterisk.my.net>;tag=T2noKmvzC
To: <sip:*11@asterisk.my.net>;tag=z9hG4bK.OXdrC2BlC
CSeq: 20 MESSAGE
WWW-Authenticate: Digest realm="asterisk.my.net",nonce="***",opaque="***",algorithm=md5,qop="auth"
Server: Asterisk PBX 15.x.y
Content-Length:  0


#  pjsip show history entry 6
<--- History Entry 6 Received from 10.11.12.211:5060 at 1555366968 --->
MESSAGE sip:*11@asterisk.my.net SIP/2.0
Via: SIP/2.0/UDP 10.11.12.211:5060;rport=5060;received=10.11.12.211;branch=z9hG4bK.mrgpt9CoH
From: "21" <sip:21@asterisk.my.net>;tag=T2noKmvzC
To: <sip:*11@asterisk.my.net>
CSeq: 21 MESSAGE
Call-ID: i4jsoh30d8
Max-Forwards: 70
Supported: replaces, outbound
Content-Type: text/plain
Content-Length: 4
Date: Mon, 15 Apr 2019 22:22:48 GMT
User-Agent: Linphone Desktop
Authorization: Digest username="21", realm="asterisk.my.net", nonce="***", uri="sip:*11@asterisk.my.net", response="***", algorithm=md5, cnonce="***", opaque="***", qop=auth, nc=00000001
Content-Type: text/plain
Content-Length:     4

test
#  pjsip show history entry 7
<--- History Entry 7 Sent to 10.11.12.211:5060 at 1555366968 --->
SIP/2.0 202 Accepted
Via: SIP/2.0/UDP 10.11.12.211:5060;rport=5060;received=10.11.12.211;branch=z9hG4bK.mrgpt9CoH
Call-ID: i4jsoh30d8
From: "21" <sip:21@asterisk.my.net>;tag=T2noKmvzC
To: <sip:*11@asterisk.my.net>;tag=z9hG4bK.mrgpt9CoH
CSeq: 21 MESSAGE
Server: Asterisk PBX 15.x.y
Content-Length:  0

#  pjsip show history entry 8
<--- History Entry 8 Sent to 10.11.12.89:5062 at 1555366968 --->
MESSAGE sip:11@10.11.12.89:5062 SIP/2.0
Via: SIP/2.0/UDP 10.11.12.241:5060;rport;branch=z9hG4bKPj91c83cc2-0cce-46ff-9c5c-c08727ca9376
From: <sip:*21@asterisk.my.net>;tag=80050dc3-95e3-4cf7-8e4e-739a526b89d9
To: <sip:11@10.11.12.89>
Contact: <sip:phone_11@10.11.12.241:5060>
Call-ID: 63b9b56e-d07f-42c1-aaa2-5ef7b928897e
CSeq: 35588 MESSAGE
Max-Forwards: 70
User-Agent: Asterisk PBX 15.x.y
Content-Type: text/plain
Content-Length:     4

test
#  pjsip show history entry 9
<--- History Entry 9 Received from 10.11.12.89:5062 at 1555366968 --->
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.11.12.241:5060;rport;branch=z9hG4bKPj91c83cc2-0cce-46ff-9c5c-c08727ca9376
From: <sip:*21@asterisk.my.net>;tag=80050dc3-95e3-4cf7-8e4e-739a526b89d9
To: <sip:11@10.11.12.89>;tag=1461608579
Call-ID: 63b9b56e-d07f-42c1-aaa2-5ef7b928897e
CSeq: 35588 MESSAGE
User-Agent: Yealink
Content-Length: 0
Content-Length:  0

Route it

One problem less is that after fixing the authentication asterisk automatically receives the message and put's the data into the specified context. There you can route it towards it's destination. Because I used * and # for internal numbers I have to do some magic in oder to push the message correctly out.

[messages]
exten => _.,1,NoOp(SMS receiving dialplan invoked)
exten => _.,n,NoOp(To ${MESSAGE(to)})
exten => _.,n,NoOp(From ${MESSAGE(from)})
exten => _.,n,NoOp(Body ${MESSAGE(body)})
exten => _.,n,Set(ACTUALTO=${CUT(MESSAGE(to),@,1)})
exten => _.,n,Set(ME_1=${CUT(MESSAGE(from),< ,2)})
exten => _.,n,Set(ACTUALFROM=${CUT(ME_1,@,1)})
exten => _.,n,MessageSend(pjsip:phone_${ACTUALTO:7},*${ACTUALFROM:4}@asterisk.my.net)
exten => _.,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => _.,n,GotoIf($["${MESSAGE_SEND_STATUS}" != "SUCCESS"]?sendfailedmsg)
exten => _.,n,Hangup()

exten => _.,n(sendfailedmsg),Set(MESSAGE(body)="${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)}] Your message to ${EXTEN} has failed. Retry later.")
exten => _.,n,MessageSend(pjsip:phone_${ACTUALFROM:4},ServiceCenter)
exten => _.,n,Hangup()

It still may happen that the message cannot be delivered. The success message you receive at this point is not 100% certain. For example if a phone isn't available at this moment. The message get's put into an delivery queue. This is marked as success. If it does not make it out of the queue, it's silently deleted.

Perhaps there is a way to put that also into an extension routing advice.