JAIN SIP #7 (Create Invite ตอนที่ 1 )

JAIN SIP #7 (Create Invite ตอนที่ 1 )

ในที่สุดก็มา ถึงเรื่องการสร้าง Invite เพื่อจัดตั้ง Connection ไปหาผู้รับ โดยหลักการของ SIP หลังจากที่ได้ Register เรียบร้อยแล้ว ก็มาถึงส่วนของการ Invite มี Flow การทำงานดังนี้

ผู้ส่ง                                  ผู้รับ

           Invite + SDP -------> 
  <--- Proxy Authentication
  <--- Trying
  <--- Ringing

  Invite + SDP + Authen -->
  <--- 200 OK + SDP

เริ่มต้นกระบวนการ เราก็มาสร้าง Request และ Invite message โดยเรียก method createInvite() จากนั้นเมื่อได้ request เราก็เอาไปสร้างเป็น transaction (เพราะเป็นแบบ stateful) แล้วก็จัดการส่ง Invite Request นี้ไปหา SIP Server (Asterisk) ได้เลยตามโค๊ดตัวอย่าง

        try {
            Request request = this.createInvite("");
            // Create the client transaction.
            inviteTid = sipProvider.getNewClientTransaction(request);
            // send the request out.
            inviteTid.sendRequest();
            System.out.println("INVITE with no Authorization sent:\n" + request);
            dialog = inviteTid.getDialog();  // Print SIP INVITE message
        } catch (Exception e) {
            System.out.println("Creating call CreateInvite()");
            System.out.println(e.getMessage());
            e.printStackTrace();
        }

เอ....  แล้วเจ้่า createInvite(""); มันหน้าตาเป็นอย่างไรนะ? ตามผมมาดูต่อได้เลย

 public Request createInvite(String callId) throws ParseException,
            InvalidArgumentException {
        String fromName = "300";
        String fromSipAddress = "147.127.240.92";
        String fromDisplayName = "pleX - [300]";

        String toSipAddress = "147.127.240.92";
        String toUser = "200";
        String toDisplayName = "Server - [200]";

        // Create ViaHeaders
        ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
        ViaHeader viaHeader = headerFactory.createViaHeader(myAddress,
                sipProvider.getListeningPoint(transport).getPort(), transport,
                null);
       
        // add via headers
        viaHeaders.add(viaHeader);
       
        // create >From Header
        SipURI fromAddress = addressFactory.createSipURI(fromName,
                fromSipAddress);

        Address fromNameAddress = addressFactory.createAddress(fromAddress);
        fromNameAddress.setDisplayName(fromDisplayName);
        FromHeader fromHeader = headerFactory.createFromHeader(fromNameAddress,
                "12345678");

        // create To Header
        SipURI toAddress = addressFactory.createSipURI(toUser, toSipAddress);
        Address toNameAddress = addressFactory.createAddress(toAddress);
        toNameAddress.setDisplayName(toDisplayName);
        ToHeader toHeader = headerFactory.createToHeader(toNameAddress, null);

        // create Request URI
        SipURI requestURI = addressFactory.createSipURI(toUser, sipServer);


        // Create ContentTypeHeader
        ContentTypeHeader contentTypeHeader = headerFactory
                .createContentTypeHeader("application", "sdp");

        // Create a new CallId header
        CallIdHeader callIdHeader;
        callIdHeader = sipProvider.getNewCallId();

       // System.out.println("== calID Header1 = " + callIdHeader.getCallId());

        if (callId.trim().length() > 0)
            callIdHeader.setCallId(callId);

        myCallId = callId; // save value for check Reinvite or New invite
       
        // Create a new Cseq header
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(invco++,
                Request.INVITE);
       
        // Create a new MaxForwardsHeader
        MaxForwardsHeader maxForwards = headerFactory
                .createMaxForwardsHeader(70);

        // Create the request.
        Request request = messageFactory.createRequest(requestURI,
                Request.INVITE, callIdHeader, cSeqHeader, fromHeader, toHeader,
                viaHeaders, maxForwards);

        // Create contact headers
        String host = myAddress;

        SipURI contactUrl = addressFactory.createSipURI(fromName, host);
        contactUrl.setPort(udpListeningPoint.getPort());

        // Create the contact name address.
        SipURI contactURI = addressFactory.createSipURI(fromName, host);
        contactURI.setPort(sipProvider.getListeningPoint(transport).getPort());

        Address contactAddress = addressFactory.createAddress(contactURI);

        // Add the contact address.
        contactAddress.setDisplayName(fromName);

        contactHeader = headerFactory.createContactHeader(contactAddress);
        request.addHeader(contactHeader);

      String sdpData =  "v=0\r\n"
                + "o=pleX 4010 341 IN IP4 "+ myAddress +"\r\n"
                + "s=pleX Test SIP Client\r\n"
                + "c=IN IP4 "+ myAddress +"\r\n"
                + "t=0 0 \r\n"
                + "m=audio " +  audioPort  + " RTP/AVP 0 4 18\r\n"
                + "a=rtpmap:0 PCMU/8000\r\n"
                + "a=rtpmap:4 G723/8000\r\n"
                + "a=rtpmap:18 G729A/8000\r\n"
                + "a=ptime:20\r\n";

        byte[] contents = sdpData.getBytes();

        request.setContent(contents, contentTypeHeader);
       
        Header callInfoHeader = headerFactory.createHeader("Call-Info",
                "<http://www.antd.nist.gov>");
        request.addHeader(callInfoHeader);

        return request;
    }

ดูตัวอย่าง code นี้ เริ่มน่ากลัวแฮะ เพราะเริ่มยาว แต่จริง ๆ แล้วก็ไม่มีอะไรครับ ก็ใช้  Header Factory ต่าง ๆ สร้าง header ขึ้น แล้วก็จับ header ที่สร้างมาทั้งหมดยัดใส่ลงไปใน Request เท่านั้นเอง  จุดที่น่าสนใจในฟังก์ชันนี้ มีนิดหน่อยตรงที่ if (callId.trim().length() > 0)   ซึ่งเงื่อนไขนี้ จะเป็นจริง เมื่อเราทำ Invite ครั้งที่ 2 (ตาม flow ที่อธิบายข้างบน) โดยเราจะดึง callId ซึ่งเป็น String parameter ของ createInvite() อยู่แล้ว  ส่วนการส่ง Invite ครั้งแรกนั้น เราสามารถสร้าง Call Id เพื่อไว้อ้างอิง SIP Session ของเราเองได้เลยครับ

ครับ เพียงเท่านี้ เราก็ส่ง Invite ไปหา อีกผู้รับได้แล้ว แต่กระบวนการขั้นตอนการ Invite ยังไม่จบครับ ติดตามตอนต่อไป ...  :-)