Prototls is a project mainly written in C++ and SHELL, based on the View license.
C++ library for asynchronous client/server communication with GnuTLS
An easy approach to implement portable interprocess communication using Protocol Buffers for data serialization and GnuTLS for security.
This library is distributed under the terms of BSD license. However, in order to use the library, you must also accept the conditions of the licenses of Boost, threadpool, GnuTLS, and Protocol Buffers
The most important features are in place and the implementation is ready for testing. We aim to maintain a version for Windows and for Linux, although we gladly accept contributions to make it run on other platforms, too. Features improving scalability may be added.
package my_protocol;
message Hello {
required string greeting = 1;
}
message ServerMessage {
optional Hello hello = 1;
// ... other message types ...
}
message ClientMessage {
optional Hello hello = 1;
// ... other message types ...
}
and run the protoc code generator:
protoc --cpp_out=. my_protocol.proto
#include "prototls.hpp"
#include "my_protocol.pb.h"
class MyPeer : public prototls::Peer {
public:
// additional connection-specific state and routines
};
class MyServer : public prototls::Server<MyPeer> {
public:
// start 8 threads to perform TLS handshakes simultaneously
MyServer() : prototls::Server<MyPeer>(8) {}
void onPacket(MyPeer&p) {
my_protocol::ClientMessage msg;
p.recv(msg);
std::cout << msg.hello().greeting() << std::endl;
// handle the message
my_protocol::ServerMessage reply;
p.send(reply);
p.flush();
}
void onJoin(MyPeer&p) {
my_protocol::ServerMessage msg;
my_protocol::Hello* hello = msg.mutable_hello();
hello->set_greeting("Welcome!");
p.send(msg);
p.flush();
}
void onLeave(MyPeer&p) {
// clean up
}
};
// server main function
int main(int argc, char** argv) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
prototls::Socket::init();
prototls::TLSSocket::init("", "", "cert.pem", "key.pem");
MyServer server;
// encryption on, serve on port 1234 for at most 1024 peers
server.serve(true, 1234, 1024);
return 0;
}
#include "prototls.hpp"
#include "my_protocol.pb.h"
int main(int argc, char** argv) {
prototls::Socket::init();
prototls::TLSSocket::init("ca-cert.pem", "", "", "");
prototls::TLSSocket* sock = new prototls::TLSSocket();
sock->connect("localhost", 1234);
if (sock->handshake()) {
std::cerr << "Handshake failed" << std::endl;
return -1;
}
prototls::TLSSocket::VerifyResult res;
if (sock->verify(res)) {
std::cerr << " verification failed !" << std::endl;
return -1;
} else {
if (res.distrusted)
std::cout << "certificate not trusted" << std::endl;
if (res.unknownIssuer)
std::cout << "certificate has unknown issuer" << std::endl;
if (res.revoked)
std::cout << "certificate has been revoked" << std::endl;
if (res.expired)
std::cout << "certificate has expired" << std::endl;
if (res.inactive)
std::cout << "certificate is not active" << std::endl;
if (res.invalidCert)
std::cout << "certificate is invalid" << std::endl;
if (res.hostnameMismatch)
std::cout << "hostname does not match" << std::endl;
}
prototls::Peer peer;
peer.setup(sock);
prototls::Select sel;
while (1) {
sel.reset();
sel.input(peer.getFd());
sel.select(1000);
if (sel.canRead(peer.getFd())) {
peer.onInput();
while (peer.hasPacket()) {
my_protocol::ServerMessage msg;
peer.recv(msg);
if (msg.has_hello()) {
std::cout << msg.hello().greeting() << std::endl;
my_protocol::ClientMessage cmsg;
*cmsg.mutable_hello()->mutable_greeting() = "Thanks!";
peer.send(cmsg);
peer.flush();
}
// handle other packet types
}
}
}
return 0;
}