суббота, 20 февраля 2010 г.

Поговорим об SMS Protocol Data Unit

Решил поближе познакомиться с форматом SMS сообщений. Далее я напишу несколько закономерностей/законов, которые помогут мне написать достойную библиотеку c виртуозной архитектурой для работы с SMS PDU. Только учтя все особенности формата, возможно создать в меру сбалансированную библиотеку. Под балансировкой я понимаю выбор достаточного числа классов, структур, перечислений, способов взаимодействия компонентов между собой и интерфейса для использования библиотеки.


В статье используются сокращения:
SME - Short Message Entity (Модуль мобильного устройства)
SMSC - SMS-Centre (Центр обработки сообщений)
PDU - Protocol Data Unit (Протокольная единица данных)

В первую очередь примечательно, что имеется 6 типов сообщений:
+ SMS-SUBMIT
+ SMS-SUBMIT-REPORT
+ SMS-DELIVER
+ SMS-DELIVER-REPORT
+ SMS-STATUS-REPORT
+ SMS-COMMAND (посылка специальных команд от SME к SMSC)

Использование первых пяти типов поясняет эта схема:
SMS PDU Types

Тип сообщения хранится в 2-х битах первого байта. Неправда ли, маловато 2-х битов для хранения 6 возможных значений? Конечно мало, но если вы знаете кто это сообщение сгенерировал, то вам остаётся прочитать из 2-х бит всего 3 возможных значения.

Типы сообщений от SME:
( 0 1 ) SMS-SUBMIT
( 0 0 ) SMS-DELIVER-REPORT
( 1 0 ) SMS-COMMAND

Типы сообщений от SMSC:
( 0 1 ) SMS-SUBMIT-REPORT
( 0 0 ) SMS-DELIVER
( 1 0 ) SMS-STATUS-REPORT

Первый байт всегда содержит флаги/индикаторы. Все данные пакета измеряются в байтах, некоторые переменной длинны. То, какие флаги присутствуют в пакете - определяется типом сообщения. Присутствующие поля определяются типом пакета и флагами.

Принципы планируемой библиотеки:
1) Каждому типу сообщения - свой класс, наследованный от базового. Каждый из них будет иметь свои флаги/индикаторы и обязательные поля. Некоторые флаги/индикаторы будут реализовываться отдельными классами, и будут иметь указатели на классы связанных с ними полей. Базовый класс будет уметь определять тип сообщения и создавать экземпляр соответствующего класса. [Напрашивается применение предыдущего поста про "кастование от родителя к наследнику"]
2) Классы храня данные только в самом PDU. (никаких промежуточных полей)
3) Каждое из полей наследуется от универсального класса "единицы данных". Имеет встроенные методы, по изменению размера и поля и перемещению данных в памяти. Обладает указателем на следующую "единицу данных", при изменении своего размера, заставляет двигаться следующую за ним "единицу данных".
4) [В разработке]


Читать дальше

пятница, 19 февраля 2010 г.

Кастование от родителя к наследнику

Класс наследуется от некого базового класса-шаблона, передавая своё имя в качестве параметра шаблону. Базовый класс имеет метод, статически кастующий указатель на экземпляр конкретного класса к шаблонному типу. Таким образом возможно удобное статическое кастование от родителя к наследнику. И как следсвие, вызов переопределённых в наследнике методов из базового класса без их виртуализации. (вольное описание приёма из библиотеки sl)

Приблизительный код:
////////////////////////////////////////////////////////////////

template <typename T>
class SelferT
{
public:

T &GetSelf()
{
return static_cast<T &>(*this);
}

const T &GetSelf() const
{
return static_cast<const T &>(*this);
}

};

////////////////////////////////////////////////////////////////

class RefCount : protected SelferT<T>
{
public:

// Конструктор копирования - увеличивает счётчик ссылок
RefCount(
IN const RefCount &rhs
) : _refCount(rhs._refCount)
{
// ...
}

// Оператор присваивания - увеличивает счётчик ссылок
RefCount &operator=(IN const RefCounted &rhs)
{
// ...
}

// Деструктор - уменьшает счётчик ссылок
~RefCount()
{
// ...

if (*_counter == 0)
GetSelt().OnDispose();
}

// Вызывается, когда число ссылок становится равно нулю
void OnDisposed()
{
}

};

////////////////////////////////////////////////////////////////

class A : public RefCount<A>
{
public:

// ...

// Вызывается, когда число ссылок становится равно нулю
void OnDisposed()
{
}

};

////////////////////////////////////////////////////////////////

Подсветка синтаксиса выполнена при помощи Notepad++




Если виртуализация методов класса позволяет добраться до последнего наследника базового класса, то данный метод позволяет добраться до конкретного наследника. С этим приёмом мы получили интерфейс в стиле Java, но без обязательного переопределения методов.

Ссылка по теме:
Преобразование ссылки на интерфейс для реализации класса в Delphi 2010

Читать дальше

понедельник, 8 февраля 2010 г.

понедельник, 4 января 2010 г.

Прикрутил Spoiler

Прикрутил к блогу спойлер by Ruby Brewed (Denis Neverov http://dotrb.blogspot.com)
Он будет весьма востребован в готовящейся в данный момент статье.



А здесь текст, который хотим сделать скрытым


Читать дальше

пятница, 20 ноября 2009 г.

Прятки в файловой системе FAT

Отличный способ без особых заморочек спрятать данные на флешке. Получить доступ к данным сможет только тот, кто знает специальный ключ. Ключом будет являться имя вашего каталога. Никакой специализированный софт для доступа не потребуется. Файловые менеджеры ваш каталог не покажут и не отобразят его содержимое поиском. Заинтриговал? Также Вы получите защиту флешки от вирусов, прописывающихся в автозапуск (в файл autorun.inf).

1. Для начала проверьте, что ваша флешка действительно имеет файловую систему FAT (FAT32, FAT16, FAT12). Если флешка отформатирована под NTFS - есть возможно переконвертировать файловую систему в FAT без потери данных(используя Partition Magic). Единственное, вы больше не сможете на ней хранить файлы объемом более 2Гб.

2. Создаем в корне флешки папку с именем "autorun.inf". Внутри папки autorun.inf создаем папку с секретным именем. Именно в ней и мы и будем прятать наши файлы, кто будет знать имя папки - тот и сможет в нее попасть. Вторичным эффектом будет защита флешки от самозапускающихся(прописывающихся в текстовый файл autorun.inf) вирусов. Убьем двух зайцев одним махом.

3. Скачиваем и запускаем низкоуровневый редактор жесткого диска. Я предпочитаю утилиту нашего соотечественника Дмитрия Cидopoва DM Disk Editor. Утилита сразу предлагает нам открыть диск. Отмечаем галочкой "Логические", а не "Физические" устройства и выбираем необходимый раздел(том) (рис. 1). И соглашаемся с диалогом автоопределения файловой системы (рис. 2).

5.07Кб
Рис. 1. Выбор раздела(тома) [5.07Кб]

5.29Кб
Рис. 2. Выбор файловой системы [5.29Кб]

4. Теперь в низкоуровневом просмотрщике жесткого диска (он сейчас находится в режиме просмотра "Директория FAT" - рис. 3) найдем строку с именем папки "autorun.inf". Обратим внимание на атрибуты директории: "----D--". Буквы слева направо отвечают за 6 атрибутов файлов в файловой системе FAT:
R - Read only
H - Hidden
S - System
V - Volume
D - Dir
A - Archive

7.45Кб
Рис. 3. Найдем строку с файлом "autorun.inf" [7.45Кб]

5. Внутри файловой системы атрибуты представлены битами внутри одного байта. Этот байт располагается сразу за 8-мью байтами имени и 3-мя байтами расширения файла. Атрибутов шесть, а битов в байте восемь. Значит два старших бита байта атрибутов не задействованы. Как показала практика, если хотя бы один из этих битов установлен, то с таким файловым объектом(файлом или папкой) ничего нельзя сделать стандартными средствами(большинством файловых браузеров). Такой файл нельзя ни открыть, ни удалить, ни переименовать. Предлагаю установить все биты в 1 кроме бита Volume, номер 4. Нехорошо давать этот атрибут кому не лень)) Значение байта атрибутов будем выставлять 0xF7.

6. В низкоуровневом просмотрщике устанавливаем курсор на строку с папкой "autorun.inf" (рис. 4). Переключаем вид: Вид->Шестнадцатиричный (F2). Смотрим на байт сразу за "AUTORUN INF", он равен 0x10. Установлен только один бит, пятый(если нумеровать с единицы) - он означает Dir. Нажимаем Правка->Режим редактирования (Ctrl+E). Ставим курсор на байт атрибутов и последовательно нажимаем клавиши F и 7 (рис. 5). Отлючаем режим редактирования так же как и включили его. И сохраняем изменения на диске: Правка->Записать изменения... (Ctrl+W). Закройте приложение DMDE.

7.50Кб
Рис. 4. Найдем байт атрибутов [7.50Кб]

7.54Кб
Рис. 5. Исправили байт атрибутов [7.54Кб]

Результаты:


Зайдите в корень флешки проводником и попытайтесь сделать что-либо с папкой autorun.inf (открыть, удалить, переименовать). Не получается, не так ли? Этого мы и добивались. Также у вас (и у большинства вирусов) не получится создать текстовый файл с именем autorun.inf.

Теперь чтобы зайти в свою секретную папку введите путь к ней в панели адреса. Например, F:\autorun.inf\secret_folder. Никому не говорите как называется ваша папка и большинство людей о ней даже не узнают.

Читать дальше

среда, 26 августа 2009 г.

Шрифты для J2ME приложений . . .

Выложил четыре маленьких моноширинных шрифта DOS-866.
Могут пригодиться для J2ME приложений (4x6, 6x9, 8x9, 8x12).
Шрифты представляют собой прямоугольную таблицу 16 на 16 символов.
Шрифты имеют лишь 2 цвета, максимально сжаты в PNG.

4x6


6x9


8x9


8x12


Читать дальше

понедельник, 24 августа 2009 г.

J2ME вообще для людей?

Попробовал опять начать программировать под J2ME. И столкнулся с прямо таки непреодолимыми проблемами. Тут и нехватка стандартных классов, и кривость виртуальной машины, и глюки эмулятора от SonyEricsson.

1. Построчное чтение файла

Каково же было моё удивление, когда я обнаружил, что ни один из стандартных классов ввода/вывода не позволяет построчно считывать и записывать файлы. Мне, например, удобно хранить списки карт/ресурсов/монстров в текстовом файле построчно. Что же делать? Помнится, пару лет назад писал функцию, считывающую текстовик целиком и делящую его на строки. На выходе получался массив String-ов. Да, знаю - я был извращенцем.

Вот новый код:

import java.io.*;

public class InputStreamTextReader extends InputStreamReader
{
protected InputStream is;

public InputStreamTextReader(InputStream is_)
{
super(is_); is = is_;
}

public InputStreamTextReader(InputStream is_, String enc_)
throws UnsupportedEncodingException
{
super(is_, enc_); is = is_;
}

public String readLine()
throws IOException
{
String str = "";
while (true)
{
int ch = is.read();
switch (ch)
{
case -1: return ((str.length() > 0) ? str : null);
case 13: return str;
case 10: if (str.length() == 0) continue;
}
str += String.valueOf((char)ch);
}
}
}

Подсветка синтаксиса выполнена при помощи Notepad++


Кстати говоря, этот перл в InputStreamReader меня вообще убил:
private Reader in;
Почему он не protected? Как так можно? Что уже говорить о том что ни один и стандартных классов не работает с методами mark/reset. Чтобы вернуться в начало файла - нужно переоткрыть поток, а значит породить вопрос к пользователю. Или написать свой класс, буферизующий поток. Это бессмысленно! Как сделать нормальное чтение "больших" текстовиков?

2. Утечки памяти в элементах стандартного GUI

Вот мой вопрос на Google ВиО по этому поводу. Там я исчерпывающе описал в чём я вижу проблему. Может это конечно эмулятор глючит, но сомневаюсь.

Попробовал Lightweight User Interface Toolkit 1.2 от Sun(хотя, теперь уже трудно сказать чья она) - те же яйца, только в профиль. Он конечно по моднее будет: лэйауты появлись и прочие прибамбасы . . . А с памятью всё также не аккуратен. Эх, жаль Qt для j2me не сделали. Кстати, Qt Jambi будет поддерживаться компанией Nokia лишь до мая 2010.

Читать дальше