рдЧреИрд░-рдЕрд╡рд░реБрджреНрдз рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо https рд╕рд░реНрд╡рд░ред рднрд╛рдЧ реи

рдпрд╣ рд▓реЗрдЦ рд▓реЗрдЦреЛрдВ рдХреА рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рд╣реИ:
Ssl рд╕рдорд░реНрдерди рдХреЗ рд╕рд╛рде рд╕рдмрд╕реЗ рд╕рд░рд▓ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╕рд░реНрд╡рд░
рдЧреИрд░-рдЕрд╡рд░реБрджреНрдз рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо https рд╕рд░реНрд╡рд░
рдЗрди рд▓реЗрдЦреЛрдВ рдореЗрдВ, рдореИрдВ рдзреАрд░реЗ-рдзреАрд░реЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЙрджрд╛рд╣рд░рдг рд╕реЗ рдПрдХ рдкреВрд░реНрдг-рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рд╡реЗрдм рд╕рд░реНрд╡рд░ рдмрдирд╛рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реВрдВ рдЬреЛ рдУрдкрдирдПрд╕рдПрд╕рдПрд▓ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред
рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВрдиреЗ рдПрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдХрдиреЗрдХреНрд╢рди рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдФрд░ рдЕрдиреБрд░реЛрдз рд╣реЗрдбрд░ рдХреЗ рд╕рд╛рде рдПрдХ html рдкреЗрдЬ рд╡рд╛рдкрд╕ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рдХреЛ "рд╕рд┐рдЦрд╛рдпрд╛" рдерд╛ред
рдЖрдЬ рдореИрдВ рд╕рд░реНрд╡рд░ рдХреЛрдб рдХреЛ рдареАрдХ рдХрд░реВрдВрдЧрд╛ рддрд╛рдХрд┐ рдпрд╣ рдПрдХ рдереНрд░реЗрдб рдореЗрдВ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рдПрдХ рдордирдорд╛рдиреА рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рдХрдиреЗрдХреНрд╢рди рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХреЗред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВ рдХреЛрдб рдХреЛ рджреЛ рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рддреЛрдбрд╝ рджреВрдВрдЧрд╛: serv.cpp рдФрд░ server.h
рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, serv.cpp рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдРрд╕рд╛ "рдЕрддреНрдпрдзрд┐рдХ рдмреБрджреНрдзрд┐рдорд╛рди" рдХреЛрдб рд╣реЛрдЧрд╛:
#include "server.h" int main() { server::CServer(); return 0; } 


рд╣рд╛рдВ, рдЖрдк рдореБрдЭреЗ рд▓рд╛рдд рдорд╛рд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЕрднреА рднреА рд▓рд┐рдЦрд╛ рд╣реИ, рд▓рд┐рдЦ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рд╣реЗрдбрд░ рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рдХреЛрдб рд▓рд┐рдЦреВрдВрдЧрд╛ рдпрджрд┐ рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ C ++ рд╕реЗ рдкреНрдпрд╛рд░ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдкрд╕рдВрдж рдХреА рд╕реНрд╡рддрдВрддреНрд░рддрд╛ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдЕрд▓рдЧ рдмрд╛рддрдЪреАрдд рд╣реИ ...

Server.h рдлрд╝рд╛рдЗрд▓ рдкрд░ рдЬрд╛рдПрдВ
рд╢реБрд░реБрдЖрдд рдореЗрдВ, рдореИрдВрдиреЗ рд╕рднреА рд╣реЗрдбрд░, рдореИрдХреНрд░реЛрдЬрд╝, рдФрд░ рдкрд░рд┐рднрд╛рд╖рд╛рдПрдБ, рдЬреЛ рдкрд╣рд▓реЗ serv.cpp рдореЗрдВ рдереАрдВ, рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛, рдФрд░ STL рд╕реЗ рдХреБрдЫ рдФрд░ рд╣реЗрдбрд░ рдЬреЛрдбрд╝реЗ:

 #ifndef _SERVER #define _SERVER #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <errno.h> #include <sys/types.h> #ifndef WIN32 #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #else #include <io.h> #include <Winsock2.h> #pragma comment(lib, "ws2_32.lib") #endif #include <openssl/rsa.h> /* SSLeay stuff */ #include <openssl/crypto.h> #include <openssl/x509.h> #include <openssl/pem.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <vector> #include <string> #include <sstream> #include <map> #include <memory> #ifdef WIN32 #define SET_NONBLOCK(socket) \ if (true) \ { \ DWORD dw = true; \ ioctlsocket(socket, FIONBIO, &dw); \ } #else #include <fcntl.h> #define SET_NONBLOCK(socket) \ if (fcntl( socket, F_SETFL, fcntl( socket, F_GETFL, 0 ) | O_NONBLOCK ) < 0) \ printf("error in fcntl errno=%i\n", errno); #define closesocket(socket) close(socket) #define Sleep(a) usleep(a*1000) #define SOCKET int #define INVALID_SOCKET -1 #endif /* define HOME to be dir for key and cert files... */ #define HOME "./" /* Make these what you want for cert & key files */ #define CERTF HOME "ca-cert.pem" #define KEYF HOME "ca-cert.pem" #define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } 


рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдкрд╣рд▓реА рдмрд╛рд░ рдирд╛рдорд╕реНрдерд╛рди рд╕рд░реНрд╡рд░ рдХреЗ рдЕрдВрджрд░ CServer рдФрд░ CClient рдХреНрд▓рд╛рд╕реЗрд╕ рдмрдирд╛рддреЗ рд╣реИрдВ:
 using namespace std; namespace server { class CClient { //   SOCKET m_hSocket; //        vector<unsigned char> m_vRecvBuffer; //        vector<unsigned char> m_vSendBuffer; //    OpenSSL SSL_CTX* m_pSSLContext; SSL* m_pSSL; //       explicit CClient(const CClient &client) {} public: CClient(const SOCKET hSocket) : m_hSocket(hSocket), m_pSSL(NULL), m_pSSLContext(NULL) {} ~CClient() { if(m_hSocket != INVALID_SOCKET) closesocket(m_hSocket); if (m_pSSL) SSL_free (m_pSSL); if (m_pSSLContext) SSL_CTX_free (m_pSSLContext); } }; class CServer { //      map<SOCKET, shared_ptr<CClient> > m_mapClients; //       explicit CServer(const CServer &server) {} public: CServer() {} }; } #endif 


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рд╣рдорд╛рд░реЗ рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рд╕рд┐рд░реНрдл рдПрдХ рд░рд┐рдХреНрдд рд╣реИред рд╣рдо рдЗрд╕ рд╡рд░реНрдХрдкреАрд╕ рдХреЛ рдзреАрд░реЗ-рдзреАрд░реЗ рдХреЛрдб рдХреЗ рд╕рд╛рде рднрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рд╣реИрдВ ред
рдкреНрд░рддреНрдпреЗрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рдЕрдкрдирд╛ SSL рд╕рдВрджрд░реНрдн рд╣реЛрддрд╛ рд╣реИ, рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ CClient рд╡рд░реНрдЧ рдХреЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
  CClient(const SOCKET hSocket) : m_hSocket(hSocket), m_pSSL(NULL), m_pSSLContext(NULL) { #ifdef WIN32 const SSL_METHOD *meth = SSLv23_server_method(); #else SSL_METHOD *meth = SSLv23_server_method(); #endif m_pSSLContext = SSL_CTX_new (meth); if (!m_pSSLContext) ERR_print_errors_fp(stderr); if (SSL_CTX_use_certificate_file(m_pSSLContext, CERTF, SSL_FILETYPE_PEM) <= 0) ERR_print_errors_fp(stderr); if (SSL_CTX_use_PrivateKey_file(m_pSSLContext, KEYF, SSL_FILETYPE_PEM) <= 0) ERR_print_errors_fp(stderr); if (!SSL_CTX_check_private_key(m_pSSLContext)) fprintf(stderr,"Private key does not match the certificate public key\n"); } 


рд╣рдо рд▓рд╛рдпрдмреНрд░реЗрд░реА рдХреЗ рдЖрд░рдВрднреАрдХрд░рдг рдХреЛ рд╣рд╕реНрддрд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВрдЧреЗ, CServer рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдХрдо рд╕реЗ рдХрдо рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд╕рд╛рде рд╕реБрдирдиреЗ рд╡рд╛рд▓реЗ рд╕реЙрдХреЗрдЯ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдФрд░ рдмрдВрдзрди:
  CServer() { #ifdef WIN32 WSADATA wsaData; if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != 0 ) { printf("Could not to find usable WinSock in WSAStartup\n"); return; } #endif SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); /* ----------------------------------------------- */ /* Prepare TCP socket for receiving connections */ SOCKET listen_sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(listen_sd, "socket"); SET_NONBLOCK(listen_sd); struct sockaddr_in sa_serv; memset (&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons (1111); /* Server Port number */ int err = ::bind(listen_sd, (struct sockaddr*) &sa_serv, sizeof (sa_serv)); CHK_ERR(err, "bind"); /* Receive a TCP connection. */ err = listen (listen_sd, 5); CHK_ERR(err, "listen"); } 


рдЙрд╕реА рдирд┐рд░реНрдорд╛рддрд╛ рдореЗрдВ рдЖрдЧреЗ, рдореИрдВ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЯреАрд╕реАрдкреА рдХрдиреЗрдХреНрд╢рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реВрдВред
рдХрд┐рд╕реА рдиреЗ рднреА рдореБрдЭреЗ рдЗрд╕рдХреЗ рдЦрд┐рд▓рд╛рдл рдХреЛрдИ рддрд░реНрдХ рдирд╣реАрдВ рджрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдХреА рддрд░рд╣ рдПрдХ рдЕрдВрддрд╣реАрди рд▓реВрдк рдореЗрдВ рдЯреАрд╕реАрдкреА рдХрдиреЗрдХреНрд╢рди рд╕реБрдиреЗрдВрдЧреЗред
рдкреНрд░рддреНрдпреЗрдХ рд╕реНрд╡реАрдХрд╛рд░ рдХреЙрд▓ рдХреЗ рдмрд╛рдж, рд╣рдо рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдирдП рдЬреБрдбрд╝реЗ рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рдЬреБрдбрд╝реЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рд╕рд╛рде рдХреБрдЫ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╢реНрд░рд╡рдг рд╕рдорд╛рд░реЛрд╣ рдХреЗ рдмрд╛рдж CServer рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдЬреЛрдбрд╝реЗрдВ:

 while(true) { Sleep(1); struct sockaddr_in sa_cli; size_t client_len = sizeof(sa_cli); #ifdef WIN32 const SOCKET sd = accept (listen_sd, (struct sockaddr*) &sa_cli, (int *)&client_len); #else const SOCKET sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); #endif Callback(sd); } 


рдФрд░ рд╕рд╣реА рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рдмрд╛рдж, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди:
  private: void Callback(const SOCKET hSocket) { if (hSocket != INVALID_SOCKET) m_mapClients[hSocket] = shared_ptr<CClient>(new CClient(hSocket)); //   auto it = m_mapClients.begin(); while (it != m_mapClients.end()) //   { if (!it->second->Continue()) // -   m_mapClients.erase(it++); //   false,    else it++; } } 


рдпрд╣ CServer рдХреНрд▓рд╛рд╕ рдХреЛрдб рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИ! рдЕрдиреНрдп рд╕рднреА рдЖрд╡реЗрджрди рддрд░реНрдХ CClient рд╡рд░реНрдЧ рдореЗрдВ рд╣реЛрдВрдЧреЗред
рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рднреА рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд▓реВрдк рдореЗрдВ рдПрдиреНрдпреВрдорд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдХреЗрд╡рд▓ рдЙрди рдХреНрд▓рд╛рдЗрдВрдЯреНрд╕ рдХреЛ рдПрдиреНрдпреВрдорд░реЗрдЯ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬрд┐рдирдХреЗ рд╕реЙрдХреЗрдЯ рдкрдврд╝рдиреЗ рдпрд╛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВред
рдпрд╣ рдЬрд╛рдирд╡рд░ рдмрд▓ рд╡рд┐рдВрдбреЛрдЬ рдкрд░ рдЪреБрдирд┐рдВрджрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдпрд╛ рд▓рд┐рдирдХреНрд╕ рдкрд░ рдПрдкреЛрд▓ рдХреЗ рд╕рд╛рде рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИред рдореИрдВ рдпрд╣ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ,
рдЗрд╕ рдмреАрдЪ, (рдлрд┐рд░ рд╕реЗ рдЖрд▓реЛрдЪрдирд╛ рдореЗрдВ рджреМрдбрд╝рдиреЗ рдХреЗ рдЬреЛрдЦрд┐рдо рдкрд░), рд╕рднреА рд╕рдорд╛рди, рдореИрдВ рдЦреБрдж рдХреЛ рдПрдХ рд╕рд░рд▓ рдЪрдХреНрд░ рддрдХ рд╕реАрдорд┐рдд рдХрд░реВрдВрдЧрд╛ред

рд╣рдо рдЕрдкрдиреЗ рд╕рд░реНрд╡рд░ рдХреЗ рдореБрдЦреНрдп "рд╡рд░реНрдХрд╣реЙрд░реНрд╕" рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ: CClient рд╡рд░реНрдЧ рдХреЛред
CClient рдХреНрд▓рд╛рд╕ рдХреЛ рди рдХреЗрд╡рд▓ рдЕрдкрдиреЗ рд╕реЙрдХреЗрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдмрд▓реНрдХрд┐ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рдЙрд╕рдХрд╛ рдЗрдВрдЯрд░реЗрдХреНрд╢рди рдХрд┐рд╕ рд╕реНрдЯреЗрдЬ рдкрд░ рд╣реИ, рдЗрд╕рдХреА рднреА рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
CClient рд╡рд░реНрдЧ рдкрд░рд┐рднрд╛рд╖рд╛ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдЬреЛрдбрд╝реЗрдВ:
  private: //    .     . enum STATES { S_ACCEPTED_TCP, S_ACCEPTED_SSL, S_READING, S_ALL_READED, S_WRITING, S_ALL_WRITED }; STATES m_stateCurrent; //    //      void SetState(const STATES state) {m_stateCurrent = state;} const STATES GetState() const {return m_stateCurrent;} public: //      const bool Continue() { if (m_hSocket == INVALID_SOCKET) return false; switch (GetState()) { case S_ACCEPTED_TCP: break; case S_ACCEPTED_SSL: break; case S_READING: break; case S_ALL_READED: break; case S_WRITING: break; case S_ALL_WRITED: break; default: return false; } return true; } 


рдпрд╣рд╛рдВ рдЬрд╛рд░реА рд╣реИ () рдЕрднреА рднреА рд╕рд┐рд░реНрдл рдПрдХ рд╕реНрдЯрдм рдлрд╝рдВрдХреНрд╢рди рд╣реИ, рдереЛрдбрд╝рд╛ рдХрдо рд╣рдо рдЗрд╕реЗ рд╕рд┐рдЦрд╛рдПрдВрдЧреЗ рдХрд┐ рдХреИрд╕реЗ рдПрдХ рдХрдиреЗрдХреНрдЯреЗрдб рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд╕рд╛рде рд╕рднреА рдХреНрд░рд┐рдпрд╛рдПрдВ рдХрд░реЗрдВред

рдирд┐рд░реНрдорд╛рддрд╛ рдореЗрдВ, рдмрджрд▓реЗрдВ:
 CClient(const SOCKET hSocket) : m_hSocket(hSocket), m_pSSL(NULL), m_pSSLContext(NULL) 

рдкрд░
 CClient(const SOCKET hSocket) : m_hSocket(hSocket), m_pSSL(NULL), m_pSSLContext(NULL), m_stateCurrent(S_ACCEPTED_TCP) 


рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдЧреНрд░рд╛рд╣рдХ рд╡рд┐рднрд┐рдиреНрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред рд╣рдо рдЗрд╕ рдмрд╛рдд рд╕реЗ рд╕рд╣рдордд рд╣реИрдВ рдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реНрдЯреЗрдЯреНрд╕ рдХреЛ рдХреЗрд╡рд▓ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдФрд░ рдХрдВрдЯрд┐рдиреНрдпреВ () рдлрдВрдХреНрд╢рди рдореЗрдВ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд╕реЗ рдХреЛрдб рдХрд╛ рдЖрдХрд╛рд░ рдереЛрдбрд╝рд╛ рдмрдврд╝ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдпрд╣ рдЗрд╕рдХреЗ рдбреАрдмрдЧрд┐рдВрдЧ рдореЗрдВ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛ рджреЗрдЧрд╛ред

рддреЛ рдкрд╣рд▓рд╛ рд╕реНрдЯреЗрдЯ рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдмрдирд╛рдП рдЬрд╛рдиреЗ рдкрд░ рдорд┐рд▓рддрд╛ рд╣реИ: S_ACCEPTED_TCPред
рд╣рдо рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рджреНрд╡рд╛рд░рд╛ рддрдм рддрдХ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм рддрдХ рдХрд┐ рдЙрд╕рдХреЗ рдкрд╛рд╕ рдпрд╣ рд╕реНрдерд┐рддрд┐ рди рд╣реЛ:
рдЗрд╕ рд▓рд╛рдЗрди рдХреЗ рд▓рд┐рдП:
  case S_ACCEPTED_TCP: break; 


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░реЗрдВ:
  case S_ACCEPTED_TCP: { switch (AcceptSSL()) { case RET_READY: printf ("SSL connection using %s\n", SSL_get_cipher (m_pSSL)); SetState(S_ACCEPTED_SSL); break; case RET_ERROR: return false; } return true; } 


рдФрд░ CClient рд╡рд░реНрдЧ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рднреА рдЬреЛрдбрд╝реЗрдВ:
  private: enum RETCODES { RET_WAIT, RET_READY, RET_ERROR }; const RETCODES AcceptSSL() { if (!m_pSSLContext) //     SSL return RET_ERROR; if (!m_pSSL) { m_pSSL = SSL_new (m_pSSLContext); if (!m_pSSL) return RET_ERROR; SSL_set_fd (m_pSSL, m_hSocket); } const int err = SSL_accept (m_pSSL); const int nCode = SSL_get_error(m_pSSL, err); if ((nCode != SSL_ERROR_WANT_READ) && (nCode != SSL_ERROR_WANT_WRITE)) return RET_READY; return RET_WAIT; } 


рдЕрдм AcceptSSL () рдлрд╝рдВрдХреНрд╢рди рдХреНрд▓рд╛рдЗрдВрдЯ рджреНрд╡рд╛рд░рд╛ рддрдм рддрдХ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм рддрдХ рдХрд┐ рдПрдХ рдПрдиреНрдХреНрд░рд┐рдкреНрдЯреЗрдб рдХрдиреЗрдХреНрд╢рди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдпрд╛ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИред

1. рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, CClient :: AcceptSSL () рдлрд╝рдВрдХреНрд╢рди RET_ERROR рдХреЛрдб рдХреЛ CClient :: Continue () рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдХреЙрд▓ рдХрд░реЗрдЧрд╛, рдЬреЛ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ CServer :: рдХреЙрд▓ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЧрд▓рдд рд▓реМрдЯрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдиреЗ рдЗрд╕реЗ рдХреЙрд▓ рдХрд┐рдпрд╛ рд╣реИ, рдЬреЛ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╕рд░реНрд╡рд░ рдХреА рдореЗрдореЛрд░реА рд╕реЗ рд╣рдЯрд╛ рджреЗрдЧрд╛ред
2. рдпрджрд┐ рдХрдиреЗрдХреНрд╢рди рд╕рдлрд▓ рд╣реЛрддрд╛ рд╣реИ, CClient :: AcceptSSL () рдлрд╝рдВрдХреНрд╢рди RET_READY рдХреЛрдб рдХреЛ CClient :: Continue () рдлрд╝рдВрдХреНрд╢рди рдкрд░ рд▓реМрдЯрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдиреЗ рдЗрд╕реЗ рдХреЙрд▓ рдХрд┐рдпрд╛ рд╣реИ, рдЬреЛ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реНрдерд┐рддрд┐ рдХреЛ S_ACCEEDED_SSL рдореЗрдВ рдмрджрд▓ рджреЗрдЧрд╛ред

рдЕрдм рд░рд╛рдЬреНрдп рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдлрд╝рдВрдХреНрд╢рди S_ACCEPTED_SSL рдЬреЛрдбрд╝реЗрдВред рдЗрд╕ рд▓рд╛рдЗрди рдХреЗ рд▓рд┐рдП
 case S_ACCEPTED_SSL: break; 


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЗ рд▓рд┐рдП рдареАрдХ рдХрд░реЗрдВ:
  case S_ACCEPTED_SSL: { switch (GetSertificate()) { case RET_READY: SetState(S_READING); break; case RET_ERROR: return false; } return true; } 


рдФрд░ CClient рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЬреЛрдбрд╝реЗрдВ:
  const RETCODES GetSertificate() { if (!m_pSSLContext || !m_pSSL) //     SSL return RET_ERROR; /* Get client's certificate (note: beware of dynamic allocation) - opt */ X509* client_cert = SSL_get_peer_certificate (m_pSSL); if (client_cert != NULL) { printf ("Client certificate:\n"); char* str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); if (!str) return RET_ERROR; printf ("\t subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); if (!str) return RET_ERROR; printf ("\t issuer: %s\n", str); OPENSSL_free (str); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free (client_cert); } else printf ("Client does not have certificate.\n"); return RET_READY; } 


рдпрд╣ рдлрд╝рдВрдХреНрд╢рди, рдкрд┐рдЫрд▓реЗ рдПрдХ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ RET_ERROR рдпрд╛ RET_READY рдХреЛ CClient :: Continue рдкрд░ рд▓реМрдЯрд╛рдПрдЧрд╛ред рддрджрдиреБрд╕рд╛рд░, CClient :: рдЬрд╛рд░реА рдпрд╛ рддреЛ рдЧрд▓рдд рд╣реЛ рдЬрд╛рдПрдЧрд╛ рдпрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ S_READING рдкрд░ рдмрджрд▓ рджреЗрдЧрд╛ред

рдлрд┐рд░ рд╕рдм рдХреБрдЫ рд╕рдорд╛рди рд╣реИ: рдХреЛрдб рдмрджрд▓реЗрдВ
  case S_READING: break; case S_ALL_READED: break; case S_WRITING: break; 


рдЗрд╕ рдкрд░:
  case S_READING: { switch (ContinueRead()) { case RET_READY: SetState(S_ALL_READED); break; case RET_ERROR: return false; } return true; } case S_ALL_READED: { switch (InitRead()) { case RET_READY: SetState(S_WRITING); break; case RET_ERROR: return false; } return true; } case S_WRITING: { switch (ContinueWrite()) { case RET_READY: SetState(S_ALL_WRITED); break; case RET_ERROR: return false; } return true; } 


рдФрд░ рдЗрд╕реА рд░рд╛рдЬреНрдп рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ:
  const RETCODES ContinueRead() { if (!m_pSSLContext || !m_pSSL) //     SSL return RET_ERROR; unsigned char szBuffer[4096]; const int err = SSL_read (m_pSSL, szBuffer, 4096); //      if (err > 0) { //     m_vRecvBuffer m_vRecvBuffer.resize(m_vRecvBuffer.size()+err); memcpy(&m_vRecvBuffer[m_vRecvBuffer.size()-err], szBuffer, err); //  http     const std::string strInputString((const char *)&m_vRecvBuffer[0]); if (strInputString.find("\r\n\r\n") != -1) return RET_READY; return RET_WAIT; } const int nCode = SSL_get_error(m_pSSL, err); if ((nCode != SSL_ERROR_WANT_READ) && (nCode != SSL_ERROR_WANT_WRITE)) return RET_ERROR; return RET_WAIT; } const RETCODES InitRead() { if (!m_pSSLContext || !m_pSSL) //     SSL return RET_ERROR; //      const std::string strInputString((const char *)&m_vRecvBuffer[0]); // html     const std::string strHTML = "<html><body><h2>Hello! Your HTTP headers is:</h2><br><pre>" + strInputString.substr(0, strInputString.find("\r\n\r\n")) + "</pre></body></html>"; //    http  std::ostringstream strStream; strStream << "HTTP/1.1 200 OK\r\n" << "Content-Type: text/html; charset=utf-8\r\n" << "Content-Length: " << strHTML.length() << "\r\n" << "\r\n" << strHTML.c_str(); // ,    m_vSendBuffer.resize(strStream.str().length()); memcpy(&m_vSendBuffer[0], strStream.str().c_str(), strStream.str().length()); return RET_READY; } const RETCODES ContinueWrite() { if (!m_pSSLContext || !m_pSSL) //     SSL return RET_ERROR; int err = SSL_write (m_pSSL, &m_vSendBuffer[0], m_vSendBuffer.size()); if (err > 0) { //    ,      if (err == m_vSendBuffer.size()) return RET_READY; //    ,      ,     vector<unsigned char> vTemp(m_vSendBuffer.size()-err); memcpy(&vTemp[0], &m_vSendBuffer[err], m_vSendBuffer.size()-err); m_vSendBuffer = vTemp; return RET_WAIT; } const int nCode = SSL_get_error(m_pSSL, err); if ((nCode != SSL_ERROR_WANT_READ) && (nCode != SSL_ERROR_WANT_WRITE)) return RET_ERROR; return RET_WAIT; } 


рд╣рдорд╛рд░рд╛ рд╕рд░реНрд╡рд░ рдЕрдм рддрдХ рдХреЗрд╡рд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЙрд╕рдХреЗ http рдЕрдиреБрд░реЛрдз рдХреЗ рд╢реАрд░реНрд╖ рд▓реЗрдЦ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИред
рд╕рд░реНрд╡рд░ рдиреЗ рдЕрдкрдиреЗ рдЙрджреНрджреЗрд╢реНрдп рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдХрдиреЗрдХреНрд╢рди рдмрдВрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреВрд▓ рд╕рдХрддрд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рдЕрдВрддрд┐рдо рдЫреЛрдЯрд╛ рдкрд░рд┐рд╡рд░реНрддрди рд╣рдорд╛рд░реЗ рдХреЛрдб рдореЗрдВ рд░рд╣рддрд╛ рд╣реИ:
 case S_ALL_WRITED: break; 


рдареАрдХ рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ
  case S_ALL_WRITED: return false; 


рд╡рд╣ рд╕рдм рд╣реИ! рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдиреЙрди-рдмреНрд▓реЙрдХрд┐рдВрдЧ рд╕реЙрдХреЗрдЯреНрд╕ рдкрд░ рдПрдХ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╕рд┐рдВрдЧрд▓-рдереНрд░реЗрдбреЗрдб https рд╕рд░реНрд╡рд░ рд╣реИ, рдЬреЛ рдХрдиреЗрдХреНрд╢рди рдХреА рдПрдХ рдордирдорд╛рдиреА (рдХреЗрд╡рд▓ рдореЗрдореЛрд░реА рдФрд░ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рджреНрд╡рд╛рд░рд╛ рд╕реАрдорд┐рдд) рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХрддрд╛ рд╣реИред

рд╡рд┐рдЬрд╝реБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ 2012 рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд╕рд╛рде рд╕рдВрдЧреНрд░рд╣ рдпрд╣рд╛рдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: 01.3s3s.org
рд▓рд┐рдирдХреНрд╕ рдкрд░ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдХреЙрдкреА рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: serv.cpp, server.h, ca-cert.pem рдФрд░ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдореЗрдВ рдЯрд╛рдЗрдк рдХрд░реЗрдВ: "g ++ -std = c ++ 0x -L / usr / lib -lssl -lcrypto рд╕рд░реНрд╡" .cpp ┬╗

рд╡рд┐рд╕реНрддрд╛рд░

Source: https://habr.com/ru/post/In211853/


All Articles