1 module ssl.socket;
2 
3 import std.exception;
4 import std.socket;
5 
6 import ssl.openssl;
7 
8 version(force_ssl_load) shared static this()
9 {
10 	loadOpenSSL();
11 }
12 
13 private SSL_CTX* sslContext;
14 
15 void initSslContext()
16 {
17 	if(!sslContext)
18 		sslContext = SSL_CTX_new_p(SSLv23_client_method_p());
19 }
20 
21 version(force_ssl_load) static this()
22 {
23 	initSslContext();
24 }
25 
26 /**
27 * Represents a secure TCP socket using SSLv3.
28 */
29 class SslSocket : Socket
30 {
31 	private:
32 	SSL* ssl;
33 
34 	public:
35 	/**
36 	* Create a new unconnected and blocking SSL socket.
37 	* See_Also:
38 	*   $(DPREF client, IrcClient.this)
39 	*/
40 	this(AddressFamily af)
41 	{
42 		loadOpenSSL();
43 		initSslContext();
44 
45 		super(af, SocketType.STREAM, ProtocolType.TCP);
46 
47 		ssl = SSL_new_p(sslContext);
48 		SSL_set_fd_p(ssl, super.handle);
49 		SSL_set_verify_p(ssl, SSL_VERIFY_NONE, null);
50 	}
51 
52 	override:
53 	void connect(Address to) @trusted
54 	{
55 		super.connect(to);
56 		sslEnforce(ssl, SSL_connect_p(ssl));
57 	}
58 
59 	ptrdiff_t receive(void[] buf)
60 	{
61 		return receive(buf, SocketFlags.NONE);
62 	}
63 
64 	ptrdiff_t receive(void[] buf, SocketFlags flags) @trusted
65 	{
66 		auto result = sslEnforce(ssl, SSL_read_p(ssl, buf.ptr, cast(int)buf.length));
67 		return cast(ptrdiff_t)result;
68 	}
69 
70 	ptrdiff_t send(const(void)[] buf)
71 	{
72 		return send(buf, SocketFlags.NONE);
73 	}
74 
75 	ptrdiff_t send(const(void)[] buf, SocketFlags flags) @trusted
76 	{
77 		auto result = sslEnforce(ssl, SSL_write_p(ssl, buf.ptr, cast(int)buf.length));
78 		return cast(ptrdiff_t)result;
79 	}
80 
81 	// TODO: What about sendTo? Throwing stub?
82 }
83