субота, 14 листопада 2009 р.

Канал через UDP

Півтора року тому для підтримки GPRS знадобилося мені реалізувати специфічний протокол SIA-over-IP. Це до возу приліпили крила й реактивний двигун, так що він тепер літає поруч із лайнерами. Тобто, сто років вже працюють у текстовому форматі SIA різні прилади, так ці самі повідомлення вже можна пропихати й через інтернет.

В документі було написано, що протокол орієнтований на з’єднання TCP, але при необхідності можна ті самі пакети слати у датаграмах UDP. Сказано — зроблено, просто для полегшення власної сверблячки зробив я обидва варіанти, хоч і ніхто не просив.

І от тижнів зо два тому телефонує інженер, який робив цей протокол для приладів, і питає, мовляв, як там у нас на сервері із UDP? Кажу, що все на місці, бери й спробуй… Працювало все нормально, але тільки до тих пір, як спробували під’єднатися до віртуального інтерфейсу. Виявилося, що пакети на сервер таки приходять, той відповідає, але вже через справжній інтерфейс. Тобто, прилад присилає на віртуальну адресу 192.168.38.14, а сервер відповідає із 192.168.38.13. Тому їх не хоче випускати у світ файрвол. Та й сам прилад, мабуть, проігнорував би.

Порившись півдня у інтернетрях, кажу архітекторові, що вся біда у прив’язці приймаючого сокета до IPADDR_ANY, давайте, мовляв, я їх заведу на кожен інтерфейс по одному, буде швидко й найдійно. — Та де там, шукай далі, як правильно обдурювати адресата, переписуючи на конверт зворотню адресу з оригіналу…

Таки надибав! Всі про це знають, але ніхто не каже вголос. Підглянув (thanks OSS!), і за день зробив. Довелося, правда, замінити recvfrom/sendto на recvmsg/sendmsg, у самому повідомленні порпатися у допоміжній інформації (struct in_pktinfo), та ще й самому її підкидати. Але так до кінця й не впевнений, що воно того було варте.

Немає коментарів:

Дописати коментар