LAMPIRAN A
Struktur Pesan Protokol SIP
Struktur pesan SIP secara umum terdiri dari empat bagian yang disusun secara berurutan, yaitu Start-Line, Message Header, Empty Line, serta Body (opsional). Pada akhir setiap bagian pesan tersebut akan disertakan karakter carriage-return line-feed (CR-LF), sehingga bagian selanjutnya akan diletakkan pada baris dibawahnya. Gambar A.1 menampilkan struktur umum dari pesan protokol SIP.
Gambar A.1 Struktur pesan SIP A.1 Start-Line Start-Line dari pesan SIP berbeda antara pesan request dan pesan response.
A-1
Universitas Sumatera Utara
A.1.1 Start-Line pesan Request Start-Line dari pesan request disebut juga sebagai Request-Line dan terdiri dari nama metoda (Method), alamat URI tujuan (Request-URI), serta versi protokol SIP (Version) yang disusun secara berurutan. Diantara setiap bagian pada Request-Line ini dipisahkan oleh satu karakter spasi tunggal (SP). Syntax dari Request-Line ini ditampilkan pada Gambar A.1 (b). Metoda dari sebuah pesan request mengandung fungsi/operasi yang diminta untuk dijalankan pada server tujuan. Protokol SIP sendiri mengenal sembilan jenis metoda, yaitu INVITE, ACK, OPTION, BYE, CANCEL, REGISTER, SUBSCRIBE, REFER, dan NOTIFY. Tabel A.1 menampilkan sembilan metoda ini beserta deskripsi fungsinya. Pada Tugas Akhir ini sendiri hanya akan digunakan Method INVITE, ACK, BYE dan CANCEL. Tabel A.1 SIP Request Method Method
Deskripsi
INVITE
Mengundang untuk memulai sesi SIP
ACK
Mengkonfirmasi bahwa pertukaran message berhasil
OPTION
Meminta informasi mengenai kemampuan pemanggil
BYE
Mengakhiri sesi yang telah terbentuk
CANCEL
Membatalkan sesi yang menunggu
REGISTER
Mendaftarkan informasi mengenai user agent pada sebuah registrar server
SUBSCRIBE
Meminta pemutakhiran informasi
REFER
Mengalihkan panggilan atau menghubungi sumber daya eksternal
NOTIFY
Menyediakan informasi tentang perubahan status
A-2
Universitas Sumatera Utara
Alamat URI (Uniform Resource Identifier) tujuan mengindikasikan pengguna atau layanan kemana pesan request ini ditujukan. Setiap pengguna akan dialamati dengan sebuah penamaan URI khusus yang dinamakan SIP URI. Format penamaan ini mirip dengan format penamaan yang digunakan pada layanan email, terdiri dari user name pengguna serta alamat domain dimana pengguna tersebut terdaftar dengan dipisahkan oleh sebuah karakter “@”. Di depan user name pengguna kemudian ditambahkan prefix “sip:”, sehingga syntax dari format penamaan ini menjadi seperti “sip:username@host”. Version ditampilkan sebagai string “SIP/x.y”, dimana x dan y masingmasing menunjukkan versi mayor dan minor dari protokol SIP yang digunakan. Saat ini versi protokol SIP terakhir yang telah dikeluarkan oleh IETF adalah versi 2.0. Berikut ini adalah contoh Request-Line dari sebuah pesan request dengan metode INVITE yang ditujukan kepada bob yang terdaftar dalam domain usu.ac.id menggunakan protokol SIP versi 2.0. INVITE sip:
[email protected] SIP/2.0
A.1.2 Start-Line pesan Response Start-line dari pesan response disebut juga sebagai Response-Line dan terdiri dari versi protokol yang digunakan (Version), Status Code dan Reason Phrase. Sebagaimana Request-line, diantara setiap bagian pada Response-Line ini dipisahkan oleh satu karakter spasi tunggal (SP). Syntax dari Respons-Line ini ditampilkan pada Gambar A.1 (c).
A-3
Universitas Sumatera Utara
Status Code merupakan tiga digit integer yang mengindikasikan tingkatan (status) dari fungsi/operasi yang diminta UAC melalui pesan request. Protokol SIP membagi pesan response kedalam enam kelas yang ditunjukkan oleh bit pertama dari Status Code. Sebagai contoh status code 100 hingga 199 termasuk dalam kelas 1xx (provisional). Tabel A.2 menampilkan pembagian kelas pesan response ini beserta deskripsinya. Tabel A.2 Kelas-kelas pesan SIP Response Status Code
Kelas
Deskripsi
1xx
Provisional
Request telah diterima dan sedang diproses
2xx
Success
Request telah diterima, dimengerti, dan disetujui
3xx
Redirection
Diperlukan langkah berikutnya untuk menyelesaikan permintaan
4xx
Client Failure
Request mengandung syntax yang salah / tidak dapat dipenuhi server
5xx
Server Failure
Tidak dapat memenuhi permintaan diakibatkan kesalahan pada server
6xx
Global Failure
Request tidak dapat dipenuhi oleh server berikutnya
Reason Phrase merupakan deskripsi tekstual singkat dari Status Code yang digunakan. Beberapa Reason Phrase dari Status Code yang umum ditemui dan akan digunakan pada Tugas Akhir ini ditampilkan pada Tabel A.3. Tabel A.3 Reason Phrase dari beberapa Status Code Status Code
Reason Phrase
100
Trying
180
Ringing
200
OK
408
Request timeout
480
Temporarily Unavailable
A-4
Universitas Sumatera Utara
Berikut ini adalah contoh Response-Line dari sebuah pesan response dengan Status Code 200 menggunakan protokol SIP versi 2.0. SIP/2.0 200 OK
A.2 Message Header Message header mengandung informasi lengkap mengenai pesan SIP dan disusun menggunakan syntax sebagaimana ditampilkan pada Gambar A.1 (d). Bagian ini terdiri dari beberapa baris header field, dimana pada setiap header field ini terdiri dari field name dan field value yang dipisahkan oleh sebuah karakter titik-dua (colon). Bagian field name akan mengindikasikan jenis informasi yang nilainya diberikan pada bagian field value. Tabel A.4 menampilkan daftar header field name yang dikenal protokol SIP beserta deskripsi informasi yang akan terkandung pada baris tersebut. Urutan setiap header field dalam message header tidak harus mengikuti susunan tertentu. Tabel A.4 Header Field yang digunakan pada protokol SIP Header Field Name
Deskripsi Informasi
Call-ID
Mengandung identitas unik untuk panggilan yang dilakukan
Contact
Menunjukkan jalur langsung untuk menghubungi pemanggil
Content-Length
Mengandung panjang bagian body dari pesan SIP (dalam byte)
Content-Type
Menunjukkan tipe pesan yang terkandung pada bagian body
CSeg
Menampilkan metode serta nomor urut pesan dalam panggilan
From
Mengandung identitas pemanggil (caller)
To
Mengandung identitas terpanggil (calle)
Via
Menampilkan informasi koneksi yang digunakan untuk pengiriman
A-5
Universitas Sumatera Utara
Sebagai contoh berikut ini diberikan message header dari sebuah pesan SIP. Via: SIP/2.0/UDP pc33.unimed.ac.id;branch=z9hG4bK776asdhds To: Bob <sip:
[email protected]> From: Alice <sip:
[email protected]>;tag=1928301774 Call-ID:
[email protected] CSeq: 314159 INVITE Contact: <sip:
[email protected] > Content-Type: application/sdp Content-Length: 142
Berikut adalah penjelasan dari setiap baris header field dari contoh diatas : •
baris Via menunjukkan darimana respons message terhadap request ini diharapkan berasal, dalam hal ini adalah sebuah proxy server dengan alamat pc33.unimed.ac.id, sementara parameter branch memberikan identitas mengenai transaksi yang sedang berlangsung.
•
baris To mengandung nama tampilan pengguna serta alamat URI kemana request message ini ditujukan, dan dalam contoh ini adalah Bob dengan alamat sip:
[email protected].
•
baris From menyediakan informasi mengenai nama tampilam pengguna serta alamat URI darimana request ini berasal, dalam contoh ini adalah Alice dengan alamat sip:
[email protected]. Terdapat pula parameter tag berupa string acak yang digunakan untuk kepentingan identifikasi pengguna.
•
baris Call-ID mengandung identifier global untuk panggilan yang sedang berlangsung, berupa kombinasi string acak (a84b4c76e66710) dan alamat domain pemanggil (pc33.unimed.ac.id). A-6
Universitas Sumatera Utara
•
baris Cseq (Command Sequence) mengandung sebuah bilangan integer (314159) dan nama Method (INVITE). Nilai Cseq akan dinaikkan untuk setiap request baru.
•
baris Contact mengandung alamat URI yang merepresentasikan rute langsung untuk menghubungi pemanggil, biasanya dalam format Fully Qualified
Domain
Name
(FQDN).
Dalam
contoh
ini
adalah
sip:
[email protected].
•
baris Content-type mengindikasikan jenis pesan/media yang terkandung pada batang tubuh pesan (Message Body), yang dalam contoh ini adalah sebuah pesan SDP. Tabel A.5 menampilkan beberapa jenis pesan/media yang dapat terkandung pada batang tubuh pesan SIP beserta nilai yang harus diberikan pada field value untuk mengindikasikannya.
•
baris Content-Length memberikan informasi mengenai panjang batang tubuh pesan (Body) dalam satuan byte. Tabel A.5 Beberapa jenis pesan/media serta field value yang digunakan Jenis pesan/media Field value yang digunakan SDP
application/sdp
Text Plain
text/plain
JPEG
image/jpeg
MP3
audio/mp3
MPEG
video/mpeg
A-7
Universitas Sumatera Utara
A.3 Message Body Batang tubuh dari pesan SIP dapat memuat berbagai jenis pesan dan untuk berbagai tujuan, namun yang paling umum adalah pesan SDP untuk mendeskripsikan sesi media yang akan dibangun saat inisiasi panggilan. Pesan SDP terdiri dari sejumlah baris teks yang mengandung deskripsi parameter-parameter sesi yang akan dibangun. Pada setiap baris ini sendiri terdiri dari dua bagian yang disebut type dan value, dan diantara keduanya dipisahkan oleh satu karakter sama dengan (“=”). Syntax umum dari pesan protokol SDP ini dapat disusun sebagai berikut. type=value Type menunjukkan jenis parameter yang akan dideskripsikan, dan terdiri dari satu karakter yang bersifat case-significant. Sedangkan value mengandung nilai parameter dengan syntax yang berbeda untuk setiap jenis parameter yang dideskripsikan. Parameter-parameter yang akan dideskripsikan dibagi kedalam tiga kelompok, yaitu Session Description, Time Description, dan Media Description. Session Description mengandung informasi mengenai sesi yang akan dibangun, dan bersifat global untuk keseluruhan sesi dan media stream yang dideskripsikan. Hanya boleh terdapat satu bagian Session Description dalam sebuah pesan SDP. Gambar A.2 (a) menampilkan parameter-parameter yang termasuk dalam kelompok Session Description. Time Description mengandung informasi mengenai waktu sesi berlangsung. Gambar A.2 (b) menampilkan parameter-
A-8
Universitas Sumatera Utara
parameter yang termasuk dalam kelompok Time Description. Media Description mengandung informasi mengenai media stream yang akan dibangun pada sesi. Sebuah pesan SDP dapat mendeskripsikan lebih dari satu media stream dengan menyertakan sejumlah Media Description, namun pada tugas akhir ini hanya membahas penggunaan satu media stream. Gambar A.2 (c) menampilkan parameter-parameter yang termasuk dalam kelompok Media Description. Beberapa parameter yang ditampilkan pada Gambar A.2 yang ditandai oleh * bersifat opsional dan tidak harus ada dalam sebuah pesan SDP. Session Description
Time Description
Media Description
Kode Deskripsi
Kode Deskripsi
Kode Deskripsi
v
Version
t
Active time
m
Media name
o
Owner/session ID
r*
Repeate time
i*
Media title
s
Session name
(b)
c*
Connection info
i*
Session info
b*
Bandwidth info
u*
URI of description
k*
Encryption key
e*
Email address
a*
Media attribute
p*
Phone number
(c)
c
Connection info
b*
Bandwidth info
z*
Time zone
a*
Session attribute
* = opsional
(a)
Gambar A.2 Parameter-parameter protokol SDP Baris Version (v) menunjukkan versi mayor protokol SDP yang digunakan. Nilai nol memiliki arti versi protokol SDP yang digunakan sesuai dengan spesifikasi yang terdapat pada dokumen RFC 2327.
A-9
Universitas Sumatera Utara
Baris Origin (o) mengandung informasi mengenai pencipta sesi (originator), dan nilainya disusun menggunakan syntax sebagai berikut. <username> <session-id>
•
Username biasanya diambil dari nama login dari pemanggil, atau dikosongkan (-) apabila nama login tidak tersedia.
•
Session-id merupakan string numerik yang berfungsi sebagai identifier untuk sesi media yang akan dibangun. Nilai untuk session-id ini umumnya diperoleh dari waktu Network Time Protocol (NTP) yang menghitung waktu sebagai jumlah detik mulai dari tanggal 1 january 1900 (sesuai spesifikasi RFC 2327).
•
Version menunjukkan nomor urut pesan ini dalam sesi yang dibangun.
•
Network-type menunjukkan jenis jaringan data yang akan digunakan pada sesi media, dan secara default bernilai IN yang berarti sesi akan menggunakan jaringan Internet.
•
Address-type menunjukkan jenis pengalamatan yang digunakan, dan secara default bernilai IP4 yang menunjukkan sesi akan menggunakan protokol IP versi 4.
•
Address merupakan alamat IP dari pencipta sesi. Baris Session Name (s) merupakan pengenal untuk sesi yang dibangun.
Dokumen RFC 2327 menspesifikasikan bahwa harus terdapat satu dan hanya satu baris Session Name pada setiap pesan SDP.
A-10
Universitas Sumatera Utara
Baris Connection Data (c) menunjukkan informasi sambungan yang digunakan pada sesi yang dibangun, dan nilainya disusun menggunakan syntax sebagai berikut. •
Network Type menunjukkan jenis jaringan yang digunakan, dan secara default bernilai IN yang berarti sesi akan menggunakan jaringan Internet.
•
Address Type menunjukkan jenis protokol pengalamatan yang digunakan, dan secara default bernilai IP4 yang menunjukkan penggunaan protokol IP versi 4.
•
Connection Address merupakan alamat IP dimana sesi media akan dikirimkan dan diterima. Dokumen RFC 2327 menspesifikasikan bahwa setiap pesan SDP harus
mengandung sedikitnya satu connection data pada setiap media description, atau hanya satu apabila disertakan pada session description. Baris Time Description (t) menampilkan waktu mulai dan akhir sesi. Karena waktu mulai dan penutupan sesi tidak ditentukan (dibatasi) secara langsung, maka baris ini akan bernilai 0 (awal dan akhir). Baris media name (m) mengandung informasi mengenai media yang digunakan pada sesi, dan nilainya (value) disusun menggunakan syntax sebagai berikut. <media-type> <port>
A-11
Universitas Sumatera Utara
•
Media-type menunjukkan jenis media yang digunakan. Dokumen RFC 2327 menspesifikasikan jenis-jenis media yang dapat dibangun adalah audio, video, application, data, dan control.
•
Port menunjukkan nomor port dimana media stream akan dikirimkan
•
Transport menunjukkan protokol yang digunakan untuk mengirimkan media stream. Dokumen RFC 2327 menspesifikasikan protokol yang dapat digunakan adalah UDP, RTP/AVP (Realtime Transport Protocol using the Audio/Video Profile Carried over UDP), serta RTP/SAVP (.
•
Format list menggambarkan format media yang digunakan. Apabila bagian transport menggunakan RTP/AVP, maka bagian ini akan mengandung nomor RTP Payload Type dari format media. Daftar lengkap Payload Type untuk setiap format media apabila menggunakan RTP/AVP diberikan pada Lampiran A. Pada contoh, nilai 0 menunjukkan format pengkodean yang digunakan adalah PCMU (G.711-uLaw). Informasi tambahan untuk sesi media yang dibangun akan diberikan pada
baris Attribute. Sebuah pesan SDP dapat mengandung satu atau lebih baris Attribute pada bagian Session Description dan Media Description. Baris Attribute pada bagian Session Description akan berlaku untuk keseluruhan sesi dan media stream, sedangkan baris Attribute pada bagian Media Description hanya berlaku pada media stream yang dideskripsikan. Tabel A.6 menampilkan daftar nilai yang dapat diberikan pada baris Attribute ini.
A-12
Universitas Sumatera Utara
Tabel A.6 Nilai Attribute yang sesuai Nilai Attribute
Keterangan
sendrecv
Mendeskripsikan media stream berlangsung dua arah
sendonly
Mendeskripsikan media stream berlangsung satu arah, hanya berasal dari pencipta sesi
recvonly
Mendeskripsikan media stream berlangsung satu arah, ditujukan hanya kepada pencipta sesi
rtpmap
Mendeskripsikan format media
Baris Attribute rtpmap mengandung keterangan (informasi) tambahan mengenai format pengkodean yang digunakan pada media. Berikut adalah syntax yang digunakan untuk nilai (value) baris Attribute rtpmap yang diperoleh dari dokumen RFC2327. rtpmap:<payload type> <encoding name>/[/<encoding parameters>]
•
Payload type menunjukkan nomor format pengkodean yang akan diterangkan pada baris Attribute rtpmap ini.
•
Encoding name menerangkan mengenai nama format pengkodean yang digunakan.
•
Clock-rate menerangkan mengenai laju pencuplikan yang digunakan oleh format pengkodean.
•
Encoding parameter dapat digunakan untuk menerangkan berbagai parameter-parameter lainnya seperti jumlah saluran audio (channel) yang dibangun .
A-13
Universitas Sumatera Utara
Pesan SDP harus diawali oleh bagian Session Description, diikuti Time Description dan satu atau lebih Media Description. Setiap bagian disusun sesuai urutannya sebagaimana ditunjukkan pada Gambar A.2. Bagian Session Description akan diawali oleh baris Version (v), dan setiap Media Description akan diawali oleh baris Media Name (m). Berikut adalah sebuah contoh pesan SDP yang mengandung parameter-parameter minimal yang dibutuhkan untuk mendeskripsikan sebuah sesi. v o c t m a a
= = = = = = =
0 alice 1279124485 1 IN IP4 192.168.0.1 IN IP4 192.168.0.1 0 0 audio 5000 RTP/AVP 0 sendrecv rtpmap:0 PCMU/8000
A-14
Universitas Sumatera Utara
LAMPIRAN B
Struktur Kelas Pustaka OPAL
Pustaka OPAL merupakan sebuah pustaka kelas bahasa C++ yang terdiri dari sejumlah kelas-kelas pemrograman. Kelas-kelas pustaka OPAL ini secara umum dapat dibagi menjadi dua bagian, yaitu bagian pensinyalan dan bagian media. B.1 Bagian Pensinyalan Bagian
pensinyalan
dari
pustaka
OPAL
berfungsi
menangani
pembentukan (inisiasi) panggilan, penutupan panggilan, serta fungsi-fungsi pensinyalan telepon lainya. Bagian ini terdiri dari enam kelas utama, yaitu OpalManager, OpalEndPoint, OpalConnection, dan OpalCall, OpalTransport, dan OpalListener. 1. OpalManager Kelas OpalManager merupakan pusat pengaturan dalam sistem yang menggunakan OPAL. Kelas OpalManager akan mengatur dan memonitor seluruh komponen lainnya yang terdapat pada sistem serta bertanggung jawab pada mekanisme panggilan. Setiap aplikasi
yang
dibuat
menggunakan pustaka OPAL harus memiliki satu objek dari kelas turunan OpalManager.
B-1
Universitas Sumatera Utara
2. OpalEndPoint Kelas OpalEndPoint merupakan kelas abstraksi dasar dari seluruh kelas endpoint yang disediakan OPAL. Implementasi yang lebih spesifik untuk setiap endpoint diberikan pada kelas-kelas turunan OpalEndPoint. Gambar B.1 menampilkan turunan-turunan dari kelas OpalEndPoint ini. Aplikasi dapat memiliki sejumlah objek kelas turunan OpalEndPoint yang semuanya terhubung (attached) pada OpalManager.
Gambar B.1 Kelas-kelas turunan OpalEndPoint
3. OpalConnection Kelas OpalConnection merupakan kelas abstraksi dasar dari seluruh sambungan
(connection)
dari
endpoint
yang
disediakan
OPAL.
Implementasi yang lebih spesifik untuk setiap sambungan dari endpoint diberikan pada kelas-kelas turunan OpalConnection.
Gambar B.2
menampilkan turunan-turunan dari kelas OpalConnection ini.
Gambar B.2 Kelas-kelas turunan OpalConnection
Kelas-kelas turunan OpalConnection ini akan diciptakan oleh kelas-kelas turunan OpalEndPoint yang bersesuaian ketika pembentukan panggilan. B-2
Universitas Sumatera Utara
Sebagai contoh, objek kelas SIPConnection akan diciptakan oleh objek kelas SIPEndPoint ketika sebuah panggilan dibangun menggunakan protokol SIP. 4. OpalCall Kelas OpalCall mewadahi sebuah panggilan yang sedang berlangsung. Kelas ini terdiri dari nol atau lebih objek kelas turunan OpalConnection. Kelas ini dapat pula meneruskan panggilan, menahan panggilan, dan fungsi-fungsi pengaturan panggilan yang mirip lainnya. Objek kelas OpalCall diciptakan oleh OpalManager ketika akan memulai panggilan, dan akan segera dimusnahkan ketika panggilan berakhir. 5. OpalTransport Kelas OpalTransport berfungsi menangani pengiriman dan penerimaan pesan-pesan VoIP melalui jaringan pada pustaka OPAL. Kelas ini merupakan kelas abstraksi dasar dari seluruh implementasi transport yang ada di pustaka OPAL. Implementasi yang lebih spesifik ditangani oleh kelas
turunan
OpalTransport
seperti
OpalTransportUDP
dan
OpalTransportTCP. Gambar B.3 menampilkan turunan-turunan dari kelas OpalTransport ini.
Gambar B.3 Kelas-kelas turunan OpalTransport
B-3
Universitas Sumatera Utara
6. OpalListener Kelas OpalListener berfungsi mendengar sambungan yang masuk pada transport tertentu, dan melepasnya dalam sebuah thread baru berdasarkan pada kelas OpalTransport yang sebenarnya. Kelas ini merupakan kelas dasar dari seluruh implementasi listener yang ada di pustaka OPAL, dimana terdapat sebuah kelas turunan OpalListener untuk setiap transport. Gambar B.4 menampilkan turunan-turunan dari kelas OpalListener ini.
Gambar B.4 Kelas-kelas turunan OpalListener
B.2 Bagian Media Bagian Media dari pustaka OPAL berfungsi mengani pertukaran data media diantara peserta panggilan.
Terdapat tiga kelas yang termasuk dalam
bagian ini, yaitu OpalMediaStream, OpalMediaPatch, dan OpalMediaFormat. 1. OpalMediaStream Kelas OpalMediaStream merupakan kelas abstraksi dasar dari seluruh media stream yang didukung pustaka OPAL. Implementasi yang spesifik untuk
setiap
media
stream
diberikan
pada
kelas-kelas
turunan
B-4
Universitas Sumatera Utara
OpalMediaStream ini. Gambar B.5 menampilkan turunan-turunan dari kelas OpalMediaStream ini.
Gambar B.5 Kelas-kelas turunan OpalMediaStream
Kelas OpalAudioMediaStream digunakan untuk mengirimkan data media audio
dari
dan
ke
perangkat
keras
suara.
Sementara
kelas
B-5
Universitas Sumatera Utara
OpalRTPMediaStream digunakan untuk mengirimkan data media dari dan ke jaringan melalui sebuah sesi media RTP. Objek kelas ini akan dibangun oleh objek kelas OpalConnection ketika pembentukan panggilan. 2. OpalMediaFormat Kelas OpalMediaFormat mendeskripsikan format pengkodean media yang digunakan untuk mengirimkan dan menerima data media pada pustaka OPAL. Setiap endpoint umumnya memiliki set format media default yang akan digunakan ketika panggilan dibentuk menggunakan sambungan dari endpoint tersebut. Namun, format media yng digunakan dapat pula ditentukan secara eksplisit pada level aplikasi. Gambar B.6 menampilkan turunan-turunan dari kelas OpalMediaFormat ini.
Gambar B.6 Kelas-kelas turunan OpalMediaFormat
3. OpalMediaPatch Kelas OpalMediaPatch berfungsi mengendalikan pengiriman data media dari dan ke media stream. Sebagai contoh, sebuah objek OpalMediaPatch menerima data media dari OpalAudioMediaStream, dan mengirimkannya ke OpalRTPMediaStream. Kelas ini juga bertanggung jawab memanggil codec yang sesuai untuk setiap media stream.
B-6
Universitas Sumatera Utara
LAMPIRAN C
Metode Pertukaran Kunci Protokol TLS
Terdapat empat metode key exchange yang dapat digunakan pada protokol TLS, yaitu RSA, Anonymous DH (Diffie Hellman), Ephemeral DH, serta Fixed DH. Metode key exchange yang akan digunakan sendiri tergantung pada hasil negosiasi yang dilakukan saat proses handshake. Ilustrasi dari keempat metode ini ditampilkan pada Gambar C.1 C.1 RSA Pada metode ini, server akan mengirimkan sertifikat digital yang mengandung kunci publik RSA miliknya melalui pesan Certificate. Client yang menerima pesan ini selanjutnya membuat sebuah premaster secret, lalu mengenkripsinya
menggunakan
kunci
publik
RSA
milik
server,
dan
mengirimkannya melalui pesan ClientKeyExchange. Dalam metode ini server tidak perlu mengirimkan pesan ServerKeyExchange karena premaster secret telah disediakan oleh client. Metode ini ditampilkan pada Gambar C.1 (a). C.2 Anonymous DH Metode ini tidak menggunakan sertifikat. Parameter-parameter Diffie Hellman dan half-key milik server (g, p, gs) akan dikirimkan melalui pesan ServerKeyExchange. Client kemudian membalas dengan mengirimkan parameterparameter Diffie Hellman dan half-key miliknya (g, p, gc) melalui pesan ClientKeyExchange. Client dan server kemudian akan menghitung premastester
C-1
Universitas Sumatera Utara
Gambar C.1 Metode pertukaran kunci pada protokol TLS secret berdasarkan parameter-parameter dan half-key ini. Metode ini ditampilkan pada Gambar C.1(b). C.3 Ephemeral DH Pada metode ini, server akan mengirimkan sertifikat tanda tangan digital RSA atau DSA miliknya melalui pesan Certificate serta parameter-parameter C-2
Universitas Sumatera Utara
Diffie Hellman dan half-key (g, p, gs) yang telah ditanda tangani melalui pesan ServerKeyExchange. Client kemudian akan melakukan verifikasi terhadap tanda tangan ini menggunakan kunci publik server yang terdapat pada sertifikat. Client umumnya juga akan mengirimkan sertifikat tanda tangan RSA atau DSA miliknya melalui pesan Certificate dan parameter-parameter Diffie Hellman serta
half-key
(g, p, gc) yang telah ditanda tangani melalui pesan
ClientKeyExchange. Server kemudian akan melakukan verifikasi terhadap tanda tangan ini menggunakan kunci publik client yang terdapat pada sertifikat. Penggunaan tanda tangan ini berfungsi untuk otentikasi server dan client. Client dan Server kemudian akan menghitung premaster secret berdasarkan parameter-parameter dan half-key. Metode ini ditampilkan pada Gambar C.1 (c). C.4 Fixed DH Pada metode ini server akan mengirimkan sertifikat tanda tangan digital RSA atau DSA yang juga mengandung parameter-parameter Diffie Hellman dan half-key (g, p, gs) melalui pesan Certificate. Client kemudian menjawab dengan mengirimkan pesan Certificate yang mengandung parameter-parameter Diffie Hellman dan half-key miliknya (g, p, gc). Client dan server kemudian akan menghitung premastester secret berdasarkan parameter-parameter dan half-key ini. Tidak ada pesan ServerKeyExchange atau ClientKeyExchange yang dikirim pada metode ini. Metode ini ditampilkan pada Gambar C.1 (d).
C-3
Universitas Sumatera Utara
LAMPIRAN D
Mekanisme Perhitungan Kunci Protokol TLS
Protokol TLS menghitung material kunci berdasarkan nilai premaster secret serta bilangan acak Client Random dan Server Random yang dihasilkan masing-masing oleh client dan server saat proses handshake. Perhitungan akan dilakukan menggunakan sebuah fungsi yang dinamakan PRF (Pseudorandom Function), dan dilakukan dalam dua langkah sebagai ditampilkan pada Gambar D.1
Gambar D.1 Mekanisme Perhitungan Kunci Langkah pertama adalah menghasilkan master secret menggunakan fungsi PRF, dimana masukan yang diberikan berupa premaster secret, sebuah string ASCII “master secret”, serta gabungan dari Cient Random dan Server Random. Master secret yang dihasilkan akan berukuran 48 byte, sehingga perlu dikembangkan (ekspansi) menggunakan fungsi PRF kembali untuk dapat
D-1
Universitas Sumatera Utara
dijadikan material kunci. Kali ini yang menjadi masukan adalah master secret yang baru saja dihasilkan, sebuah string ASCII “key expansion”, serta gabungan Server Random dan Client Random. Material kunci yang dihasilkan sekarang akan dibagi menjadi beberapa kunci sesuai dengan penggunaannya sebagai berikut • Client_MAC_Write_Key, digunakan oleh client untuk menghitung MAC • Server_MAC_Write_Key, digunakan oleh server untuk menghitung MAC • Client_Write_Key, digunakan oleh client sebagai kunci untuk enkripsi • Server_Write_Key, digunakan oleh server sebagai kunci untuk enkripsi Perlu diingat bahwa kunci-kunci tersebut digunakan secara berpasangan. Sebagai contoh, Server_Write_Key akan digunakan oleh client untuk mendekripsi (membaca) pesan yang diterima dari server. Sedangkan Client_Write_Key akan digunakan oleh server untuk mendekripsi (membaca) pesan yang diterima dari client.
Demikian
pula
pada
Client_MAC_Write_Key
dan
Client_MAC_Write_Key. D.1 Pseudorandom Function (PRF) Fungsi ini digunakan oleh protokol TLS untuk menghasilkan keluaran berupa bilangan acak (pseudorandom). Fungsi ini sendiri dikembangkan menggunakan basis algoritma HMAC yang telah dijelaskan diawal, dan algoritma lengkapnya ditampilkan pada Gambar D.2
D-2
Universitas Sumatera Utara
Gambar D.2 Pseudorandom Generator Fungsi inilah yang kemudian digunakan untuk membangun fungsi PRF, dengan mengkombinasikan dua prosedur dengan fungsi hash yang berbeda. Hal ini dilakukan untuk mengatasi kelemahan pada setiap fungsi hash. Fungsi hash yang umumnya digunakan adalah MD5 dan SHA. Gambar D.3 mengilustrasikan algoritma Pseudorandom Function (PRF) menggunakan fungsi hash MD5 dan SHA.
Gambar D.3 Pseudorandom Function D-3
Universitas Sumatera Utara
PRF pada protokol TLS membutuhkan masukan berupa kunci secret, seed, dan label. Kunci secret akan dibagi menjadi dua, masing-masing untuk setiap prosedur pseudorandom. Fungsi PRF juga akan menggabungkan label dan seed menjadi sebuah nilai tunggal. Pada kasus dimana fungsi hash yang digunakan adalah MD5 dan SHA yang memiliki keluaran berbeda, jumlah iterasi yang dilakukan mungkin saja berbeda.
D-4
Universitas Sumatera Utara
LAMPIRAN E
Implementasi Protokol TLS pada Aplikasi Menggunakan OpenSSL API
Untuk membangun sebuah sambungan TLS pada aplikasi menggunakan OpenSSL dibutuhkan beberapa langkah sebagaimana ditampilkan pada diagram alir Gambar E.1. Langkah-langkah yang dilakukan sedikit berbeda antara client dan server.
Gambar E.1 Diagram alir membangun sambungan TLS dengan OpenSSL
E-1
Universitas Sumatera Utara
E.1 Membangun struktur parameter sesi dan sambungan (server dan client) Sebuah pointer dengan tipe SSL_CTX diperlukan untuk menampung struktur parameter-parameter sesi. Struktur ini diciptakan dengan memanggil fungsi SSL_CTX_new dengan argumen berupa metode dan protokol yang akan dibangun. Karena protokol yang digunakan adalah TLS versi 1.0 maka metode yang digunakan disini adalah TLSv1_server_method pada sisi server, dan TLSv1_client_method pada sisi client. Sebuah pointer lainnya dengan tipe SSL kemudian diciptakan untuk menampung struktur sambungan SSL. SSL_CTX * ctx = SSL_CTX_new(TLSv1_server_method()); SSL * ssl
E.2 Pengelolaan sertifikat dan kunci privat (server dan client) Sertifikat diperoleh dengan memanggil fungsi SSL_CTX_use_Certificate dengan argumen berupa sebuah pointer SSL_CTX yang telah diciptakan sebelumnya, dan sebuah pointer lainnya yang menunjuk alamat memori dimana sertifikat dimana. Kemudian kunci privat diperoleh dengan memanggil fungsi SSL_CTX_use_PrivateKey. SSL_CTX_use_Certificate(ctx, cert) SSL_CTX_use_PrivateKey (ctx, privatekey)
E.3 Membuka saluran I/O untuk sambungan (server dan client) OpenSSL menggunakan sebuah kelas abstraksi yang disebut BIO untuk menangani komunikasi jaringan melalui socket. Pada sisi server akan diciptakan tiga objek BIO, masing-masing untuk mendengar dan menerima sambungan masuk, memberikan balasan untuk sambungan yang masuk, dan sebuah objek
E-2
Universitas Sumatera Utara
utama yang menggunakan struktur parameter sesi TLS yang telah dibangun sebelumnya. Objek utama ini diciptakan dengan memanggil fungsi BIO_new_ssl dengan argumen berupa pointer dengan tipe SSL_CTX yang menunjuk struktur parameter sesi serta sebuah flag yang menjelaskan tipe objek BIO yang akan diciptakan. Nilai flag 0 digunakan untuk server, sedangkan nilai flag 1 digunakan untuk client. Pointer dengan tipe SSL yang akan digunakan sebagai struktur sambungan kemudian dipanggil melalui fungsi BIO_get_ssl(). BIO *bio, *abio, *out; bio = BIO_new_ssl(ctx, 0); BIO_get_ssl(bio, &ssl);
E.4 Mendengar sambungan masuk (server) Objek BIO untuk mendengar dan menerima sambungan masuk diciptakan dengan memanggil fungsi BIO_new_accept dengan argumen berupa alamat port dimana sambungan masuk akan didengar. Karena menggunakan sambungan aman, maka objek ini harus dihubungkan dengan objek BIO utama dengan memanggil fungsi BIO_set_accept_bios. abio = BIO_new_accept("4422"); BIO_set_accept_bios(abio, bio);
Objek ini akan mulai mendengar sambungan masuk dengan memanggil fungsi BIO_do_accept dua kali berturut-turut. Panggilan pertama akan menyebabkan objek menerima sambungan masuk, dan panggilan kedua akan membuat objek menunggu sambungan masuk BIO_do_accept(abio); BIO_do_accept(abio);
E-3
Universitas Sumatera Utara
E.5 Menginisialisasi sambungan (client) Sambungan TLS dibangun melalui sebuah objek BIO dengan memanggil fungsi BIO_new_ssl_connect. Fungsi ini membutuhkan sebuah argumen berupa pointer dengan tipe SSL_CTX yang mengandung informasi-informasi sesi. Objek BIO ini kemudian akan menggunakan struktur SSL yang telah diciptakan sebelumnya dengan memanggil fungsi BIO_get_ssl(). bio = BIO_new_ssl_connect(ctx); BIO_get_ssl(bio, & ssl);
Alamat
hostname
(server)
kemudian
diatur
melalui
fungsi
BIO_set_conn_hostname, dan sambungan dapat segera dibuka dengan memangil fungsi BIO_do_connect. Fungsi ini juga akan memulai proses handshake. BIO_set_conn_hostname(bio, "hostname:port"); BIO_do_connect(bio);
E.6 Menjawab sambungan masuk (server) Sambungan yang masuk pada server akan dijawab oleh objek BIO lainnya. Objek ini diciptakan dengan memanggil fungsi BIO_pop dengan argumen berupa objek BIO yang mendengar sambungan masuk. Hal pertama yang akan dilakukan oleh objek ini ketika sebuah sambungan masuk adalah menangani proses handshake dengan memanggil fungsi BIO_do_handshake out = BIO_pop(abio); BIO_do_handshake(out);
E.7 Mengirim dan Menerima data melalui sambungan (server dan client) Pembacaan dan penulisan melalui sambungan yang telah terbentuk dilakukan dengan memanggil fungsi BIO_read dan BIO_write. Fungsi BIO_read E-4
Universitas Sumatera Utara
akan mencoba membaca sejumlah data dari sambungan dan akan mengembalikan jumlah byte data yang berhasil terbaca. Fungsi ini akan mengembalikan nilai -1 apabila terjadi kesalahan (error). int r = BIO_read(bio, buf, len); int w = BIO_write(bio, buf, len)
Fungsi BIO_write akan mencoba mengirimkan sejumlah data melalui sambungan yang telah terbentuk, dan akan mengembalikan jumlah byte yang berhasil dikirimkan. Seperti juga pada fungsi BIO_read, fungsi ini akan mengembalikan nilai -1 apabila terjadi kesalahan (error). E.8 Menutup sambungan (server & client) Sambungan yang telah terbentuk ditutup dengan memanggil fungsi BIO_reset. Fungsi ini akan menutup sambungan dan mengembalikan kondisi internal objek BIO seperti semula sehingga sambungan dapat digunakan kembali. BIO_reset(bio);
E-5
Universitas Sumatera Utara
LAMPIRAN F
Referensi Kelas PIndirectChannel dari Pustaka PTLIB 1. Deskripsi Kelas ini merupakan sebuah saluran I/O (input/output) yang bekerja secara tidak langsung melalui saluran-saluran lain. Kelas ini memungkinkan sebuah protokol untuk bekerja menggunakan mekanisme saluran, sementara pertukaran byte level rendah dilakukan melalui saluran lain seperti TCP atau Serial Port, dll. Kelas ini merupakan turunan dari kelas PChannel, yang diturunkan dari kelas PObject. Gambar B.1 berikut menampilkan diagram inheritance kelas PIndirectChannel.
Gambar B.1 Diagram inheritance kelas PIndirectChannel
V-1
Universitas Sumatera Utara
2. Dokumentasi Metode dan Variabel Metode-metode Public Konstruktor & Destruktor PIndirectChannel::PIndirectChannel ( ) Keterangan : Konstruktor yang dipanggil ketika instanisasi objek PIndirectChannel. Akan membuat sebuah saluran tidak langsung (indirect channel) tanpa satu saluran pun untuk pengalihan PIndirectChannel::~PIndirectChannel ( ) Keterangan : Destruktor yang dipanggil ketika pemusnahan objek PIndirectChannel. Berfungsi menutup saluran yang bersangkutan, serta memusnahkan saluran baca/tulis apabila diinginkan
Override dari kelas PObject Comparison PIndirectChannel::Compare ( const PObject & obj ) const Keterangan : berfungsi membandingkan apakah kedua objek merujuk pada saluran tidak langsung yang sama atau tidak. Diimplementasikan ulang dari PChannel Keluaran: EqualTo apabila saluran sama (identik) Parameter: obj = saluran tidak langsung lainnya yang menjadi perbandingan
Override dari kelas PChannel virtual PString PIndirectChannel::GetName ( ) const Keterangan : Berfungsi mengambil nama dari saluran bersangkutan. Diimplementasikan ulang dari Pchannel Keluaran : String nama saluran
V-2
Universitas Sumatera Utara
virtual PBoolean PIndirectChannel::Close ( ) Keterangan : Berfungsi menutup saluran. Metode ini akan melepaskan saluran yang bersangkurandari saluran baca and tulis. Diimplementasikan ulang dari Pchannel Keluaran: PTrue apabila saluran berhasil tertutup virtual PBoolean PIndirectChannel::Shutdown ( ShutdownValue option ) Keterangan : berfungsi menutup salah satu atau kedua aliran data (pembacaan atau penulisan) yang terkait dengan sebuah saluran Keluaran : PTrue jika penutupan sukses Parameter : option = penanda (flag) untuk menutup pembacaan, penulisan, atau keduanya virtual PBoolean PIndirectChannel::Read ( void * buf, PINDEX len) Keterangan : Berfungsi melakukan pembacaan tingkat rendah dari saluran. Metode ini mungkin akan menghalangi (block) jalannya program hingga sejumlah karakter yang diminta terbaca atau timeout pembacaan tercapai. Metode GetLastReadCount( ) dapat digunakan untuk mengetahui jumlah bytes yang terbaca sebenarnya. Metode ini sesungguhnya akan menggunakan readChannel untuk pembacaan Metode GetErrorCode( ) sebaiknya dipanggil apabila Read( ) mengembalikan nilai PFalse untuk mengetahui penyebab kegagalan. Diimplementasikan ulang dari PChannel Keluaran : PTrue apabila ada setidaknya satu karakter data yang terbaca dari saluran. PFalse apabila tidak ada data yang terbaca hingga timeout atau karena sejumlah kesalahan I/O lainnya. Parameter : buf = pointer menuju blok memory penyangga (buffer) untuk menyimpan data yang terbaca len = jumlah maksimum data yang terbaca yang dapat disimpan ke penyangga (buffer)
V-3
Universitas Sumatera Utara
virtual PBoolean PIndirectChannel::Write ( void * buf, PINDEX len ) Keterangan : Berfungsi melakukan penulisan tingkat rendah ke saluran. Metode ini mungkin akan menghalangi (block) jalannya program hingga sejumlah karakter yang diminta dituliskan atau timeout penulisan tercapai. Metode GetLastWriteCount( ) dapat digunakan untuk mengetahui jumlah bytes yang berhasil dituliskan sebenarnya. Metode ini sesungguhnya akan menggunakan writeChannel untuk penulisan. Metode GetErrorCode( ) sebaiknya dipanggil apabila Write( ) mengembalikan nilai PFalse untuk mengetahui penyebab kegagalan. Diimplementasikan ulang dari PChannel Keluaran : PTrue apabila ada setidaknya satu karakter data yang berhasil ditulis ke saluran. PFalse apabila tidak ada data yang berhasil ditulis hingga timeout atau karena sejumlah kesalahan I/O lainnya. Parameter : buf = pointer ke blok memory penyangga (buffer) yang menyimpan data yang akan ditulis len = jumlah maksimum data dari penyangga yang akan ditulis ke saluran virtual PChannel* PIndirectChannel::GetBaseReadChannel ( ) const Keterangan : Berfungsi mengambil saluran dasar terakhir untuk pembacaan dari serangkaian saluran tidak langsung yang disediakan oleh turunan PIndirectChannel Diimplementasikan ulang dari Pchannel Keluaran : Pointer ke saluran dasar virtual PChannel* PIndirectChannel::GetBaseWriteChannel ( ) Keterangan : Berfungsi mengambil saluran dasar terakhir untuk penulisan dari serangkaian saluran tidak langsung yang disediakan oleh turunan PIndirectChannel Diimplementasikan ulang dari PChannel Keluaran : Pointer ke saluran dasar
V-4
Universitas Sumatera Utara
virtual PString PIndirectChannel::GetErrorText ( ErrorGroup group ) const Keterangan : Berfungsi mengambil deskripsi pesan kesalahan. Akan mengembalikan sebuah string yang mengindikasikan pesan kesalahan yang bisa dimengerti pengguna. Keluaran : String deskripsi kesalahan sistem operasi Parameter : group = kelompok kesalahan yang akan diambil deskripsinya virtual PBoolean PIndirectChannel::IsOpen ( ) const Keterangan : Berfungsi menguji apakah saluran telah terbuka dan operasi baca tulis dapat dilakukan Diimplementasikan ulang dari Pchannel Keluaran : PTrue jika saluran terbuka
Metode-metode untuk pembentukan saluran (channel) PChannel * PIndirectChannel::GetReadChannel ( ) const Keterangan : Berfungsi mengambil saluran yang digunakan untuk operasi baca Keluaran : Pointer ke saluran baca PBoolean PIndirectChannel::SetReadChannel ( PChannel * channel, Pboolean autoDelete = PTrue ) Keterangan : Berfungsi menyetel saluran untuk operasi baca keluaran : PTrue apabila saluran telah diatur dan terbuka parameter : channel = saluran yang akan digunakan untuk operasi baca autoDelete = menghapus saluran secara otomatis PChannel * PIndirectChannel::GetWriteChannel ( ) const Keterangan : Berfungsi mengambil saluran yang digunakan untuk operasi tulis (kirim) Keluaran : Pointer ke saluran tulis
V-5
Universitas Sumatera Utara
PBoolean PIndirectChannel::SetWriteChannel ( PChannel * autoDelete = PTrue )
channel, PBoolean
Keterangan : Berfungsi menyetel saluran untuk operasi tulis Keluaran : PTrue apabila saluran telah diatur dan terbuka Parameter : channel = saluran yang akan digunakan untuk operasi tulis autoDelete = menghapus saluran secara otomatis PBoolean PIndirectChannel::Open ( PChannel * readChannel, PChannel * writeChannel, PBoolean autoDeleteRead = PTrue, PBoolean autoDeleteWrite = PTrue ) Keterangan : Berfungsi menyetel saluran untuk operasi baca dan tulis. Metode ini lalu akan menguji apakah saluran telah terbuka dan memanggil OnOpen( ). Apabila metode OnOpen( ) mengembalikan PTrue maka metode Open( ) kembali dengan sukses. Keluaran : PTrue jika kedua saluran telah diatur dan terbuka, serta OnOpen( ) mengembalikan nilai Ptrue Parameter : readChannel = saluran untuk operasi baca writeChannel = saluran untuk operasi tulis autoDeleteRead = hapus saluran baca secara otomatis autoDeleteWrite = hapus saluran tulis secara otomatis PBoolean PIndirectChannel::Open ( PChannel * channel, PBoolean autoDelete = Ptrue ) Keterangan : Berfungsi menyetel saluran untuk operasi baca dan tulis. Metode ini lalu akan menguji apakah saluran telah terbuka dan memanggil OnOpen( ). Apabila metode OnOpen( ) mengembalikan PTrue maka metode Open( ) kembali dengan sukses. Keluaran : PTrue jika kedua saluran telah diatur dan terbuka, serta OnOpen( ) mengembalikan nilai PTrue Parameter : channel = saluran untuk operasi baca dan tulis autoDelete = hapus saluran baca dan tulis secara otomatis
V-6
Universitas Sumatera Utara
PBoolean PIndirectChannel::Open ( PChannel & channel ) Keterangan : Berfungsi menyetel saluran untuk operasi baca dan tulis. Metode ini lalu akan menguji apakah saluran telah terbuka dan memanggil OnOpen( ). Apabila metode OnOpen( ) mengembalikan PTrue maka metode Open( ) kembali dengan sukses. Keluaran : PTrue jika kedua saluran telah diatur dan terbuka, serta OnOpen( ) mengembalikan nilai PTrue Parameter : channel = saluran untuk operasi baca dan tulis
Metode-metode Protected virtual PBoolean PIndirectChannel::OnOpen ( ) Keterangan : Akan dipanggil oleh metode Open( ) apabila berhasil membuka saluran. Dapat digunakan oleh saluran turunan untuk melakukan handshaking yang diperlukan oleh protokol yang diwadahinya. Secara default akan mengembalikan nilai PTrue Keluaran : PTrue apabila handshaking protokol sukses
Variabel-variabel PChannel* PIndirectChannel::readChannel Keterangan : Merupakan pointer menuju saluran (channel) untuk operasi baca PChannel* PIndirectChannel::writeChannel Keterangan : Merupakan pointer menuju saluran (channel) untuk operasi tulis/kirim PBoolean PIndirectChannel::readAutoDelete Keterangan : flag (penanda) untuk menghapus saluran baca secara otomatis ketika saluran dihapus PBoolean PIndirectChannel::writeAutoDelete Keterangan : flag (penanda) untuk menghapus saluran tulis secara otomatis ketika saluran dihapus
V-7
Universitas Sumatera Utara
LAMPIRAN G
Referensi Kelas OpalTransport dari Pustaka OPAL 1. Deskripsi Kelas ini menggambarkan sebuah transport I/O untuk sebuah protokol VoIP. Transport sendiri merupakan sebuah objek yang memungkinkan transfer dan pemrosesan data sebelum satu entitas ke entitas lainnya. Kelas ini merupakan turunan dari kelas PindirectChannel dari pustaka PTLIB. Terdapat dua realisasi OpalTransport, yaitu OpalTransportTCP yang menangani transport untuk protokol TCP, dan OpalTransportUDP yang menangani transport untuk protokol UDP. Gambar C.1 berikut menampilkan diagram inheritance kelas OpalTransport.
Gambar C.1 Diagram inheritance kelas OpalTransport
V-1
Universitas Sumatera Utara
2.
Dokumentasi Metode dan Variabel
Metode-metode Public Konstruktor & Destruktor OpalTransport::OpalTransport ( OpalEndPoint & endpoint ) Keterangan : Konstruktor yang dipanggil ketika instanisasi objek OpalTransport. Akan membuat sebuah saluran transport yang terikat pada endpoint. Parameter : endpoint = endpoint dimana transport yang bersangkutan akan terpaut OpalTransport::~OpalTransport ( OpalEndPoint & endpoint ) Keterangan : Destruktor yang dipanggil ketika pemusnahan objek OpalTransport. Akan menghapus saluran transport yang bersangkutan.
Metode-Metode Operasi Transport virtual void OpalTransport::AttachThread ( PThread * thread ) Keterangan : Berfungsi menambatkan sebuah thread untuk transport bersangkutan void OpalTransport::CleanUpOnTermination ( ) Keterangan : Berfungsi menutup saluran lalu menunggu thread terkait untuk berhenti. Digunakan untuk kompatibilitas dengan OpenH323 yang telah usang virtual PBoolean OpalTransport::Close ( ) Keterangan : Berfunsi menutup saluran void OpalTransport::CloseWait ( ) Keterangan : Berfungsi menutup saluran lalu menunggu thread terkait untuk berhenti. PBoolean OpalTransport::Connect ( ) Keterangan : Berfungsi membangun sambungan ke alamat remote. Diimplementasikan pada OpalTransportTCP dan OpalTransportUDP
V-2
Universitas Sumatera Utara
PBoolean OpalTransport::ConnectTo ( const OpalTransportAddress & address ) Keterangan : Berfungsi membangun sambungan ke alamat remote tertentu OpalEndPoint& OpalTransport::GetEndPoint ( ) const Keterangan : Berfungsi mengambil endpoint dimana transport yang bersangkuran tertambat virtual PString OpalTransport::GetInterface ( ) const Keterangan : Berfungsi mengambil interface dimana transport bersangkutan terhubung. Umumnya hanya relevan untuk transport berbasis datagram seperti UDP, sementara TCP selalu terhubung pada interface lokal setiap kali terbuka. Secara default mengembalikan alamat lokal melalui GetLocalAddress ( ) Diimplementasikan ulang pada OpalTransportUDP virtual OpalTransportAddress OpalTransport:: GetLastReceivedAddress ( ) const Keterangan : Berfungsi mengambil alamat transport darimana PDU yang terakhir diterima Secara default memanggil GetRemoteAddress( ) Diimplementasikan ulang pada OpalTransportUDP virtual PString OpalTransport::GetLastReceivedInterface ( ) const Keterangan : Berfungsi mengambil interface dimana PDU terakhir diterima tiba/sampai Secara default memanggil GetLocalAddress( ) Diimplementasikan ulang pada OpalTransportUDP virtual OpalTransportAddress OpalTransport::GetLocalAddress ( bool allowNAT = true ) Keterangan : Berfungsi mengambil nama transport dari local endpoint Parameter : allowNAT = memungkinkan translasi apabila remote membutuhkan NAT diimplementasikan pada OpalTransportIP dan OpalTransportUDP virtual const char* OpalTransport::GetProtoPrefix ( ) const Keterangan : Berfungsi mengambil prefix untuk tipe protokol transport yang bersangkutan Diimplementasikan pada OpalTransportIP, OpalTransportUDP, dan OpalTransportTCP
V-3
Universitas Sumatera Utara
virtual OpalTransportAddress OpalTransport::GetRemoteAddress ( ) const Keterangan : Berfungsi mengambil alamat transport dari endpoint remote Diimplementasikan pada OpalTransportIP virtual PBoolean OpalTransport::IsCompatibleTransport (const OpalTransportAddress & address ) const Keterangan : Berfungsi untuk menguji apakah alamat transport kompatibel (cocok) dengan transport bersangkutan Diimplementasikan pada OpalTransportTCP dan OpalTransportUDP virtual PBoolean OpalTransport:: IsReliable ( ) Keterangan : Berfungsi untuk memeriksa jenis transport yang mendasari virtual PBoolean OpalTransport::IsRunning ( ) Keterangan : Berfungsi untuk memeriksa apakah transport berjalan dengan background thread virtual PBoolean OpalTransport::ReadPDU ( PBYTEArray & packet ) Keterangan : Berfungsi melakukan peembacaan PDU (Protocol Data Unit) dari transport bersangkutan. Pembacaan menggunakan mekanisme transport sesuai batas-batas PDU, misalnya pada UDP merupakan sebuah panggilan tunggal Read( ), sementara pada TCP terdapat sebuah TPKT header yang mengindikasikan ukuran PDU. diimplementasikan pada OpalTransportTCP dan OpalTransportUDP Parameter : packet = Packet yang dibaca dari transport virtual bool OpalTransport::SetInterface ( const PString & iface ) Keterangan : berfungsi mengikat transport yang bersangkutan pada sebuah interface. Umumnya hanya relevan untuk transport berbasis datagram seperti UDP, sementara TCP selalu terhubung pada interface lokal setiap kali terbuka. Secara default tidak melakukan apa-apa. Diimplementasikan ulang pada OpalTransportUDP Parameter: iface = interface yang akan digunakan
V-4
Universitas Sumatera Utara
virtual PBoolean OpalTransport::SetLocalAddress ( const OpalTransportAddress & address ) Keterangan : Berfungsi menyetel alamat lokal darimana akan terhubung. Tidak harus bekerja pada seluruh tipe transport atau hanya bekerja sebelum Connect( ) dipanggil. Diimplementasikan pada OpalTransportIP dan OpalTransportUDP virtual void OpalTransport::SetPromiscuous ( PromisciousModes promiscuous ) Keterangan : Berfungsi mengatur pembacaan kedalam modus promiscuous. Secara normal hanya membolehkan pembacaan dari alamat remote yang telah ditentukan. Metode ini membolehkan pembacaan paket dari alamat remote manapun asalkan protokol yang mendasari dapat melakukannya, seperti UDP. virtual PBoolean OpalTransport::SetRemoteAddress ( const OpalTransportAddress & address ) Keterangan : Berfungsi menyetel alamat remote kemana akan terhubung. virtual PBoolean OpalTransport::WriteConnect ( WriteConnectCallback function, void * userData ) Keterangan : Berfungsi menuliskan paket pertama ke transport setelah terhubung untuk menyesuaikan objek transport. Akan memanggil fungsi callback, mungkin beberapa kali untuk beberapa jenis transport. Diharapkan digunakan segera setelah pemanggilan Connect ( ) dimana beberapa transport (seperti UDP) tidak dapat menentukan local addressnya sendiri yang dibutuhkan pada PDU yang akan dikirim. Hal ini dilakukan untuk setiap interface sehingga WriteConnect( ) memanggil WriteConnectCallback untuk setiap interface. Pemanggilan ReadPDU( ) selanjutnya akan mengembalikan jawaban dari interface pertama. Secara default hanya akan memanggil fungsi WriteConnectCallback Parameter : function = fungsi untuk menuliskan data userData = data pengguna untuk dilewatkan ke fungsi write virtual PBoolean OpalTransport::WritePDU ( const PBYTEArray & pdu ) Keterangan : Berfungsi menuliskan sebuah PDU ke transport, menggunakan mekanisme transport sesuai batas-batas PDU, misalnya pada UDP merupakan sebuah panggilan tunggal Read( ), sementara pada TCP akan menambahkan sebuah TPKT header yang mengindikasikan ukuran PDU. Parameter : pdu = paket PDU yang akan dituliskan
V-5
Universitas Sumatera Utara
Variabel-variabel OpalEndPoint& OpalTransport::endpoint Keterangan : endpoint dimana transport yang bersangkutan tertambat PThread* OpalTransport::thread Keterangan : Pointer ke thread yang menangani transport bersangkutan
V-6
Universitas Sumatera Utara
LAMPIRAN H
Listing Kode Program
H.1 Transport TLS (header) class OpalTransportTLS : public OpalTransportTCP { PCLASSINFO(OpalTransportTLS, OpalTransportTCP); public: /// Konstruktor OpalTransportTLS( OpalEndPoint & endpoint, ///< Eobjek endpoint PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), ///< interface lokal yang digunakan WORD port = 0, ///< port lokal yang digunakan PBoolean reuseAddr = PFalse ); /// Destruktor ~OpalTransportTCPS(); PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const; PBoolean Connect(); PBoolean OnOpen(); const char * GetProtoPrefix() const; protected: tlsContext * sslContext; };
H.2 Transport TLS (implementasi) OpalTransportTLS::OpalTransportTLS(OpalEndPoint & ep, PIPSocket::Address binding, WORD port, PBoolean reuseAddr) : OpalTransportTCP(ep, binding, port, reuseAddr) { tlsContext = new TLSContext(TLSContext::TLSv1); } OpalTransportTLS::~OpalTransportTLS() { CloseWait(); delete tlsContext; } PBoolean OpalTransportTLS::IsCompatibleTransport(const OpalTransportAddress & address) const { return OpalTransportTCP::IsCompatibleTransport(address) || address.NumCompare(TlsPrefix) == EqualTo; } PBoolean OpalTransportTCPS::Connect() { if (IsOpen()) return PTrue;
V-1
Universitas Sumatera Utara
PTCPSocket * socket = new PTCPSocket(remotePort); PReadWaitAndSignal mutex(channelPointerMutex); socket->SetReadTimeout(10000); OpalManager & manager = endpoint.GetManager(); localPort = manager.GetNextTCPPort(); socket->Connect(localPort, remoteAddress)) int errnum = socket->GetErrorNumber(); if (localPort == 0 || (errnum != EADDRINUSE && errnum != EADDRNOTAVAIL)) { return SetErrorValues(socket->GetErrorCode(), errnum); } socket->SetReadTimeout(PMaxTimeInterval); PString certificateFile = endpoint.GetTLSCertificate(); if (!SetTLSCertificate(*sslContext, certificateFile, PTrue)) { return PFalse; } TLSChannel * tlsChannel = new TLSChannel(tlsContext); if (!tlsChannel->Connect(socket)) { delete tlsChannel; return PFalse; } return Open(tlsChannel); } PBoolean OpalTransportTLS::OnOpen() { TLSChannel * tlsChannel = dynamic_cast(GetReadChannel()); if (tlsChannel == NULL) return PFalse; PIPSocket * socket = dynamic_cast(sslChannel->GetReadChannel()); if (!socket->GetPeerAddress(remoteAddress, remotePort)) { return PFalse; } if (!socket->GetLocalAddress(localAddress, localPort)) { return PFalse; } return PTrue; } const char * OpalTransportTLS::GetProtoPrefix() const { return TlsPrefix; }
H.3 TLS Channel (header) #include struct ssl_st; struct ssl_ctx_st; struct x509_st;
V-2
Universitas Sumatera Utara
struct evp_pkey_st; struct dh_st; enum PSSLFileTypes { PSSLFileTypePEM, PSSLFileTypeASN1, PSSLFileTypeDEFAULT }; class PSSLChannel : public PIndirectChannel { PCLASSINFO(PSSLChannel, PIndirectChannel) public: PSSLChannel( PSSLContext * context = NULL, ///< Context for SSL channel PBoolean autoDeleteContext = PFalse ///< Flag for context to be automatically deleted. ); PSSLChannel( PSSLContext & context ///< Context for SSL channel ); ~PSSLChannel(); // Overrides from PChannel virtual PBoolean Read(void * buf, PINDEX len); virtual PBoolean Write(const void * buf, PINDEX len); virtual PBoolean Close(); virtual PBoolean Shutdown(ShutdownValue) { return PTrue; } virtual PString GetErrorText(ErrorGroup group = NumErrorGroups) const; virtual PBoolean ConvertOSError(int error, ErrorGroup group = LastGeneralError); PBoolean Connect( PChannel * channel, ///< Channel to attach to. PBoolean autoDelete = PTrue ///< Flag for if channel should be automatically deleted. enum VerifyMode { VerifyNone, VerifyPeer, VerifyPeerMandatory, }; void SetVerifyMode( VerifyMode mode ); PSSLContext * GetContext() const { return context; } virtual PBoolean RawSSLRead(void * buf, PINDEX & len); protected: virtual PBoolean OnOpen(); protected: PSSLContext * context; PBoolean autoDeleteContext; ssl_st * ssl; };
H.4 TLS Channel (implementasi) #pragma implementation "tlsChannel.h" #include #include #include
V-3
Universitas Sumatera Utara
#include #define USE_SOCKETS extern "C" { #include #include #include }; PSSLChannel::PSSLChannel(PSSLContext * ctx, PBoolean autoDel) { if (ctx != NULL) { context = ctx; autoDeleteContext = autoDel; } else { context = new PSSLContext; autoDeleteContext = PTrue; } ssl = SSL_new(*context); if (ssl == NULL) PSSLAssert("Error creating channel: "); } PSSLChannel::PSSLChannel(PSSLContext & ctx) { context = &ctx; autoDeleteContext = PFalse; ssl = SSL_new(*context); } PSSLChannel::~PSSLChannel() { // free the SSL connection if (ssl != NULL) SSL_free(ssl); if (autoDeleteContext) delete context; } PBoolean PSSLChannel::Read(void * buf, PINDEX len) { flush(); channelPointerMutex.StartRead(); lastReadCount = 0; PBoolean returnValue = PFalse; if (readChannel == NULL) SetErrorValues(NotOpen, EBADF, LastReadError); else if (readTimeout == 0 && SSL_pending(ssl) == 0) SetErrorValues(Timeout, ETIMEDOUT, LastReadError); else { readChannel->SetReadTimeout(readTimeout); int readResult = SSL_read(ssl, (char *)buf, len); lastReadCount = readResult; returnValue = readResult > 0;
V-4
Universitas Sumatera Utara
if (readResult < 0 && GetErrorCode(LastReadError) == NoError) ConvertOSError(-1, LastReadError); } channelPointerMutex.EndRead(); return returnValue; } PBoolean PSSLChannel::Write(const void * buf, PINDEX len) { flush(); channelPointerMutex.StartRead(); lastWriteCount = 0; PBoolean returnValue; if (writeChannel == NULL) { SetErrorValues(NotOpen, EBADF, LastWriteError); returnValue = PFalse; } else { writeChannel->SetWriteTimeout(writeTimeout); int writeResult = SSL_write(ssl, (const char *)buf, len); lastWriteCount = writeResult; returnValue = lastWriteCount >= len; if (writeResult < 0 && GetErrorCode(LastWriteError) == NoError) ConvertOSError(-1, LastWriteError); } channelPointerMutex.EndRead(); return returnValue; } PBoolean PSSLChannel::Close() { PBoolean ok = SSL_shutdown(ssl); return PIndirectChannel::Close() && ok; } PBoolean PSSLChannel::Accept(PChannel & channel) { if (Open(channel)) return ConvertOSError(SSL_accept(ssl)); return PFalse; } PBoolean PSSLChannel::Accept(PChannel * channel, PBoolean autoDelete) { if (Open(channel, autoDelete)) return ConvertOSError(SSL_accept(ssl)); return PFalse; } PBoolean PSSLChannel::Connect() { if (IsOpen()) return ConvertOSError(SSL_connect(ssl)); return PFalse; } PBoolean PSSLChannel::Connect(PChannel * channel, PBoolean autoDelete)
V-5
Universitas Sumatera Utara
{ if (Open(channel, autoDelete)) return ConvertOSError(SSL_connect(ssl)); return PFalse; } PBoolean PSSLChannel::UseCertificate(const PSSLCertificate & certificate) { return SSL_use_certificate(ssl, certificate); } void PSSLChannel::SetVerifyMode(VerifyMode mode) { int verify; switch (mode) { default : case VerifyNone: verify = SSL_VERIFY_NONE; break; case VerifyPeer: verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; break; case VerifyPeerMandatory: verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } SSL_set_verify(ssl, verify, VerifyCallBack); } PBoolean PSSLChannel::OnOpen() { BIO * bio = BIO_new(&methods_Psock); if (bio == NULL) { SSLerr(SSL_F_SSL_SET_FD,ERR_R_BUF_LIB); return PFalse; } // "Open" then bio bio->ptr = this; bio->init = 1; SSL_set_bio(ssl, bio, bio); return PTrue; }
V-6
Universitas Sumatera Utara