Quantcast
Channel: vinxru
Viewing all articles
Browse latest Browse all 319

Сокеты и SSL

$
0
0
Вчера вечером возникла страшная мысль. А можно ли связать OpenSSL и WSAEventSelect/WSAAssyncSelect?

Я пока не читал документацию на OpenSSL по этому поводу. Возможно стоит еще посмотреть, как включить SSL штатными средствами Windows.

Почему я стараюсь не использовать тысячу сторонних компонентов? И почему использую OpenSSL?

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

OpenSSL как раз отвечает таким требованиям.Для использования OpenSSL необходимо заменить функции send и recv на SSL_read, SSL_write. Ну куда проще? Просто сказка. А уже эти функции самые вызовут send и recv столько раз, сколько будет необходимо.

Для работы с сокетами я написал класс обертку, которая вызывает либо стандартную функцию recv, либо функцию SSL_read. Что конкретно вызовется, зависит от подключенного плагина.

Помимо этого, класс обертка благодаря дестрактору автоматически закрывает сокет. И позволяет не влезая в программу подключать различные библиотеки SSL и упрощает перенос программы.

class Socket {
public:
  SOCKET handle;
  void* sslData;
  SocketExtension* ssl;
  
  int recv(void* buf, int len);
  ...
};

int Socket::recv(void* buf, int len) {
  return ext->recv(this, buf, len); // ext - указатель на класс DefaultSocketExtension или OpenSSL
}

// По умолчанию при вызове  Socket::recv вызывается эта функция. DefaultSocketExtension существует 
// в одном экземпляре и не имеет данных.
void DefaultSocketExtension::recv(Socket* s, void* buf, int len) {
  return ::recv(s->handle, buf, len);
}


Для фанатов ООП сразу скажу, что первая моя мысль была сделать интерфейс (абстрактный класс) Socket, и сделать реализации для обычных сокетов и SSL. Но подобная организация потребовала бы выделения памяти. А лишнее выделение памяти - лишние тормоза. Здесь же класс Socket создается на стеке и при использовании SSL никаких выделений памяти (со стороны программы) не требуется.

Плагин в случае OpenSSL выглядит так.

class OpenSSL : public SocketExtension {
public:
  virtual int recv(Socket* s, void* buf, int len) {
    return libssl32.SSL_read(s->sslData, buf, len);
  }

  virtual int send(Socket* s, const void* buf, int len) {
    return libssl32.SSL_write(s->sslData, buf, len);
  }

  virtual void close(Socket* s) {
    libssl32.SSL_free(s->sslData);
    closesocket(s->handle);
    s->handle = 0;
  }
};

//  OpenSSL существует в одном экземпляре и не имеет данных.
static OpenSSL openSSL;
SocketExtension* defaultSSL = openSSL;


Проще и понятнее не придумаешь.

Быть или не быть...

Если не получится заставить работать асинхронные сокеты с OpenSSL, я буду использовать многопоточность. И сразу получаем кроссплатформенность, так как сокеты в Unix и Windows на этом уровне идентичны.

Есть еще неплохой вариант использовать штатные средства Windows. Он я ни разу с ними не работал.

Вот так вот. Думаешь пару дней про WSA, пишешь статью и оказывается, что будешь работать по старинке.

Viewing all articles
Browse latest Browse all 319

Trending Articles