📄 netconnection.c
字号:
}
WideCharToMultiByte(CP_THREAD_ACP, 0, hostname, -1, hostname_unix, len, NULL, NULL);
if (!check_hostname(cert, hostname_unix))
{
HeapFree(GetProcessHeap(), 0, hostname_unix);
INTERNET_SetLastError(ERROR_INTERNET_SEC_CERT_CN_INVALID);
goto fail;
}
HeapFree(GetProcessHeap(), 0, hostname_unix);
connection->useSSL = TRUE;
return TRUE;
fail:
if (connection->ssl_s)
{
pSSL_shutdown(connection->ssl_s);
pSSL_free(connection->ssl_s);
connection->ssl_s = NULL;
}
#endif
return FALSE;
}
/******************************************************************************
* NETCON_connect
* Connects to the specified address.
*/
BOOL NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
unsigned int addrlen)
{
int result;
if (!NETCON_connected(connection)) return FALSE;
result = connect(connection->socketFD, serv_addr, addrlen);
if (SOCKET_ERROR == result)
{
WARN("Unable to connect to host (%s)\n", strerror(errno));
INTERNET_SetLastError(WSAGetLastError());
closesocket(connection->socketFD);
connection->socketFD = -1;
return FALSE;
}
return TRUE;
}
/******************************************************************************
* NETCON_send
* Basically calls 'send()' unless we should use SSL
* number of chars send is put in *sent
*/
BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
int *sent /* out */)
{
if (!NETCON_connected(connection)) return FALSE;
if (!connection->useSSL)
{
*sent = send(connection->socketFD, msg, len, flags);
if (SOCKET_ERROR == *sent)
{
INTERNET_SetLastError(WSAGetLastError());
return FALSE;
}
return TRUE;
}
else
{
#if defined HAVE_OPENSSL_SSL_H && defined HAVE_OPENSSL_ERR_H
if (flags)
FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
*sent = pSSL_write(connection->ssl_s, msg, len);
if (*sent < 1 && len)
return FALSE;
return TRUE;
#else
return FALSE;
#endif
}
}
/******************************************************************************
* NETCON_recv
* Basically calls 'recv()' unless we should use SSL
* number of chars received is put in *recvd
*/
BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
int *recvd /* out */)
{
if (!NETCON_connected(connection)) return FALSE;
if (!connection->useSSL)
{
*recvd = recv(connection->socketFD, buf, len, flags);
if (SOCKET_ERROR == *recvd)
{
INTERNET_SetLastError(WSAGetLastError());
return FALSE;
}
return TRUE;
}
else
{
#if defined HAVE_OPENSSL_SSL_H && defined HAVE_OPENSSL_ERR_H
if (flags & (~MSG_PEEK))
FIXME("SSL_read does not support the following flag: %08x\n", flags);
/* this ugly hack is all for MSG_PEEK. eww gross */
if (flags & MSG_PEEK && !connection->peek_msg)
{
connection->peek_msg = connection->peek_msg_mem = HeapAlloc(GetProcessHeap(), 0, (sizeof(char) * len) + 1);
}
else if (flags & MSG_PEEK && connection->peek_msg)
{
size_t peek_msg_len = strlen(connection->peek_msg);
if (len < peek_msg_len)
FIXME("buffer isn't big enough. Do the expect us to wrap?\n");
memcpy(buf, connection->peek_msg, min(len,peek_msg_len+1));
*recvd = min(len, peek_msg_len);
return TRUE;
}
else if (connection->peek_msg)
{
size_t peek_msg_len = strlen(connection->peek_msg);
memcpy(buf, connection->peek_msg, min(len,peek_msg_len+1));
connection->peek_msg += *recvd = min(len, peek_msg_len);
if (*connection->peek_msg == '\0' || *(connection->peek_msg - 1) == '\0')
{
HeapFree(GetProcessHeap(), 0, connection->peek_msg_mem);
connection->peek_msg_mem = NULL;
connection->peek_msg = NULL;
}
return TRUE;
}
*recvd = pSSL_read(connection->ssl_s, buf, len);
if (flags & MSG_PEEK) /* must copy stuff into buffer */
{
if (!*recvd)
{
HeapFree(GetProcessHeap(), 0, connection->peek_msg_mem);
connection->peek_msg_mem = NULL;
connection->peek_msg = NULL;
}
else
{
memcpy(connection->peek_msg, buf, *recvd);
connection->peek_msg[*recvd] = '\0';
}
}
if (*recvd < 1 && len)
return FALSE;
return TRUE;
#else
return FALSE;
#endif
}
}
/******************************************************************************
* NETCON_getNextLine
*/
BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer)
{
TRACE("\n");
if (!NETCON_connected(connection)) return FALSE;
if (!connection->useSSL)
{
struct timeval tv;
fd_set infd;
BOOL bSuccess = FALSE;
DWORD nRecv = 0;
int r;
FD_ZERO(&infd);
FD_SET(connection->socketFD, &infd);
tv.tv_sec=RESPONSE_TIMEOUT;
tv.tv_usec=0;
while (nRecv < *dwBuffer)
{
if (select(connection->socketFD+1,&infd,NULL,NULL,&tv) > 0)
{
r = recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0);
if (0 == r || SOCKET_ERROR == r)
{
INTERNET_SetLastError(WSAGetLastError());
goto lend;
}
if (lpszBuffer[nRecv] == '\n')
{
bSuccess = TRUE;
break;
}
if (lpszBuffer[nRecv] != '\r')
nRecv++;
}
else
{
INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
goto lend;
}
}
lend: /* FIXME: don't use labels */
if (bSuccess)
{
lpszBuffer[nRecv++] = '\0';
*dwBuffer = nRecv;
TRACE(":%lu %s\n", nRecv, lpszBuffer);
return TRUE;
}
else
{
return FALSE;
}
}
else
{
#if defined HAVE_OPENSSL_SSL_H && defined HAVE_OPENSSL_ERR_H
long prev_timeout;
DWORD nRecv = 0;
BOOL success = TRUE;
prev_timeout = pSSL_CTX_get_timeout(ctx);
pSSL_CTX_set_timeout(ctx, RESPONSE_TIMEOUT);
while (nRecv < *dwBuffer)
{
int recv = 1;
if (!NETCON_recv(connection, &lpszBuffer[nRecv], 1, 0, &recv))
{
INTERNET_SetLastError(ERROR_CONNECTION_ABORTED);
success = FALSE;
}
if (lpszBuffer[nRecv] == '\n')
{
success = TRUE;
break;
}
if (lpszBuffer[nRecv] != '\r')
nRecv++;
}
pSSL_CTX_set_timeout(ctx, prev_timeout);
if (success)
{
lpszBuffer[nRecv++] = '\0';
*dwBuffer = nRecv;
TRACE("_SSL:%lu %s\n", nRecv, lpszBuffer);
return TRUE;
}
return FALSE;
#else
return FALSE;
#endif
}
}
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
{
#if defined HAVE_OPENSSL_SSL_H && defined HAVE_OPENSSL_ERR_H
X509* cert;
unsigned char* buffer,*p;
INT len;
BOOL malloced = FALSE;
LPCVOID r = NULL;
if (!connection->useSSL)
return NULL;
cert = pSSL_get_peer_certificate(connection->ssl_s);
p = NULL;
len = pi2d_X509(cert,&p);
/*
* SSL 0.9.7 and above malloc the buffer if it is null.
* however earlier version do not and so we would need to alloc the buffer.
*
* see the i2d_X509 man page for more details.
*/
if (!p)
{
buffer = HeapAlloc(GetProcessHeap(),0,len);
p = buffer;
len = pi2d_X509(cert,&p);
}
else
{
buffer = p;
malloced = TRUE;
}
r = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
if (malloced)
free(buffer);
else
HeapFree(GetProcessHeap(),0,buffer);
return r;
#else
return NULL;
#endif
}
BOOL NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value)
{
int result;
struct timeval tv;
/* FIXME: we should probably store the timeout in the connection to set
* when we do connect */
if (!NETCON_connected(connection))
return TRUE;
/* value is in milliseconds, convert to struct timeval */
tv.tv_sec = value / 1000;
tv.tv_usec = (value % 1000) * 1000;
result = setsockopt(connection->socketFD, SOL_SOCKET,
send ? SO_SNDTIMEO : SO_RCVTIMEO, &tv,
sizeof(tv));
if (result == -1)
{
WARN("setsockopt failed (%s)\n", strerror(errno));
//INTERNET_SetLastError(sock_get_error(errno));
return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -