[prev in list] [next in list] [prev in thread] [next in thread]
List: helix-client-cvs
Subject: [Client-cvs] netwksvc hxnetwksvcpln_symbian.pcf,1.4.82.1,1.4.82.2
From: salopes () helixcommunity ! org
Date: 2010-03-30 19:47:41
Message-ID: 201003301947.o2UJloci008083 () mailer ! progressive-comp ! com
[Download RAW message or body]
Update of /cvsroot/client/netwksvc
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv13788
Modified Files:
Tag: hxclient_4_2_0_brizo
hxnetwksvcpln_symbian.pcf
Log Message:
From: ext Qiang Luo [mailto:qluo@real.com]
Sent: Monday, March 29, 2010 7:56 PM
To: Lopes Sanket (EXT-Infovision/Dallas)
Cc: nokia-private-dev@helixcommunity.org; common-dev@helixcommunity.org
Subject: Re: [Common-dev] CR: Provide HTTPS Steaming support on Helix
Looks good to me. The module has mixed symbian and helix code. I assume that \
HXBOOL/TBool, FALSE/EFalse are all equvelent, right?
Qiang
On 3/26/2010 9:01 AM, ext-sanket.lopes@nokia.com wrote:
"Nokia submits this code under the terms of a commercial contribution agreement with \
RealNetworks, and I am authorized to contribute this code under said agreement."
Modified by: ext-sanket.lopes@nokia.com
Reviewed by:
Date: 03/26/2010
Project: symbian_client_apps
ErrorId: 417-62394
Synopsis: Provide HTTPS Steaming support on Helix
Overview: An MMF Client wants to pass URL like https:// and expects to play the \
streaming media data pointed by the URL. In this case media data will be streamed \
over the https protocol. HTTPS is basically HTTP protocol with secure communication \
between the client and server. SSL/TLS protocol is used to provide the encryption and \
secure identification of the server. HTTPS depends on the digital certificates which \
are signed by Certificate Authorities (CA). HTTPS Server sends a certificate which is \
signed by a trusted certificate authority to the client. This certificate is used to \
identify the server and establish the secure connection. HTTP default port is 80 \
while the HTTPS default port is 443.
Solution:
IHXSymbianSocket can implement the IID_IHXTCPSecureSocket interface which contains \
only one function as SetSecure. CHXSymbianSocket will have to implement this new \
interface. When instructed to make a connection to the server, CHXSymbianSocket will \
call the RSocket’s connect function. After the unsecure connection is established \
then it can check if the client has requested for a secure connection. For the secure \
socket, CHXSymbianSocket will create a secure socket or TLS socket by calling
iTLSSocket = CSecureSocket::NewL( RSocket, _L("SSL3.0"));
Then it needs to call
iTLSSocket ->StartClientHandshake(iStatus); to start the client handshake and \
establish the secure connection.
Once this request completes then client can communicate with the server over the \
secure channel. Media data received by the handset will be decrypted by Symbian’s \
SSL/TLS stack and helix http filesystem will receive the usual un-encrypted data and \
streaming can be done like the existing http streaming.
Files Added: None.
Files Modified:
\common\netio\platform\symbian\hxsymbiansocket.cpp
\common\netio\pub\platform\symbian\hxsymbiansocket.h
\filesystem\http\httpfsys.cpp
\client\core\clntcoredll_symbian.pcf
\netwksvc\hxnetwksvcpln_symbian.pcf
\build\umakepf\helix-client-symbian-4-common.pfi
Image Size and Heap Use impact: minor
Module Release testing (STIF) : Yes - PASSED
Test case(s) Added : Yes (Cannot be verified HTTPS urls are blocked by CVPU2)
Memory leak check performed : Yes. No new leaks introduced
Platforms and Profiles Build Verified: armv5, winscw
Platforms and Profiles Functionality verified: armv5, winscw
Branch: 420Brizo, HEAD
Diff: ? Makefile
? Umakefil.upp
? armv5-rel32
? winscw-rel32
Index: platform/symbian/hxsymbiansocket.cpp
===================================================================
RCS file: /cvsroot/common/netio/platform/symbian/hxsymbiansocket.cpp,v
retrieving revision 1.7.34.1
diff -u -b -r1.7.34.1 hxsymbiansocket.cpp
--- platform/symbian/hxsymbiansocket.cpp 22 Dec 2009 05:32:16 -0000 1.7.34.1
+++ platform/symbian/hxsymbiansocket.cpp 25 Mar 2010 20:02:35 -0000
@@ -61,6 +61,7 @@
#include "hxtlogutil.h"
#define UDP_READ_SIZE_READCONTINUATION 4096
+_LIT(KTLS1, "SSL3.0");
CHXSymbianSocket::CHXSymbianSocket(CHXNetServices* pNetSvc, IUnknown* pContext):
m_nRefCount(0)
@@ -89,6 +90,8 @@
,m_bReadingPendingBytes(FALSE)
,m_pPendingUDPReadBuf(NULL)
,m_uPendingUDPReadBufSize(0)
+ ,m_secureConn(EFalse)
+ ,m_pTlsSocket(NULL)
{
HX_ADDREF(m_pNetSvc);
HX_ASSERT(m_pContext);
@@ -117,6 +120,7 @@
HX_RELEASE(m_pDataBuf);
HX_RELEASE(m_pPendingUDPReadBuf);
HX_DELETE(m_pUdpConnectAddr);
+ HX_DELETE(m_pTlsSocket);
if (m_pAPResponse)
{
m_pAPResponse->ClearPointers();
@@ -145,6 +149,12 @@
*ppvObj = (IHXMulticastSocket*)this;
return HXR_OK;
}
+ if (IsEqualIID(riid, IID_IHXTCPSecureSocket))
+ {
+ AddRef();
+ *ppvObj = (IHXTCPSecureSocket*)this;
+ return HXR_OK;
+ }
*ppvObj = NULL;
return HXR_NOINTERFACE;
}
@@ -507,18 +517,30 @@
// Cancel pending operations.
if (m_pConnector->IsActive())
{
+ if(m_pTlsSocket)
+ {
+ m_pTlsSocket->CancelHandshake();
+ }
m_sock.CancelConnect();
m_pConnector->Cancel();
}
if (m_pWriter->IsActive())
{
+ if(m_pTlsSocket)
+ {
+ m_pTlsSocket->CancelSend();
+ }
m_sock.CancelWrite();
m_pWriter->Cancel();
}
if (m_pReader->IsActive())
{
+ if(m_pTlsSocket)
+ {
+ m_pTlsSocket->CancelRecv();
+ }
m_sock.CancelRecv();
m_pReader->Cancel();
}
@@ -533,6 +555,10 @@
if(m_bInitialized)
{
m_bInitialized = FALSE;
+ if(m_pTlsSocket)
+ {
+ m_pTlsSocket->Close();
+ }
m_sock.Close();
}
@@ -596,8 +622,15 @@
TInetAddr *pInetAddr = NULL;
if(!m_bConnected)
pInetAddr = &m_readFrom;
+ if(m_pTlsSocket && m_secureConn)
+ {
+ m_pReader->Read(*m_pTlsSocket, m_pReadersBuf, pInetAddr);
+ }
+ else
+ {
m_pReader->Read(m_sock, m_pReadersBuf, pInetAddr);
}
+ }
return hxr;
}
@@ -635,8 +668,16 @@
if( (CreateReadBuffer(m_pReadersBuf, m_uReadSize) == HXR_OK) )
{
m_ulSocketTaskFlags |= HX_SOCK_EVENT_READ;
+ if(m_pTlsSocket && m_secureConn)
+ {
+ m_pReader->Read(*m_pTlsSocket, m_pReadersBuf, &m_readFrom);
+ }
+ else
+ {
m_pReader->Read(m_sock, m_pReadersBuf, &m_readFrom);
}
+
+ }
return hxr;
}
@@ -712,8 +753,15 @@
}
}
}
+ if(m_pTlsSocket && m_secureConn)
+ {
+ m_pWriter->Write(*m_pTlsSocket, pBuf, dest);
+ }
+ else
+ {
m_pWriter->Write(m_sock, pBuf, dest);
}
+ }
return res;
}
@@ -788,21 +836,69 @@
return HXR_NOTIMPL;
}
+STDMETHODIMP
+CHXSymbianSocket::SetSecure(HXBOOL bSecure)
+{
+ m_secureConn = bSecure;
+ return HXR_OK;
+}
+
+TBool CHXSymbianSocket::Secure()
+{
+ return m_secureConn;
+}
+
+
+
+
void
CHXSymbianSocket::OnConnect(HX_RESULT hxr)
{
- if (m_state == EConnectionPending)
+ if (m_state == EConnectionPending || m_state == EConnectSecurePending)
+ {
+ if ( m_secureConn && m_state == EConnectionPending)
{
+ HXLOGL1(HXLOG_NETW, "CHXSymbianSocket::OnConnect - Secure socket");
+ m_state = EConnectSecurePending;
+ TRAPD(err, m_pTlsSocket = CSecureSocket::NewL( m_sock, KTLS1 ));
+ if ( err == KErrNone )
+ {
+ HBufC* hostNameHB = HBufC::NewLC(m_peerAddr.Length());
+ TPtr ptr = hostNameHB->Des();
+ m_peerAddr.Output(ptr);
+ TBuf8<128> hostName8;
+ hostName8.Copy(*hostNameHB);
+ m_pTlsSocket->SetOpt(KSoSSLDomainName, KSolInetSSL, hostName8);
+ m_pConnector->MakeSecureConnection(*m_pTlsSocket);
+ CleanupStack::PopAndDestroy(hostNameHB);
+ }
+ else
+ {
+ SendEvents(HX_SOCK_EVENT_CONNECT, HXR_ABORT);
+ }
+ return;
+ }
+
m_ulSocketTaskFlags &= ~HX_SOCK_EVENT_CONNECT;
if(hxr == HXR_OK)
{
m_bConnected = ETrue;
+ HXLOGL1(HXLOG_NETW, "CHXSymbianSocket::OnConnect - Handshake Complete");
SendEvents(HX_SOCK_EVENT_CONNECT|
HX_SOCK_EVENT_READ|
HX_SOCK_EVENT_WRITE, HXR_OK);
}
else
{
+ if(m_pTlsSocket)
+ {
+ HXLOGL1(HXLOG_NETW, "CHXSymbianSocket::OnConnect - Error on \
Handshake"); + m_state = EConnectionPending;
+ m_pTlsSocket->Close();
+ delete m_pTlsSocket;
+ m_pTlsSocket = NULL;
+ m_pConnector->SetConnectionState(EConnected);
+ }
SendEvents(HX_SOCK_EVENT_CONNECT, hxr);
}
}
@@ -838,7 +934,14 @@
m_uPendingUDPReadBufSize += bytes;
// reuse same allocate buffer
m_ulSocketTaskFlags |= HX_SOCK_EVENT_READ;
+ if(m_pTlsSocket && m_secureConn)
+ {
+ m_pReader->Read(*m_pTlsSocket, m_pReadersBuf, &m_readFrom);
+ }
+ else
+ {
m_pReader->Read(m_sock, m_pReadersBuf, &m_readFrom);
+ }
m_bReadingPendingBytes = TRUE;
}
}
@@ -916,7 +1019,14 @@
}
}
}
+ if(m_pTlsSocket && m_secureConn)
+ {
+ m_pWriter->Write(*m_pTlsSocket, pBuffer, dest);
+ }
+ else
+ {
m_pWriter->Write(m_sock, pBuffer, dest);
+ }
delete pWriteReq;
}
else
@@ -1140,7 +1250,8 @@
CHXSymbianSocketConnector::CHXSymbianSocketConnector(CHXSymbianSocket* pParent):
CActive(EPriorityStandard),
- m_pParent(pParent)
+ m_pParent(pParent),
+ m_connState(EBeginConnect)
{
CActiveScheduler::Add(this);
}
@@ -1154,9 +1265,13 @@
void
CHXSymbianSocketConnector::Connect(RSocket& socket, TInetAddr &inetAddr)
{
+ if ( m_connState == EBeginConnect )
+ {
m_addr = inetAddr;
socket.Connect(m_addr, iStatus);
+ m_connState = EConnected;
SetActive();
+ }
}
void
@@ -1166,13 +1281,29 @@
m_pParent->OnConnect((iStatus.Int() == KErrNone) ?HXR_OK : HXR_NET_CONNECT);
}
+void CHXSymbianSocketConnector::MakeSecureConnection(CSecureSocket& m_pTlsSocket)
+ {
+ if ( m_connState == EConnected )
+ {
+ iStatus = KRequestPending;
+ // start the handshake
+ m_pTlsSocket.StartClientHandshake( iStatus );
+ m_connState = EConnectSecure;
+ SetActive();
+ }
+ }
void
CHXSymbianSocketConnector::DoCancel()
{
-// do nothing
+ m_connState = EBeginConnect;
}
+void
+CHXSymbianSocketConnector::SetConnectionState(TInt aState)
+{
+ m_connState = aState;
+}
CHXSymbianSocketWriter::CHXSymbianSocketWriter(CHXSymbianSocket* pParent) :
@@ -1205,7 +1336,7 @@
m_bufDes.Set(m_pBuffer->GetBuffer(),
m_pBuffer->GetSize(),
m_pBuffer->GetSize());
-
+ iStatus = KRequestPending;
if(!dest)
{
socket.Write(m_bufDes, iStatus);
@@ -1219,6 +1350,35 @@
}
}
+void
+CHXSymbianSocketWriter::Write(CSecureSocket& socket, IHXBuffer* pBuffer,
+ TInetAddr *dest)
+{
+ HXLOGL4(HXLOG_NETW, "CHXSymbianSocketWriter::Write - Secure Socket");
+ HX_RELEASE(m_pBuffer);
+ m_pBuffer = pBuffer;
+
+ if (m_pBuffer)
+ {
+ m_pBuffer->AddRef();
+ m_bufDes.Set(m_pBuffer->GetBuffer(),
+ m_pBuffer->GetSize(),
+ m_pBuffer->GetSize());
+ iStatus = KRequestPending;
+ if(!dest)
+ {
+ socket.Send(m_bufDes, iStatus);
+ }
+ else
+ {
+ TSockXfrLength amountWrite = m_bufDes.Length();
+ m_sendAddr = *dest;
+ socket.Send(m_bufDes, iStatus, amountWrite);
+ }
+ SetActive();
+ }
+}
+
void
CHXSymbianSocketWriter::RunL()
@@ -1284,6 +1444,7 @@
m_pBuffer = pBuf;
HX_ADDREF(m_pBuffer);
m_bufDes.Set(pBuf->GetBuffer(), 0, pBuf->GetSize());
+ iStatus = KRequestPending;
if(fromAddr)
{
// passing ref. Saves extra copy and possible extra return path.
@@ -1299,6 +1460,31 @@
return HXR_OK;
}
+HX_RESULT
+CHXSymbianSocketReader::Read(CSecureSocket& socket, IHXBuffer* pBuf,
+ TInetAddr *fromAddr)
+{
+ HXLOGL4(HXLOG_NETW, "CHXSymbianSocketReader::Read - Secure socket");
+ if (m_pParent)
+ {
+ m_pBuffer = pBuf;
+ HX_ADDREF(m_pBuffer);
+ m_bufDes.Set(pBuf->GetBuffer(), 0, pBuf->GetSize());
+ iStatus = KRequestPending;
+ if(fromAddr)
+ {
+ socket.Recv(m_bufDes, iStatus);
+ }
+ else
+ {
+ socket.RecvOneOrMore(m_bufDes, iStatus, m_amountRead);
+ }
+ SetActive();
+ }
+ return HXR_OK;
+}
+
+
void
CHXSymbianSocketReader::RunL()
{
Index: pub/platform/symbian/hxsymbiansocket.h
===================================================================
RCS file: /cvsroot/common/netio/pub/platform/symbian/hxsymbiansocket.h,v
retrieving revision 1.3.4.1
diff -u -b -r1.3.4.1 hxsymbiansocket.h
--- pub/platform/symbian/hxsymbiansocket.h 22 Dec 2009 05:28:49 -0000 1.3.4.1
+++ pub/platform/symbian/hxsymbiansocket.h 25 Mar 2010 20:02:35 -0000
@@ -55,6 +55,8 @@
#include "hxbuffer.h"
#include <es_sock.h>
+#include <SecureSocket.h>
+#include <ssl_internal.h>
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <in_sock_internal.h> //KSoUdpRecvBuf
@@ -76,13 +78,22 @@
~CHXSymbianSocketConnector();
void Connect(RSocket& socket, TInetAddr& inetAddr);
-
+ void MakeSecureConnection(CSecureSocket& m_pTlsSocket);
+ void SetConnectionState(TInt aState);
private:
+ enum ConnectionState
+ {
+ EBeginConnect = 0,
+ EConnected,
+ EConnectSecure,
+ ESecureConnected
+ };
void RunL();
void DoCancel();
CHXSymbianSocket* m_pParent;
TInetAddr m_addr;
+ TInt m_connState;
};
class CHXSymbianSocketReader : public CActive
@@ -92,6 +103,7 @@
~CHXSymbianSocketReader();
HX_RESULT Read(RSocket& socket, IHXBuffer *pBuf, TInetAddr *inetAdr);
+ HX_RESULT Read(CSecureSocket& socket, IHXBuffer* pBuf, TInetAddr *fromAddr);
UINT32 MoreDataAvailable();
private:
@@ -113,6 +125,8 @@
~CHXSymbianSocketWriter();
void Write(RSocket& socket, IHXBuffer* pBuffer, TInetAddr *dest);
+ void Write(CSecureSocket& socket, IHXBuffer* pBuffer, TInetAddr *dest);
+
private:
void RunL();
@@ -140,6 +154,7 @@
class CHXSymbianSocket : public IHXSocket
,public IHXMulticastSocket
+ ,public IHXTCPSecureSocket
{
private:
// Unimplemented
@@ -217,6 +232,7 @@
IHXSockAddr* pSourceAddr,
IHXSockAddr* pGroupAddr,
IHXSockAddr* pInterface);
+ STDMETHOD(SetSecure) (THIS_ HXBOOL bSecure);
void GetNativeAddr(IHXSockAddr* pAddr,
TInetAddr &inetAddr);
@@ -225,7 +241,7 @@
static void static_APConnectDone(void* pObj,
HX_RESULT status);
-
+ TBool Secure();
protected:
// callbacks for async ops
void OnConnect(HX_RESULT hxr);
@@ -262,6 +278,7 @@
EBound,
EListening,
EConnectionPending,
+ EConnectSecurePending,
EClosePending
};
@@ -302,7 +319,8 @@
IHXBuffer* m_pPendingUDPReadBuf; //Buffer to hold the UDP \
datagram > UDP_READ_SIZE_READCONTINUATION
UINT32 m_uPendingUDPReadBufSize; // UDP data read so far
TBool m_bReadingPendingBytes; // flag that indicate UDP \
datagram > UDP_READ_SIZE_READCONTINUATION
-
+ HXBOOL m_secureConn;
+ CSecureSocket* m_pTlsSocket;
};
Index: helix-client-symbian-4-common.pfi
===================================================================
RCS file: /cvsroot/ribosome/build/umakepf/helix-client-symbian-4-common.pfi,v
retrieving revision 1.2
diff -u -b -r1.2 helix-client-symbian-4-common.pfi
--- helix-client-symbian-4-common.pfi 15 Mar 2010 20:49:19 -0000 1.2
+++ helix-client-symbian-4-common.pfi 25 Mar 2010 20:03:32 -0000
@@ -57,8 +57,9 @@
#
# ***** END LICENSE BLOCK ***** */
-# features in S60 5.2 platform
+# Features in Symbian^4
project.AddDefines("HELIX_FEATURE_DRM")
project.AddDefines("HELIX_FEATURE_S60_WMDRM_DOMAIN_API")
project.AddDefines('HELIX_FEATURE_ASF_FILEFORMAT_HTTP_CLAIM_PROTOCOL')
+project.AddDefines('SUPPORT_SECURE_SOCKETS')
Index: clntcoredll_symbian.pcf
===================================================================
RCS file: /cvsroot/client/core/clntcoredll_symbian.pcf,v
retrieving revision 1.16.4.1
diff -u -b -r1.16.4.1 clntcoredll_symbian.pcf
--- clntcoredll_symbian.pcf 2 Mar 2010 22:47:30 -0000 1.16.4.1
+++ clntcoredll_symbian.pcf 25 Mar 2010 20:04:29 -0000
@@ -55,7 +55,7 @@
project.AddSystemLibraries('mediaclientaudiostream.lib')
project.AddSystemLibraries('apmime.lib', 'apgrfx.lib')
project.AddSystemLibraries('charconv.lib')
-
+project.AddSystemLibraries('securesocket.lib')
if project.IsDefined('HELIX_FEATURE_SYMBIAN_EXTENDED_CONNECTION_PREF'):
project.AddSystemLibraries("extendedconnpref.lib")
Index: hxnetwksvcpln_symbian.pcf
===================================================================
RCS file: /cvsroot/client/netwksvc/hxnetwksvcpln_symbian.pcf,v
retrieving revision 1.4.82.1
diff -u -b -r1.4.82.1 hxnetwksvcpln_symbian.pcf
--- hxnetwksvcpln_symbian.pcf 9 Mar 2010 19:42:59 -0000 1.4.82.1
+++ hxnetwksvcpln_symbian.pcf 25 Mar 2010 20:05:19 -0000
@@ -59,6 +59,7 @@
project.AddSystemLibraries('apmime.lib', 'apgrfx.lib')
project.AddSystemLibraries('charconv.lib')
project.AddSystemLibraries('commdb.lib', 'CONNMON.LIB')
+project.AddSystemLibraries('securesocket.lib')
if project.IsDefined('HELIX_FEATURE_SYMBIAN_EXTENDED_CONNECTION_PREF'):
project.AddSystemLibraries("extendedconnpref.lib")
Index: helix-client-symbian-4-common.pfi
===================================================================
RCS file: /cvsroot/ribosome/build/umakepf/helix-client-symbian-4-common.pfi,v
retrieving revision 1.2
diff -u -b -r1.2 helix-client-symbian-4-common.pfi
--- helix-client-symbian-4-common.pfi 15 Mar 2010 20:49:19 -0000 1.2
+++ helix-client-symbian-4-common.pfi 25 Mar 2010 20:19:17 -0000
@@ -57,8 +57,9 @@
#
# ***** END LICENSE BLOCK ***** */
-# features in S60 5.2 platform
+# Features in Symbian^4
project.AddDefines("HELIX_FEATURE_DRM")
project.AddDefines("HELIX_FEATURE_S60_WMDRM_DOMAIN_API")
project.AddDefines('HELIX_FEATURE_ASF_FILEFORMAT_HTTP_CLAIM_PROTOCOL')
+project.AddDefines('SUPPORT_SECURE_SOCKETS')
Index: httpfsys.cpp
===================================================================
RCS file: /cvsroot/filesystem/http/httpfsys.cpp,v
retrieving revision 1.134.4.4
diff -u -b -r1.134.4.4 httpfsys.cpp
--- httpfsys.cpp 22 Mar 2010 07:07:45 -0000 1.134.4.4
+++ httpfsys.cpp 25 Mar 2010 20:21:10 -0000
@@ -4269,6 +4269,14 @@
{
sLocation.FindAndReplace ("HTTP://", "chttp://");
}
+ if (sLocation.Find ("https://") == 0)
+ {
+ sLocation.FindAndReplace ("https://", "chttps://");
+ }
+ if (sLocation.Find ("HTTPS://") == 0)
+ {
+ sLocation.FindAndReplace ("HTTPS://", "chttps://");
+ }
}
HXLOGL2(HXLOG_HTTP, "Redirected to %s", NULLOK((const char*)sLocation));
Thanks,
Sanket
Index: hxnetwksvcpln_symbian.pcf
===================================================================
RCS file: /cvsroot/client/netwksvc/hxnetwksvcpln_symbian.pcf,v
retrieving revision 1.4.82.1
retrieving revision 1.4.82.2
diff -u -d -r1.4.82.1 -r1.4.82.2
--- hxnetwksvcpln_symbian.pcf 9 Mar 2010 19:42:59 -0000 1.4.82.1
+++ hxnetwksvcpln_symbian.pcf 30 Mar 2010 19:47:38 -0000 1.4.82.2
@@ -59,6 +59,7 @@
project.AddSystemLibraries('apmime.lib', 'apgrfx.lib')
project.AddSystemLibraries('charconv.lib')
project.AddSystemLibraries('commdb.lib', 'CONNMON.LIB')
+project.AddSystemLibraries('securesocket.lib')
if project.IsDefined('HELIX_FEATURE_SYMBIAN_EXTENDED_CONNECTION_PREF'):
project.AddSystemLibraries("extendedconnpref.lib")
_______________________________________________
Client-cvs mailing list
Client-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/client-cvs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic