@@ -58,10 +58,10 @@ static void Main()
58
58
var sipTransport = new SIPTransport ( ) ;
59
59
sipTransport . AddSIPChannel ( new SIPUDPChannel ( new IPEndPoint ( IPAddress . Any , SIP_LISTEN_PORT ) ) ) ;
60
60
61
- EnableTraceLogs ( sipTransport ) ;
61
+ // EnableTraceLogs(sipTransport);
62
62
63
- // Initialise an RTP session to receive the RTP packets from the remote SIP server .
64
- var rtpSession = new RTPSession ( ( int ) SDPMediaFormatsEnum . PCMU , null , null , true ) ;
63
+ // Get the default speaker .
64
+ var ( audioOutEvent , audioOutProvider ) = GetAudioOutputDevice ( ) ;
65
65
66
66
// Create a client/server user agent to place a call to a remote SIP server along with event handlers for the different stages of the call.
67
67
var userAgent = new SIPUserAgent ( sipTransport , null ) ;
@@ -79,17 +79,13 @@ static void Main()
79
79
if ( resp . Status == SIPResponseStatusCodesEnum . Ok )
80
80
{
81
81
Log . LogInformation ( $ "{ uac . CallDescriptor . To } Answered: { resp . StatusCode } { resp . ReasonPhrase } .") ;
82
-
83
- // Only set the remote RTP end point if there hasn't already been a packet received on it.
84
- if ( rtpSession . DestinationEndPoint == null )
85
- {
86
- rtpSession . DestinationEndPoint = SDP . GetSDPRTPEndPoint ( resp . Body ) ;
87
- Log . LogDebug ( $ "Remote RTP socket { rtpSession . DestinationEndPoint } .") ;
88
- }
82
+ PlayRemoteMedia ( userAgent . RtpSession , audioOutProvider ) ;
89
83
}
90
84
else
91
85
{
92
86
Log . LogWarning ( $ "{ uac . CallDescriptor . To } Answered: { resp . StatusCode } { resp . ReasonPhrase } .") ;
87
+ hasCallFailed = true ;
88
+ exitCts . Cancel ( ) ;
93
89
}
94
90
} ;
95
91
userAgent . OnCallHungup += ( ) =>
@@ -100,19 +96,6 @@ static void Main()
100
96
userAgent . ServerCallCancelled += ( uas ) => Log . LogInformation ( "Incoming call cancelled by caller." ) ;
101
97
userAgent . RemotePutOnHold += ( ) => Log . LogInformation ( "Remote call party has placed us on hold." ) ;
102
98
userAgent . RemoteTookOffHold += ( ) => Log . LogInformation ( "Remote call party took us off hold." ) ;
103
- userAgent . OnReinviteRequest += ( uasInviteTx ) =>
104
- {
105
- Log . LogDebug ( "Reinvite request received." ) ;
106
-
107
- // Re-INVITEs can also be changing the RTP end point. We can update this each time.
108
- IPEndPoint dstRtpEndPoint = SDP . GetSDPRTPEndPoint ( uasInviteTx . TransactionRequest . Body ) ;
109
- if ( rtpSession . DestinationEndPoint != dstRtpEndPoint )
110
- {
111
- Log . LogDebug ( $ "Remote call party RTP end point changed from { rtpSession . DestinationEndPoint } to { dstRtpEndPoint } .") ;
112
- rtpSession . DestinationEndPoint = dstRtpEndPoint ;
113
- }
114
- uasInviteTx . SendFinalResponse ( uasInviteTx . GetOkResponse ( SDP . SDP_MIME_CONTENTTYPE , userAgent . Dialogue . SDP ) ) ;
115
- } ;
116
99
117
100
sipTransport . SIPTransportRequestReceived += ( locelEndPoint , remoteEndPoint , sipRequest ) =>
118
101
{
@@ -137,12 +120,13 @@ static void Main()
137
120
{
138
121
Log . LogInformation ( $ "Incoming call request from { remoteEndPoint } : { sipRequest . StatusLine } .") ;
139
122
var incomingCall = userAgent . AcceptCall ( sipRequest ) ;
123
+ userAgent . Answer ( incomingCall ) ;
140
124
141
- SDP remoteSDP = SDP . ParseSDPDescription ( sipRequest . Body ) ;
142
- IPAddress localIPAddress = NetServices . GetLocalAddressForRemote ( IPAddress . Parse ( remoteSDP . Connection . ConnectionAddress ) ) ;
143
- var sdpOffer = rtpSession . GetSDP ( localIPAddress ) ;
125
+ PlayRemoteMedia ( userAgent . RtpSession , audioOutProvider ) ;
144
126
145
- userAgent . Answer ( incomingCall , sdpOffer ) ;
127
+ string caller = sipRequest . Header . From . FromURI . ToString ( ) ;
128
+ caller = ( string . IsNullOrEmpty ( sipRequest . Header . From . FromName ) ) ? caller : sipRequest . Header . From . FromName + " " + caller ;
129
+ Log . LogInformation ( $ "Answered incoming call from { caller } at { remoteEndPoint } .") ;
146
130
}
147
131
}
148
132
else
@@ -153,18 +137,6 @@ static void Main()
153
137
}
154
138
} ;
155
139
156
- // Wire up the RTP receive session to the default speaker.
157
- var ( audioOutEvent , audioOutProvider ) = GetAudioOutputDevice ( ) ;
158
- rtpSession . OnReceivedSampleReady += ( sample ) =>
159
- {
160
- for ( int index = 0 ; index < sample . Length ; index ++ )
161
- {
162
- short pcm = NAudio . Codecs . MuLawDecoder . MuLawToLinearSample ( sample [ index ] ) ;
163
- byte [ ] pcmSample = new byte [ ] { ( byte ) ( pcm & 0xFF ) , ( byte ) ( pcm >> 8 ) } ;
164
- audioOutProvider . AddSamples ( pcmSample , 0 , 2 ) ;
165
- }
166
- } ;
167
-
168
140
// Wire up the RTP send session to the audio output device.
169
141
WaveInEvent waveInEvent = GetAudioInputDevice ( ) ;
170
142
uint rtpSendTimestamp = 0 ;
@@ -179,9 +151,9 @@ static void Main()
179
151
sample [ sampleIndex ++ ] = ulawByte ;
180
152
}
181
153
182
- if ( rtpSession . DestinationEndPoint != null )
154
+ if ( userAgent ? . RtpSession ? . DestinationEndPoint != null )
183
155
{
184
- rtpSession . SendAudioFrame ( rtpSendTimestamp , sample ) ;
156
+ userAgent . RtpSession . SendAudioFrame ( rtpSendTimestamp , sample ) ;
185
157
rtpSendTimestamp += ( uint ) ( 8000 / waveInEvent . BufferMilliseconds ) ;
186
158
}
187
159
@@ -201,8 +173,7 @@ static void Main()
201
173
{
202
174
if ( ! userAgent . IsCallActive )
203
175
{
204
- SIPURI callUri = SIPURI . ParseSIPURI ( DEFAULT_DESTINATION_SIP_URI ) ;
205
- var callDescriptor = GetCallDescriptor ( callUri , rtpSession ) ;
176
+ var callDescriptor = GetCallDescriptor ( DEFAULT_DESTINATION_SIP_URI ) ;
206
177
userAgent . Call ( callDescriptor ) ;
207
178
}
208
179
else
@@ -281,7 +252,7 @@ static void Main()
281
252
282
253
Log . LogInformation ( "Exiting..." ) ;
283
254
284
- rtpSession ? . Close ( ) ;
255
+ userAgent ? . RtpSession ? . Close ( ) ;
285
256
waveInEvent ? . StopRecording ( ) ;
286
257
audioOutEvent ? . Stop ( ) ;
287
258
@@ -320,32 +291,42 @@ static void Main()
320
291
/// <param name="callUri">The URI to place the call to.</param>
321
292
/// <param name="rtpSession">The RTP session that will be handling the RTP/RTCP packets for the call.</param>
322
293
/// <returns>A call descriptor.</returns>
323
- private static SIPCallDescriptor GetCallDescriptor ( SIPURI callUri , RTPSession rtpSession )
294
+ private static SIPCallDescriptor GetCallDescriptor ( string callUri )
324
295
{
325
- var lookupResult = SIPDNSManager . ResolveSIPService ( callUri , false ) ;
326
- Log . LogDebug ( $ "DNS lookup result for { callUri } : { lookupResult ? . GetSIPEndPoint ( ) } .") ;
327
- var dstAddress = lookupResult . GetSIPEndPoint ( ) . Address ;
328
-
329
- IPAddress localIPAddress = NetServices . GetLocalAddressForRemote ( dstAddress ) ;
330
-
331
- var sdpOffer = rtpSession . GetSDP ( localIPAddress ) ;
332
-
333
- // Start the thread that places the call.
296
+ // Create a call descriptor to place an outgoing call.
334
297
SIPCallDescriptor callDescriptor = new SIPCallDescriptor (
335
298
SIP_USERNAME ,
336
299
SIP_PASSWORD ,
337
- callUri . ToString ( ) ,
300
+ callUri ,
338
301
$ "sip:{ SIP_USERNAME } @localhost",
339
- callUri . CanonicalAddress ,
302
+ callUri ,
340
303
null , null , null ,
341
304
SIPCallDirection . Out ,
342
305
SDP . SDP_MIME_CONTENTTYPE ,
343
- sdpOffer . ToString ( ) ,
306
+ null ,
344
307
null ) ;
345
308
346
309
return callDescriptor ;
347
310
}
348
311
312
+ /// <summary>
313
+ /// Wires up the active RTP session to the speaker.
314
+ /// </summary>
315
+ /// <param name="rtpSession">The active RTP session receiving the remote party's RTP packets.</param>
316
+ /// <param name="audioOutProvider">The audio buffer for the default system audio output device.</param>
317
+ private static void PlayRemoteMedia ( RTPSession rtpSession , BufferedWaveProvider audioOutProvider )
318
+ {
319
+ rtpSession . OnReceivedSampleReady += ( sample ) =>
320
+ {
321
+ for ( int index = 0 ; index < sample . Length ; index ++ )
322
+ {
323
+ short pcm = NAudio . Codecs . MuLawDecoder . MuLawToLinearSample ( sample [ index ] ) ;
324
+ byte [ ] pcmSample = new byte [ ] { ( byte ) ( pcm & 0xFF ) , ( byte ) ( pcm >> 8 ) } ;
325
+ audioOutProvider . AddSamples ( pcmSample , 0 , 2 ) ;
326
+ }
327
+ } ;
328
+ }
329
+
349
330
/// <summary>
350
331
/// Get the audio output device, e.g. speaker.
351
332
/// Note that NAudio.Wave.WaveOut is not available for .Net Standard so no easy way to check if
0 commit comments