introduce-ssl-client-connections--flow-control.patch

Signed-off-by: Andy Green <andy@warmcat.com>
diff --git a/lib/client-handshake.c b/lib/client-handshake.c
index 64f72cb..e93ce99 100644
--- a/lib/client-handshake.c
+++ b/lib/client-handshake.c
@@ -9,8 +9,10 @@
 void
 strtolower(char *s)
 {
-	while (*s)
-		*s++ = tolower(*s);
+	while (*s) {
+		*s = tolower(*s);
+		s++;
+	}
 }
 
 void
@@ -53,7 +55,7 @@
 	/* shut down reasonably cleanly */
 
 #ifdef LWS_OPENSSL_SUPPORT
-	if (use_ssl) {
+	if (wsi->ssl) {
 		n = SSL_get_fd(wsi->ssl);
 		SSL_shutdown(wsi->ssl);
 		close(n);
@@ -67,10 +69,29 @@
 #endif
 }
 
+
+/**
+ * libwebsocket_client_connect() - Connect to another websocket server
+ * @this:	Websocket context
+ * @address:	Remote server address, eg, "myserver.com"
+ * @port:	Port to connect to on the remote server, eg, 80
+ * @ssl_connection:	0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
+ *			signed certs
+ * @path:	Websocket path on server
+ * @host:	Hostname on server
+ * @origin:	Socket origin name
+ * @protocol:	Comma-separated list of protocols being asked for from
+ *		the server, or just one.  The server will pick the one it
+ *		likes best.
+ *
+ *	This function creates a connection to a remote server
+ */
+
 struct libwebsocket *
-libwebsocket_client_connect(struct libwebsocket_context *clients,
+libwebsocket_client_connect(struct libwebsocket_context *this,
 			      const char *address,
 			      int port,
+			      int ssl_connection,
 			      const char *path,
 			      const char *host,
 			      const char *origin,
@@ -94,12 +115,22 @@
 	int okay = 0;
 	struct libwebsocket *wsi;
 	int n;
+#ifdef LWS_OPENSSL_SUPPORT
+	char ssl_err_buf[512];
+#else
+	if (ssl_connection) {
+		fprintf(stderr, "libwebsockets not configured for ssl\n");
+		return NULL;
+	}
+#endif
 
 	wsi = malloc(sizeof(struct libwebsocket));
-	if (wsi == NULL)
+	if (wsi == NULL) {
+		fprintf(stderr, "Out of memort allocing new connection\n");
 		return NULL;
+	}
 
-	clients->wsi[clients->fds_count] = wsi;
+	this->wsi[this->fds_count] = wsi;
 
 	wsi->ietf_spec_revision = 4;
 	wsi->name_buffer_pos = 0;
@@ -137,10 +168,36 @@
 
 	if (connect(wsi->sock, (struct sockaddr *)&server_addr,
 					      sizeof(struct sockaddr)) == -1)  {
-		fprintf(stderr, "Connect failed");
+		fprintf(stderr, "Connect failed\n");
 		goto bail1;
 	}
 
+#ifdef LWS_OPENSSL_SUPPORT
+	if (ssl_connection) {
+
+		wsi->ssl = SSL_new(this->ssl_client_ctx);
+		wsi->client_bio = BIO_new_socket(wsi->sock, BIO_NOCLOSE);
+		SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
+
+		if (SSL_connect(wsi->ssl) <= 0) {
+			fprintf(stderr, "SSL connect error %s\n",
+				ERR_error_string(ERR_get_error(), ssl_err_buf));
+			goto bail2;
+		}
+
+		n = SSL_get_verify_result(wsi->ssl);
+		if (n != X509_V_OK) {
+			if (n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
+							    ssl_connection == 2)
+				goto cert_okay;
+
+		    fprintf(stderr, "server's cert didn't look good %d\n", n);
+		    goto bail2;
+		}
+	} else
+		wsi->ssl = NULL;
+cert_okay:
+#endif
 	/*
 	 * create the random key
 	 */
@@ -199,7 +256,17 @@
 
 	/* send our request to the server */
 
-	n = send(wsi->sock, pkt, p - pkt, 0);
+#ifdef LWS_OPENSSL_SUPPORT
+	if (ssl_connection)
+		n = SSL_write(wsi->ssl, pkt, p - pkt);
+	else
+#endif
+		n = send(wsi->sock, pkt, p - pkt, 0);
+
+	if (n < 0) {
+		fprintf(stderr, "ERROR writing to client socket\n");
+		goto bail2;
+	}
 
 	wsi->parser_state = WSI_TOKEN_NAME_PART;
 
@@ -230,7 +297,13 @@
 	 *  Sec-WebSocket-Protocol: chat
 	 */
 
-	len = recv(wsi->sock, pkt, sizeof pkt, 0);
+#ifdef LWS_OPENSSL_SUPPORT
+	if (ssl_connection)
+		len = SSL_read(wsi->ssl, pkt, sizeof pkt);
+	else
+#endif
+		len = recv(wsi->sock, pkt, sizeof pkt, 0);
+
 	if (len < 0) {
 		fprintf(stderr, "libwebsocket_client_handshake read error\n");
 		goto bail2;
@@ -300,7 +373,7 @@
 	if (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len) {
 
 		/* no protocol name to work from, default to first protocol */
-		wsi->protocol = &clients->protocols[0];
+		wsi->protocol = &this->protocols[0];
 
 		goto check_accept;
 	}
@@ -331,10 +404,10 @@
 	 */
 	n = 0;
 	wsi->protocol = NULL;
-	while (clients->protocols[n].callback) {
+	while (this->protocols[n].callback) {
 		if (strcmp(wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
-				       clients->protocols[n].name) == 0)
-			wsi->protocol = &clients->protocols[n];
+				       this->protocols[n].name) == 0)
+			wsi->protocol = &this->protocols[n];
 		n++;
 	}
 
@@ -373,15 +446,21 @@
 
 	/* okay he is good to go */
 
-	clients->fds[clients->fds_count].fd = wsi->sock;
-	clients->fds[clients->fds_count].revents = 0;
-	clients->fds[clients->fds_count++].events = POLLIN;
+	this->fds[this->fds_count].fd = wsi->sock;
+	this->fds[this->fds_count].revents = 0;
+	this->fds[this->fds_count++].events = POLLIN;
 
 	wsi->state = WSI_STATE_ESTABLISHED;
 	wsi->client_mode = 1;
 
 	fprintf(stderr, "handshake OK for protocol %s\n", wsi->protocol->name);
 
+	/* call him back to inform him he is up */
+
+	wsi->protocol->callback(wsi,
+			 LWS_CALLBACK_CLIENT_ESTABLISHED,
+			 wsi->user_space,
+			 NULL, 0);
 	return wsi;