dsk_boolean dsk_ssl_stream_new (DskSslStreamOptions *options, DskSslStream **stream_out, DskOctetSource **source_out, DskOctetSink **sink_out, DskError **error) { DskSslStream *stream; DskSslSink *sink; DskSslSource *source; if (sink_out == NULL || source_out == NULL) { dsk_set_error (error, "dsk_ssl_stream_new: sink/source"); return DSK_FALSE; } sink = dsk_object_new (&dsk_ssl_sink_class); source = dsk_object_new (&dsk_ssl_source_class); stream = dsk_object_new (&dsk_ssl_stream_class); BIO *bio; bio = BIO_new (&bio_method__ssl_underlying_stream); bio->ptr = stream; bio->init = 1; /// HMM... stream->ssl = SSL_new (options->context->ctx); stream->context = dsk_object_ref (options->context); SSL_set_bio (stream->ssl, bio, bio); stream->base_instance.sink = DSK_OCTET_SINK (sink); /* does not own */ stream->base_instance.source = DSK_OCTET_SOURCE (source); /* does not own */ stream->is_client = options->is_client ? 1 : 0; stream->handshaking = DSK_TRUE; sink->base_instance.stream = dsk_object_ref (stream); source->base_instance.stream = dsk_object_ref (stream); if (stream->is_client) SSL_set_connect_state (stream->ssl); else SSL_set_accept_state (stream->ssl); *sink_out = DSK_OCTET_SINK (sink); *source_out = DSK_OCTET_SOURCE (source); if (stream_out != NULL) *stream_out = stream; else dsk_object_unref (stream); return DSK_TRUE; }
static void begin_connecting (DskClientStream *stream) { if (stream->is_local_socket) { struct sockaddr_un addr; unsigned length = strlen (stream->name); if (length > sizeof (addr.sun_path)) { /* name too long */ /* TODO: catch this in constructor */ dsk_octet_stream_set_last_error (&stream->base_instance, "name too long for local socket"); return; } addr.sun_family = AF_LOCAL; memcpy (addr.sun_path, stream->name, length == sizeof (addr.sun_path) ? length : length + 1); begin_connecting_sockaddr (stream, sizeof (addr), (struct sockaddr *) &addr); } else if (stream->is_numeric_name) { struct sockaddr_storage addr; unsigned addr_len; DskIpAddress address; /* parse name into addr/addr_len */ if (!dsk_ip_address_parse_numeric (stream->name, &address)) dsk_die ("dsk_ip_address_parse_numeric failed on %s", stream->name); dsk_ip_address_to_sockaddr (&address, stream->port, &addr, &addr_len); begin_connecting_sockaddr (stream, addr_len, (struct sockaddr *) &addr); } else { /* begin dns lookup */ stream->is_resolving_name = 1; dsk_object_ref (stream); dsk_dns_lookup (stream->name, DSK_FALSE, /* is_ipv6? should be be needed */ handle_dns_done, stream); } }
dsk_boolean dsk_client_stream_new (DskClientStreamOptions *options, DskClientStream **stream_out, DskOctetSink **sink_out, DskOctetSource **source_out, DskError **error) { DskClientStream *rv; dsk_boolean has_address = !ip_address_is_default (&options->address); /* check trivial usage considerations */ dsk_warn_if_fail (!(options->hostname != NULL && has_address), "ignoring ip-address because symbolic name given"); if (options->hostname != NULL || has_address) { if (options->port == 0) { dsk_set_error (error, "port must be non-zero for client (hostname is '%s')", options->hostname); return DSK_FALSE; } dsk_warn_if_fail (options->path == NULL, "cannot decide between tcp and local client"); } rv = dsk_object_new (&dsk_client_stream_class); rv->base_instance.sink = dsk_object_new (&dsk_client_stream_sink_class); rv->base_instance.source = dsk_object_new (&dsk_client_stream_source_class); rv->base_instance.sink->stream = dsk_object_ref (rv); rv->base_instance.source->stream = dsk_object_ref (rv); rv->reconnect_time_ms = -1; rv->idle_disconnect_time_ms = -1; rv->fd = -1; if (options->hostname != NULL) { if (dsk_hostname_looks_numeric (options->hostname)) rv->is_numeric_name = 1; rv->name = dsk_strdup (options->hostname); rv->port = options->port; } else if (has_address) { rv->is_numeric_name = 1; rv->name = dsk_ip_address_to_string (&options->address); rv->port = options->port; } else if (options->path != NULL) { rv->is_local_socket = 1; rv->name = dsk_strdup (options->path); } rv->idle_disconnect_time_ms = options->idle_disconnect_time; rv->reconnect_time_ms = options->reconnect_time; begin_connecting (rv); if (options->idle_disconnect_time >= 0) dsk_client_stream_set_max_idle_time (rv, options->idle_disconnect_time); if (options->reconnect_time >= 0) dsk_client_stream_set_reconnect_time (rv, options->reconnect_time); if (source_out) *source_out = rv->base_instance.source; else if (rv->base_instance.source) dsk_object_unref (rv->base_instance.source); if (sink_out) *sink_out = rv->base_instance.sink; else if (rv->base_instance.sink) dsk_object_unref (rv->base_instance.sink); if (stream_out) *stream_out = rv; else dsk_object_unref (rv); return DSK_TRUE; }