private void Handle100Trying(SipMessage last, SipMessage current) { if (current == null) { // TODO: no message received return; } this.WaitForMessage(current, this.Handle183, 10, 50, 100, 1000, 2000, 5000); }
private void Handle183(SipMessage last, SipMessage current) { if (current.Method == "180") { this.WaitForMessage(current, this.Handle183, 100, 500, 1000); return; } if (current.SdpData != null) { this.SetSdpInformation(current.SdpData); } this.stateChanged(this, DialogState.PreAck); var resp = current as SipResponse; if (resp == null) { Console.WriteLine("sip response is null. expected a 183 response"); return; } Console.WriteLine(resp.StatusCode); if (resp.StatusCode == 183) { var ack = new AckMessage(current.CallId, last.From, current.To, 70, null, current.Via); ack.Headers["Allow"] = "INVITE,BYE,REGISTER,ACK,OPTIONS,CANCEL,INFO,SUBSCRIBE,NOTIFY,REFER,UPDATE"; ack.Contact = last.Contact; ack.Headers["CSeq"] = this.callSequence + " ACK"; ack.Headers["From"] = last.Headers["From"]; ack.Headers["Session-ID"] = current.Headers["Session-ID"]; ack.Headers["Content-Length"] = "0"; this.Send(ack); this.stateChanged(this, DialogState.Answered); SipMessage response; if (this.TryGetNextMessage(60000, out response)) { this.Handle200Ack(ack, response); } } }
private void HandleInviteResponse(SipMessage request, SipMessage response) { if (response != null) { switch (response.Method.ToLowerInvariant()) { case "100": this.WaitForMessage(response, this.Handle183, 100, 500, 1000, 2000, 5000); break; default: throw new InvalidOperationException("Cant handle this message: " + response.Method); } } }
public bool TryReceive(CancellationTokenSource tks, out SipMessage msg) { msg = null; var resp = this.client.ReceiveAsync(); UdpReceiveResult result; if (resp.IsCanceled) { Console.WriteLine("resp is cancelled"); // generate 408 timeout return(false); } try { result = resp.Result; resp.Wait(tks.Token); } catch (OperationCanceledException) { Console.WriteLine("operation cancelled"); return(false); } catch (Exception ex) { Console.WriteLine(ex); return(false); } // TODO: copy custom headers as record route var data = result.Buffer; msg = SipMessage.Parse(data); if (msg != null) { Console.WriteLine("message received: {0}", msg.Method); } return(true); }
private void WaitForMessage(SipMessage currentMessage, MessageReceivedEventHandler handler, int timer, params int[] timers) { Task.Factory.StartNew( () => { foreach (var i in new[] { timer }.Concat(timers)) { SipMessage msg; if (this.TryGetNextMessage(i, out msg)) { if (msg.CallId == this.CallId) { handler(currentMessage, msg); return; } } } handler(currentMessage, null); }); }
private bool TryGetNextMessage(int timeout, out SipMessage msg) { return(this.TryGetNextMessage(new CancellationTokenSource(timeout).Token, out msg)); }
private void Send(SipMessage msg) { var dgram = msg.Serialize(); this.connection.Send(dgram, dgram.Length, this.remoteHost); }
public void Send(SipMessage msg) { var dgram = msg.Serialize(); this.client.Send(dgram, dgram.Length, this.remoteHost); }
private void Handle200Ack(SipMessage request, SipMessage response) { if (response.Method == "200") { this.stateChanged(this, DialogState.Answered); var ack = new AckMessage(request.CallId, request.From, request.To, 70, request.Supported, request.Via); ack.Headers["CSeq"] = request.Headers["CSeq"].ToString().Split(' ')[0] + " ACK"; this.Send(ack); } while (!this.TryGetNextMessage(100, out response)) { Console.WriteLine("waiting for bye"); if (this.byeRequest.IsCancellationRequested) { response = null; break; } } if (response == null) { Console.WriteLine("but message was null"); this.stateChanged(this, DialogState.Hanging); var bye = new SipMessage(request.To, "BYE") { CallId = request.CallId, From = request.From, MaxForwards = 70, Contact = request.Contact, Via = request.Via }; bye.Headers["Allow"] = "INVITE,BYE,REGISTER,ACK,OPTIONS,CANCEL,INFO,SUBSCRIBE,NOTIFY,REFER,UPDATE"; bye.Headers["CSeq"] = Interlocked.Increment(ref this.callSequence) + " BYE"; bye.Headers["Session-ID"] = request.Headers["Session-ID"]; bye.Headers["Content-Length"] = "0"; this.Send(bye); this.stateChanged(this, DialogState.Hungup); // TODO: check this response is a 200 OK //this.TryGetNextMessage(this.byeRequest.Token, out response); this.byeRequest.Cancel(); } else { this.stateChanged(this, DialogState.Hanging); // this is a bye request var msg = new OkResponse(response.To) { CallId = response.CallId, From = response.From, MaxForwards = 70, Via = response.Via }; msg.Headers["Allow"] = "INVITE,BYE,REGISTER,ACK,OPTIONS,CANCEL,INFO,SUBSCRIBE,NOTIFY,REFER,UPDATE"; msg.Contact = request.Contact; // TODO: maybe this sequence is not correct msg.Headers["CSeq"] = response.Headers["CSeq"]; msg.Headers["Session-ID"] = response.Headers["Session-ID"]; msg.Headers["Content-Length"] = "0"; this.Send(msg); this.stateChanged(this, DialogState.Hungup); this.byeRequest.Cancel(); } }