/pr/ – programming


29999299995f5505e4223a8bff64b19becc5d – ``CMQ''

@01b18cab88594e94b645ede73c969569 Anonymous 2016-09-15 16:44:32
CMQ - circular message queue - the app/protocol name

Messages = {id: uuid, insert_timestamp: timestamp, message: text}

insert_date is the date/time in UTC of the record insertion.

http get:
1. /m/<uuid:id>/ - gets message record from Messages by id.
2. /mb/<uuid:id>/ - gets messages before <id>. The amount of returned records is limited.
3. /mbt/<timestamp:ts>/ - gets messages before <ts>.
4. /ma/<uuid:id>/ - gets messages after <ts>.
5. /mat/<timestamp:ts>/
6. /l/ - gets limits {max_msg_len: int,
@a797d64fbb084e2c87ea16f6c7af3694 Anonymous 2016-09-15 16:44:32
max_range_len: int}
7. /mbw/<uuid:id1>/<uuid:id2> - gets messages between <id1> and <id2>.
8. /mbwt/<timestamp:ts1>/<timestamp:ts2>

http post:
1. /post
id: uuid - optional.
message: text

response: id, insert_timestamp
or empty string if there is a collision
@c4550b8b39a04d3385061e11b8170092 Anonymous 2016-09-15 17:11:05
Суть такова. Http сервис, который поддерживает 8 get запросов и 1 пост запрос, перечисленные выше. Get возвращает все в json формате. В базе только одна таблица Messages. Количество записей в ней лимитировано. Работает как circular queue, т.е. если лимит в лям записей, то их не может быть больше лямя: самое старая запись удаляется, когда приходит новая. Вот. Можно получить сообщение по айди, сообщения в каком-то промежутке и т.д. Можно запостить новое (если при этом указывается айдишник, то сервис
@3bb813074fad44b28d24392a68ead5bf Anonymous 2016-09-15 17:11:06
попытается сохранить запись с этим айди, а не будет сам его генерить; если уже есть запись с таким айди, то сервер просто ничего не делает).

На основе такой очень простой, я бы даже сказал, юнихвейной хуерги можно мутить много полезной поеботы. Самое главное, что это очень, до тупизны, простая прилага. На сервисе должен быть разрешен cors для всех доменов, естественно.

Пример использования: распределенная textboard, imageboard, форум, распределенное хранилище данных. В самом Messages.message можно
@fd3b9119bcb448b994a069a929e8bd59 Anonymous 2016-09-15 17:11:06
хранить любую структуру какую хочется. Поднимается с десяток таких сервисов и создается еще несколько для синхронизации (для этого и предусмотрена в /post возможность отправлять сразу айди).

Самое главное, еще раз повторю, что это простой и понятный протокол. Понятный любому дебилу. И поэтому любой дебил в состоянии будет его поднять. Да, это не совсем эффективная архитектура в плане перформанса и т.д., но самое главное, что она проста и надежна (тут нехую ломаться). Можно отправлять зашифрованные данные
@c944a25eb2294aa0a70e0eb47532dd2f Anonymous 2016-09-15 17:11:07
и т.п. Надо чтобы по интернету были тысячи таких работающих бесплатных сервисов. Я сделаю несколько реализации на различных языках (.NET Core C#, node.js typescript, Haskell, python), все будет под GPL v3, на gnu savannah. Вот. Все. Критика, насмешки и обсирание приветствуется.
@cddaf001330e4c468d043bbe9319c62d Anonymous 2016-09-17 15:28:30
Так вот, "статья" значит. Сразу говорю, что я хуево умею излагать мысли, могу путать слова, их смыслы и, конечно же, могу противоречить самому себе (всегда так делаю). Кто-нибудь стопудов скажет "многобукав", но мои короткие описания обычно либо малопонятны, либо совсем непонятны (я считаю это все из-за использования натурального языка; мне кажется, я больше языки программирования уже использую, чем естественный язык и поэтому разучился говорить на нем; но это уже отдельная тема, не будем об этом).

Начнем
@aa248f94701743a991885d33399914ce Anonymous 2016-09-17 15:28:30
с водного вступления. Каждый из нас каким-то образом пришел к анонимному общению в сети и видит в этом некую ценность. Чтобы удовлетворить свою потребность в анонимном общении, нам нужна инфраструктура, позволяющая это делать и, желательно, удобным образом. Какую подобную инфраструктуру мы имеем на текущий момент? Нам доступны различные имдиджборды, например, 4chan.com, nowere.net; форумы с возможностью анонимного постинга, например, linux.org.ru, opennet.ru; новостные сайты с анонимным постингом,
@439a66cf50194fd8ba28117ab9508903 Anonymous 2016-09-17 15:28:30
например, theregister.com, slashdot.com, микроблоги, например, bnw.im. Все это в какой-то мере удовлетворяет нашу потребность, но, зачастую, мы сталкиваемся с различными помехами (obstacles).

Одной из таких помех является модерация. Руководствуясь набором каких-то невнятно изложенных правил, либо же, что еще чаще, просто желанием левой пятки модератора, удаляются посты, треды, банятся юзеры. Вторая помеха - это необходимость постоянно разгадывать какие-то капчи (я это считаю унизительным, например, лучше
@9e64dcb893b4438cb86f5864108f576d Anonymous 2016-09-17 15:28:31
терпеть вайп и прочие бесчинтсва, чем капчу). Третья помеха - это исчезновение ресурса как такового. В большинстве случаев, с потерей базы данных. Например, 2ch.ru, lulz.ru, shitstream.ru, 0chan, lolks.ru наконец. Четвертая помеха - это невозможность постить или вообще использовать ресурс не раскрывая свой айпи. Например, если заблокирован тор.

Чтобы избавиться от первой помехи, нужно просто отказаться от модерации полностью. Например, 0chan.ru/c/ раскрыл мне глаза на позитивные аспекты отстутствия
@08a29e25d5874011921be18cfcd0ddd3 Anonymous 2016-09-17 15:28:31
модерации. Когда, например, очевидно не соответствующий тематике раздела, ОП пост с содержанием уровня "я посрал" выливается в интересную дискуссию, вполне соответствующую тематике раздела. Скорей всего, конечно, причиной этому был в большей степени сам контингент /c/. Потому что если мы посмотрим на почти крайний случай отсутствия модерации - shitstream.ru - то мы увидим, что бессодержательные треды там превалировали. Но это, опять же, можно объяснить конкретным контингентом. И бессодержательные смехуечки
@67522b629b3d4290b39e1af7ae3189af Anonymous 2016-09-17 15:28:31
- это и была изначальная тематика шитстрима. Таким образом, что я хочу сказать. Что качество контента определяется в большей степени контингентом и текущей историей, задающей тематику, а не наличие/отсутствие модерации.

Чтобы избавиться от третьей помехи, нужно чтобы ресурс не был во власти одного человека. Какой бы милый и хороший не был бы админ, он все равно по умолчанию мудак, которому нельзя верить и полагаться на него. Викентий, Ивлад, ЕФГ, moot (он выпилил текстовые борды, если кто не в курсе,
@c6b13e407ae44a49b358a4588804dbe5 Anonymous 2016-09-17 15:28:31
т.е. убил world4ch http://tanasinn.info/wiki/World4ch ), все они яркие примеры таких пиздаболов. Короче, админ - это SPOF (a single point of failure).

Распределенность устраняет третью помеху. Если есть много нод и всеми ими не владеет только один человек, то вероятность того, что такой распределенный ресурс внезапно исчезнет полностью, очевидно, уменьшается. Также, как мне кажется, уменьшается уровень модерастии, т.к. юзер получает свободу перейти с черезчур модерирумой ноды на менее модерируемую.
@0333ac1250304e388b8f653e12aef041 Anonymous 2016-09-17 15:28:31
Текущий конгломерат чанов можно рассматривать как такую распределенную систему. Но они все имеют свои собственные базы, которые не синхронизируются и я, например, не вижу достижимых способов их синхронизировать (автоматизированным путем, а не вручную), т.к., например, нужно разгадывать капчи, каждая борда имеет свой апи для постинга и т.п. и айдишники постов разные, т.е. референсы внутри постов будут указывать в никуда, если мы переносим пост с одного чана на другой.

Сейчас есть распределенные платформы,
@ee95da7f3577416fbeedb7c92ceb3429 Anonymous 2016-09-17 15:28:32
которые можно использовать для анонимного общения: Frost, bitmessage, NNTPchan. Есть еще наверное friend-to-friend варианты, но нам это, очевидно, не подходит (ибо это равноценно инвайтопараше).

Frost работает поверх freenet, который написан на java. Я думаю мало кто согласится устанавливать богомерзкую jre, потом freenet, настраивать его, потом устанавливать фрост. А так, в принципе, это приемлемый вариант. Также фрост имеет уебанский интерфейс, надо будет свой писать. А тратить столько бесплатных
@08dcd9bb371c4ac8a79e4f40db115cf2 Anonymous 2016-09-17 15:28:32
усилий на что-то, что не обновлялось с 2011 года, работает поверх джавы и кучи говна на ней писанного, как-то не хочется. Также использование freenet подразумевает, что вы выделяете место на своем диске и чьи-то данные постоянно через вас пересылаются, что может быть неприемлемо для использования на мобильных устройствах из-за ограничений трафика (хотя, в нормальных странах есть дешевый безлимитный LTE).

Теперь про bitmessage. Те, кто пользовался им, знают насколько он убог. У сообщений нету времени
@f99561fdd05c4cd383401209a69fd4cb Anonymous 2016-09-17 15:28:32
отправления, только время получения. Поэтому если ты получаешь два сообщения, то ты не знаешь в каком порядке они были отправлены. А такое часто бывает в bitmessage, что ты подключаешься и получаешь, например, сначала сообщение, которые было отправлено вчера, а потом то, что было отправлено сегодня. Поэтому теряется нить дискуссии, сообщения дезорганизованы, ты не вдупляешь, что происходит. Но эта проблема еще терпима и не слишком критична.

Следующая проблема - это POW (proof-of-work). POW это сносная
@cd5c5ef6fef04e3f80662c74c0f9587e Anonymous 2016-09-17 15:28:32
замена капчи, но, все же, тоже неприемлема. Кто юзал битмесаг, знают как долго приходится ждать пока отправятся сообщения, если они длиннее пары предложений. Чтобы высчитать POW, под завязку нагружаются все ядра проца. Декларируемая цель POW это борьба со спамом. Но, как правильно заметил Михаил, спама в битмесаге предостаточно и POW от спама не избавляет, а юзеры при этом страдают потому, что вынуждены считать этот долбаный POW. Единственная польза POW - это защита от DDoS/DoS атак.

Я, по глупости,
@2bec3a956f8e4ef49c2d43f5ca4cfd3b Anonymous 2016-09-17 15:28:33
написал борду поверх bitmessage, но уперся в несовершенность api официального клиента. Они используют уебанский XML-RPC и даже простое выгребание сообщение по айдишнику из локальной базы занимает неприемлемо много времени. Также там нет нужных функций, например, "получить все сообщения после такого-то времени", чтобы не выгребать каждый раз все, мать его, сообщения. Причем, я писал разрабу, чтобы он добавил нужные мне функции, но толку ноль. Потом я хотел вообще переписать их официальный клиент (который
@fd5c0f5484fe4114aa27f7b79c625074 Anonymous 2016-09-17 15:28:33
написан на питоне) на haskell. Где-то процентов 30% основного говнокода я разобрал (в смысле, понял как работает; после этого у меня, кстати, появилась лютая ненависть к питону) и принялся переписывать.

Но уперся в следующую проблему: они в bitmessage используют реализацию elliptic curve point multiplication, которой нет для хаскел. Т.е. мне пришлось бы еще и свою ECC либу написать для хаскелл, которая бы делала умножение точек в точности как и у них. Но ну его нах, подумал я. К тому же, в спецификации
@9f367ccfaba747d396080eba37ad743a Anonymous 2016-09-17 15:28:33
протокола нет однозначного описания как именно шифрование происходит. Например, там не написано, что они используют Secp256k1. Видимо забыли скопипастить это со спеки bitcoin https://en.bitcoin.it/wiki/Secp256k1 Вообще, bitmessage это криво скопированная спека bitcoin. Bitmessage получил незаслуженный хайп из-за разоблачений Сноудена (о которых итак все знали у кого есть мозг). На самом деле, bitmessage - это то еще говноподелие.

to be continued
@cd1d49fbc83145a7a2f79edffeaae24d Anonymous 2016-09-17 20:10:56
Bitmessage использует дохуя шифрования, которое нам не нужно, т.к. нужная нам инфраструктура является публичной, т.е. каждый может прочитать чужое сообщение, нам не нужны личные сообщения и т.п.

Мы бы могли сделать с нуля свое что-то похожее на bitmessage или frost+freenet. Но, что их объединяет? То, что они полноценные P2P сети. А развернуть свою P2P сеть с нуля это не так-то просто. Во-первых, в начале, когда юзеров мало (допустим, 5 юзеров), очень маловероятно, что хотябы двое из них будут находится
@eae76fc3c2d64b46b40882035309ab9e Anonymous 2016-09-17 20:10:56
онлайн в одно и то же время. Но можно, допустим, договориться быть каждому онлайн в определенное время каждый день, чтобы каждый смог собрать чужие посты за день и отдать свои.

Во-вторых, эти пять юзеров будут знать статические айпи друг друга, что неприемлемо. А если у них у всех айпи динамические, то им нужен рандеву сервер(а). Чтобы решить эту проблему, можно использовать tor: хидден сервисы имеют уникальные айди, которые не раскрывает реальный айпи. Исользование tor имеет свои недостатки. Во-первых,
@4a27e9f1475b4af28d6798da825bd86d Anonymous 2016-09-17 20:10:56
пропускная способность этой сети пока неоче, из-за чего наблюдаются некоторые тормоза, хотя, в принципе, не такие уж и сильные тормоза. И нужно еще учесть, что если мы общаемся напрямую, то нужно учитывать скорость отдачи каждого пира: скорость обмена данными во всей сети будет приблизительно равна скорости отдачи самого слоупочного пира. Но, по-любому, мы ставим себя в зависимость от тора, если идем таким путем.

Договоренность быть каждый день онлайн в одно и то же время - это ненадежно: можно просто
@a47af5c86dc649e6adb82a3a952d1ffe Anonymous 2016-09-17 20:10:57
забыть, иметь какие-то срочные дела и т.п. Это проблема очень похожа на проблему отсутствия сидов на какой-нибудь не очень популярной раздаче в bittorent. Человеческий фактор нужно устранять, а не полагаться на него. Из этого всего я делаю вывод, что полноценная P2P архитектура нам не подходит. Не на начальном этапе точно.

Нам больше подходит CQC (client–queue–client) архитектура https://en.wikipedia.org/wiki/Client–queue–client с распределенностью наподобие той, что используется в xmpp,
@90736cd4e932409db0848a36f5fa9a93 Anonymous 2016-09-17 20:10:57
nntp, т.е. есть множество серверов и клиентов, которые не связаны напрямую, а через эти сервера, т.е. лишь сами сервера организованы как P2P сеть https://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/Usenet_servers_and_clients.svg/370px-Usenet_servers_and_clients.svg.png

Теперь про NNTPchan. В целом, норм, но есть недочеты (например коллизия айдишников, ебаный стыд же @bbc1f@bbc1f20ae5be42dd9f937855ea349413 ). Также они используют капчу. Насчет модерации не знаю. Но, это решение поверх nntp. Нам не нужны все фичи nntp. Это overkill.
@9e926e3a5cb044f2a432de379f3065cf Anonymous 2016-09-17 20:10:57
Это как запускать браузер, открывать в нем гугл и использовать его вместо калькулятора.

to be continued
@ac76c0a01034456ba88ce291e65edf0b Anonymous 2016-09-18 19:42:17
Теперь менее водная часть (но все еще достаточно водная). Структура типикал форума или чана состоит из разделов/борд, тредов, постов. Остановимся подробней на постах. Посты должны иметь уникальные идентификаторы. В чанах обычно используются автоикрементирующиеся целые числа (4 or 8 bytes integer) в качестве идентификаторов. В распределенной системе использование таких идентификаторов неприемлемо, т.к. мы неизбежно столкнемся с коллизиями, когда на двух разных нодах два разных поста имеют одинаковый айди.
@70e803028f3a4cf7b8c12cc157b2bc13 Anonymous 2016-09-18 19:42:18
Можно закодировать номер ноды в идентификатор, при этом продолжая использовать целые числа. Например, выделить последние три знака идентификатора на номер ноды: 1002 - первый пост ноды 2, 123005 - 123й пост ноды 5. Но сейчас я объясню почему такой подход не катит. Есть минимум два метода синхронизации постов на различных нодах: а) нода получает новый пост от клиента, генерирует айди этого поста, добавляет его себе в базу и передает этот пост вместе с его айди остальным известным ей нодам (конечно же, это
@5bf56e04243f4efb80248144847406c5 Anonymous 2016-09-18 19:42:18
не все, я опустил подробности, оставив только принцип, что нода выполняет помимо функции общения с клиентом еще и функцию синхронизации); b) есть специализированные сервера, которые занимаются только синхронизацией между нодами, т.е. они постоянно мониторят известные им ноды и если обнаруживают, что на одной ноде нет поста, который есть на второй, то постят на первую ноду недостающий пост.

Второй метод более юнихвейный (//Make each program do one thing well. To do a new job, build afresh rather than
@84eea6932baa4a1991391d1fee009227 Anonymous 2016-09-18 19:42:18
complicate old programs by adding new "features"//), т.к. мы четко разграничиваем ноды по типу задач, которые они должны выполнять. Sync node (сервер, осуществляющий синхронизацию) неотличим для storage node (сервер, который общается с юзерами и хранит посты) от любого другого клиента. Storage нода вольна ничего не знать о других нодах, о том сколько их, что на них хранится и т.п., она лишь взаимодействует со своими клиентами как в обычной client-server архитектуре. Поэтому мне второй метод видится более
@c09c7e26d6c6418397ac782e8b7bc7c0 Anonymous 2016-09-18 19:42:18
предпочтительным и надежным.

Итак, значит, мы определились, что у нас должно быть два типа нод: storage nodes and sync nodes. Теперь, если мы будет использовать идентификатор с закодированным номером ноды, как было описано выше, то мы сталкиваемся со следующей возможной атакой. Допустим есть две ноды с номерами 1 и 2, последний пост на первой ноде это 123001 и последний пост на второй это 123002. Атакующий юзер может прикинуться sync нодой (или поднять свою sync ноду) и начать отправлять посты с
@6992eefe03cc4c31b065c5fcd5b9d702 Anonymous 2016-09-18 19:42:19
айдишниками 124002, 125002 и т.д. на первую ноду несмотря на то, что таких постов на второй ноде еще не существует. Потом, через некоторое время, на второй ноде появляются посты 124002, 125002 и т.д., какая-нибудь sync нода замечает их, потом обнаруживает, что такие посты уже есть на первой ноде и ничего не делает, т.к. полагает, что уже какая-то другая sync нода успела синхронизировать посты на этих двух нодах до нее.

Эту проблему можно решить, если сделать чтобы storage ноды имели список sync нод,
@3101a0e220d6465491e6ce90edb30abc Anonymous 2016-09-18 19:42:19
которым они могут доверять, а простым юзерам запрещали отправлять посты вместе с айдишниками (либо просто игнорировать такие айдишники от всех клиентов, кроме доверенных sync нод). Но такой подход ненадежен, мы не можем никому доверять, т.к., очевидно, кто-то может прикинуться хорошеньким, а потом поднасрать.

Можно использовать свой велосипед для генерации рандомных и относительно компактных айдишников, как, например, это сделали в bnw.im (6 рандомных символов из 36 символьного алфавита для тредов и три
@970fe48f34f7429cba6debb467cb92b4 Anonymous 2016-09-18 19:42:19
рандомных символа для постов внутри треда: см. функцию genid https://github.com/stiletto/bnw/blob/master/bnw/core/base.py ). Но это несерьезно, ибо, учитывая парадокс дней рождения, 50% вероятность коллизии постов внутри треда на bwn.im достигается уже при 255 постах (кстати, есть эспериментальный XEP, который добавляет unique and stable IDs for stanza https://xmpp.org/extensions/xep-0359.html если кому-то интересно). Также с коллизиями столкнулись в NNTPchan, я уже об этом писал выше.

Поэтому не надо
@fee7bb6c36154c50b8f1403bed96e558 Anonymous 2016-09-18 19:42:19
изобретать велосипед, а нужно использовать UUID. Да, айдишники получатся довольно громоздкие (16 байт). Но их можно сделать немного визуально короче, если использовать, например, base58. Получится 22 символа вместо 36, которые обычно используют для представления UUID (например, 123e4567-e89b-12d3-a456-426655440000 и его эквивалент в base58 - 3fEgj34VWmVufdDD1fE1Su). По-прежнему громоздко, но все-таки юзать можно, как по мне. Теперь вышеописанная атака не представляется возможной, т.к. довольно сложно
@cbc0514b71f5412681717f447077899b Anonymous 2016-09-18 19:42:19
предугадать следующий айди, который будет сгенерированой на какой-то ноде (хотя, тут тоже есть тонкости, т.к. есть различные версии UUID и нужно оговаривать заранее, какая версия имеется в виду).

Помимо уникальных идентификаторов, посты должны иметь время инсерта (insert_timestamp, время инсерта записи в базу). Это нужно, в первую очередь, для самой ноды, которая хранит этот пост (потом станет ясно почему). Тут мы сталкиваемся со следующей проблемой: злонамеренная sync нода может подменить
@3db5a0e8d3eb4928b77e67b01645b0f8 Anonymous 2016-09-18 19:42:20
insert_timestamp какого-нибудь поста, подлежащего синхронизации; например, выставить будущее время или прошлое. С кейсом, когда время подменяется на будущее, все просто, т.к. мы можем позволить всем storage нодам игнорировать посты с insert_timestamp > now.

Если же время подменяется на прошлое, то все печально. Тут мы ничего не можем сделать, кроме как установить какой-нибудь тупой лимит, например, что insert_timestamp не должен быть меньше (now - 1 day). Поэтому нужно вообще отказаться от синхронизации
@e4e2d302f0c8450ab41a4f2366fac002 Anonymous 2016-09-18 19:42:20
insert_timestamp на разных нодах. Т.е. один и тот же пост на разных нодах будет иметь разный insert_timestamp. Таким образом, insert_timestamp не отражает информации о том, когда был в действительности отправлен пост юзером, мы безвозвратно теряем эту информацию. Кто-нибудь сейчас наверное может возразить: "а чем это тогда лучше той ситуации с датами в bitmessage, которую ты критиковал выше, ведь по-сути же будет то же самое?".

Будет не совсем то же самое. В нашей схеме предполагается, что сервера
@30b4f0c1f376486c9927900c980232f9 Anonymous 2016-09-18 19:42:20
работают круглосуточно. В bitmessage ты можешь запустить клиент раз в неделю и получить кашу из постов за три (или за сколько дней там теперь хранится, я уже не в курсе) последних дня. В нашей схеме мы не требуем от юзеров быть постоянно онлайн и выполнять какие-то функции сервера. Sync ноды круглосуточно мониторят и синхронизируют известные им storage ноды, благодаря этому разрыв в insert_timestamp у одинаковых постов на этих storage нодах будет достаточно небольшой. Да, определенно, будет некоторая
@8acebc12a0a6416a8ebddbe0180cfd83 Anonymous 2016-09-18 19:42:20
неупорядоченность, но не критическая.

to be continued
@26574b55dc584bb39a410ce90e9730db Anonymous 2016-10-08 21:05:48
почему nntp - оверкилл? он ведь для подобного и делался
@f449a3546a504f5caeb8c03fcdcdddba Anonymous 2017-01-18 20:56:58
Как тут со своим nntp с квадратными колёсами дела обстоят?
@2d2dccabb30b469580f05e50f69da10d Anonymous 2017-01-18 21:56:16
Никак. Ведь гуру критик все обосрал, зачем что-то делать теперь?
@92cf1f3df9f54dd7bce517d996ae2b85 Anonymous 2017-02-08 03:54:30
Действительно, зачем?
@647abe9094294a989f08a8b1fb39da6b Anonymous 2017-08-23 08:34:03
> Допустим есть две ноды с номерами 1 и 2
Зачем? Всем по паре ключей и вперёд!
@f9094433488b4a2a86536b2116ef629e Anonymous 2017-08-23 12:18:58
@647ab@647abe9094294a989f08a8b1fb39da6b не понял тебя. И что?