LINUX.ORG.RU

Сообщения s3rjke

 

В каком виде гонять данные между клиентом и сервером

Форум — Development

Привет, эксперты. Нужно придумать какой-нибудь протокол обмена между клиентом и сервером по сетке (транспорт TCP).

Данные гоняются всякие разные:

  • Авторизация клиента на сервере по логину-паролю
  • Получение клиентом настроек некоей «системы» с сервера
  • Отправка команд клиентом на сервер (сделай то-то, поменяй настройки такого-то компонента «системы»)
  • Получение клиентом различных списков с сервера (события, ошибки, отчеты)
  • Получение клиентом данных о состоянии компонентов системы (числа, графики)
  • Получение клиентом документов с сервера (текст отчетов)

Может что-то еще, о чем я забыл упомянуть.

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

Соответственно, может есть какие-нибудь банальные инструменты и популярные подходы, которыми решаются подобные задачи? Пока смотрю в сторону отправки данных в формате json или xml, слать в виде: пара байт на длину сообщения_тело сообщения (json или xml). Возможно, в будущем этот трафик надо будет шифровать.

 ,

s3rjke
()

Юморной SQLite

Форум — Admin

Привет, эксперты. Столкнулся со странным поведением sqlite. Суть такова: запрашиваю данные юзера «user» из базы, юзера находит и данные отдает, в том числе и хэш пароля. Тут же копирую этот хэш и говорю, покажи юзеров с таким хэшем, sqlite отвечает, что нет таких. Как это возможно? Может я что-то не так делаю?

sqlite> pragma table_info(users);
0|id|int|0||1
1|name|text|1||0
2|password|text|1||0
3|type|int|0|0|0
4|blocked|int|0|0|0
sqlite> select * from users where name='user';
|user|fb131bc57a477c8c9d068f1ee5622ac304195a77164ccc2d75d82dfe1a727ba8d674ed87f96143b2b416aacefb555e3045c356faa23e6d21de72b85822e39fdd|1|0
sqlite> select * from users where password='fb131bc57a477c8c9d068f1ee5622ac304195a77164ccc2d75d82dfe1a727ba8d674ed87f96143b2b416aacefb555e3045c356faa23e6d21de72b85822e39fdd';
sqlite>

Решил заюзать sqlite в своей программе, соотв., когда из программы добавляю юзеров в базу, все ок, авторизация работает. Но стоит поменять пароль юзеру из своей проги (UPDATE users SET password=хэш_пароля WHERE rowid=ид_юзера), как начинается вышепоказанная хрень — не пускает в прогу, т.к. не может найти юзера по связке имя+хэш.

 

s3rjke
()

Вопрос по systemd + mysql

Форум — Admin

Всем привет. Понадобился mysql-server на свежеустановленном Debian 9. Установил из репов, вроде как, все работает. Но на моменте настройки mysql-я я слегка подвис.

Насколько я помню, обычно он настраивается через /etc/mysql/my.cnf

Но в моем случае, этот файлик слегка пустоват:

/etc/mysql# ls -l
total 24
drwxr-xr-x 2 root root 4096 Jun 20 17:42 conf.d
-rw------- 1 root root  277 Jun 21 11:56 debian.cnf
-rwxr-xr-x 1 root root 1509 Jun  7 22:11 debian-start
-rw-r--r-- 1 root root  869 Jun  7 22:11 mariadb.cnf
drwxr-xr-x 2 root root 4096 Jun 21 11:55 mariadb.conf.d
lrwxrwxrwx 1 root root   24 Jun 20 17:42 my.cnf -> /etc/alternatives/my.cnf
-rw-r--r-- 1 root root  839 Jul  9  2016 my.cnf.fallback

/etc/mysql# cat my.cnf
[client-server]

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mariadb.conf.d/

Через ps -ax | grep mysql тоже ничего. Решил попробовать спросить у systemd, может он знает, какой файл настроек используется?

# systemctl status mysql.service
● mariadb.service - MariaDB database server
   Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2017-06-21 12:33:21 MSK; 47s ago
  Process: 6377 ExecStartPost=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 6374 ExecStartPost=/etc/mysql/debian-start (code=exited, status=0/SUCCESS)
  Process: 6258 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= ||   VAR=`/usr/bin/galera_recovery`; [ $? -eq 0 ]   && systemctl set-environment _WSREP_START_POSITION=$VAR || exit 1 (code=exited, status=0/SUCCESS)
  Process: 6253 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
  Process: 6251 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)
 Main PID: 6346 (mysqld)
   Status: "Taking your SQL requests now..."
    Tasks: 26 (limit: 4915)
   CGroup: /system.slice/mariadb.service
           └─6346 /usr/sbin/mysqld

Jun 21 12:33:19 ookd systemd[1]: Starting MariaDB database server...
Jun 21 12:33:20 ookd mysqld[6346]: 2017-06-21 12:33:20 139799975780928 [Note] /usr/sbin/mysqld (mysqld 10.1.23-MariaDB-9+deb9u1) starting as process 6346 ...
Jun 21 12:33:21 ookd systemd[1]: Started MariaDB database server.

Полез смотреть /lib/systemd/system/mariadb.service — ничего полезного.

Еще в выводе systemctl упоминается скрипт ExecStartPost=/etc/mysql/debian-start. В скрипте есть строчка MYSQL=«/usr/bin/mysql --defaults-file=/etc/mysql/debian.cnf». Я уж было обрадовался, но нет, debian.cnf начинается с: # Automatically generated for Debian scripts. DO NOT TOUCH!

Наиболее похожим на файл с конфигом mysql выглядит /etc/mysql/mariadb.conf.d/50-server.cnf, содержащий 135 строк с комментариями и всякими настройками (где pid-файл положить, где файл сокета, bind-address, etc...).

В общем, вопрос, можно ли узнать при помощи systemd откуда сервис берет настройки при запуске? И если можно, то как?

 , ,

s3rjke
()

Как спроектировать логику взаимодействия различных компонентов программы?

Форум — Development

Привет, эксперты.

Пишу сейчас демона, в задачи которого входит общение с различными устройствами по сети и запись некоторых данных/событий в БД. Написал пару классов устройств. При запуске программы, демон подключается к БД, создает несколько объектов-устройств, которые подключаются к назначенным IP-адресам и начинают получать данные с устройств путем их опроса по таймерам.

Я не уверен, как лучше сделать взаимодействие м/у кодом демона и объектами-устройствами в плане записи всякого в БД.

Пока в голову пришли следующие варианты.

Вариант 1.

Передавать ссылку на объект-подключение_к_БД каждому созданному объекту-устройству и пусть он через эту ссылку пишет в БД все, что ему надо. Минус данного подхода: объекту-устройству нужно знать про класс-подключение_к_БД и уметь с ним работать (соотв., если я сейчас заменю либу mysqlpp на что-то другое, надо будет переделывать классы объектов-устройств). И еще непонятно, насколько это будет потокобезопасно.

Вариант 2.

Объекты-устройства отправляют демону сообщения в случае необходимости, а демон уже пишет это в БД. Минус данного подхода: чисто субъективно нарушается некоторая иерархичность, т.к. объекты-устройства начинают вызывать функции из «вышестоящего» кода, в котором они были созданы. Плюс придется делать класс для самого демона (сейчас он представляет собой тупо функцию main()) и передавать указатель на него каждому созданному объекту или же решать это через функции, указатели на которые опять же надо передать объектам-устройствам.

Вариант 3.

Сделать некую очередь сообщений, подлежащих записи в БД, на каждом объекте. Опрашивать объекты-устройства на предмет того «есть ч0 положить в БД?» из кода демона по таймеру и, если что-то есть, то демон это записывает в БД. Из минусов, непонятно, как это скажется на адекватности работы программы, если устройств будет не 10, а, например 100 или 1000 (хотя навряд ли их будет больше 10-20 в реальности при любых обстоятельствах). Ну, типа, время опроса всех железок увеличивается пропорционально их количеству.

Собственно, как пишут подобные вещи нормальные пацаны? Можно не давать конкретный ответ, а указать книгу/статью, которую можно прочесть для просвещения в данном вопросе.

 ,

s3rjke
()

Сборка Qt на AMD Geode LX800 — illegal instruction

Форум — Development

Всем привет. Есть необходимость писать/запускать/отлаживать некий софт в среде QtCreator на древнем компьютере с процом AMD Geode LX800.

На этот комп без проблем встал стабильный debian с ядром 3.16.0-4-586. Ок, ставим обычный софт из реп, все работает.

Ставим qtcreator — при запуске выдает «illegal instruction». Я решил, что имеет место некая несовместимость бинарников из реп с имеющимся процом.

Попробовал скачать исходники (qt-everywhere-opensource-src-5.7.0) и собрать их, та же самая фигня:

cd widgets/ && ( test -e Makefile || /home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase/bin/qmake /home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase/src/widgets/widgets.pro -qtconf /home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase/bin/qt.conf -o Makefile ) && make -f Makefile 
Illegal instruction
make[3]: Entering directory '/home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase/src/widgets'
perl /home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase/mkspecs/features/data/unix/findclasslist.pl < QtWidgets.version.in > QtWidgets.version
/home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase/src/widgets/uic_wrapper.sh dialogs/qfiledialog.ui -o .uic/ui_qfiledialog.h
Makefile:1809: recipe for target '.uic/ui_qfiledialog.h' failed
make[3]: *** [.uic/ui_qfiledialog.h] Illegal instruction
make[3]: Leaving directory '/home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase/src/widgets'
Makefile:551: recipe for target 'sub-widgets-make_first' failed
make[2]: *** [sub-widgets-make_first] Error 2
make[2]: Leaving directory '/home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase/src'
Makefile:45: recipe for target 'sub-src-make_first' failed
make[1]: *** [sub-src-make_first] Error 2
make[1]: Leaving directory '/home/user/Downloads/qt-everywhere-opensource-src-5.7.0/qtbase'
Makefile:77: recipe for target 'module-qtbase-make_first' failed
make: *** [module-qtbase-make_first] Error 2

Пока пробую найти что-нибудь типа опций сборки qt, мне кажется, надо их настраивать.

Проблема в том, что configure и make на этом железе требуют супер-много времени. Я бы рад поэксперементировать, попересобирать, но требуется целый день, чтобы увидеть результат, получилось или нет.

Может кто-нибудь сталкивался и сразу знает ответ, что нужно сделать, чтобы заработало?

 , ,

s3rjke
()

ffmpeg: ускоренное видео с IP камеры и другие весёлости

Форум — Development

Привет, эксперты. Продолжаю пляски с бубном вокруг библиотек ffmpeg.

Ссылка на код.

По задумке, код должен делать примерно следующее (если вдруг кто-то будет пробовать запустить):

  • Кодировать входной видеофайл в видеофайл h264 (%programname% -i %вход% -o %выход.mp4%);
  • Кодировать видео с USB-вебкамеры в видеофайл h264 (%programname% -i /dev/video0 -o %выход.mp4% -w);
  • Кодировать видео с IP-камеры в видеофайл h264 (%programname% -i %неважно% -o %выход.mp4% -n).

И вроде все почти работает, кроме последнего.

Столкнулся со следующими проблемами:

  • Маленькая проблема: по дефолту ffmpeg работает с камерой по UDP. И непрерывно сыпет ошибками такого рода при обработке фреймов:
    [rtsp @ 0x2ba1080] max delay reached. need to consume packet
    [rtsp @ 0x2ba1080] RTP: missed 1324 packets                                                                                                                   
    [h264 @ 0x2ba4020] error while decoding MB 29 34, bytestream -13
    [h264 @ 0x2ba4020] concealing 4100 DC, 4100 AC, 4100 MV errors in I frame
    
    [libx264 @ 0x2dc12c0] invalid DTS: PTS is less than DTS
    frame #48 encoded
    [h264 @ 0x2d30ac0] pts (21599) < dts (35999) in stream 0
    .frame #49 decoded
    [libx264 @ 0x2dc12c0] invalid DTS: PTS is less than DTS
    frame #49 encoded
    [h264 @ 0x2d30ac0] pts (10799) < dts (17999) in stream 0
    .frame #50 decoded
    [libx264 @ 0x2dc12c0] invalid DTS: PTS is less than DTS
    frame #50 encoded
    [h264 @ 0x2d30ac0] pts (7199) < dts (21599) in stream 0
    .[rtsp @ 0x2ba1080] max delay reached. need to consume packet
    [rtsp @ 0x2ba1080] RTP: missed 19 packets
    

    Нашел вариант переключения в режим tcp. Только вот tcp сильно тяжелее, чем udp в плане нагрузки на сеть, поэтому хотелось бы побороть ошибки при использовании udp. Что можно подкрутить для этого?

  • Большая проблема: видео с IP-камеры какое-то ускоренное, раза в 2-3 по субъективным ощущениям. Я сперва грешил на настройки кодирования, но сделал параллельно сброс разжатого видео в файл, так там оно тоже ускоренное. Напрашивается вывод про корявые настройки декодирования, но опять же, непонятно, что крутить? С USB-вебки скорость воспроизведения итогового файла нормальная, если попробовать перекодировать кусок mp4-файла, там тоже со скоростью проблем нет.

    Настройки на камере, разрешение fullHD, частота кадров 25/сек, видео отдает по ссылке вида rtsp://%url%.

  • Полученные mp4-файлы не воспроизводятся штатными средствами ОС, только через ffplay. Еще ffprobe не может определить битрейт и длительность получаемых файлов. И в них не работает перемотка.

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

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

 , ,

s3rjke
()

ffmpeg: как записать корректный заголовок?

Форум — Development

Здравствуйте. Уже неделю мучаю ffmpeg. На данный момент осилено декодирование видео в несжатый вариант (raw). Теперь нужно реализовать кодирование в тот формат, который мне нужен. И вроде бы даже что-то там у меня кодируется, но на выходе получается нечитаемый файл. Судя по всему, я просто пишу корявый заголовок и поэтому понять, удалось ли что-то там кодировать — невозможно, т.к. файл-то не проиграть.

Пробую пока тупо расжать и сжать обратно mp4-файл. Вот функция, которая открывает выходной файл и пишет заголовок. По сути, слегка переделанный код из примера transcoding.c, идущего вместе с исходниками ffmpeg.

int open_output_file(const char *filename)
{
	int result;
	avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
	if (!ofmt_ctx)
	{
		printf("can't create output context\n");
		return -1;
	}

	ostream = avformat_new_stream(ofmt_ctx, NULL);
	if (!ostream)
	{
		printf("can't create new stream\n");
		return -1;
	}

	ostream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
	ostream->codecpar->codec_id = AV_CODEC_ID_H264;
	ostream->codecpar->height = decoder_ctx->height;
	ostream->codecpar->width = decoder_ctx->width;

	encoder_ctx = ostream->codec;
	encoder = avcodec_find_encoder(decoder_ctx->codec_id);
	if (!encoder)
	{
		printf("can't find encoder\n");
		return -1;
	}
	encoder_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
	encoder_ctx->codec_id = AV_CODEC_ID_H264;
	encoder_ctx->height = decoder_ctx->height;
	encoder_ctx->width = decoder_ctx->width;
	encoder_ctx->qmin = 10;
	encoder_ctx->qmax = 51;
	encoder_ctx->max_qdiff = 4;
	encoder_ctx->sample_aspect_ratio = decoder_ctx->sample_aspect_ratio;
	encoder_ctx->time_base = decoder_ctx->time_base;
	ostream->time_base = decoder_ctx->time_base;
	if (encoder->pix_fmts)
	{
		encoder_ctx->pix_fmt = encoder->pix_fmts[0];
	}
	else
	{
		encoder_ctx->pix_fmt = decoder_ctx->pix_fmt;
	}
	result = avcodec_open2(encoder_ctx, encoder, NULL)
	if (result < 0)
	{
		printf("can't open encoder for video stream \n");
		return -1;
	}

	if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
		encoder_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

	av_dump_format(ofmt_ctx, 0, filename, 1);

	result = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
	if (result < 0)
	{
		printf("can't open output file %s\n", filename);
		return -1;
	}

	result = avformat_write_header(ofmt_ctx, NULL);
	if (result < 0)
	{
		printf("can't write header\n");
		return -1;
	}

	return 0;
}

В результате работы функции получается файл размером 48 байт, с вот таким содержимым:

$ head -1 out.mp4
 ftypisomisomiso2avc1mp4freemdat

Если выполнить ffprobe на этот файл, в ответ получаем ругань:

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x3530bc0] moov atom not found
out.mp4: Invalid data found when processing input

Если посмотреть корректный mp4-файл, то там в начале вот так (те же первые 48 байт):

▒ftypmp42isommp42�KmoovlmvhdМ�"М�"X�

Если отрезать эти самые 48 байт от корректного mp4-файла и скормить их ffprobe, то он хотя бы не матерится:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2014-11-27 16:04:50
  Duration: N/A, bitrate: N/A

Предположительно, что-то не так в параметре ofmt_ctx функции avformat_write_header. Посмотрел в дебагере значения некоторых полей структуры ofmt_ctx->oformat и с точки зрения человека, не разбирающегося в кодировании видео, все выглядит нормально:

136             if (avformat_write_header(ofmt_ctx, NULL) < 0)
(gdb) print ofmt_ctx->oformat->name
$1 = 0xfb258c "mp4"
(gdb) print ofmt_ctx->oformat->mime_type
$2 = 0xf858cd "video/mp4"
(gdb) print ofmt_ctx->oformat->video_codec
$3 = AV_CODEC_ID_H264

В общем, как говорится, куда рыть, что еще смотреть?

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

 , ,

s3rjke
()

Компиляция программы на C++ с использованием статических библиотек

Форум — Development

Всем привет. Есть необходимость поработать с видеопотоком, кодированным по стандарту h264. Решил использовать библиотеки проекта ffmpeg для этой цели. Собрал ffmpeg по мануалу с официального сайта, статические библиотеки (файлы с расширением .a) легли в /home/username/ffmpeg_build/lib. Решил попробовать скомпилировать кусочек кода из вот этой статьи.

Мой учебный вариант:

#include <iostream>

#ifdef __cplusplus
extern "C"
{
	void av_register_all(void);
	void avcodec_register_all(void);
	unsigned avcodec_get_edge_width(void);
	const char * avcodec_license(void);
	struct AVFormatContext;
	struct AVInputFormat;
	struct AVDictionary;
	int avformat_open_input(AVFormatContext **, const char *, AVInputFormat *, AVDictionary **);
	int avformat_find_stream_info(AVFormatContext *, AVDictionary **);
	void av_dump_format(AVFormatContext *, int, const char*, int);
}
#endif

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		std::cout << "usage: %s filename" << std::endl;
		return 0;
	}
	av_register_all();
	int error;
	const char* filename = argv[1];
	struct AVFormatContext* format_context = nullptr;
	error = avformat_open_input(&format_context, filename, nullptr, nullptr);
	if (error < 0)
	{
		std::cout << "ffmpeg: unable to open " << argv[1] << std::endl;
		return -1;
	}
	error = avformat_find_stream_info(format_context, nullptr);
	if (error < 0)
	{
		std::cout << "ffmpeg: unable to find stream info" << std::endl;
		return -1;
	}
	std::cout << format_context->video_codec->name << std::endl; // маты компилятора
	return 0;
}

Компилирую так:

g++ -L /home/username/ffmpeg_build/lib -o prog prog.cpp -lavformat -lavcodec -lavutil -lswresample -lmp3lame -ltheora -lopus /usr/lib/x86_64-linux-gnu/libtheora.a -lvpx -lvorbis -lvorbisenc -lx264 -lva -logg -pthread -std=c++11 -lz

И компилятор матерится:

prog.cpp:42:29: error: invalid use of incomplete type ‘struct AVFormatContext’
  std::cout << format_context->video_codec->name << std::endl;
                             ^
prog.cpp:10:9: error: forward declaration of ‘struct AVFormatContext’
  struct AVFormatContext;

Как я понимаю, это связано с тем, что я типа обращаюсь к несуществующему с точки зрения компилятора полю структуры format_context.

В каталоге ffmpeg_build есть, кроме каталога со статическими либами (lib), еще каталог с заголовочными файлами .h, называющийся include. В одном из которых как раз есть определения структур и прочих типов.

Может мне нужно как-то эти заголовочные файлы прикрутить к программе? Но как именно, я не понимаю. Если указывать их в стиле #include <libavformat/avformat.h> и добавить в g++ опцию -I /home/username/ffmpeg_build/include, то компилятор уже ругается на повторные объявления функций в секции extern "C". Если эти объявления оттуда убрать, то компилятор перестает «видеть» вызываемые функции, не взирая на то, что через -l перечислены статические библиотеки, содержащие эти функции.

В общем, как сделать так, чтобы все закомпилилось, имея на руках нужные хедеры и статические либы? :-)

 , ,

s3rjke
()

Существует ли стиль для KDE как в Qt Creator?

Форум — Desktop

Здравствуйте. Использую для разработки среду Qt Creator версии 3.2.1. Суть вопроса вот в чем. Внутри Qt Creator элементы управления на форме имеют свою собственную тему/стиль. Как и интерфейс Qt Creator. Системная тема — дефолтный Oxygen на среду не применяется (работает только для скомпилированных приложений). Есть ли где-нибудь тема для кед, чтобы графические элементы кед выглядели так, как выглядят элементы внутри Qt Creator? Гугление толком ничего не дало, народ всё пытается заставить Qt Creator смотреться нативно. Существует ли готовое решение для противоположной задачи — заставить кеды выглядеть как Qt Creator? Может быть кто-то нарисовал стиль для KDE, может кто-нибудь знает, как выдрать из IDE этот стиль?

 , ,

s3rjke
()

RSS подписка на новые темы