--- Begin Message ---
Hello,
I have some question:
http://h71000.www7.hp.com/doc/83final/ba554_90007/ch04s03.html
What part is global, what part need be do by connexion?
On that's:
https://github.com/alphaonex86/CatchChallenger/blob/master/tools/epoll-with-buffer/main.cpp
I have edited it to try do simple echo server.
The handshake work, but no the echo (don't read any thing).
I try do a sample how do epoll server with SSL support (not found on internet).
And remake this graphic, and comment the code to match with this graphic. And
into C++...
I need too maximum of performance (no client cert), non blocking ops.
Thanks for your help.
--
alpha_one_x86 <alpha_one_...@first-world.info>
Main developer of Ultracopier, Esourcing and server management
IT, OS, technologies, security and business department
#include <sys/epoll.h>
#include <errno.h>
#include <iostream>
#include <list>
#include <sys/socket.h>
#include <netdb.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include "Client.h"
#include "Socket.h"
#include "Server.h"
#include "Epoll.h"
#include "Timer.h"
#include "TimerDisplayEventBySeconds.h"
#define MAXEVENTS 512
#define MAXCLIENT 6000
SSL_CTX* InitServerCTX(void)
{
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
const SSL_METHOD *method = TLSv1_2_server_method(); /* create new server-method instance */
SSL_CTX *ctx = SSL_CTX_new(method); /* create new context from method */
if(ctx == NULL)
{
ERR_print_errors_fp(stderr);
abort();
}
return ctx;
}
void LoadCertificates(SSL_CTX* ctx, const char* CertFile, const char* KeyFile)
{
SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE,NULL);
SSL_CTX_load_verify_locations(ctx,"/home/user/Desktop/CatchChallenger/test/openssl-server/cacert.pem",NULL);
/* set the local certificate from CertFile */
if(SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM)<=0)
{
ERR_print_errors_fp(stderr);
abort();
}
/* set the private key from KeyFile (may be the same as CertFile) */
if(SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM)<=0)
{
ERR_print_errors_fp(stderr);
abort();
}
/* verify private key */
if(!SSL_CTX_check_private_key(ctx))
{
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
}
int main(int argc, char *argv[])
{
SSL_library_init(); /* load encryption & hash algorithms for SSL */
SSL_load_error_strings(); /* load the error strings for good error reporting */
SSL_CTX *ctx = InitServerCTX(); /* initialize SSL */
LoadCertificates(ctx, "/home/user/Desktop/CatchChallenger/test/openssl-server/server.crt", "/home/user/Desktop/CatchChallenger/test/openssl-server/server.key"); /* load certs */
SSL *ssl = SSL_new(ctx);
if(argc != 2)
{
fprintf(stderr, "Usage: %s [port]\n", argv[0]);
exit(EXIT_FAILURE);
}
if(!Epoll::epoll.init())
abort();
Server server;
if(!server.tryListen(argv[1]))
abort();
TimerDisplayEventBySeconds timerDisplayEventBySeconds;
if(!timerDisplayEventBySeconds.init())
abort();
char buf[512];
/* Buffer where events are returned */
epoll_event events[MAXEVENTS];
Client* clients[MAXCLIENT];
int clientListSize=0;
/* The event loop */
int number_of_events, i;
while(1)
{
number_of_events = Epoll::epoll.wait(events, MAXEVENTS);
for(i = 0; i < number_of_events; i++)
{
switch(static_cast<BaseClassSwitch *>(events[i].data.ptr)->getType())
{
case BaseClassSwitch::Type::Server:
{
if((events[i].events & EPOLLERR) ||
(events[i].events & EPOLLHUP) ||
(!(events[i].events & EPOLLIN) && !(events[i].events & EPOLLOUT)))
{
/* An error has occured on this fd, or the socket is not
ready for reading (why were we notified then?) */
fprintf(stderr, "server epoll error\n");
continue;
}
/* We have a notification on the listening socket, which
means one or more incoming connections. */
while(1)
{
if(clientListSize>=MAXCLIENT)
break;
sockaddr in_addr;
socklen_t in_len = sizeof(in_addr);
const int &infd = server.accept(&in_addr, &in_len);
if(infd == -1)
{
if((errno == EAGAIN) ||
(errno == EWOULDBLOCK))
{
/* We have processed all incoming
connections. */
break;
}
else
{
perror("accept");
break;
}
}
BIO* bioIn = BIO_new(BIO_s_mem());
BIO* bioOut = BIO_new(BIO_s_mem());
SSL_set_bio(ssl, bioIn, bioOut);
int err = SSL_accept(ssl);
//just for informations
{
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
const int &s = getnameinfo(&in_addr, in_len,
hbuf, sizeof hbuf,
sbuf, sizeof sbuf,
NI_NUMERICHOST | NI_NUMERICSERV);
if(s == 0)
printf("Accepted connection on descriptor %d (host=%s, port=%s)\n", infd, hbuf, sbuf);
}
/* Make the incoming socket non-blocking and add it to the
list of fds to monitor. */
Client *client=new Client();
client->infd=infd;
client->bioIn=bioIn;
client->bioOut=bioOut;
clients[clientListSize]=client;
clientListSize++;
int s = Socket::make_non_blocking(infd);
if(s == -1)
abort();
epoll_event event;
event.data.ptr = client;
event.events = EPOLLIN | EPOLLET | EPOLLOUT;
s = Epoll::epoll.ctl(EPOLL_CTL_ADD, infd, &event);
if(s == -1)
{
perror("epoll_ctl");
abort();
}
}
continue;
}
break;
case BaseClassSwitch::Type::Client:
{
timerDisplayEventBySeconds.addCount();
Client *client=static_cast<Client *>(events[i].data.ptr);
if ((events[i].events & EPOLLERR) ||
(events[i].events & EPOLLHUP) ||
(!(events[i].events & EPOLLIN) && !(events[i].events & EPOLLOUT)))
{
/* An error has occured on this fd, or the socket is not
ready for reading (why were we notified then?) */
fprintf(stderr, "client epoll error\n");
client->close();
continue;
}
//ready to read
if(events[i].events & EPOLLIN)
{
/* We have data on the fd waiting to be read. Read and
display it. We must read whatever data is available
completely, as we are running in edge-triggered mode
and won't get a notification again for the same
data. */
while (1)
{
const ssize_t &count = client->read(buf,sizeof(buf));
int bufferUsed = BIO_write(client->bioIn, buf, count);
if(bufferUsed == -1 || bufferUsed == -2 || bufferUsed == 0)
{
// error
}
int bytesOut = SSL_read(ssl, (void*)buf, sizeof(buf));
if(bytesOut > 0)
{
}
else
{
if (SSL_want_read(ssl))
{
std::cout << "SSL_want_read" << std::endl;
}
else
{
int32_t ssl_error = SSL_get_error(ssl, bytesOut);
switch (ssl_error) {
case SSL_ERROR_NONE:
printf("SSL_ERROR_NONE\n");
break;
case SSL_ERROR_WANT_READ:
printf("SSL_ERROR_WANT_READ\n");
break;
case SSL_ERROR_WANT_WRITE:
printf("SSL_ERROR_WANT_WRITE\n");
break;
case SSL_ERROR_ZERO_RETURN:
printf("SSL_ERROR_ZERO_RETURN\n");
break;
default:
break;
}
break;
}
if (!client->bHandShakeOver && SSL_is_init_finished(ssl))
{
std::cout << "Handshake has been finished" << std::endl;
client->bHandShakeOver = true;
char cipdesc[128];
const SSL_CIPHER* sc = SSL_get_current_cipher(ssl);
if (sc)
std::cout << "encryption: " << SSL_CIPHER_description(sc, cipdesc, sizeof(cipdesc)) << std::endl;
}
}
while (1)
{
// BIO_ctrl_pending() returns the number of bytes buffered in a BIO.
size_t pending = BIO_ctrl_pending(client->bioOut);
if (pending > 0)
{
std::cout << "BIO_ctrl_pending(bioOut) == " << pending << std::endl;
// BIO_read() attempts to read len bytes from BIO b and places the data in buf.
int bytesToSend = BIO_read(client->bioOut, (void*)buf, sizeof(buf) > pending ? pending : sizeof(buf));
if (bytesToSend > 0)
{
std::cout << "BIO_read(bioOut) == " << bytesToSend << std::endl;
ssize_t nRet = client->write(buf, bytesToSend);
if(nRet<0)
{
//bReplyOver = true;
std::cerr << "send() - SOCKET_ERROR" << std::endl;
}
}
else if (!BIO_should_retry(client->bioOut))
{// BIO_should_retry() is true if the call that produced this condition should then be retried at a later time.
//reportError(ssl, bytesToSend);
}
}
else
{
std::cout << "BIO_ctrl_pending(bioOut) == 0" << std::endl;
break;
}
}
/*if (bReplyOver)
{
std::cout << "post-reply" << std::endl;
break;
}*/
if(count>0)
{
//broadcast to all the client
/*int index=0;
while(index<clientListSize)
{
clients[index]->write(buf,count);
index++;
}*/
}
else
break;
}
}
//ready to write
if(events[i].events & EPOLLOUT)
{
client->flush();
}
}
break;
case BaseClassSwitch::Type::Timer:
static_cast<Timer *>(events[i].data.ptr)->exec();
break;
default:
fprintf(stderr, "unknown event\n");
break;
}
}
}
server.close();
return EXIT_SUCCESS;
}
signature.asc
Description: This is a digitally signed message part.
--- End Message ---