static HttpConn *openConnection(HttpConn *conn, struct MprSsl *ssl) { Http *http; HttpUri *uri; MprSocket *sp; char *ip; int port, rc; assert(conn); http = conn->http; uri = conn->tx->parsedUri; if (!uri->host) { ip = (http->proxyHost) ? http->proxyHost : http->defaultClientHost; port = (http->proxyHost) ? http->proxyPort : http->defaultClientPort; } else { ip = (http->proxyHost) ? http->proxyHost : uri->host; port = (http->proxyHost) ? http->proxyPort : uri->port; } if (port == 0) { port = (uri->secure) ? 443 : 80; } if (conn && conn->sock) { if (conn->keepAliveCount-- <= 0 || port != conn->port || strcmp(ip, conn->ip) != 0 || uri->secure != (conn->sock->ssl != 0) || conn->sock->ssl != ssl) { /* Cannot reuse current socket. Close and open a new one below. */ mprCloseSocket(conn->sock, 0); conn->sock = 0; } else { httpTrace(conn, "connection.reuse", "context", "keepAlive:%d", conn->keepAliveCount); } } if (conn->sock) { return conn; } /* New socket */ if ((sp = mprCreateSocket()) == 0) { httpError(conn, HTTP_ABORT | HTTP_CODE_COMMS_ERROR, "Cannot create socket for %s", httpUriToString(uri, 0)); return 0; } if ((rc = mprConnectSocket(sp, ip, port, MPR_SOCKET_NODELAY)) < 0) { httpError(conn, HTTP_ABORT | HTTP_CODE_COMMS_ERROR, "Cannot open socket on %s:%d", ip, port); return 0; } conn->sock = sp; conn->ip = sclone(ip); conn->port = port; conn->keepAliveCount = (conn->limits->keepAliveMax) ? conn->limits->keepAliveMax : 0; #if ME_COM_SSL /* Must be done even if using keep alive for repeat SSL requests */ if (uri->secure) { char *peerName; if (ssl == 0) { ssl = mprCreateSsl(0); } peerName = isdigit(uri->host[0]) ? 0 : uri->host; if (mprUpgradeSocket(sp, ssl, peerName) < 0) { conn->errorMsg = sp->errorMsg; httpTrace(conn, "connection.upgrade.error", "error", "msg:'Cannot perform SSL upgrade. %s'", conn->errorMsg); return 0; } if (sp->peerCert) { httpTrace(conn, "context", "connection.ssl", "msg:'Connection secured with peer certificate', " \ "secure:true,cipher:'%s',peerName:'%s',subject:'%s',issuer:'%s'", sp->cipher, sp->peerName, sp->peerCert, sp->peerCertIssuer); } } #endif #if ME_HTTP_WEB_SOCKETS if (uri->webSockets && httpUpgradeWebSocket(conn) < 0) { conn->errorMsg = sp->errorMsg; return 0; } #endif httpTrace(conn, "connection.peer", "context", "peer:'%s:%d'", conn->ip, conn->port); return conn; }
static HttpConn *openConnection(HttpConn *conn, cchar *url, struct MprSsl *ssl) { Http *http; HttpUri *uri; MprSocket *sp; char *ip; int port, rc, level; mprAssert(conn); http = conn->http; uri = httpCreateUri(url, HTTP_COMPLETE_URI); conn->tx->parsedUri = uri; if (*url == '/') { ip = (http->proxyHost) ? http->proxyHost : http->defaultClientHost; port = (http->proxyHost) ? http->proxyPort : http->defaultClientPort; } else { ip = (http->proxyHost) ? http->proxyHost : uri->host; port = (http->proxyHost) ? http->proxyPort : uri->port; } if (port == 0) { port = (uri->secure) ? 443 : 80; } if (conn && conn->sock) { if (--conn->keepAliveCount < 0 || port != conn->port || strcmp(ip, conn->ip) != 0 || uri->secure != (conn->sock->ssl != 0) || conn->sock->ssl != ssl) { httpCloseConn(conn); } else { mprLog(4, "Http: reusing keep-alive socket on: %s:%d", ip, port); } } if (conn->sock) { return conn; } if ((sp = mprCreateSocket()) == 0) { httpError(conn, HTTP_CODE_COMMS_ERROR, "Can't create socket for %s", url); return 0; } if ((rc = mprConnectSocket(sp, ip, port, 0)) < 0) { httpError(conn, HTTP_CODE_COMMS_ERROR, "Can't open socket on %s:%d", ip, port); return 0; } #if BIT_PACK_SSL /* Must be done even if using keep alive for repeat SSL requests */ if (uri->secure) { if (ssl == 0) { ssl = mprCreateSsl(); } if (mprUpgradeSocket(sp, ssl, 0) < 0) { conn->errorMsg = sp->errorMsg; return 0; } } #endif conn->sock = sp; conn->ip = sclone(ip); conn->port = port; conn->secure = uri->secure; conn->keepAliveCount = (conn->limits->keepAliveMax) ? conn->limits->keepAliveMax : -1; if ((level = httpShouldTrace(conn, HTTP_TRACE_RX, HTTP_TRACE_CONN, NULL)) >= 0) { mprLog(level, "### Outgoing connection from %s:%d to %s:%d", conn->ip, conn->port, conn->sock->ip, conn->sock->port); } return conn; }