SO_PEEK_OFF Memberi UNIX Socket Cursor Peek yang Stateful

recv(..., MSG_PEEK) biasanya memeriksa data di depan receive queue socket tanpa menghapusnya. Pada UNIX-domain socket Linux, SO_PEEK_OFF dapat mengganti pola yang selalu melihat kepala queue itu dengan cursor yang bergerak maju setelah setiap peek.

Cursor tersebut merupakan state milik socket. Peek menggesernya ke depan, sedangkan konsumsi byte dari depan queue menggesernya kembali sebesar jumlah byte yang diambil. Interaksi ini memungkinkan proses memeriksa bagian queue secara berurutan tanpa mengonsumsinya, sambil mempertahankan posisi peek terhadap data yang masih tersisa.

Offset nonnegatif mengubah semantik MSG_PEEK

Socket baru memiliki peek offset -1. Nilai negatif mempertahankan perilaku konvensional: setiap receive dengan MSG_PEEK dimulai dari depan data yang mengantre.

Mengatur SO_PEEK_OFF ke nol atau offset byte positif mengaktifkan cursor. MSG_PEEK berikutnya dimulai pada offset itu, lalu peek yang berhasil menambah offset tersimpan sebesar jumlah byte yang dikembalikan.

int off = 4;

if (setsockopt(fd, SOL_SOCKET, SO_PEEK_OFF,
               &off, sizeof(off)) == -1) {
    /* handle error */
}

Jika receive queue berisi:

aabbccddeeff

offset empat menempatkan peek pertama pada cc. Peek dua byte menggeser cursor dari 4 menjadi 6. Peek dua byte berikutnya menghasilkan dd dan menggesernya menjadi 8.

Perilaku ini berbeda dari pemanggilan recv() berulang dengan MSG_PEEK tanpa offset yang dikonfigurasi. Pada mode konvensional, kedua call tidak menghapus data sehingga keduanya dimulai dari kepala queue yang sama.

Receive biasa menjaga posisi relatif cursor

Cursor bukan penghitung byte absolut sepanjang umur socket. Linux menyesuaikannya ketika data dikonsumsi dari depan melalui receive yang tidak memakai MSG_PEEK.

Melanjutkan state sebelumnya, cursor berada di 8 setelah dua peek. Jika receive biasa mengambil aa, dua byte hilang dari kepala queue dan cursor turun menjadi 6. Peek dua byte berikutnya menghasilkan ee.

queue awal          aabbccddeeff   cursor 4
peek 2              -> cc          cursor 6
peek 2              -> dd          cursor 8
receive 2           -> aa          cursor 6
queue tersisa       bbccddeeff
peek 2              -> ee          cursor 8

Penyesuaian itu mempertahankan posisi logis cursor terhadap data yang masih mengantre. Tanpa koreksi tersebut, penghapusan byte sebelum cursor akan menggeser bagian data yang sedang diperiksa.

Karena itu, offset ini juga bukan sequence number pada level aplikasi. Konsumsi queue dapat mengubah nilai numeriknya walau posisi logis peek tetap mengarah ke data lanjutan yang sama.

Peek tidak melakukan reservasi terhadap byte

SO_PEEK_OFF mengubah lokasi pembacaan MSG_PEEK. Opsi ini tidak melakukan reservasi byte, tidak mengunci receive queue, dan tidak membuat transaksi antara inspeksi dengan konsumsi berikutnya.

Jika thread atau proses lain dapat menerima data dari socket yang sama, pihak tersebut dapat menghapus data setelah sebuah peek. Kernel menyesuaikan cursor socket mengikuti konsumsi queue, tetapi asumsi aplikasi terhadap isi yang sebelumnya diperiksa tetap dapat menjadi usang.

Batas ini penting bagi parser yang memeriksa header sebelum menentukan jumlah data yang akan dikonsumsi. Cursor stateful dapat mengurangi pemindaian ulang queue, tetapi correctness tetap bergantung pada ownership dan sinkronisasi operasi receive.

Jadi, opsi ini menyediakan state posisi queue, bukan akses eksklusif terhadap state tersebut maupun byte di belakangnya.

Datagram memiliki kasus khusus pada batas packet

Cursor dinyatakan sebagai offset byte, sedangkan datagram socket mempertahankan batas message. Karena itu, offset yang dikonfigurasi dapat menunjuk ke tengah packet yang mengantre.

Dalam kondisi tersebut, Linux menandai data yang dikembalikan dengan MSG_TRUNC. Flag itu menunjukkan bahwa peek dimulai dari bagian tengah packet, bukan dari awalnya.

Perilaku ini berbeda dari stream socket, yang receive queue-nya dikonsumsi sebagai aliran byte tanpa batas datagram yang perlu dipertahankan. Kode yang memakai SO_PEEK_OFF pada UNIX datagram socket perlu menjaga perbedaan antara posisi cursor dan batas packet.

Dukungan lebih sempit daripada level SOL_SOCKET

SO_PEEK_OFF tersedia sejak Linux 3.4, tetapi dukungan yang didokumentasikan saat ini terbatas pada UNIX-domain socket. Penempatannya pada SOL_SOCKET tidak menjadikannya fasilitas portabel untuk TCP, UDP, atau semua keluarga socket.

Scope tersebut merupakan batas arsitektural bagi kode yang mungkin menganggap socket option berlaku independen dari keluarga socket. Komponen dapat memakai mekanisme ini ketika boundary IPC-nya berupa UNIX socket yang didukung, tetapi abstraksi networking generik tidak dapat mengasumsikan perilaku setara pada Internet socket.

Interface ini juga spesifik Linux. Kode portabel memerlukan model state lain, umumnya dengan menyimpan offset parsing sendiri atas data yang sudah disalin ke buffer aplikasi.

State penting berada pada relasi cursor dan queue

SO_PEEK_OFF mengubah MSG_PEEK dari observasi stateless terhadap kepala queue menjadi mekanisme traversal yang stateful. Kernel menyimpan cursor byte, memajukannya setelah peek, lalu mengompensasi ketika byte yang lebih awal dikonsumsi.

State tersebut sengaja memiliki scope sempit. Ia tidak mengonsumsi data, tidak mempertahankan byte yang sudah diperiksa dari receiver concurrent, tidak menghapus batas datagram, dan tidak meluas ke keluarga socket di luar dukungan yang didokumentasikan Linux.

Kontrak akhirnya spesifik: pada UNIX socket yang didukung, peek offset nonnegatif memilih byte queue berikutnya untuk MSG_PEEK, peek yang berhasil memajukan offset tersebut, dan konsumsi biasa dari depan queue menggesernya kembali untuk mempertahankan posisi relatif.