Я создал HTTPS-сервер epoll с помощью mbedtls. Он прослушивает два порта: один для HTTP, другой для HTTPS. HTTP работает отлично. Но для HTTPS я, похоже, получаю уведомление EPOLLIN, когда нет данных для чтения с помощью mbedtls_ssl_read().
Возможно, данные доступны, но проблема связана с контекстом SSL, поскольку mbedtls_ssl_read() возвращает MBEDTLS_ERR_NET_INVALID_CONTEXT. Но я не понимаю, откуда может возникнуть проблема. Я правильно инициализировал контекст и даже выполнил с ним рукопожатие TLS.
Вот важные части кода: Обратите внимание: я понимаю, что во многих случаях этот код не сработает. Я просто привел пример, чтобы воспроизвести ошибку. Этот код просто описывает все, что происходит, когда я принимаю один клиент, а затем, после получения EPOLLIN, пытаюсь прочитать из него данные.
#define REQUEST_SIZE 8192 структура HTTP_server { mbedtls_net_context https_context; mbedtls_entropy_context энтропия; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_config конф; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; константный символ *перс; }; структура typedef client_data { символ *запрос; протокол proto_t; союз { интервал client_fd; mbedtls_net_context https_context; }; mbedtls_ssl_context SSL; } client_data_t; структура сервера HTTP_server; сервер->перс = "ssl_server"; mbedtls_net_init(&сервер->https_context); mbedtls_ssl_config_init (& сервер-> conf); mbedtls_x509_crt_init(&сервер->srvcert); mbedtls_pk_init(&сервер->pkey); mbedtls_entropy_init(&сервер->энтропия); mbedtls_ctr_drbg_init(&сервер->ctr_drbg); если (mbedtls_ctr_drbg_seed(&server->ctr_drbg, mbedtls_entropy_func, &server->энтропия, (const unsigned char *) server->pers, strlen(server->pers)) != 0) { вернуть 0; } if (mbedtls_x509_crt_parse_file(&server->srvcert, "server.crt") != 0) { вернуть 0; } if (mbedtls_pk_parse_keyfile(&server->pkey, "server.key", "pass_phrase", mbedtls_ctr_drbg_random, &server->ctr_drbg) != 0) { вернуть 0; } if (mbedtls_net_bind(&server->https_context, NULL, "8000", MBEDTLS_NET_PROTO_TCP) != 0) { вернуть 0; } mbedtls_net_set_nonblock(&server->https_context); если (mbedtls_ssl_config_defaults(&server->conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { вернуть 0; } mbedtls_ssl_conf_rng(&server->conf, mbedtls_ctr_drbg_random, &server->ctr_drbg); if (mbedtls_ssl_conf_own_cert(&server->conf, &server->srvcert, &server->pkey) != 0) { вернуть 0; } int epoll_fd = epoll_create1 (0); если (epoll_fd == -1) { возвращаться; } event.data.fd = сервер->https_context.fd; event.events = ЭПОЛЛИН; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server->https_context.fd, &event) == -1) { перейти к epoll_close; } пока (1) { int nevents = epoll_wait(epoll_fd, события, 128, -1); если (события == -1) { перейти к epoll_close; } иначе если (ошибка == EINTR) { перейти к epoll_close; } for (int i = 0; i https_context.fd) { client_data_t client_status = malloc(sizeof(client_data_t)); mbedtls_net_context client_socket; mbedtls_net_accept(&server->https_context, &client_socket, NULL, 0, NULL); client_status-> https_context = client_socket; mbedtls_ssl_init(&client_status->ssl); if (mbedtls_ssl_setup(&client_status->ssl, &server->conf) != 0) { вернуть 0; } mbedtls_ssl_set_bio(&client_status->ssl, client_socket, mbedtls_net_send, mbedtls_net_recv, NULL); интервал врет; while (!program_interrupted && ((ret = mbedtls_ssl_handshake(&client_status->ssl)) != 0)) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { mbedtls_printf("не удалось\n! mbedtls_ssl_handshake вернул %d\n\n", ret); вернуть 0; } } client_status-> request = malloc (REQUEST_SIZE + 1); event.data.fd = client_socket.fd; event.data.ptr = client_status; event.events = ЭПОЛЛИН | ЭПОЛЛЕ; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_socket.fd, &event) == -1) { продолжать; } } еще { client_data_t *client_status = события.data.ptr; // Каждый вызов функции, пока это не было успешным, я проверял, здесь nbytes == -69 или nbytes == -76 // mbedtls_ssl_get_bytes_avail(&client_status->ssl) дает 0 ssize_t nbytes = mbedtls_ssl_read(&client_status->ssl, (беззнаковый символ *)(client_status->request), REQUEST_SIZE); // другие вещи } } } epoll_close: закрыть (epoll_fd); Сообщения об ошибках отладки mbedtls выглядят следующим образом:
ssl_msg.c:5662: => прочитать ssl_msg.c:4110: => прочитать запись ssl_msg.c => получить ввод ssl_msg.c in_left: 0, nb_want: 5 ssl_msg.c in_left: 0, nb_want: 5 ssl_msg.c ssl->f_recv(_timeout)() вернул -69 (-0x0045) ssl_msg.c:4782: mbedtls_ssl_fetch_input() вернул -69 (-0x0045) ssl_msg.c:4141: ssl_get_next_record() вернул -69 (-0x0045) ssl_msg.c:5722: mbedtls_ssl_read_record() вернул -69 (-0x0045) Изменить: обратите внимание, что я получаю EPOLLIN после отправки запроса из браузера и использую epoll() в режиме, запускаемом по краю, поэтому я использую mbedtls_ssl_read( ) до тех пор, пока сокет не будет блокироваться каждый раз, то есть пока я не получу MBEDTLS_ERR_SSL_WANT_READ.
Вот как я прочитал сообщение:
пока (1) { nbytes = mbedtls_ssl_read(&client_status->ssl, (беззнаковый символ *)(request + client_status->request_bytes_read), server_properties->max_request - client_status->request_bytes_read); если (нбайт request_bytes_read += nbytes; client_status->request[client_status->request_bytes_read] = '\0'; char *CRLF = strstr(client_status->request + client_status->request_bytes_read - nbytes, "\r\n\r\n"); если (CRLF) { // анализируем заголовки, получаем Content-Length и переходим к чтению тела // тело читается аналогичным образом перерыв; } } }
Я создал HTTPS-сервер epoll с помощью mbedtls. Он прослушивает два порта: один для HTTP, другой для HTTPS. HTTP работает отлично. Но для HTTPS я, похоже, получаю уведомление EPOLLIN, когда нет данных для чтения с помощью mbedtls_ssl_read().
Возможно, данные доступны, но проблема связана с контекстом SSL, поскольку mbedtls_ssl_read() возвращает MBEDTLS_ERR_NET_INVALID_CONTEXT. Но я не понимаю, откуда может возникнуть проблема. Я правильно инициализировал контекст и даже выполнил с ним рукопожатие TLS.
Вот важные части кода: Обратите внимание: я понимаю, что во многих случаях этот код не сработает. Я просто привел пример, чтобы воспроизвести ошибку. Этот код просто описывает все, что происходит, когда я принимаю один клиент, а затем, после получения EPOLLIN, пытаюсь прочитать из него данные.
#define REQUEST_SIZE 8192 структура HTTP_server { mbedtls_net_context https_context; mbedtls_entropy_context энтропия; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_config конф; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; константный символ *перс; }; структура typedef client_data { символ *запрос; протокол proto_t; союз { интервал client_fd; mbedtls_net_context https_context; }; mbedtls_ssl_context SSL; } client_data_t; структура сервера HTTP_server; сервер->перс = "ssl_server"; mbedtls_net_init(&сервер->https_context); mbedtls_ssl_config_init (& сервер-> conf); mbedtls_x509_crt_init(&сервер->srvcert); mbedtls_pk_init(&сервер->pkey); mbedtls_entropy_init(&сервер->энтропия); mbedtls_ctr_drbg_init(&сервер->ctr_drbg); если (mbedtls_ctr_drbg_seed(&server->ctr_drbg, mbedtls_entropy_func, &server->энтропия, (const unsigned char *) server->pers, strlen(server->pers)) != 0) { вернуть 0; } if (mbedtls_x509_crt_parse_file(&server->srvcert, "server.crt") != 0) { вернуть 0; } if (mbedtls_pk_parse_keyfile(&server->pkey, "server.key", "pass_phrase", mbedtls_ctr_drbg_random, &server->ctr_drbg) != 0) { вернуть 0; } if (mbedtls_net_bind(&server->https_context, NULL, "8000", MBEDTLS_NET_PROTO_TCP) != 0) { вернуть 0; } mbedtls_net_set_nonblock(&server->https_context); если (mbedtls_ssl_config_defaults(&server->conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { вернуть 0; } mbedtls_ssl_conf_rng(&server->conf, mbedtls_ctr_drbg_random, &server->ctr_drbg); if (mbedtls_ssl_conf_own_cert(&server->conf, &server->srvcert, &server->pkey) != 0) { вернуть 0; } int epoll_fd = epoll_create1 (0); если (epoll_fd == -1) { возвращаться; } event.data.fd = сервер->https_context.fd; event.events = ЭПОЛЛИН; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server->https_context.fd, &event) == -1) { перейти к epoll_close; } пока (1) { int nevents = epoll_wait(epoll_fd, события, 128, -1); если (события == -1) { перейти к epoll_close; } иначе если (ошибка == EINTR) { перейти к epoll_close; } for (int i = 0; i https_context.fd) { client_data_t client_status = malloc(sizeof(client_data_t)); mbedtls_net_context client_socket; mbedtls_net_accept(&server->https_context, &client_socket, NULL, 0, NULL); client_status-> https_context = client_socket; mbedtls_ssl_init(&client_status->ssl); if (mbedtls_ssl_setup(&client_status->ssl, &server->conf) != 0) { вернуть 0; } mbedtls_ssl_set_bio(&client_status->ssl, client_socket, mbedtls_net_send, mbedtls_net_recv, NULL); интервал врет; while (!program_interrupted && ((ret = mbedtls_ssl_handshake(&client_status->ssl)) != 0)) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { mbedtls_printf("не удалось\n! mbedtls_ssl_handshake вернул %d\n\n", ret); вернуть 0; } } client_status-> request = malloc (REQUEST_SIZE + 1); event.data.fd = client_socket.fd; event.data.ptr = client_status; event.events = ЭПОЛЛИН | ЭПОЛЛЕ; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_socket.fd, &event) == -1) { продолжать; } } еще { client_data_t *client_status = события[i].data.ptr; // Каждый вызов функции, пока это не было успешным, я проверял, здесь nbytes == -69 или nbytes == -76 // mbedtls_ssl_get_bytes_avail(&client_status->ssl) дает 0 ssize_t nbytes = mbedtls_ssl_read(&client_status->ssl, (беззнаковый символ *)(client_status->request), REQUEST_SIZE); // другие вещи } } } epoll_close: закрыть (epoll_fd); Сообщения об ошибках отладки mbedtls выглядят следующим образом:
ssl_msg.c:5662: => прочитать ssl_msg.c:4110: => прочитать запись ssl_msg.c:2155: => получить ввод ssl_msg.c:2295: in_left: 0, nb_want: 5 ssl_msg.c:2315: in_left: 0, nb_want: 5 ssl_msg.c:2318: ssl->f_recv(_timeout)() вернул -69 (-0x0045) ssl_msg.c:4782: mbedtls_ssl_fetch_input() вернул -69 (-0x0045) ssl_msg.c:4141: ssl_get_next_record() вернул -69 (-0x0045) ssl_msg.c:5722: mbedtls_ssl_read_record() вернул -69 (-0x0045) Изменить: обратите внимание, что я получаю EPOLLIN после отправки запроса из браузера и использую epoll() в режиме, запускаемом по краю, поэтому я использую mbedtls_ssl_read( ) до тех пор, пока сокет не будет блокироваться каждый раз, то есть пока я не получу MBEDTLS_ERR_SSL_WANT_READ.
Вот как я прочитал сообщение: пока (1) { nbytes = mbedtls_ssl_read(&client_status->ssl, (беззнаковый символ *)(request + client_status->request_bytes_read), server_properties->max_request - client_status->request_bytes_read); если (нбайт request_bytes_read += nbytes; client_status->request[client_status->request_bytes_read] = '\0'; char *CRLF = strstr(client_status->request + client_status->request_bytes_read - nbytes, "\r\n\r\n"); если (CRLF) { // анализируем заголовки, получаем Content-Length и переходим к чтению тела // тело читается аналогичным образом перерыв; } } }
Приведенный ниже скрипт отправит электронное письмо после отправки формы, но имя от имени — $name, строка темы верна, электронное письмо отправляется на правильный адрес электронной почты, ответ — $name, а сообщения электронной почты — это точное...
Я пытался использовать Babel-plugin-require-context-hook, чтобы сделать Jest Digest redect.context ()
, и в результате этого мои тесты, наконец, начали работать гладко.Metro error: __requireContext is not defined
У меня есть функция callBackend(), которая отправляет уведомления. Он отлично работает в веб-браузере, и уведомления отправляются без каких-либо проблем. Однако когда я запускаю тот же код на устройстве Android, уведомления не срабатывают....
У меня есть функция callBackend(), которая отправляет уведомления. Он отлично работает в веб-браузере, и уведомления отправляются без каких-либо проблем. Однако когда я запускаю тот же код на устройстве Android, уведомления не срабатывают....
Я работаю над созданием SVG-файлов для отчета, и мне нужно нарисовать линии разного цвета с соответствующими маркерами для начала и конца. Похоже, что в Firefox эту проблему исправили 14 дней назад, но Chrome не понимает атрибут Stroke=...