winamp/Src/Components/wac_network/util.cpp

211 lines
3.9 KiB
C++

/*
** JNetLib
** Copyright (C) 2000-2007 Nullsoft, Inc.
** Author: Justin Frankel
** File: util.cpp - JNL implementation of basic network utilities
** License: see jnetlib.h
*/
#include "netinc.h"
#include "util.h"
#include "foundation\error.h"
#ifdef USE_SSL
#include "wac_network_ssl_connection.h"
#ifdef _WIN32
#include <wincrypt.h>
#endif // !_WIN32
#include <openssl/rand.h>
#ifdef _WIN32
static HCRYPTPROV GetKeySet()
{
HCRYPTPROV hCryptProv;
LPCWSTR UserName = L"WinampKeyContainer"; // name of the key container
if ( CryptAcquireContext(
&hCryptProv, // handle to the CSP
UserName, // container name
NULL, // use the default provider
PROV_RSA_FULL, // provider type
0 ) ) // flag values
{
return hCryptProv;
}
else if ( CryptAcquireContext(
&hCryptProv,
UserName,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET ) )
{
return hCryptProv;
}
else
return 0;
}
#endif
static void InitSSL()
{
SSL_load_error_strings();
SSL_library_init();
#ifdef _WIN32
HCRYPTPROV hCryptProv = GetKeySet();
if ( hCryptProv )
{
BYTE pbData[ 8 * sizeof( unsigned long ) ] = { 0 };
if ( CryptGenRandom( hCryptProv, 8 * sizeof( unsigned long ), pbData ) )
{
RAND_seed( pbData, 16 );
}
CryptReleaseContext( hCryptProv, 0 );
}
#endif
// sslContext = SSL_CTX_new(SSLv23_client_method());
// SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
// SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
}
static int open_ssl_initted = 0;
#endif
static int was_initted = 0;
int JNL::open_socketlib()
{
#ifdef _WIN32
if ( !was_initted )
{
WSADATA wsaData = { 0 };
if ( WSAStartup( MAKEWORD( 1, 1 ), &wsaData ) )
{
return NErr_Error;
}
}
#endif // !_WIN32
#ifdef USE_SSL
if ( !open_ssl_initted )
{
InitSSL();
open_ssl_initted = 1;
}
#endif // !USE_SSL
return NErr_Success;
}
void JNL::close_socketlib()
{
#ifdef _WIN32
if ( was_initted )
{
WSACleanup();
}
#ifdef USE_SSL
// TODO need to do some reference counting to free this correctly
//SSL_CTX_free(sslContext);
#endif // !USE_SSL
#endif // !_WIN32
}
static char *jnl_strndup( const char *str, size_t n )
{
char *o = (char *)calloc( n + 1, sizeof( char ) );
if ( !o )
return 0;
strncpy( o, str, n );
o[ n ] = 0;
return o;
}
int JNL::parse_url( const char *url, char **prot, char **host, unsigned short *port, char **req, char **lp )
{
free( *prot ); *prot = 0;
free( *host ); *host = 0;
free( *req ); *req = 0;
free( *lp ); *lp = 0;
*port = 0;
const char *p;
const char *protocol = strstr( url, "://" );
if ( protocol )
{
*prot = jnl_strndup( url, protocol - url );
p = protocol + 3;
}
else
{
p = url;
}
while ( p && *p && *p == '/' ) p++; // skip extra /
size_t end = strcspn( p, "@/" );
// check for username
if ( p[ end ] == '@' )
{
*lp = jnl_strndup( p, end );
p = p + end + 1;
end = strcspn( p, "[:/" );
}
if ( p[ 0 ] == '[' ) // IPv6 style address
{
p++;
const char *ipv6_end = strchr( p, ']' );
if ( !ipv6_end )
return NErr_Malformed;
*host = jnl_strndup( p, ipv6_end - p );
p = ipv6_end + 1;
}
else
{
end = strcspn( p, ":/" );
*host = jnl_strndup( p, end );
p += end;
}
// is there a port number?
if ( p[ 0 ] == ':' )
{
char *new_end;
*port = (unsigned short)strtoul( p + 1, &new_end, 10 );
p = new_end;
}
if ( p[ 0 ] )
{
// benski> this is here to workaround a bug with YP and NSV streams
if ( !strcmp( p, ";stream.nsv" ) )
return NErr_Success;
*req = _strdup( p );
}
return NErr_Success;
}
#if 0
unsigned long JNL::ipstr_to_addr( const char *cp )
{
return inet_addr( cp );
}
void JNL::addr_to_ipstr( unsigned long addr, char *host, int maxhostlen )
{
in_addr a; a.s_addr = addr;
sprintf( host, /*maxhostlen,*/ "%u.%u.%u.%u", a.S_un.S_un_b.s_b1, a.S_un.S_un_b.s_b2, a.S_un.S_un_b.s_b3, a.S_un.S_un_b.s_b4 );
//char *p=::inet_ntoa(a); strncpy(host,p?p:"",maxhostlen);
}
#endif