Я хотел бы знать, как правильно обрабатывать новое соединение от клиента с помощью AcceptEx и OpenSSL. У меня есть отлично работающий сервер, который использует AcceptEx с портами завершения ввода-вывода через обычный HTTP. Я бы хотел добавить к нему поддержку OpenSSL.
Я прочитал несколько статей в Интернете об использовании OpenSSL с неблокирующими сокетами:
- Порты завершения ввода-вывода и OpenSSL
- http://zzz.zggg.com/2007/12/22/ssl-server-with-openssl-memory-bio-aka-prerequisite-to-asynchronous-openssl/
- http://marc.info/?l=openssl-users&m=99909952822335&w=2 < / а>
- http://www.lenholgate.com/blog/2002/11/using-openssl-with-asynchronous-sockets.html
Кажется, никто из них не касается того, как это сделать, потому что они в основном озабочены клиентской стороной соединения. 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.
Я сейчас застрял, но я буду пробовать еще кое-что. Я дополню этот вопрос комментариями, если что-нибудь выясню.