Complete real-life example usage that might be useful
```d
#!/usr/bin/env -S gdc -run -lssl -lcrypto
// gcc -E -P '-D__restrict= ' '-D__extension__= ' '-D__asm__(x)=
' -std=c11 /usr/include/openssl/ssl.h > ssl.i
// gcc -E -P '-D__restrict= ' '-D__extension__= ' '-D__asm__(x)=
' -std=c11 /usr/include/openssl/err.h > err.i
//
// gdc example.d -lssl -lcrypto
//
// You can ignore most warnings about
// - conflicting types for built-in function ‘vsscanf’ and
similar
// they are harmless to big extent.
import core.sys.posix.sys.socket;
import core.sys.posix.netinet.in_;
import core.sys.posix.arpa.inet;
import core.sys.posix.netdb : hostent, gethostbyname;
import core.sys.posix.unistd;
import core.stdc.string : memcpy;
import core.stdc.stdio : stderr;
import core.stdc.stdlib;
import std.string : toStringz;
// Explicitly define missing constants
enum SSL_VERIFY_PEER = 0x01;
enum SSL_VERIFY_NONE = 0x00;
enum SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 0x02;
enum SSL_CTRL_SET_TLSEXT_HOSTNAME = 55; // Defined in OpenSSL
enum TLSEXT_NAMETYPE_host_name = 0x0; // Defined in OpenSSL
void main() {
import ssl;
import err;
SSL_METHOD* method = TLS_client_method();
SSL_CTX* ctx = SSL_CTX_new(method);
if (ctx is null) {
ERR_print_errors_fp(cast(_IO_FILE*)stderr);
return;
}
scope(exit) SSL_CTX_free(ctx);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, null);
SSL_CTX_set_default_verify_paths(ctx);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
return;
}
scope(exit) close(sock);
string hostname = "example.com";
hostent* host = gethostbyname(toStringz(hostname));
if (host is null) {
perror("gethostbyname");
return;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(443);
// Copy first IP address
memcpy(&addr.sin_addr, host.h_addr_list[0], host.h_length);
if (connect(sock, cast(sockaddr*)&addr, sockaddr_in.sizeof) !=
0) {
return;
}
SSL* s = SSL_new(ctx);
scope(exit) SSL_free(s);
SSL_set_fd(s, sock);
// SSL_CTX_set_tlsext_host_name is a macro, so lets expand
things.
if (SSL_ctrl(s, SSL_CTRL_SET_TLSEXT_HOSTNAME,
TLSEXT_NAMETYPE_host_name, cast(void*)toStringz(hostname)) != 1) {
ERR_print_errors_fp(cast(_IO_FILE*)stderr);
return;
}
if (SSL_connect(s) <= 0) {
ERR_print_errors_fp(cast(_IO_FILE*)stderr);
return;
}
scope(exit) SSL_shutdown(s);
string request =
"GET / HTTP/1.1\r\n" ~
"Host: example.com\r\n" ~
"Connection: close\r\n\r\n";
SSL_write(s, request.ptr, cast(int)request.length);
ubyte[4096] buffer;
int bytes;
while ((bytes = SSL_read(s, buffer.ptr, buffer.length)) > 0) {
fwrite(buffer.ptr, 1, bytes, stdout);
}
return;
}
```