C++ man(3)

Давно хотел разжиться маном по плюсам ибо задрало лазить в инет за этой информацией.
Подходящий ман берется вот тут: ftp://ftp.gwdg.de//pub/misc/gcc/libstdc++/doxygen/
И копируется вот сюда: /usr/share/man/man3
Ну а если к Vim-у добавить вот этот плагин, жизнь становится еще прекраснее :)))

cURL & Proxy & HTTPS & Authorization == CURLE_RECV_ERROR

Да, баги в тулзах преследуют меня всю неделю. На сей раз отличился cURL с древним багом связанным с запросом отправляемым по HTTPS через прокси. Похоже что ситуация не слишком распространенная, т.к. надо не только работать через прокси, но еще на прокси должна быть включена авторизация и при отправке запроса пароль должен быть не указан. В принципе, в такой ситуации ожидаешь код 407, просишь пользователя ввести пароль и наступает счастье. Но вот cURL думает иначе. Вместо того чтоб вернуть 407 и страничку с ошибкой от прокси, которые судя по его логу присутствуют, зачем-то возвращается CURLE_RECV_ERROR.

Ignore 1380 bytes of response-body
Received HTTP code 407 from proxy after CONNECT
Closing connection #0
Failure when receiving data from the peer

Какого-либо корректного выхода из данной ситуации я не нашел. Так что, при работе через прокси, если пароль не задан и возникает ошибка CURLE_RECV_ERROR, единственное что остается – повторить запрос, предварительно указав параметры авторизации на проксе.

LLVM, чтоб его.

Баг 2008 года в LLVM портит мне жизнь. Берем тестовый файлик следующего содержания:

class RPC_Service
{
public:
  virtual ~RPC_Service ();
};
class EventLoggingInterface
{
  virtual void
    Ev (const char *file, int line, int sev, const char *fmt,
        ...) const = 0;
};
class RPCCore : RPC_Service, EventLoggingInterface
{
  virtual void
    Ev (const char *file, int line, int sev, const char *fmt, ...) const;
};
void
RPCCore::Ev (const char *file, int line, int sev, const char *format, ...) const
{
}

Выполняем команду:

/Developer/usr/bin/llvm-g++ thunk_error.cpp -c

И в результате получаем:

thunk_error.cpp:19: error: generic thunk code fails for method ‘virtual void RPCCore::Ev(const char*, int, int, const char*, ...) const’ which uses ‘...’

Неужели придется отказаться от LLVM? Интерфейс, в моем случае, поменять врятли удастся. Вобщем писать кроссплатформенный код это еще та засада

Работаем с таймерами.

До появления вот этой темы на РСДНе я как-то не предавал особого значения таймерам в Mac OS X. Ну есть они и есть, как будет нужно так разберусь. Но как оказалось, стандартных POSIX вызовов, таких как timer_create/timer_delete у нас нет, а то что есть не всегда подходит.

Хорошенько поковырявшись в документации я пришел к следующему выводу. Всего доступны 3 способа работы с таймерами, дающие приблизительно одинаковый эффект:

  • NSTimer из Foundation;
  • RunLoop из CoreFoundation;
  • Таймеры из Mach. Хотя у меня данный пункт вызвал некоторые трудности.

Так что по порядку, с краткими иллюстрациями.

Continue reading

HTTPS & cURL

В пятницу, работая над одной из наших подсистем, я занимался прикручиванием cURL и тихо охреневал с того, что пишет народ народ в интернете по поводу реализации работы с HTTPS при использовании cURL. Лично я всегда считал что HTTPS необходим для установки защищенного соединения. Из чего следует что, во-первых, данные передаются в шифрованном виде, и во-вторых, мы знаем с кем общаемся.
Так вот, как выяснилось на практике, если с шифрованием ни у кого вопросов не возникает, то вот на авторизацию все кладут болт.
Причем основательно, например так:

curl_easy_setopt( curl_, CURLOPT_SSL_VERIFYPEER, 0 );

Что отключает проверку полученного сертификата. Ну а особо одаренные делают даже так:

curl_easy_setopt( curl_, CURLOPT_SSL_VERIFYHOST, 0 );

Что отключает проверку соответствия хоста, указанного в сертификате, с хостом, с которым мы общаемся.

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

Так вот, как оказалось все дело в том, что если не выключить проверку канала то возникают различные неприятные ошибки связанные с невозможностью проверки сертификата канала. Например вот такие:

error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

В то же время информации том, что делать в такой ситуации в интернете по большому счету нет. Но все не так уж и страшно, всего-то немного терпения и экспериментов.

Все решается довольно просто. Необходимо скачать набор сертификатов с сайта cURL и передать их в библиотеку при помощи CURLOPT_CAINFO. Хотя в документации к библиотеке и говорится что эта функция не работает под Windows, это не соответствует действительности. Она отлично работает как в Mac OS X так и в Windows. В cURL для установки сертификатов будет вызвана OpenSSL функция SSL_CTX_load_verify_locations, соответственно все сертификаты должны быть в PEM формате.

Собственно это все, после этого все должно отлично работать.

Дружественные шаблонные операторы

Как человек, довольно редко использующий шаблоны и метаопрограммирование, периодически путаюсь них. Недавно был сильно озадачен, пытаясь написать оператор << для шаблонного класса. Хотелось получить поддержку следующего синтаксиса:

Buffer<int> buff;
int data1 = 100;
int data2 = 200;

buff << data1 << data2;


Казалось бы ничего сложного (да и без казалось ничего сложного), тем не менее пришлось подумать. Основная проблема – синтаксис который позволял использовать компилятор из вендовой студии не сработал:

template<typename T>
class Buffer
{
public:
friend Buffer<T>& operator<< ( Buffer<T> buff, const T& data );

Buffer()
{}
~Buffer()
{}
};

template<typename T>
Buffer<T>& operator<<( Buffer<T>& buff, const T& data )
{
// do smth
return buff;
}

Погуглив, я понял, что эта проблема волнует не только меня, но врет решения предлагались несколько кривоваты, например можно сделать так:

template<typename U>
friend Buffer& operator<< ( Buffer& buff, const U& data );

Но это не то что требуется. Хотя на самом деле, все просто и логично:

template<typename T>
class Buffer;

template<typename T>
Buffer<T>& operator<<( Buffer<T>& buff, const T& data );

template<typename T>
class Buffer
{
public:
friend Buffer<T>& operator<< <T> ( Buffer<T>& buff, const T& data );

Buffer()
{}
~Buffer()
{}
};

template<typename T>
Buffer<T>& operator<<( Buffer<T>& buff, const T& data )
{
// do smth
return buff;
}

Автоопределение прокси

Казалось бы, тривиальнейшая задача – определить настройки прокси сервиса, заданные при помощи .pac файла либо полученные в результате работы автоконфигурации. А в действительности оказывается что информации в интернете кот наплакал, а та что есть посвящена венде (что еще печальнее). Чтобы исправить эту жутко не справедливую ситуацию, я опишу как можно определить настройки прокси в Mac OS X приложении.
Итак, необходимый API появился в Mac OS X начиная с версии 10.5, так же API присутствует в iOS, но деталей по версиям я уже сказать не могу. Continue reading

printf и CoreFoudation

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

#include <CoreFoundation/CoreFoundation.h>

int main (int argc, const char * argv[])
{
    CFStringRef outStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("Output string: %@, %d"), CFSTR("additional string"), 10);
    CFShow( outStr );
    CFRelease( outStr );
    return 0;
}

Можно это дело еще в макрос завернуть, наверное, но зачем? Вобщем, пусть так будет.

C++ не нужен?

В преддверии лекции Страуструпа, посвященной C++0x, наша маленькая но разношерстная команда разработки под Mac OS X разошлась во мнениях о ее потенциальной полезности. Одна часть, что показательно молодежь, утверждает что и от книги мозги вскипают, а от лекции и подавно поплохеет. Другая часть, постарше, ожидает что будет очень интересно.
Так вот, получается довольно интересная ситуация. Приток новых людей в область сильно сокращется, новички хотят иметь в языке как минимум сборку мусора, а старые разработчики уходят кто куда.
С учетом всего этого, очень интересно, что ждет область лет через 10. С одной стороны, плюсы это далеко не настольно незаменимы как чистый Си, с другой стороны, на данный момент это единственный язык позволяющий писать достаточно шустрый код для конечного пользователя. Но, как ни крути, такая ситуация будет не всегда, мощность компьютеров рано или поздно позволит работать программам на управляемых языках с приемлимой скоростью.
В целом, тенденция с сокращением количества C++ разработчиков не так уж и плоха, будем как кобол-динозавры, жутко редкими и жутко дорогими. С другой, скучно, наверное, в говнищах 30 летней давности копаться? Но, на данный момент, описанная выше тенденция сплошной плюс – зарплаты растут, количество вакансий растет, интресных задач все больше.