⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netconnection.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
    }
    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 + -