diff options
Diffstat (limited to 'nci/jni/PeerToPeer.cpp')
| -rw-r--r-- | nci/jni/PeerToPeer.cpp | 2158 |
1 files changed, 2158 insertions, 0 deletions
diff --git a/nci/jni/PeerToPeer.cpp b/nci/jni/PeerToPeer.cpp new file mode 100644 index 0000000..4c02da2 --- /dev/null +++ b/nci/jni/PeerToPeer.cpp @@ -0,0 +1,2158 @@ +/***************************************************************************** +** +** Name: PeerToPeer.cpp +** +** Description: Communicate with a peer using NFC-DEP, LLCP, SNEP. +** +** Copyright (c) 2012, Broadcom Corp., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ +#include "PeerToPeer.h" +#include "NfcJniUtil.h" +#include "llcp_defs.h" +#include "config.h" + +namespace android +{ + extern jmethodID gCachedNfcManagerNotifyLlcpLinkActivation; + extern jmethodID gCachedNfcManagerNotifyLlcpLinkDeactivated; + extern void nativeNfcTag_registerNdefTypeHandler (); + extern void nativeNfcTag_deregisterNdefTypeHandler (); +} + + +PeerToPeer PeerToPeer::sP2p; +const std::string PeerToPeer::sSnepServiceName ("urn:nfc:sn:snep"); +const std::string PeerToPeer::sNppServiceName ("com.android.npp"); + + +/******************************************************************************* +** +** Function: PeerToPeer +** +** Description: Initialize member variables. +** +** Returns: None +** +*******************************************************************************/ +PeerToPeer::PeerToPeer () +: mRemoteWKS (0), + mIsP2pListening (false), + mP2pListenTechMask (NFA_TECHNOLOGY_MASK_A + | NFA_TECHNOLOGY_MASK_F + | NFA_TECHNOLOGY_MASK_A_ACTIVE + | NFA_TECHNOLOGY_MASK_F_ACTIVE), + mJniHandleSendingNppViaSnep (0), + mSnepRegHandle (NFA_HANDLE_INVALID), + mRcvFakeNppJniHandle (0), + mNppFakeOutBuffer (NULL), + mNppTotalLen (0), + mNppReadSoFar (0), + mNdefTypeHandlerHandle (NFA_HANDLE_INVALID), + mAppLogLevel (1), + mJniVersion (403) +{ + unsigned long num = 0; + memset (mServers, 0, sizeof(mServers)); + memset (mClients, 0, sizeof(mClients)); + if (GetNumValue ("APPL_TRACE_LEVEL", &num, sizeof (num))) + mAppLogLevel = num; + + if (GetNumValue ("P2P_LISTEN_TECH_MASK", &num, sizeof (num))) + mP2pListenTechMask = num; +} + + +/******************************************************************************* +** +** Function: ~PeerToPeer +** +** Description: Free all resources. +** +** Returns: None +** +*******************************************************************************/ +PeerToPeer::~PeerToPeer () +{ +} + + +/******************************************************************************* +** +** Function: getInstance +** +** Description: Get the singleton PeerToPeer object. +** +** Returns: Singleton PeerToPeer object. +** +*******************************************************************************/ +PeerToPeer& PeerToPeer::getInstance () +{ + return sP2p; +} + + +/******************************************************************************* +** +** Function: initialize +** +** Description: Initialize member variables. +** jniVersion: JNI version. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::initialize (long jniVersion) +{ + ALOGD ("PeerToPeer::initialize"); + mJniVersion = jniVersion; +} + + +/******************************************************************************* +** +** Function: findServer +** +** Description: Find a PeerToPeer object by connection handle. +** nfaP2pServerHandle: Connectin handle. +** +** Returns: PeerToPeer object. +** +*******************************************************************************/ +P2pServer *PeerToPeer::findServer (tNFA_HANDLE nfaP2pServerHandle) +{ + for (int i = 0; i < sMax; i++) + { + if ( (mServers[i] != NULL) + && (mServers[i]->mNfaP2pServerHandle == nfaP2pServerHandle) ) + { + return (mServers [i]); + } + } + + // If here, not found + return NULL; +} + + +/******************************************************************************* +** +** Function: findServer +** +** Description: Find a PeerToPeer object by connection handle. +** serviceName: service name. +** +** Returns: PeerToPeer object. +** +*******************************************************************************/ +P2pServer *PeerToPeer::findServer (tBRCM_JNI_HANDLE jniHandle) +{ + for (int i = 0; i < sMax; i++) + { + if ( (mServers[i] != NULL) + && (mServers[i]->mJniHandle == jniHandle) ) + { + return (mServers [i]); + } + } + + // If here, not found + return NULL; +} + + +/******************************************************************************* +** +** Function: findServer +** +** Description: Find a PeerToPeer object by service name +** serviceName: service name. +** +** Returns: PeerToPeer object. +** +*******************************************************************************/ +P2pServer *PeerToPeer::findServer (const char *serviceName) +{ + for (int i = 0; i < sMax; i++) + { + if ( (mServers[i] != NULL) && (mServers[i]->mServiceName.compare(serviceName) == 0) ) + return (mServers [i]); + } + + // If here, not found + return NULL; +} + + +/******************************************************************************* +** +** Function: registerServer +** +** Description: Let a server start listening for peer's connection request. +** jniHandle: Connection handle. +** serviceName: Server's service name. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::registerServer (tBRCM_JNI_HANDLE jniHandle, const char *serviceName) +{ + static const char fn [] = "PeerToPeer::registerServer"; + ALOGD ("%s: enter; service name: %s JNI handle: %u", fn, serviceName, jniHandle); + tNFA_STATUS stat = NFA_STATUS_OK; + P2pServer *pSrv = NULL; + UINT8 serverSap = NFA_P2P_ANY_SAP; + + // Check if already registered + if ((pSrv = findServer(serviceName)) != NULL) + { + ALOGD ("%s: service name=%s already registered, handle: 0x%04x", fn, serviceName, pSrv->mNfaP2pServerHandle); + + // Update JNI handle + pSrv->mJniHandle = jniHandle; + return (true); + } + + for (int ii = 0; ii < sMax; ii++) + { + if (mServers[ii] == NULL) + { + pSrv = mServers[ii] = new P2pServer; + pSrv->mServiceName.assign (serviceName); + pSrv->mJniHandle = jniHandle; + + ALOGD ("%s: added new p2p server index: %d handle: %u name: %s", fn, ii, jniHandle, serviceName); + break; + } + } + + if (pSrv == NULL) + { + ALOGE ("%s: service name=%s no free entry", fn, serviceName); + return (false); + } + + /********************** + default values for all LLCP parameters: + - Local Link MIU (LLCP_MIU) + - Option parameter (LLCP_OPT_VALUE) + - Response Waiting Time Index (LLCP_WAITING_TIME) + - Local Link Timeout (LLCP_LTO_VALUE) + - Inactivity Timeout as initiator role (LLCP_INIT_INACTIVITY_TIMEOUT) + - Inactivity Timeout as target role (LLCP_TARGET_INACTIVITY_TIMEOUT) + - Delay SYMM response (LLCP_DELAY_RESP_TIME) + - Data link connection timeout (LLCP_DATA_LINK_CONNECTION_TOUT) + - Delay timeout to send first PDU as initiator (LLCP_DELAY_TIME_TO_SEND_FIRST_PDU) + ************************/ + stat = NFA_P2pSetLLCPConfig (LLCP_MIU, + LLCP_OPT_VALUE, + LLCP_WAITING_TIME, + LLCP_LTO_VALUE, + 0, //use 0 for infinite timeout for symmetry procedure when acting as initiator + 0, //use 0 for infinite timeout for symmetry procedure when acting as target + LLCP_DELAY_RESP_TIME, + LLCP_DATA_LINK_CONNECTION_TOUT, + LLCP_DELAY_TIME_TO_SEND_FIRST_PDU); + if (stat != NFA_STATUS_OK) + ALOGE ("%s: fail set LLCP config; error=0x%X", fn, stat); + + if (sSnepServiceName.compare(serviceName) == 0) + serverSap = LLCP_SAP_SNEP; //LLCP_SAP_SNEP == 4 + + SyncEventGuard guard (pSrv->mListenEvent); + stat = NFA_P2pRegisterServer (serverSap, NFA_P2P_DLINK_TYPE, const_cast<char*>(serviceName), nfaServerCallback); + if (stat != NFA_STATUS_OK) + { + ALOGE ("%s: fail register p2p server; error=0x%X", fn, stat); + removeServer (jniHandle); + return (false); + } + ALOGD ("%s: wait for listen-completion event", fn); + // Wait for NFA_P2P_LISTEN_EVT + pSrv->mListenEvent.wait (); + + if (pSrv->mNfaP2pServerHandle == NFA_HANDLE_INVALID) + { + ALOGE ("%s: invalid server handle", fn); + removeServer (jniHandle); + return (false); + } + else + { + ALOGD ("%s: got new p2p server h=0x%X", fn, pSrv->mNfaP2pServerHandle); + return (true); + } +} + + +/******************************************************************************* +** +** Function: removeServer +** +** Description: Free resources related to a server. +** jniHandle: Connection handle. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::removeServer (tBRCM_JNI_HANDLE jniHandle) +{ + static const char fn [] = "PeerToPeer::removeServer"; + + for (int i = 0; i < sMax; i++) + { + if ( (mServers[i] != NULL) && (mServers[i]->mJniHandle == jniHandle) ) + { + ALOGD ("%s: server jni_handle: %u; nfa_handle: 0x%04x; name: %s; index=%d", + fn, jniHandle, mServers[i]->mNfaP2pServerHandle, mServers[i]->mServiceName.c_str(), i); + + delete mServers [i]; + mServers [i] = NULL; + return; + } + } + ALOGE ("%s: unknown server jni handle: %u", fn, jniHandle); +} + + +/******************************************************************************* +** +** Function: llcpActivatedHandler +** +** Description: Receive LLLCP-activated event from stack. +** nat: JVM-related data. +** activated: Event data. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::llcpActivatedHandler (nfc_jni_native_data* nat, tNFA_LLCP_ACTIVATED& activated) +{ + static const char fn [] = "PeerToPeer::llcpActivatedHandler"; + ALOGD ("%s: enter", fn); + JNIEnv* e = NULL; + jclass tag_cls = NULL; + jobject tag = NULL; + jmethodID ctor = 0; + jfieldID f = 0; + + //no longer need to receive NDEF message from a tag + android::nativeNfcTag_deregisterNdefTypeHandler (); + + //register a type handler in case we need to send NDEF messages received from SNEP through NPP + mNdefTypeHandlerHandle = NFA_HANDLE_INVALID; + NFA_RegisterNDefTypeHandler (TRUE, NFA_TNF_DEFAULT, (UINT8 *)"", 0, ndefTypeCallback); + + mRemoteWKS = activated.remote_wks; + + nat->vm->AttachCurrentThread (&e, NULL); + if (e == NULL) + { + ALOGE ("%s: jni env is null", fn); + return; + } + + ALOGD ("%s: get object class", fn); + tag_cls = e->GetObjectClass (nat->cached_P2pDevice); + if (e->ExceptionCheck()) + { + e->ExceptionClear(); + ALOGE ("%s: fail get p2p device", fn); + goto TheEnd; + } + + ALOGD ("%s: instantiate", fn); + /* New target instance */ + ctor = e->GetMethodID (tag_cls, "<init>", "()V"); + tag = e->NewObject (tag_cls, ctor); + + /* Set P2P Target mode */ + f = e->GetFieldID (tag_cls, "mMode", "I"); + + if (activated.is_initiator == TRUE) + { + ALOGD ("%s: p2p initiator", fn); + e->SetIntField (tag, f, (jint) MODE_P2P_INITIATOR); + } + else + { + ALOGD ("%s: p2p target", fn); + e->SetIntField (tag, f, (jint) MODE_P2P_TARGET); + } + + /* Set tag handle */ + f = e->GetFieldID (tag_cls, "mHandle", "I"); + e->SetIntField (tag, f, (jint) 0x1234); // ?? This handle is not used for anything + + if (nat->tag != NULL) + { + e->DeleteGlobalRef (nat->tag); + } + nat->tag = e->NewGlobalRef (tag); + + ALOGD ("%s: notify nfc service", fn); + + /* Notify manager that new a P2P device was found */ + e->CallVoidMethod (nat->manager, android::gCachedNfcManagerNotifyLlcpLinkActivation, tag); + if (e->ExceptionCheck()) + { + e->ExceptionClear(); + ALOGE ("%s: fail notify", fn); + } + + e->DeleteLocalRef (tag); + +TheEnd: + nat->vm->DetachCurrentThread (); + ALOGD ("%s: exit", fn); +} + + +/******************************************************************************* +** +** Function: llcpDeactivatedHandler +** +** Description: Receive LLLCP-deactivated event from stack. +** nat: JVM-related data. +** deactivated: Event data. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::llcpDeactivatedHandler (nfc_jni_native_data* nat, tNFA_LLCP_DEACTIVATED& deactivated) +{ + static const char fn [] = "PeerToPeer::llcpDeactivatedHandler"; + ALOGD ("%s: enter", fn); + JNIEnv* e = NULL; + + nat->vm->AttachCurrentThread (&e, NULL); + if (e == NULL) + { + ALOGE ("%s: jni env is null", fn); + return; + } + + ALOGD ("%s: notify nfc service", fn); + /* Notify manager that the LLCP is lost or deactivated */ + e->CallVoidMethod (nat->manager, android::gCachedNfcManagerNotifyLlcpLinkDeactivated, nat->tag); + if (e->ExceptionCheck()) + { + e->ExceptionClear(); + ALOGE ("%s: fail notify", fn); + } + + nat->vm->DetachCurrentThread (); + + //PeerToPeer no longer needs to handle NDEF data event + NFA_DeregisterNDefTypeHandler (mNdefTypeHandlerHandle); + mNdefTypeHandlerHandle = NFA_HANDLE_INVALID; + + //let the tag-reading code handle NDEF data event + android::nativeNfcTag_registerNdefTypeHandler (); + ALOGD ("%s: exit", fn); +} + + +/******************************************************************************* +** +** Function: accept +** +** Description: Accept a peer's request to connect. +** serverJniHandle: Server's handle. +** connJniHandle: Connection handle. +** maxInfoUnit: Maximum information unit. +** recvWindow: Receive window size. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::accept (tBRCM_JNI_HANDLE serverJniHandle, tBRCM_JNI_HANDLE connJniHandle, int maxInfoUnit, int recvWindow) +{ + static const char fn [] = "PeerToPeer::accept"; + tNFA_STATUS nfaStat = NFA_STATUS_FAILED; + NfaConn *pConn = NULL; + bool stat = false; + int ii = 0; + P2pServer *pSrv = NULL; + + ALOGD ("%s: enter; server jni handle: %u; conn jni handle: %u; maxInfoUnit: %d; recvWindow: %d", fn, + serverJniHandle, connJniHandle, maxInfoUnit, recvWindow); + + if ((pSrv = findServer (serverJniHandle)) == NULL) + { + ALOGE ("%s: unknown server jni handle: %u", fn, serverJniHandle); + return (false); + } + + // First, find a free connection block to handle the connection + for (ii = 0; ii < MAX_NFA_CONNS_PER_SERVER; ii++) + { + if (pSrv->mServerConn[ii] == NULL) + { + ALOGD ("%s: serverJniHandle: %u; connJniHandle: %u; allocate server conn index: %u", fn, + serverJniHandle, connJniHandle, ii); + pSrv->mServerConn[ii] = new NfaConn; + pSrv->mServerConn[ii]->mJniHandle = connJniHandle; + break; + } + } + + if (ii == MAX_NFA_CONNS_PER_SERVER) + { + ALOGE ("%s: fail allocate connection block", fn); + return (false); + } + + { + // Wait for NFA_P2P_CONN_REQ_EVT or NFA_NDEF_DATA_EVT when remote device requests connection + SyncEventGuard guard (pSrv->mConnRequestEvent); + ALOGD ("%s: serverJniHandle: %u; connJniHandle: %u; server conn index: %u; wait for incoming connection", fn, + serverJniHandle, connJniHandle, ii); + pSrv->mConnRequestEvent.wait(); + ALOGD ("%s: serverJniHandle: %u; connJniHandle: %u; server conn index: %u; nfa conn h: 0x%X; got incoming connection", fn, + serverJniHandle, connJniHandle, ii, pSrv->mServerConn[ii]->mNfaConnHandle); + } + + // If we had gotten a message via SNEP, fake it out to be for NPP + if (mRcvFakeNppJniHandle == serverJniHandle) + { + ALOGD ("%s: server jni handle %u diverted to NPP fake receive on conn jni handle %u", fn, serverJniHandle, connJniHandle); + delete (pSrv->mServerConn[ii]); + pSrv->mServerConn[ii] = NULL; + mRcvFakeNppJniHandle = connJniHandle; + return (true); + } + + if (pSrv->mServerConn[ii]->mNfaConnHandle == NFA_HANDLE_INVALID) + { + delete (pSrv->mServerConn[ii]); + pSrv->mServerConn[ii] = NULL; + ALOGD ("%s: no handle assigned", fn); + return (false); + } + + ALOGD ("%s: serverJniHandle: %u; connJniHandle: %u; server conn index: %u; nfa conn h: 0x%X; try accept", fn, + serverJniHandle, connJniHandle, ii, pSrv->mServerConn[ii]->mNfaConnHandle); + nfaStat = NFA_P2pAcceptConn (pSrv->mServerConn[ii]->mNfaConnHandle, maxInfoUnit, recvWindow); + + if (nfaStat != NFA_STATUS_OK) + { + ALOGE ("%s: fail to accept remote; error=0x%X", fn, nfaStat); + return (false); + } + + ALOGD ("%s: exit; serverJniHandle: %u; connJniHandle: %u; server conn index: %u; nfa conn h: 0x%X", fn, + serverJniHandle, connJniHandle, ii, pSrv->mServerConn[ii]->mNfaConnHandle); + return (true); +} + + +/******************************************************************************* +** +** Function: deregisterServer +** +** Description: Stop a P2pServer from listening for peer. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::deregisterServer (tBRCM_JNI_HANDLE jniHandle) +{ + static const char fn [] = "PeerToPeer::deregisterServer"; + ALOGD ("%s: enter; JNI handle: %u", fn, jniHandle); + tNFA_STATUS nfaStat = NFA_STATUS_FAILED; + P2pServer *pSrv = NULL; + + if ((pSrv = findServer (jniHandle)) == NULL) + { + ALOGE ("%s: NFA_P2P_LISTEN_EVT for unknown service handle: %u", fn, jniHandle); + return (false); + } + + // Server does not call NFA_P2pDisconnect(), so unblock the accept() + SyncEventGuard guard (pSrv->mConnRequestEvent); + pSrv->mConnRequestEvent.notifyOne(); + + nfaStat = NFA_P2pDeregister (pSrv->mNfaP2pServerHandle); + if (nfaStat != NFA_STATUS_OK) + { + ALOGE ("%s: deregister error=0x%X", fn, nfaStat); + } + + removeServer (jniHandle); + + ALOGD ("%s: exit", fn); + return true; +} + + +/******************************************************************************* +** +** Function: createClient +** +** Description: Create a P2pClient object for a new out-bound connection. +** jniHandle: Connection handle. +** miu: Maximum information unit. +** rw: Receive window size. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::createClient (tBRCM_JNI_HANDLE jniHandle, UINT16 miu, UINT8 rw) +{ + static const char fn [] = "PeerToPeer::createClient"; + int i = 0; + ALOGD ("%s: enter: jni h: %u miu: %u rw: %u", fn, jniHandle, miu, rw); + + for (i = 0; i < sMax; i++) + { + if (mClients[i] == NULL) + { + mClients [i] = new P2pClient; + + mClients [i]->mClientConn.mJniHandle = jniHandle; + mClients [i]->mClientConn.mMaxInfoUnit = miu; + mClients [i]->mClientConn.mRecvWindow = rw; + break; + } + } + + if (i == sMax) + { + ALOGE ("%s: fail", fn); + return (false); + } + + ALOGD ("%s: pClient: 0x%p assigned for client jniHandle: %u", fn, mClients[i], jniHandle); + + SyncEventGuard guard (mClients[i]->mRegisteringEvent); + NFA_P2pRegisterClient (NFA_P2P_DLINK_TYPE, nfaClientCallback); + mClients[i]->mRegisteringEvent.wait(); //wait for NFA_P2P_REG_CLIENT_EVT + + if (mClients[i]->mNfaP2pClientHandle != NFA_HANDLE_INVALID) + { + ALOGD ("%s: exit; new client jniHandle: %u NFA Handle: 0x%04x", fn, jniHandle, mClients[i]->mClientConn.mNfaConnHandle); + return (true); + } + else + { + ALOGE ("%s: FAILED; new client jniHandle: %u NFA Handle: 0x%04x", fn, jniHandle, mClients[i]->mClientConn.mNfaConnHandle); + removeConn (jniHandle); + return (false); + } +} + + +/******************************************************************************* +** +** Function: removeConn +** +** Description: Free resources related to a connection. +** jniHandle: Connection handle. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::removeConn(tBRCM_JNI_HANDLE jniHandle) +{ + static const char fn[] = "PeerToPeer::removeConn"; + int ii = 0, jj = 0; + + // If the connection is a for a client, delete the client itself + for (ii = 0; ii < sMax; ii++) + { + if (mClients[ii] && (mClients[ii]->mClientConn.mJniHandle == jniHandle)) + { + if (mClients[ii]->mNfaP2pClientHandle != NFA_HANDLE_INVALID) + NFA_P2pDeregister (mClients[ii]->mNfaP2pClientHandle); + + delete mClients[ii]; + mClients[ii] = NULL; + ALOGD ("%s: deleted client handle: %u index: %u", fn, jniHandle, ii); + return; + } + } + + // If the connection is for a server, just delete the connection + for (ii = 0; ii < sMax; ii++) + { + if (mServers[ii] != NULL) + { + for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) + { + if ( (mServers[ii]->mServerConn[jj] != NULL) + && (mServers[ii]->mServerConn[jj]->mJniHandle == jniHandle) ) + { + ALOGD ("%s: delete server conn jni h: %u; index: %d; server jni h: %u", + fn, mServers[ii]->mServerConn[jj]->mJniHandle, jj, mServers[ii]->mJniHandle); + delete mServers[ii]->mServerConn[jj]; + mServers[ii]->mServerConn[jj] = NULL; + return; + } + } + } + } + + if (jniHandle == mRcvFakeNppJniHandle) + { + ALOGD ("%s: Reset mRcvFakeNppJniHandle: %u", fn, jniHandle); + mRcvFakeNppJniHandle = 0; + if (mNppFakeOutBuffer != NULL) + { + free (mNppFakeOutBuffer); + mNppFakeOutBuffer = NULL; + } + } + else + ALOGE ("%s: could not find handle: %u", fn, jniHandle); +} + + +/******************************************************************************* +** +** Function: connectConnOriented +** +** Description: Estabish a connection-oriented connection to a peer. +** jniHandle: Connection handle. +** serviceName: Peer's service name. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::connectConnOriented (tBRCM_JNI_HANDLE jniHandle, const char* serviceName) +{ + static const char fn [] = "PeerToPeer::connectConnOriented"; + ALOGD ("%s: enter; h: %u service name=%s", fn, jniHandle, serviceName); + + // If we are connecting to NPP and the other side supports SNEP, use SNEP + if ( (sNppServiceName.compare(serviceName)==0) && (mSnepRegHandle != NFA_HANDLE_INVALID) ) + { + P2pClient *pClient = NULL; + + if ((pClient = findClient (jniHandle)) == NULL) + { + ALOGE ("%s: can't find client, JNI handle: %u", fn, jniHandle); + return (false); + } + + if (mJniHandleSendingNppViaSnep != 0) + { + ALOGE ("%s: SNEP already active, SNEP JNI handle: %u new JNI handle: %u", fn, mJniHandleSendingNppViaSnep, jniHandle); + return (false); + } + + // Save JNI Handle and try to connect to SNEP + mJniHandleSendingNppViaSnep = jniHandle; + + if (NFA_SnepConnect (mSnepRegHandle, "urn:nfc:sn:snep") == NFA_STATUS_OK) + { + SyncEventGuard guard (pClient->mSnepEvent); + pClient->mSnepEvent.wait(); + + // If the connect attempt failed, connection handle is invalid + if (pClient->mSnepConnHandle != NFA_HANDLE_INVALID) + { + // return true, as if we were connected. + pClient->mClientConn.mRemoteMaxInfoUnit = 248; + pClient->mClientConn.mRemoteRecvWindow = 1; + return (true); + } + } + mJniHandleSendingNppViaSnep = 0; + } + + // If here, we did not establish a SNEP connection + bool stat = createDataLinkConn (jniHandle, serviceName, 0); + ALOGD ("%s: exit; h: %u stat: %u", fn, jniHandle, stat); + return stat; +} + + +/******************************************************************************* +** +** Function: connectConnOriented +** +** Description: Estabish a connection-oriented connection to a peer. +** jniHandle: Connection handle. +** destinationSap: Peer's service access point. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::connectConnOriented (tBRCM_JNI_HANDLE jniHandle, UINT8 destinationSap) +{ + static const char fn [] = "PeerToPeer::connectConnOriented"; + ALOGD ("%s: enter; h: %u dest sap: 0x%X", fn, jniHandle, destinationSap); + bool stat = createDataLinkConn (jniHandle, NULL, destinationSap); + ALOGD ("%s: exit; h: %u stat: %u", fn, jniHandle, stat); + return stat; +} + + +/******************************************************************************* +** +** Function: createDataLinkConn +** +** Description: Estabish a connection-oriented connection to a peer. +** jniHandle: Connection handle. +** serviceName: Peer's service name. +** destinationSap: Peer's service access point. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::createDataLinkConn (tBRCM_JNI_HANDLE jniHandle, const char* serviceName, UINT8 destinationSap) +{ + static const char fn [] = "PeerToPeer::createDataLinkConn"; + ALOGD ("%s: enter", fn); + tNFA_STATUS nfaStat = NFA_STATUS_FAILED; + P2pClient *pClient = NULL; + + if ((pClient = findClient (jniHandle)) == NULL) + { + ALOGE ("%s: can't find client, JNI handle: %u", fn, jniHandle); + return (false); + } + + SyncEventGuard guard (pClient->mConnectingEvent); + pClient->mIsConnecting = true; + + if (serviceName) + nfaStat = NFA_P2pConnectByName (pClient->mNfaP2pClientHandle, + const_cast<char*>(serviceName), pClient->mClientConn.mMaxInfoUnit, + pClient->mClientConn.mRecvWindow); + else if (destinationSap) + nfaStat = NFA_P2pConnectBySap (pClient->mNfaP2pClientHandle, destinationSap, + pClient->mClientConn.mMaxInfoUnit, pClient->mClientConn.mRecvWindow); + + if (nfaStat == NFA_STATUS_OK) + { + ALOGD ("%s: wait for connected event mConnectingEvent: 0x%p", fn, pClient); + pClient->mConnectingEvent.wait(); + + if (pClient->mClientConn.mNfaConnHandle == NFA_HANDLE_INVALID) + { + removeConn (jniHandle); + nfaStat = NFA_STATUS_FAILED; + } + else + pClient->mIsConnecting = false; + } + else + { + removeConn (jniHandle); + ALOGE ("%s: fail; error=0x%X", fn, nfaStat); + } + + ALOGD ("%s: exit", fn); + return nfaStat == NFA_STATUS_OK; +} + + +/******************************************************************************* +** +** Function: findClient +** +** Description: Find a PeerToPeer object with a client connection handle. +** nfaConnHandle: Connection handle. +** +** Returns: PeerToPeer object. +** +*******************************************************************************/ +P2pClient *PeerToPeer::findClient (tNFA_HANDLE nfaConnHandle) +{ + for (int i = 0; i < sMax; i++) + { + if (mClients[i] && (mClients[i]->mNfaP2pClientHandle == nfaConnHandle)) + return (mClients[i]); + } + return (NULL); +} + + +/******************************************************************************* +** +** Function: findClient +** +** Description: Find a PeerToPeer object with a client connection handle. +** jniHandle: Connection handle. +** +** Returns: PeerToPeer object. +** +*******************************************************************************/ +P2pClient *PeerToPeer::findClient (tBRCM_JNI_HANDLE jniHandle) +{ + for (int i = 0; i < sMax; i++) + { + if (mClients[i] && (mClients[i]->mClientConn.mJniHandle == jniHandle)) + return (mClients[i]); + } + return (NULL); +} + + +/******************************************************************************* +** +** Function: findClientCon +** +** Description: Find a PeerToPeer object with a client connection handle. +** nfaConnHandle: Connection handle. +** +** Returns: PeerToPeer object. +** +*******************************************************************************/ +P2pClient *PeerToPeer::findClientCon (tNFA_HANDLE nfaConnHandle) +{ + for (int i = 0; i < sMax; i++) + { + if (mClients[i] && (mClients[i]->mClientConn.mNfaConnHandle == nfaConnHandle)) + return (mClients[i]); + } + return (NULL); +} + + +/******************************************************************************* +** +** Function: findConnection +** +** Description: Find a PeerToPeer object with a connection handle. +** nfaConnHandle: Connection handle. +** +** Returns: PeerToPeer object. +** +*******************************************************************************/ +NfaConn *PeerToPeer::findConnection (tNFA_HANDLE nfaConnHandle) +{ + int ii = 0, jj = 0; + + // First, look through all the client control blocks + for (ii = 0; ii < sMax; ii++) + { + if ( (mClients[ii] != NULL) + && (mClients[ii]->mClientConn.mNfaConnHandle == nfaConnHandle) ) + return (&mClients[ii]->mClientConn); + } + + // Not found yet. Look through all the server control blocks + for (ii = 0; ii < sMax; ii++) + { + if (mServers[ii] != NULL) + { + for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) + { + if ( (mServers[ii]->mServerConn[jj] != NULL) + && (mServers[ii]->mServerConn[jj]->mNfaConnHandle == nfaConnHandle) ) + return (mServers[ii]->mServerConn[jj]); + } + } + } + + // Not found... + return NULL; +} + + +/******************************************************************************* +** +** Function: findConnection +** +** Description: Find a PeerToPeer object with a connection handle. +** jniHandle: Connection handle. +** +** Returns: PeerToPeer object. +** +*******************************************************************************/ +NfaConn *PeerToPeer::findConnection (tBRCM_JNI_HANDLE jniHandle) +{ + int ii = 0, jj = 0; + + // First, look through all the client control blocks + for (ii = 0; ii < sMax; ii++) + { + if ( (mClients[ii] != NULL) + && (mClients[ii]->mClientConn.mJniHandle == jniHandle) ) + return (&mClients[ii]->mClientConn); + } + + // Not found yet. Look through all the server control blocks + for (ii = 0; ii < sMax; ii++) + { + if (mServers[ii] != NULL) + { + for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) + { + if ( (mServers[ii]->mServerConn[jj] != NULL) + && (mServers[ii]->mServerConn[jj]->mJniHandle == jniHandle) ) + return (mServers[ii]->mServerConn[jj]); + } + } + } + + // Not found... + return NULL; +} + + +/******************************************************************************* +** +** Function: send +** +** Description: Send data to peer. +** jniHandle: Handle of connection. +** buffer: Buffer of data. +** bufferLen: Length of data. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::send (tBRCM_JNI_HANDLE jniHandle, UINT8 *buffer, UINT16 bufferLen) +{ + static const char fn [] = "PeerToPeer::send"; + tNFA_STATUS nfaStat = NFA_STATUS_FAILED; + NfaConn *pConn = NULL; + + if ((pConn = findConnection (jniHandle)) == NULL) + { + ALOGE ("%s: can't find connection handle: %u", fn, jniHandle); + return (false); + } + + ALOGD_IF ((mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: send data; jniHandle: %u nfaHandle: 0x%04X mJniHandleSendingNppViaSnep: %u", + fn, pConn->mJniHandle, pConn->mNfaConnHandle, mJniHandleSendingNppViaSnep); + + // Is this a SNEP fake-out + if (jniHandle == mJniHandleSendingNppViaSnep) + { + return (sendViaSnep(jniHandle, buffer, bufferLen)); + } + + nfaStat = NFA_P2pSendData (pConn->mNfaConnHandle, bufferLen, buffer); + + while (nfaStat == NFA_STATUS_CONGESTED) + { + SyncEventGuard guard (pConn->mCongEvent); + pConn->mCongEvent.wait (); + + if (pConn->mNfaConnHandle == NFA_HANDLE_INVALID) + return (false); + + nfaStat = NFA_P2pSendData (pConn->mNfaConnHandle, bufferLen, buffer); + } + + if (nfaStat == NFA_STATUS_OK) + ALOGD_IF ((mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: exit OK; JNI handle: %u NFA Handle: 0x%04x", fn, jniHandle, pConn->mNfaConnHandle); + else + ALOGE ("%s: Data not sent; JNI handle: %u NFA Handle: 0x%04x error: 0x%04x", + fn, jniHandle, pConn->mNfaConnHandle, nfaStat); + + return nfaStat == NFA_STATUS_OK; +} + + +/******************************************************************************* +** +** Function: sendViaSnep +** +** Description: Send out-bound data to the stack's SNEP protocol. +** jniHandle: Handle of connection. +** buffer: Buffer of data. +** dataLen: Length of data. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::sendViaSnep (tBRCM_JNI_HANDLE jniHandle, UINT8 *buffer, UINT16 dataLen) +{ + static const char fn [] = "PeerToPeer::sendViaSnep"; + tNFA_STATUS nfaStat = NFA_STATUS_FAILED; + P2pClient *pClient = NULL; + + if ((pClient = findClient (jniHandle)) == NULL) + { + ALOGE ("%s: can't find client, JNI handle: %u", fn, jniHandle); + mJniHandleSendingNppViaSnep = 0; + return (false); + } + + ALOGD_IF ((mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: send data; jniHandle: %u mSnepNdefMsgLen: %lu mSnepNdefBufLen: %lu dataLen: %d", + fn, jniHandle, pClient->mSnepNdefMsgLen, pClient->mSnepNdefBufLen, dataLen); + + if (pClient->mSnepNdefMsgLen == 0) + { + pClient->mSnepNdefMsgLen = (buffer[6] << 24) | (buffer[7] << 16) | (buffer[8] << 8) | buffer[9]; + if ((pClient->mSnepNdefBuf = (UINT8 *)malloc (pClient->mSnepNdefMsgLen + 1000)) == NULL) + { + ALOGE ("%s: can't malloc len: %lu", fn, pClient->mSnepNdefMsgLen); + mJniHandleSendingNppViaSnep = 0; + return (false); + } + buffer += 10; + dataLen -= 10; + } + + if ((pClient->mSnepNdefBufLen + dataLen) > pClient->mSnepNdefMsgLen) + { + ALOGE ("%s: len error mSnepNdefBufLen: %lu dataLen: %u mSnepNdefMsgLen: %lu", fn, + pClient->mSnepNdefBufLen, dataLen, pClient->mSnepNdefMsgLen); + mJniHandleSendingNppViaSnep = 0; + free (pClient->mSnepNdefBuf); + pClient->mSnepNdefBuf = NULL; + return (false); + } + + // Save the data in the buffer + memcpy (pClient->mSnepNdefBuf + pClient->mSnepNdefBufLen, buffer, dataLen); + + pClient->mSnepNdefBufLen += dataLen; + + // If we got all the data, send it via SNEP + if (pClient->mSnepNdefBufLen == pClient->mSnepNdefMsgLen) + { + ALOGD ("%s GKI_poolcount(2): %u GKI_poolfreecount(2): %u", fn, GKI_poolcount(2), GKI_poolfreecount(2)); + + nfaStat = NFA_SnepPut (pClient->mSnepConnHandle, pClient->mSnepNdefBufLen, pClient->mSnepNdefBuf); + + if (nfaStat != NFA_STATUS_OK) + { + ALOGE ("%s: NFA_SnepPut failed, code: 0x%04x", fn, nfaStat); + mJniHandleSendingNppViaSnep = 0; + free (pClient->mSnepNdefBuf); + pClient->mSnepNdefBuf = NULL; + return (false); + } + + SyncEventGuard guard (pClient->mSnepEvent); + pClient->mSnepEvent.wait (); + + free (pClient->mSnepNdefBuf); + pClient->mSnepNdefBuf = NULL; + mJniHandleSendingNppViaSnep = 0; + return (pClient->mIsSnepSentOk); + } + return (true); +} + + +/******************************************************************************* +** +** Function: receive +** +** Description: Receive data from peer. +** jniHandle: Handle of connection. +** buffer: Buffer to store data. +** bufferLen: Max length of buffer. +** actualLen: Actual length received. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::receive (tBRCM_JNI_HANDLE jniHandle, UINT8* buffer, UINT16 bufferLen, UINT16& actualLen) +{ + static const char fn [] = "PeerToPeer::receive"; + ALOGD_IF ((mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: enter; jniHandle: %u bufferLen: %u", fn, jniHandle, bufferLen); + NfaConn *pConn = NULL; + + if (jniHandle == mRcvFakeNppJniHandle) + return (feedNppFromSnep(buffer, bufferLen, actualLen)); + + if ((pConn = findConnection (jniHandle)) == NULL) + { + ALOGE ("%s: can't find connection handle: %u", fn, jniHandle); + return (false); + } + + ALOGD_IF ((mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: jniHandle: %u nfaHandle: 0x%04X buf len=%u", fn, pConn->mJniHandle, pConn->mNfaConnHandle, bufferLen); + + // Only wait for data if data queue is empty. + if (pConn->mInboundQ.isEmpty()) + { + // And don't wait if we're disconnected. + if (pConn->mNfaConnHandle != NFA_HANDLE_INVALID) + { + ALOGD_IF ((mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: waiting for data...", fn); + SyncEventGuard guard (pConn->mReadEvent); + pConn->mReadEvent.wait(); + } + + // If the connection was disconnected while we were blocked... + if (pConn->mNfaConnHandle == NFA_HANDLE_INVALID) + { + ALOGD ("%s: already disconnected while waiting", fn); + return (false); + } + } + + bool stat = pConn->mInboundQ.dequeue (buffer, bufferLen, actualLen); + ALOGD_IF ((mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: exit; client h=0x%X stat=%u actual len=%u", fn, pConn->mNfaConnHandle, stat, actualLen); + return stat; +} + + +/******************************************************************************* +** +** Function: feedNppFromSnep +** +** Description: Send incomming data to the NFC service's NDEF Push Protocol. +** buffer: Buffer of data to send. +** bufferLen: Length of data in buffer. +** actualLen: Actual length sent. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::feedNppFromSnep (UINT8* buffer, UINT16 bufferLen, UINT16& actualLen) +{ + static const char fn [] = "PeerToPeer::feedNppFromSnep"; + + ALOGD_IF ((mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: mNppTotalLen: %lu mNppReadSoFar: %lu bufferLen: %u", + fn, mNppTotalLen, mNppReadSoFar, bufferLen); + + if (bufferLen > (mNppTotalLen - mNppReadSoFar)) + bufferLen = mNppTotalLen - mNppReadSoFar; + + memcpy (buffer, mNppFakeOutBuffer + mNppReadSoFar, bufferLen); + + mNppReadSoFar += bufferLen; + actualLen = bufferLen; + + if (mNppReadSoFar == mNppTotalLen) + { + ALOGD ("%s: entire message consumed", fn); + free (mNppFakeOutBuffer); + mNppFakeOutBuffer = NULL; + mRcvFakeNppJniHandle = 0; + } + return (true); +} + + +/******************************************************************************* +** +** Function: disconnectConnOriented +** +** Description: Disconnect a connection-oriented connection with peer. +** jniHandle: Handle of connection. +** +** Returns: True if ok. +** +*******************************************************************************/ +bool PeerToPeer::disconnectConnOriented (tBRCM_JNI_HANDLE jniHandle) +{ + static const char fn [] = "PeerToPeer::disconnectConnOriented"; + tNFA_STATUS nfaStat = NFA_STATUS_FAILED; + P2pClient *pClient = NULL; + NfaConn *pConn = NULL; + + ALOGD ("%s: enter; jni handle: %u", fn, jniHandle); + + if ((pConn = findConnection(jniHandle)) == NULL) + { + ALOGE ("%s: can't find connection handle: %u", fn, jniHandle); + return (false); + } + + // If this is a client, he may not be connected yet, so unblock him just in case + if ( ((pClient = findClient(jniHandle)) != NULL) && (pClient->mIsConnecting) ) + { + SyncEventGuard guard (pClient->mConnectingEvent); + pClient->mConnectingEvent.notifyOne(); + return (true); + } + + { + SyncEventGuard guard1 (pConn->mCongEvent); + pConn->mCongEvent.notifyOne (); //unblock send() if congested + } + { + SyncEventGuard guard2 (pConn->mReadEvent); + pConn->mReadEvent.notifyOne (); //unblock receive() + } + + if (pConn->mNfaConnHandle != NFA_HANDLE_INVALID) + { + ALOGD ("%s: try disconn nfa h=0x%04X", fn, pConn->mNfaConnHandle); + SyncEventGuard guard (pConn->mDisconnectingEvent); + nfaStat = NFA_P2pDisconnect (pConn->mNfaConnHandle, FALSE); + + if (nfaStat != NFA_STATUS_OK) + ALOGE ("%s: fail p2p disconnect", fn); + else + pConn->mDisconnectingEvent.wait(); + } + + mDisconnectMutex.lock (); + removeConn (jniHandle); + mDisconnectMutex.unlock (); + + ALOGD ("%s: exit; jni handle: %u", fn, jniHandle); + return nfaStat == NFA_STATUS_OK; +} + + +/******************************************************************************* +** +** Function: getRemoteMaxInfoUnit +** +** Description: Get peer's max information unit. +** jniHandle: Handle of the connection. +** +** Returns: Peer's max information unit. +** +*******************************************************************************/ +UINT16 PeerToPeer::getRemoteMaxInfoUnit (tBRCM_JNI_HANDLE jniHandle) +{ + static const char fn [] = "PeerToPeer::getRemoteMaxInfoUnit"; + NfaConn *pConn = NULL; + + if ((pConn = findConnection(jniHandle)) == NULL) + { + ALOGE ("%s: can't find client jniHandle: %u", fn, jniHandle); + return 0; + } + ALOGD ("%s: jniHandle: %u MIU: %u", fn, jniHandle, pConn->mRemoteMaxInfoUnit); + return (pConn->mRemoteMaxInfoUnit); +} + + +/******************************************************************************* +** +** Function: getRemoteRecvWindow +** +** Description: Get peer's receive window size. +** jniHandle: Handle of the connection. +** +** Returns: Peer's receive window size. +** +*******************************************************************************/ +UINT8 PeerToPeer::getRemoteRecvWindow (tBRCM_JNI_HANDLE jniHandle) +{ + static const char fn [] = "PeerToPeer::getRemoteRecvWindow"; + ALOGD ("%s: client jni handle: %u", fn, jniHandle); + NfaConn *pConn = NULL; + + if ((pConn = findConnection(jniHandle)) == NULL) + { + ALOGE ("%s: can't find client", fn); + return 0; + } + return pConn->mRemoteRecvWindow; +} + + +/******************************************************************************* +** +** Function: enableP2pListening +** +** Description: Start/stop polling/listening to peer that supports P2P. +** isEnable: Is enable polling/listening? +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::enableP2pListening (bool isEnable) +{ + static const char fn [] = "PeerToPeer::enableP2pListening"; + tNFA_STATUS nfaStat = NFA_STATUS_FAILED; + + ALOGD ("%s: enter isEnable: %u mIsP2pListening: %u", fn, isEnable, mIsP2pListening); + + // If request to enable P2P listening, and we were not already listening + if ( (isEnable == true) && (mIsP2pListening == false) && (mP2pListenTechMask != 0) ) + { + SyncEventGuard guard (mSetTechEvent); + if ((nfaStat = NFA_SetP2pListenTech (mP2pListenTechMask)) == NFA_STATUS_OK) + { + mSetTechEvent.wait (); + mIsP2pListening = true; + } + else + ALOGE ("%s: fail enable listen; error=0x%X", fn, nfaStat); + } + else if ( (isEnable == false) && (mIsP2pListening == true) ) + { + SyncEventGuard guard (mSetTechEvent); + // Request to disable P2P listening, check if it was enabled + if ((nfaStat = NFA_SetP2pListenTech(0)) == NFA_STATUS_OK) + { + mSetTechEvent.wait (); + mIsP2pListening = false; + } + else + ALOGE ("%s: fail disable listen; error=0x%X", fn, nfaStat); + } + ALOGD ("%s: exit; mIsP2pListening: %u", fn, mIsP2pListening); +} + + +/******************************************************************************* +** +** Function: handleNfcOnOff +** +** Description: Handle events related to turning NFC on/off by the user. +** isOn: Is NFC turning on? +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::handleNfcOnOff (bool isOn) +{ + static const char fn [] = "PeerToPeer::handleNfcOnOff"; + ALOGD ("%s: enter; is on=%u", fn, isOn); + tNFA_STATUS stat = NFA_STATUS_FAILED; + + mIsP2pListening = false; // In both cases, P2P will not be listening + + if (isOn) + { + // Start with no clients or servers + memset (mServers, 0, sizeof(mServers)); + memset (mClients, 0, sizeof(mClients)); + + //Android older than 4.0.3 (Ice Cream Sandwich) do not have SNEP in the + //NFC service, so the JNI and stack have to implement SNEP. + if (mJniVersion < 403) + { + { + SyncEventGuard guard (mSnepDefaultServerStartStopEvent); + stat = NFA_SnepStartDefaultServer (snepClientCallback); + if (stat == NFA_STATUS_OK) + mSnepDefaultServerStartStopEvent.wait (); //wait for NFA_SNEP_DEFAULT_SERVER_STARTED_EVT + else + ALOGE ("%s: fail start snep server; error=0x%X", fn, stat); + } + + { + SyncEventGuard guard (mSnepRegisterEvent); + stat = NFA_SnepRegisterClient (snepClientCallback); + if (stat == NFA_STATUS_OK) + mSnepRegisterEvent.wait (); //wait for NFA_SNEP_REG_EVT + else + ALOGE ("%s: fail register snep client; error=0x%X", fn, stat); + } + } + } + else + { + int ii = 0, jj = 0; + + // Disconnect through all the clients + for (ii = 0; ii < sMax; ii++) + { + if (mClients[ii] != NULL) + { + if (mClients[ii]->mClientConn.mNfaConnHandle == NFA_HANDLE_INVALID) + { + SyncEventGuard guard (mClients[ii]->mConnectingEvent); + mClients[ii]->mConnectingEvent.notifyOne(); + } + else + { + mClients[ii]->mClientConn.mNfaConnHandle = NFA_HANDLE_INVALID; + { + SyncEventGuard guard1 (mClients[ii]->mClientConn.mCongEvent); + mClients[ii]->mClientConn.mCongEvent.notifyOne (); //unblock send() + } + { + SyncEventGuard guard2 (mClients[ii]->mClientConn.mReadEvent); + mClients[ii]->mClientConn.mReadEvent.notifyOne (); //unblock receive() + } + } + } + } //loop + + // Now look through all the server control blocks + for (ii = 0; ii < sMax; ii++) + { + if (mServers[ii] != NULL) + { + for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) + { + if (mServers[ii]->mServerConn[jj] != NULL) + { + mServers[ii]->mServerConn[jj]->mNfaConnHandle = NFA_HANDLE_INVALID; + { + SyncEventGuard guard1 (mServers[ii]->mServerConn[jj]->mCongEvent); + mServers[ii]->mServerConn[jj]->mCongEvent.notifyOne (); //unblock write (if congested) + } + { + SyncEventGuard guard2 (mServers[ii]->mServerConn[jj]->mReadEvent); + mServers[ii]->mServerConn[jj]->mReadEvent.notifyOne (); //unblock receive() + } + } + } + } + } //loop + + mJniHandleSendingNppViaSnep = 0; + mRcvFakeNppJniHandle = 0; + mSnepRegHandle = NFA_HANDLE_INVALID; + + if (mNppFakeOutBuffer != NULL) + { + free (mNppFakeOutBuffer); + mNppFakeOutBuffer = NULL; + } + } + ALOGD ("%s: exit", fn); +} + + +/******************************************************************************* +** +** Function: nfaServerCallback +** +** Description: Receive LLCP-related events from the stack. +** p2pEvent: Event code. +** eventData: Event data. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::nfaServerCallback (tNFA_P2P_EVT p2pEvent, tNFA_P2P_EVT_DATA* eventData) +{ + static const char fn [] = "PeerToPeer::nfaServerCallback"; + P2pServer *pSrv = NULL; + NfaConn *pConn = NULL; + + ALOGD_IF ((sP2p.mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: enter; event=0x%X", fn, p2pEvent); + + switch (p2pEvent) + { + case NFA_P2P_LISTEN_EVT: // NFA_P2pRegisterServer() has started to listen + ALOGD ("%s: NFA_P2P_LISTEN_EVT; handle: 0x%04x; service sap=0x%02x name: %s", fn, + eventData->listen.server_handle, eventData->listen.server_sap, eventData->listen.service_name); + + if ((pSrv = sP2p.findServer(eventData->listen.service_name)) == NULL) + { + ALOGE ("%s: NFA_P2P_LISTEN_EVT for unknown service: %s", fn, eventData->listen.service_name); + } + else + { + SyncEventGuard guard (pSrv->mListenEvent); + pSrv->mNfaP2pServerHandle = eventData->listen.server_handle; + pSrv->mListenEvent.notifyOne(); //unblock registerServer() + } + break; + + case NFA_P2P_ACTIVATED_EVT: //remote device has activated + ALOGD ("%s: NFA_P2P_ACTIVATED_EVT; handle: 0x%04x", fn, eventData->activated.handle); + break; + + case NFA_P2P_DEACTIVATED_EVT: + ALOGD ("%s: NFA_P2P_DEACTIVATED_EVT; handle: 0x%04x", fn, eventData->activated.handle); + break; + + case NFA_P2P_CONN_REQ_EVT: + ALOGD ("%s: NFA_P2P_CONN_REQ_EVT; nfa server h=0x%04x; nfa conn h=0x%04x; remote sap=0x%02x", fn, + eventData->conn_req.server_handle, eventData->conn_req.conn_handle, eventData->conn_req.remote_sap); + + if ((pSrv = sP2p.findServer(eventData->conn_req.server_handle)) == NULL) + { + ALOGE ("%s: NFA_P2P_CONN_REQ_EVT; unknown server h", fn); + return; + } + ALOGD ("%s: NFA_P2P_CONN_REQ_EVT; server jni h=%u", fn, pSrv->mJniHandle); + + // Look for a connection block that is waiting (handle invalid) + if ((pConn = pSrv->findServerConnection(NFA_HANDLE_INVALID)) == NULL) + { + ALOGE ("%s: NFA_P2P_CONN_REQ_EVT; server not listening", fn); + } + else + { + SyncEventGuard guard (pSrv->mConnRequestEvent); + pConn->mNfaConnHandle = eventData->conn_req.conn_handle; + pConn->mRemoteMaxInfoUnit = eventData->conn_req.remote_miu; + pConn->mRemoteRecvWindow = eventData->conn_req.remote_rw; + ALOGD ("%s: NFA_P2P_CONN_REQ_EVT; server jni h=%u; conn jni h=%u; notify conn req", fn, pSrv->mJniHandle, pConn->mJniHandle); + pSrv->mConnRequestEvent.notifyOne(); //unblock accept() + } + break; + + case NFA_P2P_CONNECTED_EVT: + ALOGD ("%s: NFA_P2P_CONNECTED_EVT; h=0x%x remote sap=0x%X", fn, + eventData->connected.client_handle, eventData->connected.remote_sap); + break; + + case NFA_P2P_DISC_EVT: + ALOGD ("%s: NFA_P2P_DISC_EVT; h=0x%04x; reason=0x%X", fn, eventData->disc.handle, eventData->disc.reason); + // Look for the connection block + if ((pConn = sP2p.findConnection(eventData->disc.handle)) == NULL) + { + ALOGE ("%s: NFA_P2P_DISC_EVT: can't find conn for NFA handle: 0x%04x", fn, eventData->disc.handle); + } + else + { + sP2p.mDisconnectMutex.lock (); + pConn->mNfaConnHandle = NFA_HANDLE_INVALID; + { + ALOGD ("%s: NFA_P2P_DISC_EVT; try guard disconn event", fn); + SyncEventGuard guard3 (pConn->mDisconnectingEvent); + pConn->mDisconnectingEvent.notifyOne (); + ALOGD ("%s: NFA_P2P_DISC_EVT; notified disconn event", fn); + } + { + ALOGD ("%s: NFA_P2P_DISC_EVT; try guard congest event", fn); + SyncEventGuard guard1 (pConn->mCongEvent); + pConn->mCongEvent.notifyOne (); //unblock write (if congested) + ALOGD ("%s: NFA_P2P_DISC_EVT; notified congest event", fn); + } + { + ALOGD ("%s: NFA_P2P_DISC_EVT; try guard read event", fn); + SyncEventGuard guard2 (pConn->mReadEvent); + pConn->mReadEvent.notifyOne (); //unblock receive() + ALOGD ("%s: NFA_P2P_DISC_EVT; notified read event", fn); + } + sP2p.mDisconnectMutex.unlock (); + } + break; + + case NFA_P2P_DATA_EVT: + // Look for the connection block + if ((pConn = sP2p.findConnection(eventData->data.handle)) == NULL) + { + ALOGE ("%s: NFA_P2P_DATA_EVT: can't find conn for NFA handle: 0x%04x", fn, eventData->data.handle); + } + else + { + ALOGD_IF ((sP2p.mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: NFA_P2P_DATA_EVT; h=0x%X; remote sap=0x%X", fn, + eventData->data.handle, eventData->data.remote_sap); + const int maxBufSize = 2 * 1024; + UINT8 buffer [maxBufSize]; + UINT32 actualDataLen = 0; + BOOLEAN isMoreData = TRUE; + while (isMoreData) + { + actualDataLen = 0; + isMoreData = FALSE; + tNFA_STATUS stat = NFA_P2pReadData (eventData->data.handle, maxBufSize, &actualDataLen, buffer, &isMoreData); + if ((stat == NFA_STATUS_OK) && (actualDataLen > 0)) + pConn->mInboundQ.enqueue (buffer, actualDataLen); + } + SyncEventGuard guard (pConn->mReadEvent); + pConn->mReadEvent.notifyOne(); + } + break; + + case NFA_P2P_CONGEST_EVT: + // Look for the connection block + if ((pConn = sP2p.findConnection(eventData->congest.handle)) == NULL) + { + ALOGE ("%s: NFA_P2P_CONGEST_EVT: can't find conn for NFA handle: 0x%04x", fn, eventData->congest.handle); + } + else + { + ALOGD ("%s: NFA_P2P_CONGEST_EVT; nfa handle: 0x%04x congested: %u", fn, + eventData->congest.handle, eventData->congest.is_congested); + + SyncEventGuard guard (pConn->mCongEvent); + pConn->mCongEvent.notifyOne(); + } + break; + + default: + ALOGE ("%s: unknown event 0x%X ????", fn, p2pEvent); + break; + } + ALOGD_IF ((sP2p.mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: exit", fn); +} + + +/******************************************************************************* +** +** Function: nfaClientCallback +** +** Description: Receive LLCP-related events from the stack. +** p2pEvent: Event code. +** eventData: Event data. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::nfaClientCallback (tNFA_P2P_EVT p2pEvent, tNFA_P2P_EVT_DATA* eventData) +{ + static const char fn [] = "PeerToPeer::nfaClientCallback"; + NfaConn *pConn = NULL; + P2pClient *pClient = NULL; + + ALOGD_IF ((sP2p.mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: enter; event=%u", fn, p2pEvent); + + switch (p2pEvent) + { + case NFA_P2P_REG_CLIENT_EVT: + // Look for a client that is trying to register + if ((pClient = sP2p.findClient ((tNFA_HANDLE)NFA_HANDLE_INVALID)) == NULL) + { + ALOGE ("%s: NFA_P2P_REG_CLIENT_EVT: can't find waiting client", fn); + } + else + { + ALOGD ("%s: NFA_P2P_REG_CLIENT_EVT; Conn Handle: 0x%04x, pClient: 0x%p", fn, eventData->reg_client.client_handle, pClient); + + SyncEventGuard guard (pClient->mRegisteringEvent); + pClient->mNfaP2pClientHandle = eventData->reg_client.client_handle; + pClient->mRegisteringEvent.notifyOne(); + } + break; + + case NFA_P2P_ACTIVATED_EVT: + // Look for a client that is trying to register + if ((pClient = sP2p.findClient (eventData->activated.handle)) == NULL) + { + ALOGE ("%s: NFA_P2P_ACTIVATED_EVT: can't find client", fn); + } + else + { + ALOGD ("%s: NFA_P2P_ACTIVATED_EVT; Conn Handle: 0x%04x, pClient: 0x%p", fn, eventData->activated.handle, pClient); + } + break; + + case NFA_P2P_DEACTIVATED_EVT: + ALOGD ("%s: NFA_P2P_DEACTIVATED_EVT: conn handle: 0x%X", fn, eventData->deactivated.handle); + break; + + case NFA_P2P_CONNECTED_EVT: + // Look for the client that is trying to connect + if ((pClient = sP2p.findClient (eventData->connected.client_handle)) == NULL) + { + ALOGE ("%s: NFA_P2P_CONNECTED_EVT: can't find client: 0x%04x", fn, eventData->connected.client_handle); + } + else + { + ALOGD ("%s: NFA_P2P_CONNECTED_EVT; client_handle=0x%04x conn_handle: 0x%04x remote sap=0x%X pClient: 0x%p", fn, + eventData->connected.client_handle, eventData->connected.conn_handle, eventData->connected.remote_sap, pClient); + + SyncEventGuard guard (pClient->mConnectingEvent); + pClient->mClientConn.mNfaConnHandle = eventData->connected.conn_handle; + pClient->mClientConn.mRemoteMaxInfoUnit = eventData->connected.remote_miu; + pClient->mClientConn.mRemoteRecvWindow = eventData->connected.remote_rw; + pClient->mConnectingEvent.notifyOne(); //unblock createDataLinkConn() + } + break; + + case NFA_P2P_DISC_EVT: + ALOGD ("%s: NFA_P2P_DISC_EVT; h=0x%04x; reason=0x%X", fn, eventData->disc.handle, eventData->disc.reason); + // Look for the connection block + if ((pConn = sP2p.findConnection(eventData->disc.handle)) == NULL) + { + // If no connection, may be a client that is trying to connect + if ((pClient = sP2p.findClientCon ((tNFA_HANDLE)NFA_HANDLE_INVALID)) == NULL) + { + ALOGE ("%s: NFA_P2P_DISC_EVT: can't find conn for NFA handle: 0x%04x", fn, eventData->disc.handle); + return; + } + // Unblock createDataLinkConn() + SyncEventGuard guard (pClient->mConnectingEvent); + pClient->mConnectingEvent.notifyOne(); + } + else + { + sP2p.mDisconnectMutex.lock (); + pConn->mNfaConnHandle = NFA_HANDLE_INVALID; + { + ALOGD ("%s: NFA_P2P_DISC_EVT; try guard disconn event", fn); + SyncEventGuard guard3 (pConn->mDisconnectingEvent); + pConn->mDisconnectingEvent.notifyOne (); + ALOGD ("%s: NFA_P2P_DISC_EVT; notified disconn event", fn); + } + { + ALOGD ("%s: NFA_P2P_DISC_EVT; try guard congest event", fn); + SyncEventGuard guard1 (pConn->mCongEvent); + pConn->mCongEvent.notifyOne(); //unblock write (if congested) + ALOGD ("%s: NFA_P2P_DISC_EVT; notified congest event", fn); + } + { + ALOGD ("%s: NFA_P2P_DISC_EVT; try guard read event", fn); + SyncEventGuard guard2 (pConn->mReadEvent); + pConn->mReadEvent.notifyOne(); //unblock receive() + ALOGD ("%s: NFA_P2P_DISC_EVT; notified read event", fn); + } + sP2p.mDisconnectMutex.unlock (); + } + break; + + case NFA_P2P_DATA_EVT: + // Look for the connection block + if ((pConn = sP2p.findConnection(eventData->data.handle)) == NULL) + { + ALOGE ("%s: NFA_P2P_DATA_EVT: can't find conn for NFA handle: 0x%04x", fn, eventData->data.handle); + } + else + { + ALOGD_IF ((sP2p.mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: NFA_P2P_DATA_EVT; h=0x%X; remote sap=0x%X", fn, + eventData->data.handle, eventData->data.remote_sap); + const int maxBufSize = 2 * 1024; + UINT8 buffer [maxBufSize]; + UINT32 actualDataLen = 0; + BOOLEAN isMoreData = TRUE; + while (isMoreData) + { + actualDataLen = 0; + isMoreData = FALSE; + tNFA_STATUS stat = NFA_P2pReadData (eventData->data.handle, maxBufSize, &actualDataLen, buffer, &isMoreData); + if ((stat == NFA_STATUS_OK) && (actualDataLen > 0)) + pConn->mInboundQ.enqueue (buffer, actualDataLen); + } + SyncEventGuard guard (pConn->mReadEvent); + pConn->mReadEvent.notifyOne(); + } + break; + + case NFA_P2P_CONGEST_EVT: + // Look for the connection block + if ((pConn = sP2p.findConnection(eventData->congest.handle)) == NULL) + { + ALOGE ("%s: NFA_P2P_CONGEST_EVT: can't find conn for NFA handle: 0x%04x", fn, eventData->congest.handle); + } + else + { + ALOGD_IF ((sP2p.mAppLogLevel>=BT_TRACE_LEVEL_DEBUG), "%s: NFA_P2P_CONGEST_EVT; nfa handle: 0x%04x congested: %u", fn, + eventData->congest.handle, eventData->congest.is_congested); + + SyncEventGuard guard (pConn->mCongEvent); + pConn->mCongEvent.notifyOne(); + } + break; + + default: + ALOGE ("%s: unknown event 0x%X ????", fn, p2pEvent); + break; + } +} + + +/******************************************************************************* +** +** Function: snepClientCallback +** +** Description: Receive SNEP-related events from the stack. +** snepEvent: Event code. +** eventData: Event data. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::snepClientCallback (tNFA_SNEP_EVT snepEvent, tNFA_SNEP_EVT_DATA *eventData) +{ + static const char fn [] = "PeerToPeer::snepClientCallback"; + P2pClient *pClient; + + switch (snepEvent) + { + case NFA_SNEP_REG_EVT: + { + ALOGD ("%s NFA_SNEP_REG_EVT Status: %u Handle: 0x%X", fn, eventData->reg.status, eventData->reg.reg_handle); + SyncEventGuard guard (sP2p.mSnepRegisterEvent); + if (eventData->reg.status == NFA_STATUS_OK) + sP2p.mSnepRegHandle = eventData->reg.reg_handle; + sP2p.mSnepRegisterEvent.notifyOne (); + break; + } + + case NFA_SNEP_ACTIVATED_EVT: + ALOGD ("%s NFA_SNEP_ACTIVATED_EVT mJniHandleSendingNppViaSnep: %u", fn, sP2p.mJniHandleSendingNppViaSnep); + break; + + case NFA_SNEP_DEACTIVATED_EVT: + ALOGD ("%s NFA_SNEP_ACTIVATED_EVT mJniHandleSendingNppViaSnep: %u", fn, sP2p.mJniHandleSendingNppViaSnep); + break; + + case NFA_SNEP_CONNECTED_EVT: + if ((pClient = sP2p.findClient (sP2p.mJniHandleSendingNppViaSnep)) == NULL) + { + ALOGE ("%s: NFA_SNEP_CONNECTED_EVT - can't find SNEP client, mJniHandleSendingNppViaSnep: %u", fn, sP2p.mJniHandleSendingNppViaSnep); + } + else + { + ALOGD ("%s NFA_SNEP_CONNECTED_EVT mJniHandleSendingNppViaSnep: %u ConnHandle: 0x%04x", fn, sP2p.mJniHandleSendingNppViaSnep, eventData->connect.conn_handle); + + pClient->mSnepConnHandle = eventData->connect.conn_handle; + SyncEventGuard guard (pClient->mSnepEvent); + pClient->mSnepEvent.notifyOne(); + } + break; + + case NFA_SNEP_PUT_RESP_EVT: + if ((pClient = sP2p.findClient (sP2p.mJniHandleSendingNppViaSnep)) == NULL) + { + ALOGE ("%s: NFA_SNEP_PUT_RESP_EVT - can't find SNEP client, mJniHandleSendingNppViaSnep: %u", fn, sP2p.mJniHandleSendingNppViaSnep); + } + else + { + ALOGD ("%s NFA_SNEP_PUT_RESP_EVT mJniHandleSendingNppViaSnep: %u Result: 0x%X", fn, sP2p.mJniHandleSendingNppViaSnep, eventData->put_resp.resp_code); + + pClient->mIsSnepSentOk = (eventData->put_resp.resp_code == NFA_SNEP_RESP_CODE_SUCCESS); + + NFA_SnepDisconnect (eventData->put_resp.conn_handle, FALSE); + + SyncEventGuard guard (pClient->mSnepEvent); + pClient->mSnepEvent.notifyOne(); + } + break; + + case NFA_SNEP_DISC_EVT: + if ((pClient = sP2p.findClient (sP2p.mJniHandleSendingNppViaSnep)) == NULL) + { + ALOGE ("%s: NFA_SNEP_DISC_EVT - can't find SNEP client, mJniHandleSendingNppViaSnep: %u", fn, sP2p.mJniHandleSendingNppViaSnep); + } + else + { + ALOGD ("%s NFA_SNEP_DISC_EVT mJniHandleSendingNppViaSnep: %u", fn, sP2p.mJniHandleSendingNppViaSnep); + pClient->mSnepConnHandle = NFA_HANDLE_INVALID; + + SyncEventGuard guard (pClient->mSnepEvent); + pClient->mSnepEvent.notifyOne(); + } + break; + + case NFA_SNEP_DEFAULT_SERVER_STARTED_EVT: + { + ALOGE ("%s: NFA_SNEP_DEFAULT_SERVER_STARTED_EVT", fn); + SyncEventGuard guard (sP2p.mSnepDefaultServerStartStopEvent); + sP2p.mSnepDefaultServerStartStopEvent.notifyOne(); //unblock NFA_SnepStartDefaultServer() + break; + } + + case NFA_SNEP_DEFAULT_SERVER_STOPPED_EVT: + { + ALOGE ("%s: NFA_SNEP_DEFAULT_SERVER_STOPPED_EVT", fn); + SyncEventGuard guard (sP2p.mSnepDefaultServerStartStopEvent); + sP2p.mSnepDefaultServerStartStopEvent.notifyOne(); //unblock NFA_SnepStopDefaultServer() + break; + } + break; + + default: + ALOGE ("%s UNKNOWN EVENT: 0x%04x mJniHandleSendingNppViaSnep: %u", fn, snepEvent, sP2p.mJniHandleSendingNppViaSnep); + break; + } +} + + +/******************************************************************************* +** +** Function: ndefTypeCallback +** +** Description: Receive NDEF-related events from the stack. +** ndefEvent: Event code. +** eventData: Event data. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::ndefTypeCallback (tNFA_NDEF_EVT ndefEvent, tNFA_NDEF_EVT_DATA *eventData) +{ + static const char fn [] = "PeerToPeer::ndefTypeCallback"; + P2pServer *pSvr = NULL; + + if (ndefEvent == NFA_NDEF_REGISTER_EVT) + { + tNFA_NDEF_REGISTER& ndef_reg = eventData->ndef_reg; + ALOGD ("%s NFA_NDEF_REGISTER_EVT Status: %u; h=0x%X", fn, ndef_reg.status, ndef_reg.ndef_type_handle); + sP2p.mNdefTypeHandlerHandle = ndef_reg.ndef_type_handle; + } + else if (ndefEvent == NFA_NDEF_DATA_EVT) + { + ALOGD ("%s NFA_NDEF_DATA_EVT Len: %lu", fn, eventData->ndef_data.len); + + if (sP2p.mRcvFakeNppJniHandle != 0) + { + ALOGE ("%s Got NDEF Data while busy, mRcvFakeNppJniHandle: %u", fn, sP2p.mRcvFakeNppJniHandle); + return; + } + + if ((pSvr = sP2p.findServer ("com.android.npp")) == NULL) + { + ALOGE ("%s Got NDEF Data but no NPP server listening", fn); + return; + } + + if ((sP2p.mNppFakeOutBuffer = (UINT8 *)malloc(eventData->ndef_data.len + 10)) == NULL) + { + ALOGE ("%s failed to malloc: %lu bytes", fn, eventData->ndef_data.len + 10); + return; + } + + sP2p.mNppFakeOutBuffer[0] = 0x01; + sP2p.mNppFakeOutBuffer[1] = 0x00; + sP2p.mNppFakeOutBuffer[2] = 0x00; + sP2p.mNppFakeOutBuffer[3] = 0x00; + sP2p.mNppFakeOutBuffer[4] = 0x01; + sP2p.mNppFakeOutBuffer[5] = 0x01; + sP2p.mNppFakeOutBuffer[6] = (UINT8)(eventData->ndef_data.len >> 24); + sP2p.mNppFakeOutBuffer[7] = (UINT8)(eventData->ndef_data.len >> 16); + sP2p.mNppFakeOutBuffer[8] = (UINT8)(eventData->ndef_data.len >> 8); + sP2p.mNppFakeOutBuffer[9] = (UINT8)(eventData->ndef_data.len); + + memcpy (&sP2p.mNppFakeOutBuffer[10], eventData->ndef_data.p_data, eventData->ndef_data.len); + + ALOGD ("%s NFA_NDEF_DATA_EVT Faking NPP on Server Handle: %u", fn, pSvr->mJniHandle); + + sP2p.mRcvFakeNppJniHandle = pSvr->mJniHandle; + sP2p.mNppTotalLen = eventData->ndef_data.len + 10; + sP2p.mNppReadSoFar = 0; + { + SyncEventGuard guard (pSvr->mConnRequestEvent); + pSvr->mConnRequestEvent.notifyOne(); + } + } + else + { + ALOGE ("%s UNKNOWN EVENT: 0x%X", fn, ndefEvent); + } + +} + + +/******************************************************************************* +** +** Function: getLogLevel +** +** Description: Get the diagnostic logging level. +** +** Returns: Log level; 0=no logging; 1=error only; 5=debug +** +*******************************************************************************/ +UINT32 PeerToPeer::getLogLevel () +{ + return mAppLogLevel; +} + + +/******************************************************************************* +** +** Function: connectionEventHandler +** +** Description: Receive events from the stack. +** event: Event code. +** eventData: Event data. +** +** Returns: None +** +*******************************************************************************/ +void PeerToPeer::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* eventData) +{ + switch (event) + { + case NFA_SET_P2P_LISTEN_TECH_EVT: + { + SyncEventGuard guard (mSetTechEvent); + mSetTechEvent.notifyOne(); //unblock NFA_SetP2pListenTech() + break; + } + } +} + + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + + +/******************************************************************************* +** +** Function: P2pServer +** +** Description: Initialize member variables. +** +** Returns: None +** +*******************************************************************************/ +P2pServer::P2pServer() +: mNfaP2pServerHandle (NFA_HANDLE_INVALID), + mJniHandle (0) +{ + memset (mServerConn, 0, sizeof(mServerConn)); +} + + +/******************************************************************************* +** +** Function: findServerConnection +** +** Description: Find a P2pServer that has the handle. +** nfaConnHandle: NFA connection handle. +** +** Returns: P2pServer object. +** +*******************************************************************************/ +NfaConn *P2pServer::findServerConnection (tNFA_HANDLE nfaConnHandle) +{ + int jj = 0; + + for (jj = 0; jj < MAX_NFA_CONNS_PER_SERVER; jj++) + { + if ( (mServerConn[jj] != NULL) && (mServerConn[jj]->mNfaConnHandle == nfaConnHandle) ) + return (mServerConn[jj]); + } + + // If here, not found + return (NULL); +} + + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + + +/******************************************************************************* +** +** Function: P2pClient +** +** Description: Initialize member variables. +** +** Returns: None +** +*******************************************************************************/ +P2pClient::P2pClient () +: mNfaP2pClientHandle (NFA_HANDLE_INVALID), + mIsConnecting (false), + mSnepConnHandle (NFA_HANDLE_INVALID), + mSnepNdefMsgLen (0), + mSnepNdefBufLen (0), + mSnepNdefBuf (NULL), + mIsSnepSentOk (false) +{ +} + + +/******************************************************************************* +** +** Function: ~P2pClient +** +** Description: Free all resources. +** +** Returns: None +** +*******************************************************************************/ +P2pClient::~P2pClient () +{ + if (mSnepNdefBuf) + free (mSnepNdefBuf); +} + + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + + +/******************************************************************************* +** +** Function: NfaConn +** +** Description: Initialize member variables. +** +** Returns: None +** +*******************************************************************************/ +NfaConn::NfaConn() +: mNfaConnHandle (NFA_HANDLE_INVALID), + mJniHandle (0), + mMaxInfoUnit (0), + mRecvWindow (0), + mRemoteMaxInfoUnit (0), + mRemoteRecvWindow (0) +{ +} + |
