Мар 28

Прячем виртуальный хост в малиновый пирог

МагияПро OpenVPN написано уже довольно дофига. И даже мной. Но вот возникла необходимость сделать ВЖУХ.


Итак:
Сервер на Raspberry-pi, eth0 в мост с tap1
Клиент на libvirt хост, VPN поднимает хост, отдает мостом (br1 tap1) гостю. Гость прозрачно сидит в локальной сети, про VPN не знает.
Можно отключить гостю virbr0, тогда он еще и в интернет ходить будет через впн. Такая вот петрушка.
Имеем — без малинки сервера нет, но малинка сама по себе не знает откуда он берется, изучать её на в другом месте или при выключенном VPN-клиенте бессмыслительно. Еще логи в /dev/null переправить и предусмотреть аварийное выключение VPN клиента.
А еще порт понестандартнее и ваще огонь.
Конфиги чуть внизу.
Continue reading

Июн 15

UART размер экрана

Для общения через UART с железками (avr, stm32 и прочими) в основном использую GNU screen:

$ screen /dev/tty.ubserial 9600

А вот что-то дернуло, раскрасить вывод микроконтроллера и раскрасил (не мудрено, печатаем что-то вроде \033[31m и вперед, ну только цвета меняем). А потом поехало: захотелось печатать в разных местах экрана (\033[y;xH), а вот как напечатать в центре? Надо же знать размер экрана, а он у меня (да и у всех) каждый раз разный.
Долго возился, выяснил, что screen отдавать размер окна (\033[18t) не умеет. Зато DCS передает напрямую терминалу из которого запущен: вот и нашелся грязный хак: оборачиваем запрос размера в ESC-P последовательность, и вот уже знаем размер экрана.
Печатаем хитрую строку:

\033P\033[18t033\

и получаем ответ:

\[8;31;163t

31 строка, 163 колонки, а 8 — это номер CSI-репорта. Он всегда такой.

вот тут большой список похоже что вообще всех ESC-последовательностей которые терминалы поддерживают: ttssh2.osdn.jp

P.S.
Ну а бонусом — таким же способом можно поставить заголовок окна который screen ставить умеет только через жопу.

\033P\033]0;New Window Title\a\033\\
Июл 12

Немного указательных трюков AVR

Очень и очень часто приходится манипулировать кучей никак не связанных между собой пинов, вот и возникают куча дифайнов и прочей лабуды.
Есть довольно простое решение, немного тормознее, чем хардкод, и память кушает, но много удобнее.
В принципе, ничего нового для программистов я не скажу, а вот для тех у кого в голове ARDUINO, будет полезно
Оформляем структуру в которой будем хранить пины:

1
2
3
4
typedef struct {
    volatile uint8_t *port;
    uint8_t pin;
} out_t;

а дальше создаем массив этих структур:

1
2
3
4
out_t outs = {
 { &PORTA, PA1},
 { &PORTB, PB4},
};

ну и так далее. Получается удобно проходить в цикле.

1
2
3
4
uint8_t i;
for(i=0;i<sizeof(outs)/sizeof(out_t);i++){
 *outs[i].port |= _BV(outs[i].pin);
}

ну и как бонус — инициализация. в AVR регистр направления DDRx всегда на 1 байт младше, чем соответствующий PORTx, получается небольшой трюк:

1
2
3
4
uint8_t i;
for(i=0;i<sizeof(outs)/sizeof(out_t);i++){
 *(outs[i].port-1) |= _BV(outs[i].pin);
}
  • инициализация на выход всего массива. Это много медленнее, чем одной операцией проставить все нужные пины, но если время не критично — поддерживать такой код порядком проще: добавили запись в массив — и готово.
    Да, чтобы не тратить память, можно все это хранить в PROGMEM и доставать по необходимости.

ну и еще напоследок, удобный макрос от разработчиков ядра Linux для ловли багов:

1
2
3
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
// и его применение
BUILD_BUG_ON(sizeof(phs_entry_t) != sizeof(uint32_t));

если структура phs_entry_t размером не равна uint32_t (32 бита) — код не соберется

Фев 06

ARM Semihosting

В ARM-контроллерах есть полезнейшая вещица, Semihosting, позволяет переадресовывать I/O операции к хосту
Почему-то при отладке, в основном используют только printf() для вывода отладочных сообщений, хотя возможности порядком шире: можно переадресовать любую(!) I/O операцию. Например запись файла.
Для быстрого примера, создадим проект в Eclipse, конфигуратор проекта спросит про системные вызовы:
Use system calls — вот тут надо выбрать Semihosting (POSIX system calls via host) — это полное перенаправление всех POSIX вызовов к хосту.
Trace output — не важно, пусть будет Semihosting STDOUT, отладочные сообщения будут падать в STDOUT сервера
Ну и чтобы побыстрее все проверить — content — стандартный шаблон Blinky — мигалка светодиодом.

А дальше все просто — добавляем в main обычный код для вывода в файл:

 FILE* f = fopen("./test.txt", "w");
  if(f){
      fprintf(f, "Hello from ARM...\n");
      fclose(f);
  }

Думаю, и так понятно, что мы открываем файл test.txt для записи в текущем (относительно semihosting сервера) файл, и если открылся — записываем в него строку.
собираем, а вот запускать для наглядности будем из консоли:
у меня под рукой STM32VL-Discovery, поэтому конфиг запуска для неё

$ openocd -f board/stm32vldiscovery.cfg

Далее, запускаем openocd который и будет semihosting server
цепляемся к нему отладчиком

$ arm-none-eabi-gdb project.elf

и выполняем следующие команды в отладчике

target remote :3333  # подключаемся а GDB-серверу OpenOCD
monitor arm semihosting enable # включаем semihosting
monitor init # инициализируем кристал
monitor reset init # сбрасываем кристал
load  # загружаем в кристал файл указанный в параметре запука gdb
continue # запускаем запущенную программу

прошивка blinky содержит в себе примеры отладочных сообщений, так что можно вполне их посмотреть в консоли OpenOCD, а после выполнения добавленного участка кода — можно смотреть на файл test.txt:

$ cat test.txt
Hello from ARM...

Да, самое главное — прошивка с включенным Semihosting не сможет работать в standalone режиме (т.е. без подключенного отладчика), застопорится на первом же обращении к хосту. Поэтому в release версии нужно отключать. Для этого в элипс достаточно удалить define в соответствующей конфигурации

Дек 13

responseText ошибки при AJAX-запросе

За формирование страницы ошибки отвечает функция technical_500_response из django.views.debug,
программисты джанги пошли странным путем, жестко задав (без возможности настройки): если запрос AJAX — ответ будет текстом, в остальных случаях HTML.
Все бы ничего, но raise Http404(), например, плевать на этот механизм хотела, и все равно выбрасывает HTML, если выводить ошибку в консоль — сущий ад.
Изменить поведение можно например так:
Добавить Middleware которая, в случае ошибки уберет из request соответствующий заголовок,
дальше джанга отработает по своему алгоритму и вернет красивый HTML.
Криво конечно, т.к. пропадает возможность узнать был Ajax или не было, но не нужно патчить Django

1
2
3
4
class DisableAjaxException(object):
    @staticmethod
    def process_exception(req, exception):
        req.META['HTTP_X_REQUESTED_WITH'] = None

Ну и остается напомнить, порядок Middleware в settings.py важен

Июн 07

MySQL и foreign key constraint fails

Cannot add or update a child row: a foreign key constraint fails
Такое случается, если включена проверка InnoDB foreign key, но ссылается ключ на таблицу не InnoDB (например MyISAM)
лечится:

  • конвертированием всех таблиц в InnoDB
  • конвертирование всех таблиц в MyISAM
  • или отключением проверки:
DATABASES = {
'default': {
    ...         
    'OPTIONS': {
         "init_command": "SET foreign_key_checks = 0;",
    },
 }
}

Статейка про InnoDB

Июн 03

Откат iOS8 beta

После того, как все поигрались, потеряли сеть итд, хочется обратно нормальной стабильной работы.
Откатывать как обычно:

  1. Подключаем к компьютеру
  2. Вводим телефон в режим DFU: удерживаем Home+Power 10 секунд (экран отключится), отпускаем Power, и ждем еще 10 секунд, отпускаем Home
  3. iTunes найдет телефон в режиме восстановления и предложит поставить на него текущий релиз iOS (на сейчас это 7.1.1) — устанавливаем
  4. После завершения установки, будет предложено восстановить из резервной копии (вы ведь сделали её?)
  5. Ждем более стабильной беты