connectivity/com.nokia.tcf/native/TCFNative/TCFClient/TCAPIConnectionJni.cpp
changeset 60 9d2210c8eed2
child 914 46f36a149510
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/connectivity/com.nokia.tcf/native/TCFNative/TCFClient/TCAPIConnectionJni.cpp	Mon Apr 06 15:18:48 2009 -0500
@@ -0,0 +1,1639 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+#include "stdafx.h"
+#include "TCAPIConnectionJni.h"
+#include "TCConstants.h"
+#include "TCErrorConstants.h"
+#include "ClientManager.h"
+#include "ServerClient.h"
+#include "TCDebugLog.h"
+#include "InputStream.h"
+#include "ErrorMonitorData.h"
+#include <list>
+#include <vector>
+
+extern CClientManager* gManager;
+
+#ifdef _DEBUG
+extern BOOL gDoLogging;
+char TCDebugMsg[100];
+#define TCDEBUGOPEN() if (gDoLogging) { gManager->m_DebugLog->WaitForAccess(); }
+#define TCDEBUGLOGS(s) if (gDoLogging) { sprintf(TCDebugMsg,"%s", s); gManager->m_DebugLog->log(TCDebugMsg); }
+#define TCDEBUGLOGA1(s, a1) if (gDoLogging) { sprintf(TCDebugMsg, s, a1); gManager->m_DebugLog->log(TCDebugMsg); }
+#define TCDEBUGLOGA2(s, a1, a2) if (gDoLogging) { sprintf(TCDebugMsg, s, a1, a2); gManager->m_DebugLog->log(TCDebugMsg); }
+#define TCDEBUGLOGA3(s, a1, a2, a3) if (gDoLogging) { sprintf(TCDebugMsg, s, a1, a2, a3); gManager->m_DebugLog->log(TCDebugMsg); }
+#define TCDEBUGCLOSE() if (gDoLogging) { gManager->m_DebugLog->ReleaseAccess(); }
+#else
+#define TCDEBUGOPEN()
+#define TCDEBUGLOGS(s)
+#define TCDEBUGLOGA1(s, a1)
+#define TCDEBUGLOGA2(s, a1, a2)
+#define TCDEBUGLOGA3(s, a1, a2, a3)
+#define TCDEBUGCLOSE()
+#endif
+
+#ifdef _DEBUG
+FILE* fLog1 = NULL;
+FILE* fLog2 = NULL;
+static void OpenLogFile1(char* filename);
+static void CloseLogFile1();
+static void OpenLogFile2(char* filename);
+static void CloseLogFile2();
+#define OPENLOGf1(f) OpenLogFile1(f)
+#define CLOSELOG1() CloseLogFile1()
+#define OPENLOGf2(f) OpenLogFile2(f)
+#define CLOSELOG2() CloseLogFile2()
+#else
+#define OPENLOGf1(f)
+#define CLOSELOG1()
+#endif
+
+static void ConvertRealSerialSettingsToHost(char* pBaud, char* pDataBits, char* pParity, char* pStopBits, char* pFlowControl, pRealSerialConnectData pData);
+static void ConvertRealSerialSettingsToServer(const char* pBaud, const char* pDataBits, const char* pParity, const char* pStopBits, const char* pFlowControl, pRealSerialConnectData pData);
+static const char* GetErrorText(unsigned long error);
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeConnect
+ * Signature: (Ljava/lang/String;[J[Ljava/lang/String;[JLjava/lang/String;[J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeConnect
+  (JNIEnv *env, jobject pThis, jstring inType, jlongArray inOptions, jobjectArray inSettings, jlongArray inMessageOptions, jstring inFilePath, jlongArray outClientId)
+ {
+ 	// inOptions are connection options
+ 	// inMessageOptions are client's message options
+	// inFilePath will be null if message destination is not DESTINATION_CLIENTFILE 
+	long ret = TCAPI_ERR_NONE;
+	unsigned long osError = 0;
+	long clientId;
+
+	TCDEBUGOPEN();
+
+	TCDEBUGLOGS("nativeConnect\n");
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	{
+		jboolean isCopy = false;
+		// options per connection
+		jlong* pOptions = env->GetLongArrayElements(inOptions, &isCopy);
+		DWORD retryInterval = (DWORD)pOptions[0];
+		DWORD retryTimeout = (DWORD)pOptions[1];
+
+
+
+		env->ReleaseLongArrayElements(inOptions, pOptions, 0);
+
+		pOptions = env->GetLongArrayElements(inMessageOptions, &isCopy);
+
+		// options per client
+		long unWrapFormat = pOptions[0];
+		long ostVersion = pOptions[1];
+		env->ReleaseLongArrayElements(inMessageOptions, pOptions, 0);
+
+
+		TCDEBUGLOGA2(" retryInterval=%d, retryTimeout=%d\n", retryInterval, retryTimeout);
+
+		TCDEBUGLOGA3(" unWrapFormat=%d, ostVersion=%d destination=%s\n", unWrapFormat, ostVersion, ((inFilePath == NULL) ? "stream" : "file"));
+
+		char* pType = (char*)env->GetStringUTFChars(inType, &isCopy);
+		TCDEBUGLOGA1("  pType = %s\n", pType);
+
+		if (strcmp(pType, "musti") == 0 || strcmp(pType, "platsim") == 0) 
+		{
+			jstring addString = (jstring)env->GetObjectArrayElement(inSettings, 0);
+			jstring portString = (jstring)env->GetObjectArrayElement(inSettings, 1);
+			jstring chanString = (jstring)env->GetObjectArrayElement(inSettings, 2);
+			jstring decodeString = (jstring)env->GetObjectArrayElement(inSettings, 3);
+
+			const char* pAddress = env->GetStringUTFChars(addString, NULL);
+			const char* pPort = env->GetStringUTFChars(portString, NULL);
+			const char* pChan = env->GetStringUTFChars(chanString, NULL);
+			const char* pDecode = env->GetStringUTFChars(decodeString, NULL);
+
+			TCDEBUGLOGA2(" TCP: ipAddress=%s, ipPort=%s\n", pAddress, pPort);
+			TCDEBUGLOGA2(" TCP: channel=%s, decode=%s\n", pChan, pDecode);
+
+			ServerCommandData cmd;
+			cmd.command = eCmdConnect;
+			strncpy(cmd.connectSettings.connectType, pType, MAX_CONNECTION_TYPE);
+			strncpy(cmd.connectSettings.tcpSettings.ipAddress, pAddress, MAX_IPADDRESS_SIZE);
+			strncpy(cmd.connectSettings.tcpSettings.ipPort, pPort, MAX_PORT_SIZE);
+
+			cmd.connectSettings.retryInterval = retryInterval;
+			cmd.connectSettings.retryTimeout = retryTimeout;
+			strncpy(cmd.connectSettings.decodeFormat, pDecode, MAX_DECODE_FORMAT);
+
+			if (pChan != NULL)
+			{
+				if (strcmp(pChan, "1") == 0)
+				{
+					cmd.connectSettings.traceBoxChannel = 1;
+				}
+				else
+				{
+					cmd.connectSettings.traceBoxChannel = 2;
+				}
+			}
+			else
+			{
+				cmd.connectSettings.traceBoxChannel = 2;
+			}
+
+
+			cmd.clientOptions.unWrapFormat = unWrapFormat;
+			cmd.clientOptions.ostVersion = ostVersion;
+
+			gManager->m_Server->SendCommand(&cmd);
+			gManager->m_Server->GetResponse(&cmd);
+
+			if (cmd.response == eRspError)
+			{
+				TCDEBUGLOGA1("  from server: ret = %d\n", cmd.error);
+				ret = cmd.error;
+				osError = cmd.osError;
+			}
+			else
+			{
+				TCDEBUGLOGA1("  from server: id = %d\n", cmd.clientId);
+				clientId = cmd.clientId;
+
+				gManager->WaitForErrorMonitorListAccess();
+				TCDEBUGLOGS(" TODO: create error monitor storage if server connected\n");
+				CErrorMonitor* monitor = new CErrorMonitor(clientId);
+				if (monitor != NULL)
+				{
+					monitor->CreateData();
+					gManager->AddErrorMonitor(monitor);
+				}
+
+				gManager->ReleaseErrorMonitorListAccess();
+
+				TCDEBUGLOGA1(" clientId=%d\n", clientId);
+				jlong jClientId = clientId;
+				env->SetLongArrayRegion(outClientId, 0, 1, &jClientId);
+
+			}
+			env->ReleaseStringUTFChars(addString, pAddress);
+			env->ReleaseStringUTFChars(portString, pPort);
+			env->ReleaseStringUTFChars(chanString, pChan);
+			env->ReleaseStringUTFChars(decodeString, pDecode);
+		}
+		else if (strcmp(pType, "tcp") == 0)
+		{
+			jstring addString = (jstring)env->GetObjectArrayElement(inSettings, 0);
+			jstring portString = (jstring)env->GetObjectArrayElement(inSettings, 1);
+			jstring decodeString = (jstring)env->GetObjectArrayElement(inSettings, 2);
+
+			const char* pAddress = env->GetStringUTFChars(addString, NULL);
+			const char* pPort = env->GetStringUTFChars(portString, NULL);
+			const char* pDecode = env->GetStringUTFChars(decodeString, NULL);
+
+			TCDEBUGLOGA3(" TCP: ipAddress=%s, ipPort=%s decode=%s\n", pAddress, pPort, pDecode);
+
+			ServerCommandData cmd;
+			cmd.command = eCmdConnect;
+			strncpy(cmd.connectSettings.connectType, pType, MAX_CONNECTION_TYPE);
+			strncpy(cmd.connectSettings.tcpSettings.ipAddress, pAddress, MAX_IPADDRESS_SIZE);
+			strncpy(cmd.connectSettings.tcpSettings.ipPort, pPort, MAX_PORT_SIZE);
+
+			cmd.connectSettings.retryInterval = retryInterval;
+			cmd.connectSettings.retryTimeout = retryTimeout;
+			strncpy(cmd.connectSettings.decodeFormat, pDecode, MAX_DECODE_FORMAT);
+			cmd.clientOptions.unWrapFormat = unWrapFormat;
+			cmd.clientOptions.ostVersion = ostVersion;
+
+			gManager->m_Server->SendCommand(&cmd);
+			gManager->m_Server->GetResponse(&cmd);
+
+			if (cmd.response == eRspError)
+			{
+				TCDEBUGLOGA1("  from server: ret = %d\n", cmd.error);
+				ret = cmd.error;
+				osError = cmd.osError;
+			}
+			else
+			{
+				TCDEBUGLOGA1("  from server: id = %d\n", cmd.clientId);
+				clientId = cmd.clientId;
+
+				gManager->WaitForErrorMonitorListAccess();
+				TCDEBUGLOGS(" TODO: create error monitor storage if server connected\n");
+				CErrorMonitor* monitor = new CErrorMonitor(clientId);
+				if (monitor != NULL)
+				{
+					monitor->CreateData();
+					gManager->AddErrorMonitor(monitor);
+				}
+
+				gManager->ReleaseErrorMonitorListAccess();
+
+				TCDEBUGLOGA1(" clientId=%d\n", clientId);
+				jlong jClientId = clientId;
+				env->SetLongArrayRegion(outClientId, 0, 1, &jClientId);
+
+			}
+			env->ReleaseStringUTFChars(addString, pAddress);
+			env->ReleaseStringUTFChars(portString, pPort);
+			env->ReleaseStringUTFChars(decodeString, pDecode);
+		}
+		else if (strcmp(pType, "virtualserial") == 0)
+		{
+			jstring portString = (jstring)env->GetObjectArrayElement(inSettings, 0);
+			const char* pPort = env->GetStringUTFChars(portString, NULL);
+			jstring decodeString = (jstring)env->GetObjectArrayElement(inSettings, 1);
+			const char* pDecode = env->GetStringUTFChars(decodeString, NULL);
+
+			TCDEBUGLOGA2(" vserial: pPort=%s decode=%s\n", pPort, pDecode);
+
+			ServerCommandData cmd;
+			cmd.command = eCmdConnect;
+			strncpy(cmd.connectSettings.connectType, pType, MAX_CONNECTION_TYPE); 
+			strncpy(cmd.connectSettings.virtualSerialSettings.comPort, pPort, MAX_COMPORT_SIZE);
+
+			cmd.connectSettings.retryInterval = retryInterval;
+			cmd.connectSettings.retryTimeout = retryTimeout;
+			strncpy(cmd.connectSettings.decodeFormat, pDecode, MAX_DECODE_FORMAT);
+			cmd.clientOptions.unWrapFormat = unWrapFormat;
+			cmd.clientOptions.ostVersion = ostVersion;
+
+			gManager->m_Server->SendCommand(&cmd);
+			gManager->m_Server->GetResponse(&cmd);
+
+			if (cmd.response == eRspError)
+			{
+				TCDEBUGLOGA1("  from server: ret = %d\n", cmd.error);
+				ret = cmd.error;
+				osError = cmd.osError;
+			}
+			else
+			{
+				TCDEBUGLOGA1("  from server: id = %d\n", cmd.clientId);
+				clientId = cmd.clientId;
+
+				gManager->WaitForErrorMonitorListAccess();
+				CErrorMonitor* monitor = new CErrorMonitor(clientId);
+				if (monitor != NULL)
+				{
+					monitor->CreateData();
+					gManager->AddErrorMonitor(monitor);
+				}
+
+				gManager->ReleaseErrorMonitorListAccess();
+
+				TCDEBUGLOGA1(" clientId=%d\n", clientId);
+				jlong jClientId = clientId;
+				env->SetLongArrayRegion(outClientId, 0, 1, &jClientId);
+			}
+			env->ReleaseStringUTFChars(portString, pPort);
+			env->ReleaseStringUTFChars(decodeString, pDecode);
+		}
+		else if (strcmp(pType, "serial") == 0)
+		{
+			jstring portString = (jstring)env->GetObjectArrayElement(inSettings, 0);
+			const char* pPort = env->GetStringUTFChars(portString, NULL);
+
+			jstring baudString = (jstring)env->GetObjectArrayElement(inSettings, 1);
+			const char* pBaud = env->GetStringUTFChars(baudString, NULL);
+			
+			jstring dataBitsString = (jstring)env->GetObjectArrayElement(inSettings, 2);
+			const char* pDataBits = env->GetStringUTFChars(dataBitsString, NULL);
+			
+			jstring parityString = (jstring)env->GetObjectArrayElement(inSettings, 3);
+			const char* pParity = env->GetStringUTFChars(parityString, NULL);
+			
+			jstring stopBitsString = (jstring)env->GetObjectArrayElement(inSettings, 4);
+			const char* pStopBits = env->GetStringUTFChars(stopBitsString, NULL);
+			
+			jstring flowControlString = (jstring)env->GetObjectArrayElement(inSettings, 5);
+			const char* pFlowControl = env->GetStringUTFChars(flowControlString, NULL);
+
+			jstring decodeString = (jstring)env->GetObjectArrayElement(inSettings, 6);
+			const char* pDecode = env->GetStringUTFChars(decodeString, NULL);
+
+			TCDEBUGLOGA3(" real serial: pPort=%s pBaud=%s pDataBits=%s\n", pPort, pBaud, pDataBits);
+
+			ServerCommandData cmd;
+			cmd.command = eCmdConnect;
+			strncpy(cmd.connectSettings.connectType, pType, MAX_CONNECTION_TYPE); 
+			strncpy(cmd.connectSettings.realSerialSettings.comPort, pPort, MAX_COMPORT_SIZE);
+			ConvertRealSerialSettingsToServer(pBaud, pDataBits, pParity, pStopBits, pFlowControl, &cmd.connectSettings.realSerialSettings);
+
+			cmd.connectSettings.retryInterval = retryInterval;
+			cmd.connectSettings.retryTimeout = retryTimeout;
+			strncpy(cmd.connectSettings.decodeFormat, pDecode, MAX_DECODE_FORMAT);
+			cmd.clientOptions.unWrapFormat = unWrapFormat;
+			cmd.clientOptions.ostVersion = ostVersion;
+
+			gManager->m_Server->SendCommand(&cmd);
+			gManager->m_Server->GetResponse(&cmd);
+
+			if (cmd.response == eRspError)
+			{
+				TCDEBUGLOGA1("  from server: ret = %d\n", cmd.error);
+				ret = cmd.error;
+				osError = cmd.osError;
+			}
+			else
+			{
+				TCDEBUGLOGA1("  from server: id = %d\n", cmd.clientId);
+				clientId = cmd.clientId;
+
+				gManager->WaitForErrorMonitorListAccess();
+				CErrorMonitor* monitor = new CErrorMonitor(clientId);
+				if (monitor != NULL)
+				{
+					monitor->CreateData();
+					gManager->AddErrorMonitor(monitor);
+				}
+
+				gManager->ReleaseErrorMonitorListAccess();
+
+				TCDEBUGLOGA1(" clientId=%d\n", clientId);
+				jlong jClientId = clientId;
+				env->SetLongArrayRegion(outClientId, 0, 1, &jClientId);
+			}
+			env->ReleaseStringUTFChars(portString, pPort);
+			env->ReleaseStringUTFChars(baudString, pBaud);
+			env->ReleaseStringUTFChars(dataBitsString, pDataBits);
+			env->ReleaseStringUTFChars(parityString, pParity);
+			env->ReleaseStringUTFChars(stopBitsString, pStopBits);
+			env->ReleaseStringUTFChars(flowControlString, pFlowControl);
+			env->ReleaseStringUTFChars(decodeString, pDecode);
+		}
+		else
+		{
+			TCDEBUGLOGS(" TCAPI_ERR_MEDIA_NOT_SUPPORTED\n");
+			ret = TCAPI_ERR_MEDIA_NOT_SUPPORTED;
+		}
+
+		env->ReleaseStringUTFChars(inType, pType);
+
+		
+		// handle message destinations
+		//  input stream is done by java on open input stream not here
+		//  message file is done here
+		if (ret == TCAPI_ERR_NONE)
+		{
+			long destination = DESTINATION_INPUTSTREAM;
+			char* pMessageFile = NULL;
+			if (inFilePath != NULL)
+			{
+				destination = DESTINATION_CLIENTFILE;
+				jboolean isCopy=FALSE;
+				pMessageFile = (char*)env->GetStringUTFChars(inFilePath, &isCopy);
+
+				// send to TCFServer
+				ServerCommandData cmd;
+				cmd.command = eCmdOpenMessageFile;
+				cmd.clientId = clientId;
+				cmd.destinationOptions.destination = eDestinationFile;
+				strncpy(cmd.destinationOptions.destinationFile, pMessageFile, MAX_FILEPATH);
+				gManager->m_Server->SendCommand(&cmd);
+				gManager->m_Server->GetResponse(&cmd);
+
+				env->ReleaseStringUTFChars(inFilePath, pMessageFile);
+			}
+		}
+	}
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA3("nativeConnect return ret=%d, osError=%d : %s\n", ret, osError, GetErrorText(osError));
+
+	TCDEBUGCLOSE();
+
+	if (ret != TCAPI_ERR_NONE && osError > 0)
+	{
+		jclass clazz = env->FindClass("Ljava/lang/Exception;");
+		env->ThrowNew(clazz, GetErrorText(osError));
+	}
+
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeDisconnect
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeDisconnect
+  (JNIEnv *env, jobject pThis, jlong inClientId)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeDisconnect\n");
+
+	if (gManager->m_Server == NULL)
+	{
+		TCDEBUGLOGS(" TCAPI_ERR_INVALID_HANDLE - gServer NULL\n");
+		ret = TCAPI_ERR_INVALID_HANDLE;
+	}
+	else if (inClientId <= 0)
+	{
+		TCDEBUGLOGS(" TCAPI_ERR_INVALID_HANDLE - inClientId <= 0\n");
+		ret = TCAPI_ERR_INVALID_HANDLE;
+	}
+	else
+	{
+		gManager->m_Server->WaitforServerPipeAccess();
+
+		BOOL found = FALSE;
+		long id = inClientId;
+
+		TCDEBUGLOGA1(" look for clientId=%d\n", id);
+
+		TCDEBUGLOGS(" TODO: tell server to disconnect this client\n");
+		ServerCommandData cmdrsp;
+		pServerCommandData pCmdrsp = &cmdrsp;
+		pCmdrsp->command = eCmdDisconnect;
+		pCmdrsp->clientId = id;
+
+		gManager->m_Server->SendCommand(pCmdrsp);
+		gManager->m_Server->GetResponse(pCmdrsp);
+		if (pCmdrsp->response == eRspError)
+		{
+			ret = pCmdrsp->error;
+		}
+
+		{
+			gManager->WaitForErrorMonitorListAccess();
+			TCDEBUGLOGS(" TODO: destroy error monitor for this client\n");
+			CErrorMonitor *monitor = gManager->FindErrorMonitor(id);
+			if (monitor != NULL)
+			{
+				gManager->RemoveErrorMonitor(monitor);
+				delete monitor;
+			}
+			gManager->ReleaseErrorMonitorListAccess();
+		}
+		gManager->m_Server->ReleaseServerPipeAccess();
+	}
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+	return ret;
+}
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeGetNumberConnections
+ * Signature: ([J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeGetNumberConnections
+  (JNIEnv *env, jobject pThis, jlongArray outNumber)
+{
+	long ret = TCAPI_ERR_NONE;
+	long number = 0;
+
+	TCDEBUGOPEN();
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	TCDEBUGLOGS("nativeGetNumberConnections\n");
+	ServerCommandData cmdrsp;
+	pServerCommandData pCmdrsp = &cmdrsp;
+	pCmdrsp->command = eCmdGetNumberConnections;
+
+	BOOL sent = gManager->m_Server->SendCommand(pCmdrsp);
+
+	BOOL recd = gManager->m_Server->GetResponse(pCmdrsp);
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+	else
+	{
+		number = pCmdrsp->numConnections;
+
+		jlong jNumber = number;
+		env->SetLongArrayRegion(outNumber, 0, 1, &jNumber);
+
+		TCDEBUGLOGA1(" number=%d\n", number);
+	}
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeGetTypeOfConnection
+ * Signature: (J[Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeGetTypeOfConnection
+  (JNIEnv *env, jobject pThis, jlong inIndex, jobjectArray outType)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	TCDEBUGLOGS("nativeGetTypeOfConnection\n");
+	ServerCommandData cmdrsp;
+	pServerCommandData pCmdrsp = &cmdrsp;
+	pCmdrsp->command = eCmdGetConnectionType;
+	pCmdrsp->index = inIndex;
+
+	BOOL sent = gManager->m_Server->SendCommand(pCmdrsp);
+
+	BOOL recd = gManager->m_Server->GetResponse(pCmdrsp);
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+	else
+	{
+		env->SetObjectArrayElement(outType, 0, env->NewStringUTF(pCmdrsp->connectSettings.connectType));
+	}
+
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+
+	return ret;
+}
+
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeGetConnectionSettings
+ * Signature: (J[Ljava/lang/String;[J[Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeGetConnectionSettings
+  (JNIEnv *env, jobject pThis, jlong inIndex, jobjectArray outType, jlongArray outOptions, jobjectArray outSettings)
+{
+	long ret = TCAPI_ERR_FEATURE_NOT_IMPLEMENTED;
+
+	TCDEBUGOPEN();
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	TCDEBUGLOGS("nativeGetConnectionSettings\n");
+	ServerCommandData cmdrsp;
+	pServerCommandData pCmdrsp = &cmdrsp;
+	pCmdrsp->command = eCmdGetConnection;
+	pCmdrsp->index = inIndex;
+
+	BOOL sent = gManager->m_Server->SendCommand(pCmdrsp);
+
+	BOOL recd = gManager->m_Server->GetResponse(pCmdrsp);
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+	else
+	{
+		env->SetObjectArrayElement(outType, 0, env->NewStringUTF(pCmdrsp->connectSettings.connectType));
+		if (strcmp(pCmdrsp->connectSettings.connectType, "musti") == 0 || strcmp(pCmdrsp->connectSettings.connectType, "platsim") == 0)
+		{
+			env->SetObjectArrayElement(outSettings, 0, env->NewStringUTF(pCmdrsp->connectSettings.tcpSettings.ipAddress));
+			env->SetObjectArrayElement(outSettings, 1, env->NewStringUTF(pCmdrsp->connectSettings.tcpSettings.ipPort));
+			char *pChan = NULL;
+			if (pCmdrsp->connectSettings.traceBoxChannel == 1)
+				pChan = "1";
+			else
+				pChan = "2";
+			env->SetObjectArrayElement(outSettings, 2, env->NewStringUTF(pChan));
+			env->SetObjectArrayElement(outSettings, 3, env->NewStringUTF(pCmdrsp->connectSettings.decodeFormat));
+		}
+		else if (strcmp(pCmdrsp->connectSettings.connectType, "tcp") == 0)
+		{
+			env->SetObjectArrayElement(outSettings, 0, env->NewStringUTF(pCmdrsp->connectSettings.tcpSettings.ipAddress));
+			env->SetObjectArrayElement(outSettings, 1, env->NewStringUTF(pCmdrsp->connectSettings.tcpSettings.ipPort));
+			env->SetObjectArrayElement(outSettings, 2, env->NewStringUTF(pCmdrsp->connectSettings.decodeFormat));
+		}
+		else if (strcmp(pCmdrsp->connectSettings.connectType, "virtualserial") == 0)
+		{
+			env->SetObjectArrayElement(outSettings, 0, env->NewStringUTF(pCmdrsp->connectSettings.virtualSerialSettings.comPort));
+			env->SetObjectArrayElement(outSettings, 1, env->NewStringUTF(pCmdrsp->connectSettings.decodeFormat));
+		}
+		else if (strcmp(pCmdrsp->connectSettings.connectType, "serial") == 0)
+		{
+			env->SetObjectArrayElement(outSettings, 0, env->NewStringUTF(pCmdrsp->connectSettings.realSerialSettings.comPort));
+
+			char baud[10], databits[10], parity[10], stopbits[10], flowcontrol[15];
+			ConvertRealSerialSettingsToHost(baud, databits, parity, stopbits, flowcontrol, &pCmdrsp->connectSettings.realSerialSettings);
+			env->SetObjectArrayElement(outSettings, 1, env->NewStringUTF(baud));
+			env->SetObjectArrayElement(outSettings, 2, env->NewStringUTF(databits));
+			env->SetObjectArrayElement(outSettings, 3, env->NewStringUTF(parity));
+			env->SetObjectArrayElement(outSettings, 4, env->NewStringUTF(stopbits));
+			env->SetObjectArrayElement(outSettings, 5, env->NewStringUTF(flowcontrol));
+			env->SetObjectArrayElement(outSettings, 6, env->NewStringUTF(pCmdrsp->connectSettings.decodeFormat));
+		}
+		else if (strcmp(pCmdrsp->connectSettings.connectType, "usb") == 0)
+		{
+			env->SetObjectArrayElement(outSettings, 0, env->NewStringUTF(pCmdrsp->connectSettings.usbSettings.device));
+		}
+		jlong jRetryInterval = pCmdrsp->connectSettings.retryInterval;
+		env->SetLongArrayRegion(outOptions, 0, 1, &jRetryInterval);
+		jlong jRetryTimeout = pCmdrsp->connectSettings.retryTimeout;
+		env->SetLongArrayRegion(outOptions, 1, 1, &jRetryTimeout);
+	}
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativePollError
+ * Signature: (J[I[Z[J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativePollError
+  (JNIEnv *env, jobject pThis, jlong inClientId, jintArray outErrorCode, 
+	jbooleanArray outHasOSErrorCode, jlongArray outOSErrorCode)
+{
+	jboolean foundError = false;
+	long id = inClientId;
+	LONG tcfError = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativePollError\n");
+//	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->WaitForErrorMonitorListAccess();
+
+	if (gManager->ErrorMonitorListSize() > 0)
+	{
+//		TCDEBUGLOGA1(" size of gManager->ErrorMonitorListSize=%d\n", gManager->ErrorMonitorListSize());
+
+		CErrorMonitor* errorMonitor = gManager->FindErrorMonitor(id);
+//		TCDEBUGLOGA1(" errorMonitor = %x\n", errorMonitor);
+
+		if (errorMonitor != NULL)
+		{
+//			TCDEBUGLOGS(" found client\n");
+
+			BOOL osErrorUsed = FALSE;
+			DWORD osError = 0;
+			BOOL found = errorMonitor->GetError(&tcfError, &osErrorUsed, &osError);
+			if (found)
+			{
+//				TCDEBUGLOGA1("nativePollError error for client=%d\n", inClientId);
+//				TCDEBUGLOGA3(" found tcfError=%d, osErrorUsed=%d, osError=%d\n",
+//					tcfError, osErrorUsed, osError);
+
+				foundError = true;
+				jint jval = tcfError;
+				env->SetIntArrayRegion(outErrorCode, 0, 1, &jval);
+				jboolean jos = osErrorUsed;
+				env->SetBooleanArrayRegion(outHasOSErrorCode, 0, 1, &jos);
+				jlong jlval = osError;
+				env->SetLongArrayRegion(outOSErrorCode, 0, 1, &jlval);
+
+//				TCDEBUGOPEN();
+//				TCDEBUGLOGS("nativePollError found error\n");
+//				TCDEBUGCLOSE();
+			}
+		}
+	}
+	gManager->ReleaseErrorMonitorListAccess();
+
+	TCDEBUGLOGA2(" return foundError=%d tcfError=%d\n", foundError, tcfError);
+
+	TCDEBUGCLOSE();
+	return foundError;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeGetNumberVersionEntities
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeGetNumberVersionEntities
+  (JNIEnv *env, jobject pThis, jlong inClientId)
+{
+	long number = 0;
+	long id = inClientId;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeGetNumberVersionEntities\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	// eCmdGetNumberVersions
+	ServerCommandData cmdrsp;
+	pServerCommandData pCmdrsp = &cmdrsp;
+	pCmdrsp->command = eCmdGetNumberVersions;
+	pCmdrsp->clientId = id;
+
+	BOOL sent = gManager->m_Server->SendCommand(pCmdrsp);
+
+	BOOL recd = gManager->m_Server->GetResponse(pCmdrsp);
+	if (pCmdrsp->response == eRspError)
+	{
+	}
+	else
+	{
+		number = pCmdrsp->number + 1; // + 1 for DLL version
+	}
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" numberVersions = %d\n", number);
+	TCDEBUGCLOSE();
+	return number;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeGetVersion
+ * Signature: (JJ[Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeGetVersion
+  (JNIEnv *env, jobject pThis, jlong inClientId, jlong inNumToGet, jobjectArray outVersion)
+{
+	long ret = TCAPI_ERR_NONE;
+	long id = inClientId;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeGetVersion\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	// eCmdGetVersion
+	ServerCommandData cmdrsp;
+	pServerCommandData pCmdrsp = &cmdrsp;
+	pCmdrsp->command = eCmdGetVersion;
+	pCmdrsp->clientId = id;
+
+
+	// index = 0 ==> TCFClient.dll version
+	env->SetObjectArrayElement(outVersion, 0, env->NewStringUTF(gManager->m_Version));
+	long numberGot = 1;
+
+	if (inNumToGet > 0)
+	{
+		// index = 1 ==> TCFServer.exe version
+		pCmdrsp->command = eCmdGetVersion;
+		pCmdrsp->clientId = id;
+		pCmdrsp->index = 1;
+		BOOL sent = gManager->m_Server->SendCommand(pCmdrsp);
+		BOOL recd = gManager->m_Server->GetResponse(pCmdrsp);
+		if (pCmdrsp->response == eRspOK)
+		{
+			env->SetObjectArrayElement(outVersion, 1, env->NewStringUTF(pCmdrsp->version));
+			numberGot++;
+
+			if (inNumToGet > 1)
+			{
+				// index = 2 ==> connection version
+				pCmdrsp->command = eCmdGetVersion;
+				pCmdrsp->clientId = id;
+				pCmdrsp->index = 2;
+				BOOL sent = gManager->m_Server->SendCommand(pCmdrsp);
+				BOOL recd = gManager->m_Server->GetResponse(pCmdrsp);
+				if (pCmdrsp->response == eRspOK)
+				{
+					env->SetObjectArrayElement(outVersion, 2, env->NewStringUTF(pCmdrsp->version));
+					numberGot++;
+				}
+			}
+		}
+	}
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return numberGot=%d\n", numberGot);
+	TCDEBUGCLOSE();
+	return numberGot;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativePollInputStream
+ * Signature: (J[J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativePollInputStream
+  (JNIEnv *env, jobject pThis, jlong inClientId, jlongArray outNumberMessages)
+{
+	long ret = TCAPI_ERR_NONE;
+	long number = 0;
+	long id = inClientId;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativePollInputStream\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	TCDEBUGLOGS(" TODO: get number from client's input stream\n");
+
+	gManager->WaitForStreamListAccess();
+
+	CInputStream* inputStream = gManager->FindInputStream(id);
+
+	if (inputStream != NULL)
+	{
+		TCDEBUGLOGA1(" -- found id inputStream=%x\n", inputStream);
+		number = inputStream->GetNumberMessages();
+	}
+
+	gManager->ReleaseStreamListAccess();
+	jlong jNumber = number;
+	env->SetLongArrayRegion(outNumberMessages, 0, 1, &jNumber);
+
+	TCDEBUGLOGA2(" numberMessages=%d ret=%d\n", number, ret);
+
+	TCDEBUGCLOSE();
+	return ret;
+}
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativePollInputStream2
+ * Signature: (JJ[J[J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativePollInputStream2
+  (JNIEnv *env, jobject pThis, jlong inClientId, jlong inNumberMessagesToPeek, jlongArray outNumberMessagesPeeked, jlongArray outNumberBytesPeeked)
+{
+	long ret = TCAPI_ERR_NONE;
+	long id = inClientId;
+	long numberToGet = inNumberMessagesToPeek;
+	long numberStored = 0;
+	DWORD numberBytes = 0;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativePollInputStream2\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->WaitForStreamListAccess();
+
+	CInputStream* inputStream = gManager->FindInputStream(id);
+
+	if (inputStream != NULL)
+	{
+		TCDEBUGLOGA1(" -- found id inputStream=%x\n", inputStream);
+		numberStored = inputStream->GetNumberMessages();
+
+		if ((numberToGet == 0) || (numberToGet > numberStored))
+		{
+			numberToGet = numberStored;
+		}
+		if (numberToGet > 0)
+		{
+			inputStream->GetTotalMessageSize(numberToGet, numberBytes);
+		}
+	}
+
+	gManager->ReleaseStreamListAccess();
+
+	jlong jNumber = numberToGet;
+	env->SetLongArrayRegion(outNumberMessagesPeeked, 0, 1, &jNumber);
+	jNumber = numberBytes;
+	env->SetLongArrayRegion(outNumberBytesPeeked, 0, 1, &jNumber);
+
+	TCDEBUGLOGA3(" numberMessages=%d numberBytes=%d ret=%d\n", numberToGet, numberBytes, ret);
+
+	TCDEBUGCLOSE();
+	return ret;
+}
+
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeGetInputStreamMessageBytes
+ * Signature: (JJ[J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeGetInputStreamMessageBytes
+  (JNIEnv *env, jobject pThis, jlong inClientId, jlong inNumberMessages, jlongArray outMessageSizes)
+{
+	long ret = TCAPI_ERR_NONE;
+	long id = inClientId;
+	long numberToGet = inNumberMessages;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeGetInputStreamMessageBytes\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->WaitForStreamListAccess();
+
+	CInputStream* inputStream = gManager->FindInputStream(id);
+
+	if (inputStream != NULL)
+	{
+		TCDEBUGLOGA1(" -- found id inputStream=%x\n", inputStream);
+		DWORD* pSizes = new DWORD[numberToGet];
+		inputStream->GetMessageSizes(numberToGet, pSizes);
+		for (int i = 0; i < numberToGet; i++)
+		{
+			TCDEBUGLOGA2(" -- message size[%d] = %d\n", i, pSizes[i]);
+			jlong jsize = pSizes[i];
+			env->SetLongArrayRegion(outMessageSizes, i, 1, &jsize);
+		}
+		delete[] pSizes;
+	}
+
+	gManager->ReleaseStreamListAccess();
+
+	TCDEBUGLOGA1("nativeGetInputStreamMessageBytes ret=%d\n", ret);
+
+	TCDEBUGCLOSE();
+
+	return ret;
+}
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeReadInputStream
+ * Signature: (JJ[J[JJ[B)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeReadInputStream
+  (JNIEnv *env, jobject pThis, jlong inClientId, jlong inNumberMessages, jlongArray outNumberMessages, jlongArray outNumberBytesRead, jlong inNumberMaxBytes, jbyteArray outMessageData)
+{
+	long ret = TCAPI_ERR_NONE;
+	long id = inClientId;
+	long numberToGet = inNumberMessages;
+	long numberMaxBytes = inNumberMaxBytes;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeReadInputStream start\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->WaitForStreamListAccess();
+
+	CInputStream* inputStream = gManager->FindInputStream(id);
+	if (inputStream != NULL)
+	{
+		long numberBytesRead = 0;
+		long numberMessagesRead = 0;
+#if (0)
+		DWORD mSize = 0;
+		DWORD outOffset = 0;
+		BYTE* pData = new BYTE[64*1024];
+		for (int i = 0; i < numberToGet; i++)
+		{
+			TCDEBUGLOGS("nativeReadInputStream 1\n");
+			mSize = inputStream->GetNextMessageSize();
+			if ((numberBytesRead + mSize) > numberMaxBytes)
+				break;
+			if (mSize != 0)
+			{
+				mSize = inputStream->GetNextMessage(mSize, pData);
+				TCDEBUGLOGA3("outOffset = %d mSize = %d pData[0] = %02.2x\n", outOffset, mSize, pData[0]);
+				jbyte* pByte = (jbyte*)pData;
+				env->SetByteArrayRegion(outMessageData, outOffset, mSize, pByte);
+				outOffset += mSize;
+				numberBytesRead += mSize;
+				numberMessagesRead++;
+
+				if ((i % 500) == 0)
+					Sleep(1);
+			}
+		}
+		delete [] pData;
+#endif
+		numberMessagesRead = inputStream->GetMessages(env, numberToGet, numberMaxBytes, numberBytesRead, numberMessagesRead, outMessageData);
+		jlong jMsgs = numberMessagesRead;
+		env->SetLongArrayRegion(outNumberMessages, 0, 1, &jMsgs);
+		jlong jNum = numberBytesRead;
+		env->SetLongArrayRegion(outNumberBytesRead, 0, 1, &jNum);
+
+		TCDEBUGLOGS("nativeReadInputStream 2\n");
+	}
+
+	gManager->ReleaseStreamListAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeOpenInputStream
+ * Signature: (JLjava/lang/String;JZ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeOpenInputStream
+  (JNIEnv *env, jobject pThis, jlong inClientId, jstring inFileBaseName, jlong inStreamSize, jboolean inOverflowToFile)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeOpenInputStream\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+	TCDEBUGLOGA1(" inFileBaseName=%x\n", inFileBaseName);
+	TCDEBUGLOGA1(" inStreamSize=%d\n", inStreamSize);
+	TCDEBUGLOGA1(" inOverflowToFile=%d\n", inOverflowToFile);
+
+	gManager->m_Server->WaitforServerPipeAccess();
+	gManager->WaitForStreamListAccess();
+
+	char* pFileName = NULL;
+
+	if (inFileBaseName != NULL)
+	{
+		TCDEBUGLOGS("nativeOpenInputStream GetStringUTFChars on inFileBaseName\n");
+		jboolean isCopy=FALSE;
+		pFileName = (char*)env->GetStringUTFChars(inFileBaseName, &isCopy);
+		TCDEBUGLOGS("nativeOpenInputStream return GetStringUTFChars\n");
+		TCDEBUGLOGA1(" pFileName=%x\n", pFileName);
+//		if (pFileName != NULL)
+//		{
+//			TCDEBUGLOGA1(" pFileName=%s\n", pFileName);
+//		}
+	}
+	else
+	{
+		TCDEBUGLOGS("nativeOpenInputStream inFileBaseName == NULL\n");
+	}
+
+
+	TCDEBUGLOGS("nativeOpenInputStream continue after GetStringUTFChars\n");
+	DWORD streamSize = inStreamSize;
+	TCDEBUGLOGA1(" streamSize=%d\n", streamSize);
+
+	BOOL overflowOption = FALSE;
+	TCDEBUGLOGA1(" overflowOption=%d\n", overflowOption);
+
+	long id = inClientId;
+
+	TCDEBUGLOGA1(" gManager->InputStreamListSize=%d\n", gManager->InputStreamListSize());
+
+	// create stream
+	CInputStream* stream = new CInputStream(pFileName, streamSize, overflowOption, id);
+	stream->CreateStream();
+	gManager->AddInputStream(stream);
+
+	ServerCommandData cmdrsp; pServerCommandData pCmdrsp = &cmdrsp;
+	pCmdrsp->command = eCmdOpenStream;
+	pCmdrsp->clientId = id;
+	pCmdrsp->destinationOptions.destination = eDestinationInputStream;
+	pCmdrsp->destinationOptions.streamSize = streamSize;
+	pCmdrsp->destinationOptions.overFlowToFile = FALSE;
+	if (pFileName != NULL)
+	{
+		strncpy(pCmdrsp->destinationOptions.destinationFile, pFileName, MAX_FILEPATH);
+	}
+	else
+	{
+		pCmdrsp->destinationOptions.destinationFile[0] = NULL;
+	}
+	if (inFileBaseName != NULL)
+	{
+		TCDEBUGLOGS("nativeOpenInputStream ReleaseStringUTFChars on inFileBaseName\n");
+		env->ReleaseStringUTFChars(inFileBaseName, pFileName);
+	}
+
+	gManager->m_Server->SendCommand(pCmdrsp);
+	gManager->m_Server->GetResponse(pCmdrsp);
+
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+
+	TCDEBUGLOGA1(" gManager->InputStreamListSize=%d\n", gManager->InputStreamListSize());
+
+	gManager->ReleaseStreamListAccess();
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeCloseInputStream
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeCloseInputStream
+  (JNIEnv *env, jobject pThis, jlong inClientId)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeCloseInputStream\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+	
+	gManager->m_Server->WaitforServerPipeAccess();
+	gManager->WaitForStreamListAccess();
+
+	long id = inClientId;
+
+	TCDEBUGLOGA1(" gManager->InputStreamListSize=%d\n", gManager->InputStreamListSize());
+
+	TCDEBUGLOGS(" TODO: tell server to close this stream\n");
+
+	ServerCommandData cmdrsp; pServerCommandData pCmdrsp = &cmdrsp;
+	pCmdrsp->command = eCmdCloseStream;
+	pCmdrsp->clientId = id;
+
+	gManager->m_Server->SendCommand(pCmdrsp);
+	gManager->m_Server->GetResponse(pCmdrsp);
+
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+
+	CInputStream* inputStream = gManager->FindInputStream(id);
+	if (inputStream != NULL)
+	{
+		TCDEBUGLOGA1(" -- found id inputStream=%x\n", inputStream);
+		gManager->RemoveInputStream(inputStream);
+		delete inputStream;
+	}
+
+	TCDEBUGLOGA1(" gManager->InputStreamListSize=%d\n", gManager->InputStreamListSize());
+	gManager->ReleaseStreamListAccess();
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeSetMessageIds
+ * Signature: (J[B)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeSetMessageIds
+  (JNIEnv *env, jobject pThis, jlong inClientId, jbyteArray inIds)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeSetMessageIds\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	ServerCommandData cmdrsp; pServerCommandData pCmdrsp = &cmdrsp;
+
+	pCmdrsp->command = eCmdSetMessageIds;
+	pCmdrsp->clientId = inClientId;
+	jsize numberIds = env->GetArrayLength(inIds);
+	pCmdrsp->number = numberIds;
+	jboolean isCopy = FALSE;
+	jbyte* bytes = env->GetByteArrayElements(inIds, &isCopy);
+	for (int i = 0; i < numberIds; i++)
+	{
+		pCmdrsp->messageIds[i] = bytes[i];
+		TCDEBUGLOGA1(" -- msgId = 0x%02.2X\n",  pCmdrsp->messageIds[i]);
+	}
+	env->ReleaseByteArrayElements(inIds, bytes, 0);
+	gManager->m_Server->SendCommand(pCmdrsp);
+	gManager->m_Server->GetResponse(pCmdrsp);
+
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeClearFile
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeClearFile
+  (JNIEnv *env, jobject pThis, jlong inClientId)
+{
+	long ret = TCAPI_ERR_NONE;
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	long id = inClientId;
+
+	ServerCommandData cmdrsp;
+	pServerCommandData pCmdrsp = &cmdrsp;
+	pCmdrsp->command = eCmdClearMessageFile;
+	pCmdrsp->clientId = id;
+
+	gManager->m_Server->SendCommand(pCmdrsp);
+	gManager->m_Server->GetResponse(pCmdrsp);
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeSendMessage
+ * Signature: (J[J[Ljava/lang/String;[B)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeSendMessage
+  (JNIEnv *env, jobject pThis, jlong inClientId, jlongArray inFormattingOptions, jobjectArray inSettings, jbyteArray inMessage)
+{
+	long ret = TCAPI_ERR_NONE;
+	unsigned long osError = 0;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeSendMessage\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	jboolean isCopy = false;
+	// formatting options
+	jlong* pOptions = env->GetLongArrayElements(inFormattingOptions, &isCopy);
+//	long encodeFormat = (long)pOptions[0];	// not used
+	long encodeOption = (long)pOptions[1];	// formatting option for protocol
+	long protocolVersion = (long)pOptions[2];	// OST version byte to use if protocol is OST
+	BYTE myId = (BYTE)(pOptions[3] & 0xff);	// my message ID to use of adding protocol
+	BOOL useMyId = (pOptions[4] == 1) ? TRUE : FALSE;	// use my ID or not
+	env->ReleaseLongArrayElements(inFormattingOptions, pOptions, 0);
+
+	jstring decodeString = (jstring)env->GetObjectArrayElement(inSettings, 0);
+	const char* pDecode = env->GetStringUTFChars(decodeString, NULL); // not used
+	env->ReleaseStringUTFChars(decodeString, pDecode);
+
+	jsize numberBytes = 0;
+	if (inMessage != NULL)
+		numberBytes = env->GetArrayLength(inMessage);
+	long inLength = numberBytes;		// this can be null
+
+	jbyte* inData = NULL;
+	if (inLength > 0)
+		inData = env->GetByteArrayElements(inMessage, &isCopy);
+
+	ServerCommandData cmdrsp; pServerCommandData pCmdrsp = &cmdrsp;
+
+	pCmdrsp->command = eCmdSendMessage;
+	pCmdrsp->clientId = inClientId;
+	pCmdrsp->encodeOption = encodeOption;
+	pCmdrsp->useMyId = useMyId;
+	pCmdrsp->myId = myId;
+	pCmdrsp->protocolVersion = protocolVersion & 0xff;
+
+	// send message to server
+	pCmdrsp->osError = 0;
+	gManager->m_Server->SendCommand(pCmdrsp, inLength, (BYTE*)inData);
+
+	TCDEBUGLOGS(" nativeSendMessage  GetResponse\n");
+
+	// get response from server
+	gManager->m_Server->GetResponse(pCmdrsp);
+
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+		osError = pCmdrsp->osError;
+	}
+	if (inData != NULL)
+		env->ReleaseByteArrayElements(inMessage, inData, 0);
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA3("nativeSendMessage return ret=%d, osError=%d : %s\n", ret, osError, GetErrorText(osError));
+	TCDEBUGCLOSE();
+
+	if (ret == TCAPI_ERR_COMM_ERROR && osError > 0)
+	{
+		jclass clazz = env->FindClass("Ljava/lang/Exception;");
+		env->ThrowNew(clazz, GetErrorText(osError));
+	}
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeStart
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeStart
+  (JNIEnv *env, jobject pThis, jlong inClientId)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeStart\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	TCDEBUGLOGS(" TODO: tell server to start this client\n");
+	ServerCommandData cmdrsp; pServerCommandData pCmdrsp = &cmdrsp;
+
+	pCmdrsp->command = eCmdStart;
+	pCmdrsp->clientId = inClientId;
+
+	gManager->m_Server->SendCommand(pCmdrsp);
+
+	gManager->m_Server->GetResponse(pCmdrsp);
+
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeStop
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeStop
+  (JNIEnv *env, jobject pThis, jlong inClientId)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeStop\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	TCDEBUGLOGS(" TODO: tell server to stop this client\n");
+	ServerCommandData cmdrsp; pServerCommandData pCmdrsp = &cmdrsp;
+
+	pCmdrsp->command = eCmdStop;
+	pCmdrsp->clientId = inClientId;
+
+	gManager->m_Server->SendCommand(pCmdrsp);
+
+	gManager->m_Server->GetResponse(pCmdrsp);
+
+	if (pCmdrsp->response == eRspError)
+	{
+		ret = pCmdrsp->error;
+	}
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeTestConnection
+ * Signature: (I[J[Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeTestConnection__I_3J_3Ljava_lang_String_2
+  (JNIEnv *env, jobject pThis, jint inType, jlongArray inOptions, jobjectArray inSettings)
+{
+	long ret = TCAPI_ERR_FEATURE_NOT_IMPLEMENTED;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeTestConnection\n");
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	TCDEBUGLOGS(" TODO: ask server to test this connection\n");
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeTestConnection
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeTestConnection__J
+  (JNIEnv *env, jobject pThis, jlong inClientId)
+{
+	long ret = TCAPI_ERR_FEATURE_NOT_IMPLEMENTED;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeTestConnection\n");
+	TCDEBUGLOGA1(" inClientId=%d\n", inClientId);
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	TCDEBUGLOGS(" TODO: ask server to test this client's connection\n");
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+
+	return ret;
+}
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeStartServer
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeStartServer
+  (JNIEnv *env, jobject pThis)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeStartServer\n");
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	ret = gManager->StartServer();
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+
+	return ret;
+}
+
+/*
+ * Class:     com_nokia_tcf_impl_TCAPIConnection
+ * Method:    nativeStopServer
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_nokia_tcf_impl_TCAPIConnection_nativeStopServer
+  (JNIEnv *env, jobject pThis)
+{
+	long ret = TCAPI_ERR_NONE;
+
+	TCDEBUGOPEN();
+	TCDEBUGLOGS("nativeStopServer\n");
+
+	gManager->m_Server->WaitforServerPipeAccess();
+
+	ret = gManager->StopServer();
+
+	gManager->m_Server->ReleaseServerPipeAccess();
+
+	TCDEBUGLOGA1(" return ret=%d\n", ret);
+	TCDEBUGCLOSE();
+
+	return ret;
+}
+
+void ConvertRealSerialSettingsToServer(const char* pBaud, const char* pDataBits, const char* pParity, const char* pStopBits, const char* pFlowControl, pRealSerialConnectData pData)
+{
+	// no error checking - all error checking is done at the Java level
+	pData->baudRate = atol(pBaud);
+	pData->dataBits = atol(pDataBits);
+
+	pData->parity = eParityNone;
+	if (strcmp(pParity, "odd") == 0)
+	{
+		pData->parity = eParityOdd;
+	}
+	else if (strcmp(pParity, "even") == 0)
+	{
+		pData->parity = eParityEven;
+	}
+
+	pData->stopBits = eStopBits1;
+	if (strcmp(pStopBits, "1.5") == 0)
+	{
+		pData->stopBits = eStopBits15;
+	}
+	else if (strcmp(pStopBits, "2") == 0)
+	{
+		pData->stopBits = eStopBits2;
+	}
+
+	pData->flowControl = eFlowControlNone;
+	if (strcmp(pFlowControl, "software") == 0)
+	{
+		pData->flowControl = eFlowControlSW;
+	} 
+	else if (strcmp(pFlowControl, "hardware") == 0)
+	{
+		pData->flowControl = eFlowControlHW;
+	}
+}
+void ConvertRealSerialSettingsToHost(char* pBaud, char* pDataBits, char* pParity, char* pStopBits, char* pFlowControl, pRealSerialConnectData pData)
+{
+	sprintf(pBaud, "%ld", pData->baudRate);
+	sprintf(pDataBits, "%ld", pData->dataBits);
+
+	switch (pData->parity)
+	{
+	default:
+	case eParityNone:
+		strcpy(pParity, "none");
+		break;
+	case eParityEven:
+		strcpy(pParity, "even");
+		break;
+	case eParityOdd:
+		strcpy(pParity, "odd");
+		break;
+	}
+
+	switch (pData->stopBits)
+	{
+	default:
+	case eStopBits1:
+		strcpy(pStopBits, "1");
+		break;
+	case eStopBits15:
+		strcpy(pStopBits, "1.5");
+		break;
+	case eStopBits2:
+		strcpy(pStopBits, "2");
+		break;
+	}
+	
+	switch (pData->flowControl)
+	{
+	default:
+	case eFlowControlNone:
+		strcpy(pFlowControl, "none");
+		break;
+	case eFlowControlHW:
+		strcpy(pFlowControl, "hardware");
+		break;
+	case eFlowControlSW:
+		strcpy(pFlowControl, "software");
+		break;
+	}
+}
+
+#ifdef _DEBUG
+void OpenLogFile1(char* filename)
+{
+	if (fLog1 == NULL)
+		fLog1 = _fsopen(filename, "at", _SH_DENYNO);
+}
+
+void CloseLogFile1()
+{
+	if (fLog1 != NULL)
+	{
+		fclose(fLog1);
+		fLog1 = NULL;
+	}
+}
+void OpenLogFile2(char* filename)
+{
+	if (fLog2 == NULL)
+		fLog2 = _fsopen(filename, "at", _SH_DENYNO);
+}
+
+void CloseLogFile2()
+{
+	if (fLog2 != NULL)
+	{
+		fclose(fLog2);
+		fLog2 = NULL;
+	}
+}
+void LogTime(FILE* f)
+{
+	SYSTEMTIME sTime;
+	GetLocalTime(&sTime);
+	if (f)
+		fprintf(f, "%02.2d%02.2d-%02.2d:%02.2d:%02.2d.%03.3d: ", sTime.wDay, sTime.wMonth, sTime.wHour, sTime.wMinute, sTime.wSecond, sTime.wMilliseconds);
+}
+#endif
+
+static const char* GetErrorText(unsigned long error)
+{
+	if (error == ERROR_FILE_NOT_FOUND)
+		return "Could not open the device\n";
+
+	else if (error == ERROR_ACCESS_DENIED)
+		return "The device is currently in use\n";
+
+	static char msg[256];
+	FormatMessage(
+		FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		error,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+		(LPTSTR) &msg,
+		sizeof(msg) - 1,
+		NULL);
+
+	return msg;
+}