mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-09 16:52:09 +07:00
98 lines
3.2 KiB
C
98 lines
3.2 KiB
C
#include "internal.h"
|
|
|
|
static SOCKET conn2(const char *host, int port, int use_ssl,
|
|
char *ebuf, size_t ebuf_len) {
|
|
struct sockaddr_in sin;
|
|
struct hostent *he = NULL;
|
|
SOCKET sock = INVALID_SOCKET;
|
|
|
|
(void) use_ssl; // Prevent warning for -DNO_SSL case
|
|
|
|
if (host == NULL) {
|
|
snprintf(ebuf, ebuf_len, "%s", "NULL host");
|
|
#ifndef NO_SSL
|
|
} else if (use_ssl && SSLv23_client_method == NULL) {
|
|
snprintf(ebuf, ebuf_len, "%s", "SSL is not initialized");
|
|
// TODO(lsm): use something threadsafe instead of gethostbyname()
|
|
#endif
|
|
} else if ((he = gethostbyname(host)) == NULL) {
|
|
snprintf(ebuf, ebuf_len, "gethostbyname(%s): %s", host, strerror(ERRNO));
|
|
} else if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
|
|
snprintf(ebuf, ebuf_len, "socket(): %s", strerror(ERRNO));
|
|
} else {
|
|
set_close_on_exec(sock);
|
|
sin.sin_family = AF_INET;
|
|
sin.sin_port = htons((uint16_t) port);
|
|
sin.sin_addr = * (struct in_addr *) he->h_addr_list[0];
|
|
if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
|
|
snprintf(ebuf, ebuf_len, "connect(%s:%d): %s",
|
|
host, port, strerror(ERRNO));
|
|
closesocket(sock);
|
|
sock = INVALID_SOCKET;
|
|
}
|
|
}
|
|
return sock;
|
|
}
|
|
|
|
struct mg_connection *mg_connect(const char *host, int port, int use_ssl,
|
|
char *ebuf, size_t ebuf_len) {
|
|
static struct mg_context fake_ctx;
|
|
struct mg_connection *conn = NULL;
|
|
SOCKET sock;
|
|
|
|
if ((sock = conn2(host, port, use_ssl, ebuf, ebuf_len)) == INVALID_SOCKET) {
|
|
} else if ((conn = (struct mg_connection *)
|
|
calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) {
|
|
snprintf(ebuf, ebuf_len, "calloc(): %s", strerror(ERRNO));
|
|
closesocket(sock);
|
|
#ifndef NO_SSL
|
|
} else if (use_ssl && (conn->client_ssl_ctx =
|
|
SSL_CTX_new(SSLv23_client_method())) == NULL) {
|
|
snprintf(ebuf, ebuf_len, "SSL_CTX_new error");
|
|
closesocket(sock);
|
|
free(conn);
|
|
conn = NULL;
|
|
#endif // NO_SSL
|
|
} else {
|
|
socklen_t len = sizeof(struct sockaddr);
|
|
conn->buf_size = MAX_REQUEST_SIZE;
|
|
conn->buf = (char *) (conn + 1);
|
|
conn->ctx = &fake_ctx;
|
|
conn->client.sock = sock;
|
|
getsockname(sock, &conn->client.rsa.sa, &len);
|
|
conn->client.is_ssl = use_ssl;
|
|
#ifndef NO_SSL
|
|
if (use_ssl) {
|
|
// SSL_CTX_set_verify call is needed to switch off server certificate
|
|
// checking, which is off by default in OpenSSL and on in yaSSL.
|
|
SSL_CTX_set_verify(conn->client_ssl_ctx, 0, 0);
|
|
sslize(conn, conn->client_ssl_ctx, SSL_connect);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return conn;
|
|
}
|
|
|
|
struct mg_connection *mg_download(const char *host, int port, int use_ssl,
|
|
char *ebuf, size_t ebuf_len,
|
|
const char *fmt, ...) {
|
|
struct mg_connection *conn;
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
ebuf[0] = '\0';
|
|
if ((conn = mg_connect(host, port, use_ssl, ebuf, ebuf_len)) == NULL) {
|
|
} else if (mg_vprintf(conn, fmt, ap) <= 0) {
|
|
snprintf(ebuf, ebuf_len, "%s", "Error sending request");
|
|
} else {
|
|
getreq(conn, ebuf, ebuf_len);
|
|
}
|
|
if (ebuf[0] != '\0' && conn != NULL) {
|
|
mg_close_connection(conn);
|
|
conn = NULL;
|
|
}
|
|
|
|
return conn;
|
|
}
|