Я хотел бы знать, как правильно обрабатывать новое соединение от клиента, используя AcceptEx и OpenSSL. У меня есть отлично работающий сервер, который использует AcceptEx с портами завершения ввода-вывода по обычному HTTP. Я хотел бы добавить поддержку OpenSSL.
Я прочитал несколько статей в интернете об использовании OpenSSL с неблокирующими сокетами:
Никто из них, кажется, не касается того, как это сделать, потому что они в основном касаются клиентской стороны соединения. AcceptEx устанавливает соединение с сокетом И возвращает вам первый фрагмент данных, отправленных клиентом. Первая ссылка, которую я разместил, обсуждает, как вы должны обрабатывать входящие данные с IOCP. Я попробовал то, что размещено там без какой-либо удачи до сих пор. В основном то, что я вижу на своем сервере, выглядит следующим образом:
- Получено принятое завершение соединения.
- Я создаю объект SSL с SSL_new (ctx)
- Я создаю входящие и исходящие объекты BIO с помощью BIO_new (BIO_s_mem ()).
- Я установил BIO в объекте SSL, вызвав SSL_set_bio (ssl, bioIn, bioOut).
- Я вызываю SSL_set_accept_state (ssl), чтобы разрешить SSL_read и SSL_write проводить переговоры.
Затем я пытаюсь разобраться с первым буфером данных, который был прочитан вызовом AcceptEx.
- Я вызываю BIO_Write (bioIn, buf, len) для копирования прочитанных данных в SSL.
- Затем я проверяю ожидающие данные рукопожатия на bioOut, чтобы узнать, нужно ли их отправлять обратно клиенту. Принимая новое соединение, я никогда не видел никаких данных в bioOut на этом этапе.
- Затем я вызываю SSL_read (ssl, plainTextBuf, len), чтобы попытаться расшифровать данные, которые я поместил в bioIn на шаге 6. Это всегда возвращает -1, а SSL_get_error возвращает ERROR_SSL_WANT_READ. Насколько я понимаю, это означает, что bioIn не имеет полной записи SSL, поэтому для SSL требуется больше данных от клиента, прежде чем он сможет что-либо расшифровать.
Здесь я начинаю сталкиваться с проблемами и думаю, что мне нужно какое-то направление. Я перепробовал несколько вещей. Если я неоднократно вызываю SSL_read на этом этапе, он будет бесконечно возвращать ERROR_SSL_WANT_READ, предположительно, потому что использование памяти BIO на самом деле не связывается через сокет, чтобы получить больше данных. Должен ли я опубликовать вызов WSARecv для ожидания дополнительных данных от клиента?
В этот момент я также пытался проверить буфер bioOut с помощью BIO_read, чтобы посмотреть, есть ли данные, которые мне нужно отправить обратно клиенту. На самом деле они есть, и я отправляю их обратно, используя WSASend, а также отправляю еще один вызов WSARecv, чтобы дождаться новых данных (в ответ на мою отправку). Это приводит к получению дополнительных данных от клиента (WSARecv завершает работу после отправки), поэтому создается впечатление, что соединение прогрессирует. Однако когда я обрабатываю это завершенное чтение, и SSL_read, и BIO_read возвращают ERROR_SSL_WANT_READ. Итак, у меня недостаточно данных для расшифровки полной записи, и мне нечего отправить клиенту. Отправка другого вызова WSARecv в ответ на эту ситуацию также не получает больше данных от клиента. Я не знаю, чего здесь хочет SSL.
Я застрял прямо сейчас, но я буду продолжать пробовать больше вещей. Я дополню этот вопрос комментариями, если что-нибудь выясню.